00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "structures.h"
00030 #include "structures_private.h"
00031
00032 namespace MSWrite
00033 {
00034 PageLayout::PageLayout () : m_numModified (0)
00035 {
00036 }
00037
00038 PageLayout::~PageLayout ()
00039 {
00040 }
00041
00042 PageLayout &PageLayout::operator= (const PageLayout &rhs)
00043 {
00044 if (this == &rhs)
00045 return *this;
00046
00047 PageLayoutGenerated::operator= (rhs);
00048 NeedsHeader::operator= (rhs);
00049
00050 m_numModified = rhs.m_numModified;
00051
00052 return *this;
00053 }
00054
00055 bool PageLayout::readFromDevice (void)
00056 {
00057 CHECK_DEVICE;
00058
00059 #ifdef DEBUG_PAGELAYOUT
00060 m_device->debug ("\n<<<< PageLayout::readFromDevice >>>>\n");
00061 #endif
00062
00063 int numPageLayoutPages = m_header->getNumPageSectionProperty ();
00064
00065 #ifdef DEBUG_PAGELAYOUT
00066 m_device->debug ("num pageLayoutPages: ", numPageLayoutPages);
00067 #endif
00068
00069
00070 if (numPageLayoutPages == 0)
00071 return true;
00072 else if (numPageLayoutPages > 1)
00073 ErrorAndQuit (Error::InvalidFormat, "invalid #pageLayoutPages\n");
00074
00075
00076 if (!m_device->seekInternal (m_header->getPageSectionProperty () * 128, SEEK_SET))
00077 ErrorAndQuit (Error::FileError, "could not seek to pageLayout\n");
00078
00079 if (!PageLayoutGenerated::readFromDevice ())
00080 return false;
00081
00082 #ifdef DEBUG_PAGELAYOUT
00083 Dump (magic102);
00084 Dump (magic512);
00085
00086 Dump (pageHeight);
00087 Dump (pageWidth);
00088 Dump (pageNumberStart);
00089 Dump (topMargin);
00090 Dump (textHeight);
00091 Dump (leftMargin);
00092 Dump (textWidth);
00093
00094 Dump (magic256);
00095
00096 Dump (headerFromTop);
00097 Dump (footerFromTop);
00098
00099 Dump (magic720);
00100 Dump (zero);
00101 Dump (magic1080);
00102 Dump (unknown);
00103 Dump (zero2);
00104 #endif
00105
00106 #define UpdateModifiedCount(variable) if (m_##variable != variable##Default) m_numModified++
00107 UpdateModifiedCount (magic102);
00108 UpdateModifiedCount (magic512);
00109 UpdateModifiedCount (pageHeight);
00110 UpdateModifiedCount (pageWidth);
00111 UpdateModifiedCount (pageNumberStart);
00112 UpdateModifiedCount (topMargin);
00113 UpdateModifiedCount (textHeight);
00114 UpdateModifiedCount (leftMargin);
00115 UpdateModifiedCount (textWidth);
00116 UpdateModifiedCount (magic256);
00117 UpdateModifiedCount (headerFromTop);
00118 UpdateModifiedCount (footerFromTop);
00119 UpdateModifiedCount (magic720);
00120 UpdateModifiedCount (zero);
00121 UpdateModifiedCount (magic1080);
00122
00123 UpdateModifiedCount (zero2);
00124 #undef UpdateModifiedCount
00125
00126 return true;
00127 }
00128
00129 bool PageLayout::writeToDevice (void)
00130 {
00131 CHECK_DEVICE;
00132
00133 #ifdef DEBUG_PAGELAYOUT
00134 m_device->debug ("\n>>>> PageLayout::writeToDevice <<<<\n");
00135 #endif
00136
00137 m_header->setPageSectionProperty (m_device->tellInternal () / 128);
00138
00139
00140 if (!getIsModified ())
00141 return true;
00142
00143 if (!PageLayoutGenerated::writeToDevice ())
00144 return false;
00145
00146 return true;
00147 }
00148
00149
00150 Font::Font (const Byte *name, const Byte family) : m_name (NULL)
00151 {
00152 if (name) setName (name);
00153 FontGenerated::m_family = family;
00154 }
00155
00156 Font::~Font ()
00157 {
00158 delete [] m_name;
00159 }
00160
00161 Font &Font::operator= (const Font &rhs)
00162 {
00163 if (this == &rhs)
00164 return *this;
00165
00166 FontGenerated::operator= (rhs);
00167
00168 setName (rhs.getName ());
00169
00170 return *this;
00171 }
00172
00173 bool Font::readFromDevice (void)
00174 {
00175 CHECK_DEVICE;
00176
00177 if (!FontGenerated::readFromDevice ())
00178 return false;
00179
00180 #ifdef DEBUG_FONT
00181 Dump (numDataBytes);
00182 Dump (family);
00183 #endif
00184
00185
00186 if (m_numDataBytes == 0xFFFF)
00187 return false;
00188
00189
00190 if (m_numDataBytes == 0)
00191 return false;
00192
00193
00194 if (m_numDataBytes > 128 - sizeof (m_numDataBytes))
00195 ErrorAndQuit (MSWrite::Error::InvalidFormat, "Font nameLen is too big\n");
00196
00197
00198 int nameLen = m_numDataBytes - sizeof (m_family) - 1 ;
00199
00200
00201 m_name = new Byte [nameLen + 1];
00202 if (!m_name)
00203 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for fontName\n");
00204
00205
00206 if (!m_device->readInternal (m_name, nameLen + 1))
00207 ErrorAndQuit (Error::FileError, "could not read fontName\n");
00208
00209
00210 if (m_name [nameLen] != '\0')
00211 ErrorAndQuit (Error::InvalidFormat, "fontName not NUL-terminated\n");
00212
00213 #ifdef DEBUG_FONT
00214 m_device->debug ("\tfontName=", (const char *) m_name);
00215 #endif
00216 return true;
00217 }
00218
00219 bool Font::writeToDevice (void)
00220 {
00221 CHECK_DEVICE;
00222
00223
00224 Word offset = m_device->tellInternal () % 128;
00225 if (offset + sizeof (m_numDataBytes) + m_numDataBytes + sizeof (m_numDataBytes) > 128)
00226 {
00227
00228 Byte scratch [2] = {0xFF, 0xFF};
00229 if (!m_device->writeInternal (scratch, 2))
00230 ErrorAndQuit (Error::FileError, "could not write Font 0xFFFF\n");
00231 return false;
00232 }
00233
00234
00235
00236
00237 if (!FontGenerated::writeToDevice ())
00238 return false;
00239
00240 if (!m_device->writeInternal (m_name, m_numDataBytes - sizeof (m_family)))
00241 ErrorAndQuit (Error::FileError, "could not write fontName\n");
00242
00243 return true;
00244 }
00245
00246
00247 FormatCharProperty::FormatCharProperty () : m_fontTable (NULL)
00248 {
00249
00250
00251 }
00252
00253 FormatCharProperty::~FormatCharProperty ()
00254 {
00255 }
00256
00257 FormatCharProperty &FormatCharProperty::operator= (const FormatCharProperty &rhs)
00258 {
00259 if (this == &rhs)
00260 return *this;
00261
00262 FormatCharPropertyGenerated::operator= (rhs);
00263
00264 m_afterEndCharByte = rhs.m_afterEndCharByte;
00265 m_fontTable = rhs.m_fontTable;
00266 m_font = rhs.m_font;
00267
00268 return *this;
00269 }
00270
00271 bool FormatCharProperty::operator== (FormatCharProperty &rhs)
00272 {
00273 DWord numDataBytes;
00274
00275 if ((numDataBytes = getNumDataBytes ()) != rhs.getNumDataBytes ())
00276 return false;
00277
00278 writeToArray ();
00279 rhs.writeToArray ();
00280
00281 return memcmp (m_data + sizeof (m_numDataBytes), rhs.m_data + sizeof (m_numDataBytes), numDataBytes) == 0;
00282 }
00283
00284 bool FormatCharProperty::readFromDevice (void)
00285 {
00286 CHECK_DEVICE;
00287
00288 #ifdef DEBUG_CHAR
00289 m_device->debug ("\nFormatCharProperty::readFromDevice\n");
00290 #endif
00291
00292 if (!FormatCharPropertyGenerated::readFromDevice ())
00293 return false;
00294
00295 if (!m_fontTable)
00296 ErrorAndQuit (Error::InternalError, "m_fontTable not setup for FormatCharProperty::readFromDevice\n");
00297
00298
00299 if (!updateFont ()) return false;
00300
00301 return true;
00302 }
00303
00304 bool FormatCharProperty::writeToDevice (void)
00305 {
00306 CHECK_DEVICE;
00307
00308 #ifdef DEBUG_CHAR
00309 m_device->debug ("\nFormatCharProperty::writeToDevice, #bytes=", getNumDataBytes ());
00310 #endif
00311
00312 return FormatCharPropertyGenerated::writeToDevice ();
00313 }
00314
00315 bool FormatCharProperty::updateFont (void)
00316 {
00317 Font *fontPtr = m_fontTable->getFont (getFontCode ());
00318 if (!fontPtr)
00319 ErrorAndQuit (Error::InvalidFormat, "fontCode out of range\n");
00320
00321 m_font = *fontPtr;
00322 return true;
00323 }
00324
00325 bool FormatCharProperty::updateFontCode (void)
00326 {
00327 DWord code = m_fontTable->addFont (&m_font);
00328 if (code == 0xFFFFFFFF)
00329 return false;
00330 else
00331 {
00332 setFontCode (code);
00333 return true;
00334 }
00335 }
00336
00337
00338 FormatParaPropertyTabulator::FormatParaPropertyTabulator ()
00339 {
00340 }
00341
00342 FormatParaPropertyTabulator::~FormatParaPropertyTabulator ()
00343 {
00344 }
00345
00346 FormatParaPropertyTabulator &FormatParaPropertyTabulator::operator= (const FormatParaPropertyTabulator &rhs)
00347 {
00348 if (this == &rhs)
00349 return *this;
00350
00351 FormatParaPropertyTabulatorGenerated::operator= (rhs);
00352
00353 return *this;
00354 }
00355
00356 bool FormatParaPropertyTabulator::readFromDevice (void)
00357 {
00358 CHECK_DEVICE;
00359
00360 #ifdef DEBUG_PARA_TAB
00361 m_device->debug ("\nFormatParaPropertyTabulator::readFromDevice\n");
00362 #endif
00363
00364 if (!FormatParaPropertyTabulatorGenerated::readFromDevice ())
00365 return false;
00366
00367 #ifdef DEBUG_PARA_TAB
00368 Dump (indent);
00369 Dump (type);
00370 Dump (zero);
00371 #endif
00372
00373 return true;
00374 }
00375
00376 bool FormatParaPropertyTabulator::writeToDevice (void)
00377 {
00378 CHECK_DEVICE;
00379
00380 #ifdef DEBUG_PARA_TAB
00381 m_device->debug ("\nFormatParaPropertyTabulator::writeToDevice\n");
00382 #endif
00383
00384 return FormatParaPropertyTabulatorGenerated::writeToDevice ();
00385 }
00386
00387
00388 FormatParaProperty::FormatParaProperty () : m_leftMargin (0xFFFF),
00389 m_rightMargin (0xFFFF),
00390 m_numTabulators (0),
00391 m_addedTooManyTabs (false)
00392 {
00393
00394 }
00395
00396 FormatParaProperty::~FormatParaProperty ()
00397 {
00398 }
00399
00400 FormatParaProperty &FormatParaProperty::operator= (const FormatParaProperty &rhs)
00401 {
00402 if (this == &rhs)
00403 return *this;
00404
00405 FormatParaPropertyGenerated::operator= (rhs);
00406
00407 m_afterEndCharByte = rhs.m_afterEndCharByte;
00408 m_leftMargin = rhs.m_leftMargin, m_rightMargin = rhs.m_rightMargin;
00409 m_numTabulators = rhs.m_numTabulators;
00410 m_addedTooManyTabs = rhs.m_addedTooManyTabs;
00411
00412 return *this;
00413 }
00414
00415 bool FormatParaProperty::operator== (FormatParaProperty &rhs)
00416 {
00417 DWord numDataBytes;
00418 if ((numDataBytes = getNumDataBytes ()) != rhs.getNumDataBytes ())
00419 return false;
00420
00421 writeToArray ();
00422 rhs.writeToArray ();
00423
00424 return memcmp (m_data + sizeof (m_numDataBytes), rhs.m_data + sizeof (m_numDataBytes), numDataBytes) == 0;
00425 }
00426
00427 bool FormatParaProperty::readFromDevice (void)
00428 {
00429 CHECK_DEVICE;
00430
00431 #ifdef DEBUG_PARA
00432 m_device->debug ("\nFormatParaProperty::readFromDevice\n");
00433 #endif
00434
00435 #ifdef CHECK_INTERNAL
00436 if (m_leftMargin == 0xFFFF && m_rightMargin == 0xFFFF)
00437 ErrorAndQuit (Error::InternalError, "FormatParaProperty::readFromDevice call not setup\n");
00438 #endif
00439
00440 if (!FormatParaPropertyGenerated::readFromDevice ())
00441 return false;
00442
00443
00444
00445
00446
00447
00448
00449
00450 if (getIsNotNormalParagraph ())
00451 {
00452
00453 if (m_leftMargin < m_leftIndent)
00454 m_leftIndent -= m_leftMargin;
00455 else
00456 m_leftIndent = 0;
00457
00458
00459 if (m_rightMargin < m_rightIndent)
00460 m_rightIndent -= m_rightMargin;
00461 else
00462 m_rightIndent = 0;
00463 }
00464
00465 if (m_numDataBytes > 22)
00466 m_numTabulators = (m_numDataBytes - 22) / FormatParaPropertyTabulator::s_size;
00467 else
00468 m_numTabulators = 0;
00469
00470
00471 if (getNumDataBytes () != m_numDataBytes && !m_numTabulators)
00472 m_device->error (Error::Warn, "m_numDataBytes != getNumDataBytes ()\n");
00473 UseThisMuch::signalHaveSetData (false, m_numDataBytes * 8);
00474
00475 return true;
00476 }
00477
00478 bool FormatParaProperty::writeToDevice (void)
00479 {
00480 CHECK_DEVICE;
00481
00482 #ifdef CHECK_INTERNAL
00483 if (m_leftMargin == 0xFFFF && m_rightMargin == 0xFFFF)
00484 ErrorAndQuit (Error::InternalError, "FormatParaProperty::writeToDevice call not setup\n");
00485 #endif
00486
00487 #ifdef DEBUG_PARA
00488 m_device->debug ("\nFormatParaProperty::writeToDevice, #bytes=", getNumDataBytes ());
00489 #endif
00490
00491 if (m_addedTooManyTabs)
00492 ErrorAndQuit (Error::InternalError, "cannot have more than 14 tabulators; shouldn't even have more than 12\n");
00493
00494 if (m_numTabulators > 12)
00495 m_device->error (Error::Warn, "should not have more than 12 tabulators since you can only access 12 tabs via the GUI\n");
00496
00497
00498
00499 if (!FormatParaPropertyGenerated::writeToDevice ())
00500 return false;
00501
00502 return true;
00503 }
00504
00505
00506 Image::Image () : m_externalImage (NULL),
00507 m_externalImageSize (0),
00508 m_externalImageUpto (0),
00509 m_originalWidth (0), m_originalHeight (0),
00510 m_displayedWidth (0), m_displayedHeight (0)
00511 {
00512 }
00513
00514 Image::~Image ()
00515 {
00516 delete [] m_externalImage;
00517 }
00518
00519 Image &Image::operator= (const Image &rhs)
00520 {
00521 if (this == &rhs)
00522 return *this;
00523
00524 ImageGenerated::operator= (rhs);
00525
00526 m_externalImageSize = rhs.m_externalImageSize;
00527 m_externalImageUpto = rhs.m_externalImageUpto;
00528
00529 delete [] m_externalImage;
00530 m_externalImage = new Byte [m_externalImageSize];
00531 if (!m_externalImage)
00532 return *this;
00533
00534 if (rhs.m_externalImage)
00535 memcpy (m_externalImage, rhs.m_externalImage, m_externalImageUpto);
00536
00537 m_originalWidth = rhs.m_originalWidth;
00538 m_originalHeight = rhs.m_originalHeight;
00539
00540 m_displayedWidth = rhs.m_displayedWidth;
00541 m_displayedHeight = rhs.m_displayedHeight;
00542
00543 return *this;
00544 }
00545
00546
00547 int Image::getBytesPerScanLine (const int width, const int bitsPerPixel, const int padBytes)
00548 {
00549 int bitWidth;
00550 int byteWidth;
00551
00552
00553 bitWidth = width * bitsPerPixel;
00554 byteWidth = bitWidth / 8;
00555 if (bitWidth % 8)
00556 byteWidth++;
00557
00558
00559
00560 byteWidth = (byteWidth + padBytes - 1) / padBytes * padBytes;
00561
00562 return byteWidth;
00563 }
00564
00565 bool Image::readFromDevice (void)
00566 {
00567 CHECK_DEVICE;
00568
00569 #ifdef DEBUG_IMAGE
00570 m_device->debug ("\n<<<< Image::readFromDevice >>>>\n");
00571 #endif
00572
00573 if (!ImageGenerated::readFromDevice ())
00574 return false;
00575
00576 #ifdef DEBUG_IMAGE
00577 Dump (mappingMode);
00578 Dump (MFP_width);
00579 Dump (MFP_height);
00580 Dump (MFP_unknown);
00581
00582 Dump (indent);
00583 Dump (width);
00584 Dump (height);
00585 Dump (zero);
00586
00587 Dump (numHeaderBytes);
00588 Dump (numDataBytes);
00589 Dump (horizontalScalingRel1000);
00590 Dump (verticalScalingRel1000);
00591 #endif
00592
00593 if (getIsWMF ())
00594 {
00595
00596
00597
00598
00599 if (m_bmh->getWidth () || m_bmh->getHeight ())
00600 m_device->error (Error::Warn, "m_bmh structure should be 0 for WMFs\n");
00601
00602 m_originalWidth = Milli2Twip (double (m_MFP_width) / 100.0) * 4.0/3.0;
00603 m_originalHeight = Milli2Twip (double (m_MFP_height) / 100.0) * 4.0/3.0;
00604
00605 m_displayedWidth = double (m_width);
00606 m_displayedHeight = double (m_height);
00607
00608 if (m_horizontalScalingRel1000 != 1000)
00609 m_device->error (Error::Warn, "horizontal scaling should not be set for WMFs\n");
00610 if (m_verticalScalingRel1000 != 1000)
00611 m_device->error (Error::Warn, "vertical scaling should not be set for WMFs\n");
00612
00613
00614
00615
00616
00617
00618 m_externalImage = new Byte [m_externalImageSize = getNumDataBytes ()];
00619 if (!m_externalImage)
00620 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external WMF image\n");
00621
00622 if (!m_device->readInternal (m_externalImage, m_externalImageSize))
00623 ErrorAndQuit (Error::FileError, "could not read internal WMF\n");
00624
00625
00626 WMFHeader wmfHeader;
00627 m_device->setCache (m_externalImage);
00628 wmfHeader.setDevice (m_device);
00629 if (!wmfHeader.readFromDevice ())
00630 return false;
00631
00632
00633
00634
00635 m_device->setCache (NULL);
00636 }
00637 else
00638 {
00639
00640
00641
00642
00643 m_originalWidth = Point2Twip (DWord (m_bmh->getWidth ()));
00644 m_originalHeight = Point2Twip (DWord (m_bmh->getHeight ()));
00645
00646 m_displayedWidth = m_originalWidth / 1.38889 * m_horizontalScalingRel1000 / 1000;
00647 m_displayedHeight = m_originalHeight / 1.38889 * m_verticalScalingRel1000 / 1000;
00648
00649 #define MSWrite_fabs(val) (((val)>=0)?(val):(-(val)))
00650
00651 if (MSWrite_fabs (m_MFP_width / double (m_bmh->getWidth ()) - 2.64) > .3)
00652 m_device->error (Error::Warn, "m_MFP_width != m_bmh->getWidth() * 2.64\n");
00653 if (MSWrite_fabs (m_MFP_height / double (m_bmh->getHeight ()) - 2.64) > .3)
00654 m_device->error (Error::Warn, "m_MFP_height != m_bmh->getHeight() * 2.64\n");
00655
00656 #undef MSWrite_fabs
00657
00658 if (m_width)
00659 m_device->error (Error::Warn, "m_width should not be set for BMPs\n");
00660
00661 if (m_height)
00662 m_device->error (Error::Warn, "m_height should not be set for BMPs\n");
00663
00664
00665
00666
00667
00668
00669 Byte *internalData = new Byte [getNumDataBytes ()];
00670 if (!internalData)
00671 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for internal BMP image\n");
00672 if (!m_device->readInternal (internalData, getNumDataBytes ()))
00673 ErrorAndQuit (Error::FileError, "could not read internal BMP\n");
00674
00675
00676 BMP_BitmapInfoHeader infoHeader;
00677 infoHeader.setWidth (m_bmh->getWidth ());
00678 infoHeader.setHeight (m_bmh->getHeight ());
00679 if (m_bmh->getNumPlanes () != 1)
00680 ErrorAndQuit (Error::InvalidFormat, "bmh.m_numPlanes != 1\n");
00681 infoHeader.setNumPlanes (m_bmh->getNumPlanes ());
00682 infoHeader.setBitsPerPixel (m_bmh->getBitsPerPixel ());
00683 infoHeader.setCompression (0);
00684 infoHeader.setSizeImage (0);
00685 infoHeader.setXPixelsPerMeter (0), infoHeader.setYPixelsPerMeter (0);
00686 infoHeader.setColoursUsed (1 << infoHeader.getBitsPerPixel ());
00687 infoHeader.setColoursImportant (infoHeader.getColoursUsed ());
00688
00689 if (infoHeader.getColoursUsed () != 2)
00690 ErrorAndQuit (Error::InternalError, "colour bitmap??? Please email clarencedang@users.sourceforge.net this file\n");
00691
00692 Word colourTableSize = infoHeader.getColoursUsed () * BMP_BitmapColourIndex::s_size;
00693
00694
00695 BMP_BitmapFileHeader fileHeader;
00696 DWord fileSize = BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size
00697 + colourTableSize
00698 + (m_bmh->getHeight ()
00699 * getBytesPerScanLine (m_bmh->getWidth (), m_bmh->getBitsPerPixel (), 4));
00700
00701 fileHeader.setTotalBytes (fileSize);
00702 fileHeader.setActualImageOffset (BMP_BitmapFileHeader::s_size + BMP_BitmapInfoHeader::s_size
00703 + colourTableSize);
00704
00705
00706 BMP_BitmapColourIndex *colourIndex = new BMP_BitmapColourIndex [infoHeader.getColoursUsed ()];
00707 if (!colourIndex)
00708 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for colourIndex[]\n");
00709
00710
00711
00712 colourIndex [0].setRed (0), colourIndex [0].setGreen (0), colourIndex [0].setBlue (0);
00713 colourIndex [1].setRed (0xFF), colourIndex [1].setGreen (0xFF), colourIndex [1].setBlue (0xFF);
00714
00715 m_externalImage = new Byte [m_externalImageSize = fileSize];
00716 if (!m_externalImage)
00717 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external BMP image\n");
00718
00719 MemoryDevice device;
00720 device.setCache (m_externalImage);
00721 fileHeader.setDevice (&device);
00722 fileHeader.writeToDevice ();
00723 infoHeader.setDevice (&device);
00724 infoHeader.writeToDevice ();
00725 for (int i = 0; i < 2; i++)
00726 {
00727 colourIndex [i].setDevice (&device);
00728 colourIndex [i].writeToDevice ();
00729 }
00730
00731
00732
00733 Word scanLineWRILength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 2);
00734 if (scanLineWRILength != m_bmh->getWidthBytes ())
00735 ErrorAndQuit (Error::InvalidFormat, "scanLineWRILength != m_bmh->getWidthBytes()\n");
00736 Word scanLineBMPLength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 4);
00737
00738 #ifdef DEBUG_IMAGE
00739 m_device->debug ("in: scanLineWRILength: ", scanLineWRILength);
00740 m_device->debug ("out: scanLineBMPLength: ", scanLineBMPLength);
00741 #endif
00742
00743 Byte *padding = new Byte [scanLineBMPLength - scanLineWRILength];
00744 if (!padding)
00745 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for scanline\n");
00746 memset (padding, 0, scanLineBMPLength - scanLineWRILength);
00747
00748
00749 for (int i = (int) infoHeader.getHeight () - 1; i >= 0; i--)
00750 {
00751
00752 device.writeInternal (internalData + i * scanLineWRILength, scanLineWRILength * sizeof (Byte));
00753
00754
00755 device.writeInternal (padding, (scanLineBMPLength - scanLineWRILength) * sizeof (Byte));
00756 }
00757
00758 delete [] padding;
00759
00760 device.setCache (NULL);
00761
00762 delete [] colourIndex;
00763 delete [] internalData;
00764 }
00765
00766 return true;
00767 }
00768
00769 bool Image::writeToDevice (void)
00770 {
00771 CHECK_DEVICE;
00772
00773 #ifdef DEBUG_IMAGE
00774 m_device->debug ("\n>>>> Image::writeToDevice <<<<\n");
00775 #endif
00776
00777 #ifdef DEBUG_IMAGE
00778 Dump (mappingMode);
00779
00780
00781 Dump (MFP_unknown);
00782
00783 Dump (indent);
00784
00785
00786 Dump (zero);
00787
00788 Dump (numHeaderBytes);
00789
00790
00791
00792 #endif
00793
00794
00795
00796
00797
00798 if (getIsWMF ())
00799 {
00800
00801 WMFHeader wmfHeader;
00802 m_device->setCache (m_externalImage);
00803 wmfHeader.setDevice (m_device);
00804 if (!wmfHeader.readFromDevice ()) return false;
00805
00806
00807
00808
00809 m_device->setCache (NULL);
00810
00811
00812
00813
00814
00815
00816
00817 m_bmh->setWidth (0);
00818 m_bmh->setHeight (0);
00819 m_bmh->setWidthBytes (0);
00820 m_bmh->setNumPlanes (0);
00821 m_bmh->setBitsPerPixel (0);
00822
00823 m_MFP_width = Word (Twip2Milli (m_originalWidth * 0.75) * 100.0);
00824 m_MFP_height = Word (Twip2Milli (m_originalHeight * 0.75) * 100.0);
00825
00826 m_width = Word (m_displayedWidth);
00827 m_height = Word (m_displayedHeight);
00828
00829
00830 m_horizontalScalingRel1000 = m_verticalScalingRel1000 = 1000;
00831
00832
00833
00834 setNumDataBytes (m_externalImageSize);
00835 if (!ImageGenerated::writeToDevice ())
00836 return false;
00837
00838
00839 if (!m_device->writeInternal (m_externalImage, m_externalImageSize)) return false;
00840 }
00841 else
00842 {
00843 m_device->setCache (m_externalImage);
00844
00845 BMP_BitmapFileHeader fileHeader;
00846 fileHeader.setDevice (m_device);
00847 if (!fileHeader.readFromDevice ()) return false;
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 BMP_BitmapInfoHeader infoHeader;
00864 infoHeader.setDevice (m_device);
00865 if (!infoHeader.readFromDevice ()) return false;
00866
00867
00868
00869 Word scanLineWRILength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 2);
00870 Word scanLineBMPLength = getBytesPerScanLine (infoHeader.getWidth (), infoHeader.getBitsPerPixel (), 4);
00871
00872 if (infoHeader.getWidth () != Word (Twip2Point (m_originalWidth)))
00873 ErrorAndQuit (Error::Warn, "infoHeader width != m_originalWidth\n");
00874 if (infoHeader.getHeight () != Word (Twip2Point (m_originalHeight)))
00875 ErrorAndQuit (Error::Warn, "infoHeader.height != m_originalHeight\n");
00876
00877 m_bmh->setWidth (infoHeader.getWidth ());
00878 m_bmh->setHeight (infoHeader.getHeight ());
00879 m_bmh->setWidthBytes (scanLineWRILength);
00880 if (infoHeader.getNumPlanes () != 1)
00881 ErrorAndQuit (Error::InvalidFormat, "infoHeader.getNumPlanes() != 1\n");
00882 m_bmh->setNumPlanes (infoHeader.getNumPlanes ());
00883 m_bmh->setBitsPerPixel (infoHeader.getBitsPerPixel ());
00884 if (infoHeader.getCompression () != 0)
00885 ErrorAndQuit (Error::Unsupported, "compressed bitmaps unsupported\n");
00886
00887
00888 infoHeader.setColoursUsed (1 << infoHeader.getBitsPerPixel ());
00889
00890
00891 if (infoHeader.getColoursUsed () != 2)
00892 ErrorAndQuit (Error::Unsupported, "can't save colour BMPs, use WMFs for that purpose\n");
00893
00894
00895 BMP_BitmapColourIndex *colourIndex = new BMP_BitmapColourIndex [infoHeader.getColoursUsed ()];
00896 if (!colourIndex)
00897 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for colourIndex[]\n");
00898 colourIndex [0].setDevice (m_device);
00899 if (!colourIndex [0].readFromDevice ()) return false;
00900 if (colourIndex [0].getRed () != 0 || colourIndex [0].getGreen () != 0 || colourIndex [0].getBlue () != 0)
00901 m_device->error (Error::Warn, "black not black\n");
00902 colourIndex [1].setDevice (m_device);
00903 if (!colourIndex [1].readFromDevice ()) return false;
00904 if (colourIndex [1].getRed () != 0xFF || colourIndex [1].getGreen () != 0xFF || colourIndex [1].getBlue () != 0xFF)
00905 m_device->error (Error::Warn, "white not white\n");
00906
00907
00908 m_device->setCache (NULL);
00909
00910
00911
00912
00913
00914
00915 m_MFP_width = Word (Twip2Point (m_originalWidth) * 2.64);
00916 m_MFP_height = Word (Twip2Point (m_originalHeight) * 2.64);
00917
00918
00919 m_width = 0, m_height = 0;
00920
00921 m_horizontalScalingRel1000 = Word (m_displayedWidth * 1.38889 * 1000.0 / m_originalWidth);
00922 m_verticalScalingRel1000 = Word (m_displayedHeight * 1.38889 * 1000.0 / m_originalHeight);
00923
00924
00925
00926 setNumDataBytes (infoHeader.getHeight () * scanLineBMPLength);
00927 if (!ImageGenerated::writeToDevice ())
00928 return false;
00929
00930
00931 Byte *bmpData = m_externalImage + fileHeader.getActualImageOffset () + (infoHeader.getHeight () - 1) * scanLineBMPLength;
00932 for (int i = (int) infoHeader.getHeight () - 1; i >= 0; i--)
00933 {
00934
00935
00936 if (!m_device->writeInternal (bmpData, scanLineWRILength))
00937 return false;
00938
00939 bmpData -= scanLineBMPLength;
00940 }
00941
00942 delete [] colourIndex;
00943 }
00944
00945 return true;
00946 }
00947
00948
00949 OLE::OLE () : m_externalObject (NULL),
00950 m_externalObjectSize (0), m_externalObjectUpto (0)
00951 {
00952 }
00953
00954 OLE::~OLE ()
00955 {
00956 delete [] m_externalObject;
00957 }
00958
00959 OLE &OLE::operator= (const OLE &rhs)
00960 {
00961 if (this == &rhs)
00962 return *this;
00963
00964 OLEGenerated::operator= (rhs);
00965
00966 m_externalObjectSize = rhs.m_externalObjectSize;
00967 m_externalObjectUpto = rhs.m_externalObjectUpto;
00968
00969 delete [] m_externalObject;
00970 m_externalObject = new Byte [m_externalObjectSize];
00971 if (!m_externalObject)
00972 return *this;
00973
00974 if (rhs.m_externalObject)
00975 memcpy (m_externalObject, rhs.m_externalObject, m_externalObjectUpto);
00976
00977 return *this;
00978 }
00979
00980 bool OLE::readFromDevice (void)
00981 {
00982 CHECK_DEVICE;
00983
00984 #ifdef DEBUG_OBJECT
00985 m_device->debug ("\n<<<< OLE::readFromDevice >>>>\n");
00986 #endif
00987
00988 if (!OLEGenerated::readFromDevice ())
00989 return false;
00990
00991 #ifdef DEBUG_OBJECT
00992 Dump (zero);
00993
00994 switch (m_objectType)
00995 {
00996 case OLEType::Static:
00997 m_device->debug ("\tobjectType: 1 - static\n");
00998 break;
00999 case OLEType::Embedded:
01000 m_device->debug ("\tobjectType: 2 - embedded\n");
01001 break;
01002 case OLEType::Link:
01003 m_device->debug ("\tobjectType: 3 - link\n");
01004 break;
01005 }
01006
01007 Dump (indent);
01008 Dump (width);
01009 Dump (height);
01010 Dump (zero2);
01011 Dump (numDataBytes);
01012 Dump (zero3);
01013 Dump (objectName);
01014 Dump (zero4);
01015 Dump (numHeaderBytes);
01016 Dump (zero5);
01017 Dump (widthScaledRel1000);
01018 Dump (heightScaledRel1000);
01019 #endif
01020
01021
01022 m_externalObject = new Byte [m_externalObjectSize = getNumDataBytes ()];
01023 if (!m_externalObject)
01024 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external OLE object\n");
01025
01026 if (!m_device->readInternal (m_externalObject, m_externalObjectSize))
01027 return false;
01028
01029 return true;
01030 }
01031
01032 bool OLE::writeToDevice (void)
01033 {
01034 CHECK_DEVICE;
01035
01036 #ifdef DEBUG_OBJECT
01037 m_device->debug ("\n>>>> OLE::writeToDevice <<<<\n");
01038 #endif
01039
01040 #ifdef DEBUG_OBJECT
01041 Dump (zero);
01042
01043 switch (m_objectType)
01044 {
01045 case OLEType::Static:
01046 m_device->debug ("\tobjectType: 1 - static\n");
01047 break;
01048 case OLEType::Embedded:
01049 m_device->debug ("\tobjectType: 2 - embedded\n");
01050 break;
01051 case OLEType::Link:
01052 m_device->debug ("\tobjectType: 3 - link\n");
01053 break;
01054 }
01055
01056 Dump (indent);
01057 Dump (width);
01058 Dump (height);
01059 Dump (zero2);
01060 Dump (numDataBytes);
01061 Dump (zero3);
01062 Dump (objectName);
01063 Dump (zero4);
01064 Dump (numHeaderBytes);
01065 Dump (zero5);
01066 Dump (widthScaledRel1000);
01067 Dump (heightScaledRel1000);
01068 #endif
01069
01070
01071 if (!OLEGenerated::writeToDevice ())
01072 return false;
01073
01074
01075 if (!m_device->writeInternal (m_externalObject, m_externalObjectSize))
01076 return false;
01077
01078 return true;
01079 }
01080
01081 }
01082
01083