Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

933 lines
28 KiB

  1. /****************************************************************************
  2. Unit GetData; Implementation
  3. *****************************************************************************
  4. GetData implements the structured reading of the imput stream. As such, it
  5. will handle the necessary byte-swapping that must occur when reading a
  6. native Macintosh file.
  7. Module Prefix: Get
  8. ****************************************************************************/
  9. #include "headers.c"
  10. #pragma hdrstop
  11. #include <math.h> /* for abs() function */
  12. #include "getdata.h" /* own module interface */
  13. /*********************** Exported Data **************************************/
  14. /*********************** Private Data ***************************************/
  15. /*--- octochrome color tables --- */
  16. #define blackColor 33
  17. #define whiteColor 30
  18. #define redColor 205
  19. #define greenColor 341
  20. #define blueColor 409
  21. #define cyanColor 273
  22. #define magentaColor 137
  23. #define yellowColor 69
  24. typedef struct
  25. {
  26. LongInt octochromeColor;
  27. RGBColor rgbColor;
  28. } colorEntry, * colorEntryPtr;
  29. private colorEntry octochromeLookup[8] =
  30. {
  31. { blackColor, RGB( 0x00, 0x00, 0x00 ) },
  32. { whiteColor, RGB( 0xFF, 0xFF, 0xFF ) },
  33. { redColor, RGB( 0xDD, 0x08, 0x06 ) },
  34. { greenColor, RGB( 0x00, 0x80, 0x11 ) },
  35. { blueColor, RGB( 0x00, 0x00, 0xD4 ) },
  36. { cyanColor, RGB( 0x02, 0xAB, 0xEA ) },
  37. { magentaColor, RGB( 0xF2, 0x08, 0x84 ) },
  38. { yellowColor, RGB( 0xFC, 0xF3, 0x05 ) }
  39. };
  40. /*********************** Private Function Definitions ***********************/
  41. /*********************** Function Implementation ****************************/
  42. void GetWord( Word far * wordLPtr )
  43. /*==========*/
  44. /* Retrieves an 16-bit unsigned integer from the input stream */
  45. {
  46. Byte far * byteLPtr = (Byte far *)wordLPtr;
  47. /* this initialization should be here for win32 */
  48. *wordLPtr = 0;
  49. /* Assign high-order byte first, followed by low-order byte. */
  50. GetByte( byteLPtr + 1);
  51. GetByte( byteLPtr );
  52. } /* GetWord */
  53. void GetDWord( DWord far * dwordLPtr )
  54. /*===========*/
  55. /* Retrieves a 32-bit unsigned long from the input stream */
  56. {
  57. Byte far * byteLPtr = (Byte far *)dwordLPtr;
  58. * dwordLPtr = 0;
  59. GetByte( byteLPtr + 3);
  60. GetByte( byteLPtr + 2);
  61. GetByte( byteLPtr + 1);
  62. GetByte( byteLPtr );
  63. } /* GetDWord */
  64. #ifdef WIN32
  65. void GetPoint( Point * pointLPtr )
  66. /*===========*/
  67. /* Retrieves 2 2-byte words from the input stream and assign them
  68. to a POINT structure */
  69. {
  70. Word * wordLPtr = (Word *)pointLPtr;
  71. GetWord( wordLPtr + 1 );
  72. // This is done to extend the sign bit
  73. *( wordLPtr + 1 ) = (short)(*( wordLPtr + 1 ));
  74. GetWord( wordLPtr );
  75. *( wordLPtr ) = (short)(*( wordLPtr ));
  76. } /* GetPoint */
  77. #endif
  78. #ifdef WIN32
  79. void GetCoordinate( Point * pointLPtr )
  80. /*===========*/
  81. /* Retrieves 2 2-byte words from the input stream and assign them
  82. to a POINT structure. Currently, there is no difference between
  83. this function and GetPoint. GetCoordinate is provided to provide for
  84. future modifications. */
  85. {
  86. Word * wordLPtr = (Word *)pointLPtr;
  87. GetWord( wordLPtr + 1 );
  88. // This is done to extend the sign bit
  89. *( wordLPtr + 1 ) = (short)(*( wordLPtr + 1 ));
  90. GetWord( wordLPtr );
  91. *( wordLPtr ) = (short)(*( wordLPtr ));
  92. } /* GetCoordinate */
  93. #endif
  94. void GetBoolean( Boolean far * bool )
  95. /*=============*/
  96. /* Retrieves an 8-bit Mac boolean and coverts to 16-bit Windows Boolean */
  97. {
  98. /* make sure that the high-order byte is zeroed out */
  99. *bool = 0;
  100. /* read low-order byte */
  101. GetByte( (Byte far *)bool );
  102. } /* GetBoolean */
  103. void GetRect( Rect far * rect)
  104. /*==========*/
  105. /* Returns a RECT structure consisting of upper left and lower right
  106. coordinate pair */
  107. {
  108. Integer temp;
  109. Point far * pointLPtr = (Point far *)rect;
  110. /* Get the bounding coordinates */
  111. GetCoordinate( pointLPtr++ );
  112. GetCoordinate( pointLPtr );
  113. /* Make sure that the rectangle coords are upper-left and lower-right */
  114. if (rect->left > rect->right)
  115. {
  116. temp = rect->right;
  117. rect->right = rect->left;
  118. rect->left = temp;
  119. }
  120. if (rect->top > rect->bottom)
  121. {
  122. temp = rect->bottom;
  123. rect->bottom = rect->top;
  124. rect->top = temp;
  125. }
  126. } /* GetRect */
  127. void GetString( StringLPtr stringLPtr )
  128. /*============*/
  129. /* Retrieves a Pascal-style string and formats it C-style. If the input
  130. parameter is NIL, then the ensuing data is simply skipped */
  131. {
  132. Byte dataLen;
  133. Byte unusedByte;
  134. Byte increment;
  135. StringLPtr destLPtr;
  136. /* Determine if we should be savin the text string or whether it simply
  137. ends up in the bit bucket. Set the correct destination pointer and
  138. increment value. */
  139. if (stringLPtr == NIL)
  140. {
  141. destLPtr = &unusedByte;
  142. increment = 0;
  143. }
  144. else
  145. {
  146. destLPtr = stringLPtr;
  147. increment = 1;
  148. }
  149. /* Determine exactly how many bytes should be read. */
  150. GetByte( &dataLen );
  151. /* continue reading bytes as determined by length. */
  152. while (dataLen--)
  153. {
  154. GetByte( destLPtr );
  155. destLPtr += increment;
  156. }
  157. /* terminate string with NUL byte */
  158. *destLPtr = 0;
  159. } /* GetString */
  160. void GetRGBColor( RGBColor far * rgbLPtr )
  161. /*==============*/
  162. /* Returns an RGB color */
  163. {
  164. Word red;
  165. Word green;
  166. Word blue;
  167. /* read successive components from the stream */
  168. GetWord( &red );
  169. GetWord( &green );
  170. GetWord( &blue );
  171. /* use RGB macro to create an RGBColor */
  172. *rgbLPtr = RGB( red>>8, green>>8 , blue>>8 );
  173. } /* GetRGBColor */
  174. void GetOctochromeColor( RGBColor far * rgbLPtr )
  175. /*=====================*/
  176. /* Returns an RGB color - this will be converted from a PICT octochrome
  177. color if this is a version 1 picture */
  178. {
  179. LongInt color;
  180. colorEntryPtr entry;
  181. /* read in the LongInt octochrome color from the I/O stream */
  182. GetDWord( &color );
  183. /* search through the table, looking for the matching entry */
  184. entry = octochromeLookup;
  185. while (entry->octochromeColor != color)
  186. {
  187. entry++;
  188. }
  189. *rgbLPtr = entry->rgbColor;
  190. }
  191. Boolean GetPolygon( Handle far * polyHandleLPtr, Boolean check4Same )
  192. /*================*/
  193. /* Retrieves a polygon definition from the I/O stream and places in the
  194. Handle passed down. If the handle is previously != NIL, then the
  195. previous data is de-allocated.
  196. If check4Same is TRUE, then the routine will compare the point list
  197. against the previous polygon definition, checking for equality. If
  198. pointlists match, then the routine returns TRUE, otherwise, it will
  199. always return FALSE. Use this to merge fill and frame operations. */
  200. {
  201. Handle newPolyH;
  202. Word polySize;
  203. Word far * polySizeLPtr;
  204. Point far * polyPointsLPtr;
  205. Boolean sameCoordinates;
  206. /* the polygon coordinates are assumed to be different */
  207. sameCoordinates = FALSE;
  208. /* determine how large the polygon buffer should be. */
  209. GetWord( &polySize );
  210. /* allocate the necessary size for the polygon. */
  211. #ifdef WIN32
  212. {
  213. DWord dwSizeToAllocate;
  214. Word uNumPoints;
  215. uNumPoints = (polySize - sizeofMacWord) / sizeofMacPoint;
  216. // a Word is needed to store polySize then POINT * uNumPoints
  217. dwSizeToAllocate = sizeof( Word ) +
  218. ( uNumPoints * sizeof ( Point ));
  219. newPolyH = GlobalAlloc( GHND, (DWord)dwSizeToAllocate );
  220. }
  221. #else
  222. newPolyH = GlobalAlloc( GHND, (DWord)polySize );
  223. #endif
  224. /* check to make sure that the allocation succeeded. */
  225. if (newPolyH == NIL)
  226. {
  227. ErSetGlobalError( ErMemoryFull );
  228. }
  229. else
  230. {
  231. Boolean check4Closure;
  232. Point far * firstPtLPtr;
  233. /* Lock the memory handle and make sure it succeeds */
  234. polySizeLPtr = (Word far *)GlobalLock( newPolyH );
  235. /* save the size parameter and adjust the counter variables */
  236. *polySizeLPtr = polySize;
  237. polySize -= ( sizeofMacWord );
  238. polyPointsLPtr = (Point far *)(polySizeLPtr + 1);
  239. /* determine if we should check adjust first point to match last
  240. point if they are within 1 metafile unit of oneanother. */
  241. check4Closure = (polySize / sizeofMacPoint >= 6);
  242. firstPtLPtr = polyPointsLPtr + 2;
  243. /* continue reading points until the buffer is completely filled. */
  244. while (polySize)
  245. {
  246. GetCoordinate( polyPointsLPtr++ );
  247. polySize -= sizeofMacPoint;
  248. }
  249. /* should we check adjust for start, end points off by 1 unit? */
  250. if (check4Closure)
  251. {
  252. Point first;
  253. Point last;
  254. /* get the first and last points */
  255. first = *firstPtLPtr;
  256. last = *(--polyPointsLPtr);
  257. /* compare x and y components - see if delta in x or y < 1 */
  258. if ((abs( first.x - last.x ) <= 1) &&
  259. (abs( first.y - last.y ) <= 1))
  260. {
  261. /* if small delta, set last point equal to first point */
  262. *polyPointsLPtr = first;
  263. }
  264. }
  265. /* find out if the first and last point are within one metafile unit
  266. of oneanother - close the polygon in this case */
  267. /* determine if we should check against previous coordinates */
  268. if (*polyHandleLPtr != NIL && check4Same)
  269. {
  270. Word far * checkSizeLPtr;
  271. DWord far * checkDWordLPtr;
  272. DWord far * polyDWordLPtr;
  273. /* go back and see if the same set of coordinates was specified -
  274. first check to see if the sizes are the same */
  275. checkSizeLPtr = (Word far *)GlobalLock( *polyHandleLPtr );
  276. if (*checkSizeLPtr == *polySizeLPtr)
  277. {
  278. /* reset the coordinate pointers to beginning of lists */
  279. polyDWordLPtr = (DWord far *)(polySizeLPtr + 1);
  280. checkDWordLPtr= (DWord far *)(checkSizeLPtr + 1);
  281. polySize = *checkSizeLPtr - sizeofMacWord;
  282. /* assume at this point that they are the same pointList */
  283. sameCoordinates = TRUE;
  284. /* continue check for equality until pointlist is exhausted */
  285. while (polySize)
  286. {
  287. /* compare the two coordinate pairs */
  288. if (*polyDWordLPtr++ != *checkDWordLPtr++)
  289. {
  290. /* if one of the coordinates mis-compares, bail */
  291. sameCoordinates = FALSE;
  292. break;
  293. }
  294. else
  295. {
  296. /* otherwise, decrement the count and continue */
  297. polySize -= sizeofMacDWord;
  298. }
  299. }
  300. }
  301. /* unlock the previous polygon handle */
  302. GlobalUnlock( *polyHandleLPtr );
  303. }
  304. /* unlock the handle before returning */
  305. GlobalUnlock( newPolyH );
  306. }
  307. /* de-allocate the previous handle before continuing */
  308. if (*polyHandleLPtr != NIL)
  309. {
  310. GlobalFree( *polyHandleLPtr );
  311. }
  312. /* assign the new polygon handle */
  313. *polyHandleLPtr = newPolyH;
  314. /* return whether coordinates were same or not */
  315. return sameCoordinates;
  316. } /* GetPolygon */
  317. void GetRegion( Handle far * rgnHandleLPtr )
  318. /*=============*/
  319. /* Retrieves a region definition from the I/O stream and places in the
  320. Handle passed down. If the handle is previously != NIL, then the
  321. previous data is de-allocated. */
  322. {
  323. Word rgnSize;
  324. Word far * rgnDataLPtr;
  325. Word far * rgnSizeLPtr;
  326. /* de-allocate the previous handle before continuing */
  327. if (*rgnHandleLPtr != NIL)
  328. {
  329. GlobalFree( *rgnHandleLPtr );
  330. }
  331. // buffer should have enough room for a RECT and a series of Word's
  332. /* determine how large the region buffer should be. */
  333. GetWord( &rgnSize );
  334. #ifdef WIN32
  335. /* allocate the necessary size for the region. */
  336. {
  337. Word uSizeToAllocate;
  338. uSizeToAllocate = (((rgnSize - sizeofMacRect) / sizeofMacWord)
  339. * sizeof ( Word ))
  340. + sizeof ( RECT );
  341. *rgnHandleLPtr = GlobalAlloc( GHND, (DWord)uSizeToAllocate );
  342. }
  343. #else
  344. /* allocate the necessary size for the polygon. */
  345. *rgnHandleLPtr = GlobalAlloc( GHND, (DWord)rgnSize );
  346. #endif
  347. /* check to make sure that the allocation succeeded. */
  348. if (*rgnHandleLPtr == NIL)
  349. {
  350. ErSetGlobalError( ErMemoryFull );
  351. }
  352. else
  353. {
  354. /* Lock the memory handle and make sure it succeeds */
  355. rgnSizeLPtr = (Word far *)GlobalLock( *rgnHandleLPtr );
  356. if (rgnSizeLPtr == NIL)
  357. {
  358. ErSetGlobalError( ErMemoryFail );
  359. GlobalFree( *rgnHandleLPtr );
  360. }
  361. else
  362. {
  363. /* save the size parameter and adjust the counter variables */
  364. *rgnSizeLPtr++ = rgnSize;
  365. rgnSize -= sizeofMacWord;
  366. rgnDataLPtr = (Word far *)rgnSizeLPtr;
  367. /* read out the bounding box */
  368. GetRect( (Rect far *)rgnDataLPtr );
  369. rgnDataLPtr += sizeofMacRect / sizeofMacWord;
  370. rgnSize -= sizeofMacRect;
  371. /* continue reading Data until the buffer is completely filled. */
  372. while (rgnSize)
  373. {
  374. /* read the next value from the source file */
  375. GetWord( rgnDataLPtr++ );
  376. rgnSize -= sizeofMacWord;
  377. }
  378. /* unlock the handle before returning */
  379. GlobalUnlock( *rgnHandleLPtr );
  380. }
  381. }
  382. } /* GetRegion */
  383. void GetPattern( Pattern far * patLPtr )
  384. /*=============*/
  385. /* Returns a Pattern structure */
  386. {
  387. Byte i;
  388. Byte far * byteLPtr = (Byte far *)patLPtr;
  389. for (i = 0; i < sizeof( Pattern); i++)
  390. {
  391. GetByte( byteLPtr++ );
  392. }
  393. } /* GetPattern */
  394. void GetColorTable( Handle far * colorHandleLPtr )
  395. /*================*/
  396. {
  397. ColorTable cTab;
  398. LongInt bytesNeeded;
  399. ColorTable far * colorHeaderLPtr;
  400. RGBColor far * colorEntryLPtr;
  401. /* read in the header information */
  402. GetDWord( (DWord far *)&cTab.ctSeed );
  403. GetWord( (Word far *)&cTab.ctFlags );
  404. GetWord( (Word far *)&cTab.ctSize );
  405. /* calculate the number of bytes needed for the color table */
  406. bytesNeeded = sizeof( ColorTable ) + cTab.ctSize * sizeof( RGBColor );
  407. /* adjust the size of the color table size by 1 */
  408. cTab.ctSize++;
  409. /* allocate the data block */
  410. *colorHandleLPtr = GlobalAlloc( GHND, bytesNeeded );
  411. /* flag global error if memory is not available */
  412. if (*colorHandleLPtr == NULL)
  413. {
  414. ErSetGlobalError( ErMemoryFull );
  415. }
  416. else
  417. {
  418. /* lock the memory */
  419. colorHeaderLPtr = (ColorTable far *)GlobalLock( *colorHandleLPtr );
  420. /* copy over the color handle header */
  421. *colorHeaderLPtr = cTab;
  422. /* convert the pointer to a RGBQUAD pointer */
  423. colorEntryLPtr = (RGBColor far *)colorHeaderLPtr->ctColors;
  424. /* read in the color table entries */
  425. while (cTab.ctSize--)
  426. {
  427. Word unusedValue;
  428. /* read the value field */
  429. GetWord( &unusedValue );
  430. /* read the ensuing RGB color */
  431. GetRGBColor( colorEntryLPtr++ );
  432. }
  433. /* Unlock the data once finished */
  434. GlobalUnlock( *colorHandleLPtr );
  435. }
  436. } /* GetColorTable */
  437. void GetPixPattern( PixPatLPtr pixPatLPtr )
  438. /*================*/
  439. /* Retrieves a Pixel Pattern structure. */
  440. {
  441. /* release the memory from the patData field before continuing */
  442. if (pixPatLPtr->patData != NULL)
  443. {
  444. GlobalFree( pixPatLPtr->patMap.pmTable );
  445. GlobalFree( pixPatLPtr->patData );
  446. pixPatLPtr->patData = NULL;
  447. }
  448. /* read the pattern type to determine how the data is organized */
  449. GetWord( &pixPatLPtr->patType );
  450. GetPattern( &pixPatLPtr->pat1Data );
  451. /* read the additional data depending on the pattern type */
  452. if (pixPatLPtr->patType == QDDitherPat)
  453. {
  454. /* if this is a rare dither pattern, save off the desired color */
  455. GetRGBColor( &pixPatLPtr->patMap.pmReserved );
  456. }
  457. else /* (patType == newPat) */
  458. {
  459. /* read in the pixMap header and create a pixmap bitmap */
  460. GetPixMap( &pixPatLPtr->patMap, TRUE );
  461. GetColorTable( &pixPatLPtr->patMap.pmTable );
  462. GetPixData( &pixPatLPtr->patMap, &pixPatLPtr->patData );
  463. }
  464. } /* GetPixPattern */
  465. void GetPixMap( PixMapLPtr pixMapLPtr, Boolean forcePixMap )
  466. /*============*/
  467. /* Retrieves a Pixel Map from input stream */
  468. {
  469. Boolean readPixelMap;
  470. /* Read the rowBytes number and check the high-order bit. If set, it
  471. is a pixel map containing multiple bits per pixel; if not, it is
  472. a bitmap containing one bit per pixel */
  473. GetWord( (Word far *)&pixMapLPtr->rowBytes );
  474. readPixelMap = forcePixMap || ((pixMapLPtr->rowBytes & PixelMapBit) != 0);
  475. /* read the bitmap's bounding rectangle */
  476. GetRect( (Rect far *)&pixMapLPtr->bounds );
  477. if (readPixelMap)
  478. {
  479. /* read the different data fields into the record structure */
  480. GetWord( (Word far *)&pixMapLPtr->pmVersion );
  481. GetWord( (Word far *)&pixMapLPtr->packType );
  482. GetDWord( (DWord far *)&pixMapLPtr->packSize );
  483. GetFixed( (Fixed far *)&pixMapLPtr->hRes );
  484. GetFixed( (Fixed far *)&pixMapLPtr->vRes );
  485. GetWord( (Word far *)&pixMapLPtr->pixelType );
  486. GetWord( (Word far *)&pixMapLPtr->pixelSize );
  487. GetWord( (Word far *)&pixMapLPtr->cmpCount );
  488. GetWord( (Word far *)&pixMapLPtr->cmpSize );
  489. GetDWord( (DWord far *)&pixMapLPtr->planeBytes );
  490. GetDWord( (DWord far *)&pixMapLPtr->pmTable );
  491. GetDWord( (DWord far *)&pixMapLPtr->pmReserved );
  492. }
  493. else
  494. {
  495. LongInt bytesNeeded;
  496. ColorTable far * colorHeaderLPtr;
  497. /* if this is a bitmap, then we assign the various fields. */
  498. pixMapLPtr->pmVersion = 0;
  499. pixMapLPtr->packType = 0;
  500. pixMapLPtr->packSize = 0;
  501. pixMapLPtr->hRes = 0x00480000;
  502. pixMapLPtr->vRes = 0x00480000;
  503. pixMapLPtr->pixelType = 0;
  504. pixMapLPtr->pixelSize = 1;
  505. pixMapLPtr->cmpCount = 1;
  506. pixMapLPtr->cmpSize = 1;
  507. pixMapLPtr->planeBytes = 0;
  508. pixMapLPtr->pmTable = 0;
  509. pixMapLPtr->pmReserved = 0;
  510. /* calculate the number of bytes needed for the color table */
  511. bytesNeeded = sizeof( ColorTable ) + sizeof( RGBColor );
  512. /* allocate the data block */
  513. pixMapLPtr->pmTable = GlobalAlloc( GHND, bytesNeeded );
  514. /* make sure that the allocation was successfull */
  515. if (pixMapLPtr->pmTable == NULL)
  516. {
  517. ErSetGlobalError( ErMemoryFull );
  518. }
  519. else
  520. {
  521. CGrafPortLPtr port;
  522. /* Get the QuickDraw port for foreground and bkground colors */
  523. QDGetPort( &port );
  524. /* lock the memory handle and prepare to assign color table */
  525. colorHeaderLPtr = (ColorTable far *)GlobalLock( pixMapLPtr->pmTable );
  526. /* 2 colors are present - black and white */
  527. colorHeaderLPtr->ctSize = 2;
  528. colorHeaderLPtr->ctColors[0] = port->rgbFgColor;
  529. colorHeaderLPtr->ctColors[1] = port->rgbBkColor;
  530. /* unlock the memory */
  531. GlobalUnlock( pixMapLPtr->pmTable );
  532. }
  533. }
  534. } /* GetPixMap */
  535. void GetPixData( PixMapLPtr pixMapLPtr, Handle far * pixDataHandle )
  536. /*=============*/
  537. /* Read a pixel map from the data stream */
  538. {
  539. Integer rowBytes;
  540. Integer linesToRead;
  541. LongInt bitmapBytes;
  542. Integer bytesPerLine;
  543. /* determine the number of lines in the pixel map */
  544. linesToRead = Height( pixMapLPtr->bounds );
  545. /* make sure to turn off high-order bit - used to signify pixel map */
  546. rowBytes = pixMapLPtr->rowBytes & RowBytesMask;
  547. /* determine number of bytes to read for each line */
  548. if (pixMapLPtr->pixelSize <= 16)
  549. {
  550. /* use the masked rowBytes value (adjusted for pixel maps) */
  551. bytesPerLine = rowBytes;
  552. }
  553. else /* if (pixMapLPtr->pixelSize == 24) */
  554. {
  555. /* adjust for 32-bit pixel images that don't contain high-order byte */
  556. bytesPerLine = rowBytes * 3 / 4;
  557. }
  558. /* calculate the size of the bitmap that will be created */
  559. bitmapBytes = (LongInt)linesToRead * (LongInt)bytesPerLine;
  560. /* allocate the necessary memory */
  561. *pixDataHandle = GlobalAlloc( GHND, bitmapBytes );
  562. /* flag global error if memory is not available */
  563. if (*pixDataHandle == NULL)
  564. {
  565. ErSetGlobalError( ErMemoryFull );
  566. }
  567. else
  568. {
  569. Boolean compressed;
  570. Boolean invertBits;
  571. Boolean doubleByte;
  572. Byte huge * rowHPtr;
  573. Byte huge * insertHPtr;
  574. /* lock the memory handle and get a pointer to the first byte */
  575. rowHPtr = (Byte huge *)GlobalLock( *pixDataHandle );
  576. /* determine if the bitmap is compressed or not */
  577. compressed = !((rowBytes < 8) ||
  578. (pixMapLPtr->packType == 1) ||
  579. (pixMapLPtr->packType == 2));
  580. /* determine if we should read 2 bytes at a time (16-bit pixelmap) */
  581. doubleByte = (pixMapLPtr->packType == 3);
  582. /* determine if bits should be inverted (monochrome bitmap) */
  583. /* must test for high bit of Mac word set, sign is not propagated
  584. when a Mac word is read into a 32-bit Windows int */
  585. invertBits = ((short)pixMapLPtr->rowBytes > 0 );
  586. /* decompress the bitmap into the global memory block */
  587. while (linesToRead-- && (ErGetGlobalError() == NOERR))
  588. {
  589. Integer runLength;
  590. Integer bytesRead;
  591. Integer bytesToSkip;
  592. /* see if we need to read the scanline runlength */
  593. if (compressed)
  594. {
  595. /* get the run length - depends on the rowbytes field */
  596. if (rowBytes > 250)
  597. {
  598. GetWord( (Word far *)&runLength );
  599. }
  600. else
  601. {
  602. runLength = 0;
  603. GetByte( (Byte far *)&runLength );
  604. }
  605. }
  606. else
  607. {
  608. /* if not compressed, runLength is equal to rowBytes */
  609. runLength = bytesPerLine;
  610. }
  611. /* set the next insertion point to the beginning of the scan line */
  612. insertHPtr = rowHPtr;
  613. /* if this is a 24-bit image that contains 32-bits of information,
  614. then we must skip the high-order byte component. This byte was
  615. originally spec'ed by Apple as a luminosity component, but is
  616. unused in Windows 24-bit DIBs. */
  617. bytesToSkip = (pixMapLPtr->cmpCount == 4) ? (rowBytes / 4) : 0;
  618. /* continue decompressing until run-length is exhausted */
  619. for (bytesRead = 0; bytesRead < runLength; )
  620. {
  621. SignedByte tempRepeatCount = 0;
  622. Integer repeatCount;
  623. /* check on how the data should be read */
  624. if (compressed)
  625. {
  626. /* if compressed, get the repeat count byte */
  627. GetByte( (Byte far *)&tempRepeatCount );
  628. bytesRead++;
  629. }
  630. else
  631. {
  632. /* if no compression, fake the count of bytes to follow */
  633. tempRepeatCount = 0;
  634. }
  635. /* make sure that we didn't read a byte used to word-align */
  636. if (bytesRead == runLength)
  637. {
  638. /* this should force the read loop to be exited */
  639. continue;
  640. }
  641. /* if less than 0, indicates repeat count of following byte */
  642. if (tempRepeatCount < 0)
  643. {
  644. /* check for a flag-counter value of -128 (0x80) - QuickDraw
  645. will never create this, but another application that packs
  646. bits may. As noted in the January 1992 release of TechNote
  647. #171, we need to ignore this value and use the next byte
  648. as the flag-counter byte. */
  649. if (tempRepeatCount != -128)
  650. {
  651. Byte repeatByte1;
  652. Byte repeatByte2 = 0;
  653. /* calculate the repeat count and retrieve repeat byte */
  654. repeatCount = 1 - (Integer)tempRepeatCount;
  655. GetByte( &repeatByte1 );
  656. /* increment the number of bytes read */
  657. bytesRead++;
  658. /* check for special handling cases */
  659. if (invertBits)
  660. {
  661. /* if this is a monochrome bitmap, then invert bits */
  662. repeatByte1 ^= (Byte)0xFF;
  663. }
  664. else if (doubleByte)
  665. {
  666. /* 16-bit images (pixel chunks) - read second byte */
  667. GetByte( &repeatByte2 );
  668. /* and increment byte count */
  669. bytesRead++;
  670. }
  671. /* continue stuffing byte until repeat count exhausted */
  672. while (repeatCount--)
  673. {
  674. /* check if we are skipping the luminosity byte for
  675. 32-bit images (this isn't used in Windows DIBs) */
  676. if (bytesToSkip)
  677. {
  678. bytesToSkip--;
  679. }
  680. else
  681. {
  682. /* insert new Byte */
  683. *insertHPtr++ = repeatByte1;
  684. }
  685. /* check if second repeat byte needs to be inserted */
  686. if (doubleByte)
  687. {
  688. *insertHPtr++ = repeatByte2;
  689. }
  690. }
  691. }
  692. }
  693. else /* if (tempRepeatCount >= 0) */
  694. {
  695. /* adjust the number of bytes that will be transferred */
  696. if (compressed)
  697. {
  698. /* if greater than 0, is number of bytes that follow */
  699. repeatCount = 1 + (Integer)tempRepeatCount;
  700. /* double the number of bytes if 16-bit pixelmap */
  701. if (doubleByte)
  702. {
  703. repeatCount *= 2;
  704. }
  705. }
  706. else
  707. {
  708. /* the number of bytes to read = bytesPerLine */
  709. repeatCount = bytesPerLine;
  710. }
  711. /* increment the number of bytes read */
  712. bytesRead += repeatCount;
  713. /* check if iversion is required */
  714. if (invertBits)
  715. {
  716. /* if this is a monochrome bitmap, then invert bits */
  717. while (repeatCount--)
  718. {
  719. GetByte( insertHPtr );
  720. *insertHPtr++ ^= (Byte)0xFF;
  721. }
  722. }
  723. else
  724. {
  725. /* continue reading bytes into the insert point */
  726. while (repeatCount--)
  727. {
  728. /* check if we are skipping the luminosity byte for
  729. 32-bit images (this isn't used in Windows DIBs) */
  730. if (bytesToSkip)
  731. {
  732. /* pass the current insertion pointer, but don't
  733. increment (overwritten in ensuing read). */
  734. bytesToSkip--;
  735. GetByte( insertHPtr );
  736. }
  737. else
  738. {
  739. GetByte( insertHPtr++ );
  740. }
  741. }
  742. }
  743. }
  744. }
  745. /* increment the line pointer to the next scan line */
  746. rowHPtr += bytesPerLine;
  747. /* call IO module to update current read position */
  748. IOUpdateStatus();
  749. }
  750. /* Unlock the data block */
  751. GlobalUnlock( *pixDataHandle );
  752. /* if an error occured, make sure to remove the data block */
  753. if (ErGetGlobalError() != NOERR)
  754. {
  755. GlobalFree( *pixDataHandle );
  756. *pixDataHandle = NULL;
  757. }
  758. }
  759. } /* GetPixData */
  760. /******************************* Private Routines ***************************/