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.

1376 lines
47 KiB

  1. /*****************************************************************************
  2. *
  3. * objects - Entry points for Win32 to Win 16 converter
  4. *
  5. * Date: 7/1/91
  6. * Author: Jeffrey Newman (c-jeffn)
  7. *
  8. * Copyright 1991 Microsoft Corp
  9. *
  10. *
  11. * 14-Jan-1992
  12. * Jeffrey Newman
  13. *
  14. * CR1: 14-Jan-1992 - this entire comment and the design that it
  15. * specifies.
  16. *
  17. * The Object system in mf3216.
  18. *
  19. * Overview
  20. *
  21. * The Win32 objects (represented by object handle indicies) must be
  22. * mapped to Win16 objects (also represented by object handle indices).
  23. * Win32 uses stock objects, Win16 does not. MF3216 uses a scheme
  24. * for lazy stock object creation. Through lazy stock object creation
  25. * no unused objects will be emitted into the Win16 metafile.
  26. *
  27. * Objects in a Win16 metafile are maintained in an Object Table. The
  28. * object table is not recorded in the Win16 metafile. It is created at
  29. * play-time. Each entry in the Win16-Object-Table is called a slot.
  30. * Slots are allocated one per object. If an object is deleted then the
  31. * slot becomes available for the next object created. The first object-
  32. * slot, starting from 0, in a linear search, that is available will be
  33. * used to hold the next create object request.
  34. *
  35. * Objects in either a Win32 or a Win16 metafile are represented as an
  36. * index into the Object Table. Every object created must occupy
  37. * the same slot at play-time that it would have occupied at record-time.
  38. *
  39. * Win32 objects have an object ID (index in the handle table) recorded
  40. * with them. Win16 objects do not.
  41. *
  42. * Data Structures
  43. *
  44. * There are two primary data structures used in the translation of
  45. * Win32 objects to Win16 objects. Both of them are dynamically
  46. * allocated arrays. The size of these arrays are determined by
  47. * estimating the number of objects required in the Win16 metafile from
  48. * the size of the handle table used in the Win32 metafile. The size of
  49. * the handle table is recorded in the Win32 metafile header.
  50. *
  51. * The data structure piW16ObjectHandleSlotStatus is used to represent
  52. * the status of the Win16 handle table as it would appear at any point
  53. * during the Win16 metafile playback process. A slot is either in
  54. * use or free.
  55. *
  56. * The data structure piW32ToW16ObjectMap is a translation table
  57. * from the Win32 object indicies to the Win16 object indicies.
  58. * The position in the array (aka the index into the array) is the
  59. * Win32 handle. The value in this entry is the Win16 slot number
  60. * for the handle.
  61. *
  62. * The first 16 entries in piW32ToW16ObjectMap array are used for the
  63. * stock objects.
  64. *
  65. * Support Routines
  66. *
  67. * bInitHandleTableManager
  68. *
  69. * 1] Allocate memory for pW16ObjHndlSlotStatus and
  70. * piW32ToW16ObjectMap arrays.
  71. *
  72. * 2] Initialize pW16ObjHndlSlotStatus and
  73. * piW32ToW16ObjectMap to empty and UNMAPPED respectively.
  74. *
  75. * 3] Returns a TRUE if there were no problems with the
  76. * initialization, FALSE if anything went wrong.
  77. *
  78. * 4] It is expected that this routie will be called once from
  79. * the entry level routine when translation is first started.
  80. *
  81. * iNormalizeHandle
  82. *
  83. * 1] The idea behind this routine is to isolate the handling
  84. * of stock object handles to one place.
  85. *
  86. * 2] Input will be a Win32 handle index, either stock or a
  87. * standard object.
  88. *
  89. * 3] Output will be the index of the entry in the
  90. * piW32ToW16ObjectMap table that corresponds to the W32
  91. * handle. If an error is detected -1 is returned.
  92. *
  93. * 4] All the stock objects will be between the range of 0
  94. * and LAST_STOCK, and all the non-stock objects will be
  95. * greater than LAST_STOCK.
  96. *
  97. * iGetW16ObjectHandleSlot
  98. *
  99. * 1] This routine searches the pW16ObjHndlSlotStatus array
  100. * looking for the first available open slot.
  101. *
  102. * 2] Mark the slot found as to its intended use.
  103. *
  104. * 3] Returns the first open slot if found, else return -1.
  105. *
  106. * 4] In essence this routine mimics the actions of the
  107. * Win16 play-time handle allocation system, in either
  108. * Win3.0 or Win3.1
  109. *
  110. * 5] We also keep track of the max object count here.
  111. *
  112. * iAllocateW16Handle
  113. *
  114. * 1] This routine actually does the handle allocation.
  115. *
  116. * 2] It sets the entry in pW16ObjHndlSlotStatus array
  117. * for the slot allocated by iGetW16ObjectHandleSlot to
  118. * an "in-use" status (for the intended use).
  119. *
  120. * 3] It returns a ihW16 (an index handle to the Win16 handle
  121. * table, aka the Win16 handle slot number).
  122. *
  123. * iValidateHandle
  124. *
  125. * 1] This routine does a lot more than validate a Win32 handle.
  126. * It does some limited error checking on the Win32 handle,
  127. * to make sure its within a reasonable range. Then if a
  128. * Win16 handle table slot has already been allocated for
  129. * this Win32 handle it will return the Win16 handle that
  130. * was previously allocated. Alternatively, if a Win16
  131. * handle has not been previously allocated for a Win32
  132. * STOCK handle it will allocate a W16 handle and return the
  133. * Win16 handle. This function is called by FillRgn, FrameRgn
  134. * and SelectObject to allow lazy allocation of stock objects.
  135. *
  136. * 2] Input is a Win32 handle, either a stock or a non-stock
  137. * handle.
  138. *
  139. * 3] Output is a Win16 handle, this is the value in the
  140. * Win32-index of the piW32ToW16ObjectMap. If a stock object
  141. * does not exist, it will create one.
  142. *
  143. * 4] If there is an error a -1 is returned.
  144. *
  145. * Doer Routines
  146. *
  147. * All the Doers return a bool. TRUE if everything went OK.
  148. * FALSE if there were any problems.
  149. *
  150. * NOTE: The Doers that create an object actually must do
  151. * quite a bit of work to translate the object's prameters.
  152. * This is in addition to managing the handle table. The
  153. * work outlined below just deals with the management of the
  154. * handle table.
  155. *
  156. * DoSelectObject
  157. *
  158. * 1] For stock objects this is the workhorse routine.
  159. *
  160. * 2] For normal, non-stock, objects this routine will verify
  161. * that an object has been created for this Win32 object-index.
  162. * Then it will emit a Win16SelectObject metafile record.
  163. *
  164. * 3] For stock objects things get a little more complicated.
  165. * First this routine must make sure a Win16 object has been
  166. * created for this stock object. If a Win16 object has not
  167. * been created yet, then it will be. After a Win16 object
  168. * is created a Win16SelectObject record will be emitted for
  169. * the object.
  170. *
  171. * DoDeleteObject
  172. *
  173. * 1] The object handle is checked for reasonable limits.
  174. * We will also make sure that the Win16 slot has a handle
  175. * allocated to it. If it does not then we will return an
  176. * error.
  177. *
  178. * 2] If this is a stock object we fail and return an error.
  179. *
  180. * 3] If this is a non-stock object we emit a Win16DeleteObject
  181. * record. Then we set pW16ObjHndlSlotStatus to
  182. * indicate that this slot is available. We also set
  183. * piW32ToW16ObjectMap to -1 (UNMAPPED).
  184. *
  185. * DoCreatePen
  186. * DoExtCreatePen
  187. * DoCreateBrushIndirect
  188. * DoCreateMonoBrush
  189. * DoCreateDIBPatternBrush
  190. * DoExtCreateFont
  191. *
  192. * 1] Make sure the Win32 handle is not already being used
  193. * for something else. If it is return an error.
  194. *
  195. * 2] Validate the handle for this Object. This will return
  196. * a Win16 object table index (actually a slot number).
  197. * We really don't care what the slot number is as long
  198. * as we got one. DoDeleteObject and DoSelectObject always
  199. * refer to handles by their Win32 object indicies, and there
  200. * is no place else where used.
  201. *
  202. * 3] Emit a Win16CreateObject metafile record.
  203. *
  204. *
  205. * Special Routines
  206. *
  207. * bCommonRegionCode
  208. * Need to list the bitblt routines that use handles also
  209. *
  210. * 1] These routines just need to create objects in the Win16
  211. * metafile. There are no corresponding objects in the Win32
  212. * metafile.
  213. *
  214. * 2] Allocate a Win16 handle.
  215. *
  216. * 3] Use the object as needed. This includes emitting a
  217. * region or bitmap object into the Win16 metafile.
  218. *
  219. * 4] De-allocate the object. This include emitting a
  220. * DeleteObject record.
  221. *
  222. * CR1
  223. * Paths require the current pen to selected into the helperDC.
  224. * In order to keep track of create, select, & delete of the pen
  225. * object we will add an extra field to the W16ObjectHandleSlotStatus
  226. * array entries. This new field will contain either a NULL handle
  227. * or a valid Win32 handle. Currently only pens need to be selected
  228. * into the helper DC for paths, so they are the only objects whose
  229. * W32 handle field is not NULL.
  230. *
  231. *****************************************************************************/
  232. #include "precomp.h"
  233. #pragma hdrstop
  234. #define ABS(A) ((A) < 0 ? (-(A)) : (A))
  235. // Stock objects Name Stock
  236. // Object
  237. // ID
  238. LOGBRUSH albStock[] = {
  239. {BS_SOLID, 0x0FFFFFF, 0}, // White Brush 0
  240. {BS_SOLID, 0x0C0C0C0, 0}, // Ligh Grey Brush 1
  241. {BS_SOLID, 0x0808080, 0}, // Grey Brush 2
  242. {BS_SOLID, 0x0404040, 0}, // Dark Grey Brush 3
  243. {BS_SOLID, 0x0000000, 0}, // Black Brush 4
  244. {BS_HOLLOW, 0x0000000, 0} // Hollow Brush 5
  245. } ;
  246. LOGPEN alpnStock[] = {
  247. {PS_SOLID, 0, 0, 0x0FFFFFF}, // White Pen 6
  248. {PS_SOLID, 0, 0, 0x0000000}, // Black Pen 7
  249. {PS_NULL, 0, 0, 0x0FFFFFF} // Null Pen 8
  250. } ;
  251. // Internal function prototypes.
  252. BOOL bCreateStockObject(PLOCALDC pLocalDC, INT ihw32Norm) ;
  253. BOOL bCreateStockFont(PLOCALDC pLocalDC, INT ihW32) ;
  254. /***************************************************************************
  255. * bInitHandleTableManager - Init the Handle Table Manager.
  256. *
  257. * 1] Allocate memory for pW16ObjHndlSlotStatus and
  258. * piW32ToW16ObjectMap arrays.
  259. *
  260. * 2] Initialize pW16ObjHndlSlotStatus and
  261. * piW32ToW16ObjectMap to empty and UNMAPPED respectively.
  262. *
  263. * 3] Returns a TRUE if there were no problems with the
  264. * initialization, FALSE if anything went wrong.
  265. *
  266. * 4] It is expected that this routie will be called once from
  267. * the entry level routine when translation is first started.
  268. *
  269. **************************************************************************/
  270. BOOL bInitHandleTableManager(PLOCALDC pLocalDC, PENHMETAHEADER pmf32header)
  271. {
  272. BOOL b ;
  273. UINT i ;
  274. b = FALSE ;
  275. // The total number of handles required will be the stock handles
  276. // plus the handles used by the Win32 metafile plus one extra
  277. // for temporary brush used in opaque rectangle in textout.
  278. pLocalDC->cW32ToW16ObjectMap = pmf32header->nHandles + (STOCK_LAST + 1) + 1;
  279. // Allocate storage for the translation map.
  280. i = pLocalDC->cW32ToW16ObjectMap * sizeof(INT) ;
  281. pLocalDC->piW32ToW16ObjectMap = (PINT) LocalAlloc(LMEM_FIXED, i) ;
  282. if (pLocalDC->piW32ToW16ObjectMap == NULL)
  283. goto error_exit ;
  284. // Initialize the W32 to W16 object map to UNMAPPED (-1).
  285. // Since we never will have mapping to -1 we can test for
  286. // -1 in the map to make sure we are not double allocating a slot.
  287. for (i = 0 ; i < pLocalDC->cW32ToW16ObjectMap ; i++)
  288. pLocalDC->piW32ToW16ObjectMap[i] = UNMAPPED ;
  289. // Allocate storage for the slot status tables.
  290. // The number of Win16 object table slot may expand during conversion
  291. // due to temporary bitmaps and regions. It is my educated guess
  292. // that we will never need more than 5 extra slots, because we
  293. // only use a slot for a very short time, then free it. We are
  294. // allocating 256 extra slots in the name of robustness.
  295. // Note that the multi-format comment record may take up some
  296. // of these slots and increase the high water mark for object index.
  297. // We need to expand the table when required.
  298. pLocalDC->cW16ObjHndlSlotStatus = pLocalDC->cW32ToW16ObjectMap + 256 ;
  299. if (pLocalDC->cW16ObjHndlSlotStatus > (UINT) (WORD) MAXWORD)
  300. goto error_exit ; // w16 handle index is only 16-bit
  301. i = pLocalDC->cW16ObjHndlSlotStatus * sizeof(W16OBJHNDLSLOTSTATUS) ;
  302. pLocalDC->pW16ObjHndlSlotStatus
  303. = (PW16OBJHNDLSLOTSTATUS) LocalAlloc(LMEM_FIXED, i) ;
  304. if (pLocalDC->pW16ObjHndlSlotStatus == NULL)
  305. goto error_exit ;
  306. // Initialize the W16ObjectHandleSlotStatus to a state where every
  307. // handle is available.
  308. for (i = 0 ; i < pLocalDC->cW16ObjHndlSlotStatus ; i++)
  309. {
  310. pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT ;
  311. pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
  312. }
  313. // Initialize the pW32hPal palette handle table.
  314. // This table is used to store the W32 palette handles created during
  315. // the conversion.
  316. pLocalDC->cW32hPal = pmf32header->nHandles;
  317. i = pLocalDC->cW32hPal * sizeof(HPALETTE);
  318. pLocalDC->pW32hPal = (HPALETTE *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, i) ;
  319. if (pLocalDC->pW32hPal == NULL)
  320. goto error_exit ;
  321. b = TRUE;
  322. error_exit:
  323. if (!b)
  324. {
  325. if (pLocalDC->piW32ToW16ObjectMap)
  326. {
  327. if (LocalFree(pLocalDC->piW32ToW16ObjectMap))
  328. ASSERTGDI(FALSE, "MF3216: LocalFree failed");
  329. pLocalDC->piW32ToW16ObjectMap = (PINT) NULL;
  330. }
  331. if (pLocalDC->pW16ObjHndlSlotStatus)
  332. {
  333. if (LocalFree(pLocalDC->pW16ObjHndlSlotStatus))
  334. ASSERTGDI(FALSE, "MF3216: LocalFree failed");
  335. pLocalDC->pW16ObjHndlSlotStatus = NULL;
  336. }
  337. }
  338. return(b) ;
  339. }
  340. /***************************************************************************
  341. * bDeleteW16Object - Delete a W16 Object.
  342. *
  343. * This is the routine that is called to Delete a W16 Object that has
  344. * no corresponding W32 object. Region and Bitmaps are two examples.
  345. **************************************************************************/
  346. BOOL bDeleteW16Object(PLOCALDC pLocalDC, INT ihW16)
  347. {
  348. BOOL b ;
  349. ASSERTGDI
  350. (
  351. pLocalDC->pW16ObjHndlSlotStatus[ihW16].use != OPEN_AVAILABLE_SLOT,
  352. "MF3216: bDeleteW16Object, bad use value"
  353. );
  354. // Mark the W16 Slot just freed as available.
  355. pLocalDC->pW16ObjHndlSlotStatus[ihW16].use = OPEN_AVAILABLE_SLOT ;
  356. // Emit a Win16 DeleteOject record for the Object
  357. b = bEmitWin16DeleteObject(pLocalDC, LOWORD(ihW16)) ;
  358. return (b) ;
  359. }
  360. /***************************************************************************
  361. * iGetW16ObjectHandleSlot - return the first W16 open slot in the handle
  362. * table.
  363. *
  364. * 1] This routine searches the pW16ObjHndlSlotStatus array
  365. * looking for the first available open slot.
  366. *
  367. * 2] Mark the slot found as to its intended use.
  368. *
  369. * 3] Returns the first open slot if found, else return -1.
  370. *
  371. * 4] In essence this routine mimics the actions of the
  372. * Win16 play-time handle allocation system, in either
  373. * Win3.0 or Win3.1
  374. *
  375. * 5] We also keep track of the max object count here.
  376. *
  377. **************************************************************************/
  378. INT iGetW16ObjectHandleSlot(PLOCALDC pLocalDC, INT iIntendedUse)
  379. {
  380. BOOL b ;
  381. UINT i ;
  382. b = FALSE ;
  383. // Search for an available slot.
  384. for (i = 0 ; i < pLocalDC->cW16ObjHndlSlotStatus ; i++)
  385. {
  386. if (pLocalDC->pW16ObjHndlSlotStatus[i].use == OPEN_AVAILABLE_SLOT)
  387. {
  388. b = TRUE ;
  389. break ;
  390. }
  391. }
  392. // If a slot was found then mark its intended use.
  393. // Also set the W32 handle that may be associated with this
  394. // W16 handle to NULL. (Meaning no association at this time.)
  395. if (b)
  396. {
  397. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle == 0,
  398. "MF3216: iGetW16ObjectHandleSlot: w32Handle is not 0");
  399. pLocalDC->pW16ObjHndlSlotStatus[i].use = iIntendedUse ;
  400. pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
  401. // Update the number of object counts. This will be used
  402. // when we update the metafile header.
  403. if ((INT) i >= pLocalDC->nObjectHighWaterMark)
  404. pLocalDC->nObjectHighWaterMark = (INT) i;
  405. return((INT) i);
  406. }
  407. else
  408. {
  409. RIP("MF3216: iGetW16ObjectHandleSlot, Slot not found\n") ;
  410. return(-1) ;
  411. }
  412. }
  413. /***************************************************************************
  414. * iNormalizeHandle
  415. *
  416. * CR1 - this entire routine is part of the handle system redesign.
  417. *
  418. * 1] The idea behind this routine is to isolate the handling
  419. * of stock object handles to one place.
  420. *
  421. * 2] Input will be a Win32 handle index, either stock or a
  422. * standard object.
  423. *
  424. * 3] Output will be the index of the entry in the
  425. * piW32ToW16ObjectMap table that corresponds to the W32
  426. * handle. If an error is detected -1 is returned.
  427. *
  428. * 4] All the stock objects will be between the range of 0
  429. * and LAST_STOCK, and all the non-stock objects will be
  430. * greater than LAST_STOCK.
  431. *
  432. **************************************************************************/
  433. INT iNormalizeHandle(PLOCALDC pLocalDC, INT ihW32)
  434. {
  435. INT ihW32Norm ;
  436. if (ihW32 & ENHMETA_STOCK_OBJECT)
  437. {
  438. ihW32Norm = ihW32 & ~ENHMETA_STOCK_OBJECT ;
  439. if ((UINT) ihW32Norm > STOCK_LAST)
  440. {
  441. RIP("MF3216: iNormalizeHandle, bad stock object\n") ;
  442. ihW32Norm = -1 ;
  443. }
  444. }
  445. else
  446. {
  447. ihW32Norm = ihW32 + STOCK_LAST + 1 ;
  448. if ((UINT) ihW32Norm >= pLocalDC->cW32ToW16ObjectMap)
  449. {
  450. RIP("MF3216: iNormalizeHandle, bad standard object\n") ;
  451. ihW32Norm = -1 ;
  452. }
  453. }
  454. return(ihW32Norm) ;
  455. }
  456. /***************************************************************************
  457. * iAllocateW16Handle
  458. *
  459. * CR1 - this entire routine is part of the handle system redesign.
  460. * It is to be called from the object creation routines.
  461. *
  462. * 1] This routine actually does the handle allocation.
  463. *
  464. * 2] It sets the entry in pW16ObjHndlSlotStatus array
  465. * for the slot allocated by iGetW16ObjectHandleSlot to
  466. * an "in-use" status (for the intended use).
  467. *
  468. * 3] It returns a ihW16 (an index handle to the Win16 handle
  469. * table, aka the Win16 handle slot number).
  470. *
  471. **************************************************************************/
  472. INT iAllocateW16Handle(PLOCALDC pLocalDC, INT ihW32, INT iIntendedUse)
  473. {
  474. INT ihW32Norm,
  475. ihW16 ;
  476. // Assume the worst, set up for a failed return code.
  477. ihW16 = -1 ;
  478. // Normalize the handle.
  479. ihW32Norm = iNormalizeHandle(pLocalDC, ihW32) ;
  480. if (ihW32Norm == -1)
  481. goto error_exit ;
  482. // Check for double allocation of a Win32 handle index.
  483. // If we find a double allocation, this would indicate an error
  484. // in the Win32 metafile.
  485. // Error out on this due to the possibility of
  486. // a brush being used for a bitmap, or some other wrong use of a handle.
  487. if (pLocalDC->piW32ToW16ObjectMap[ihW32Norm] != UNMAPPED)
  488. {
  489. RIP("MF3216: iAllocateW16Handle, Double W32 handle allocation detected\n") ;
  490. goto error_exit ;
  491. }
  492. // Get a slot in the Win16 handle table.
  493. ihW16 = iGetW16ObjectHandleSlot(pLocalDC, iIntendedUse) ;
  494. if (ihW16 == -1)
  495. goto error_exit ;
  496. // Set the W32 to W16 slot mapping
  497. pLocalDC->piW32ToW16ObjectMap[ihW32Norm] = ihW16 ;
  498. error_exit:
  499. return(ihW16) ;
  500. }
  501. /***************************************************************************
  502. * iValidateHandle
  503. *
  504. * CR1 - this entire routine is part of the handle system redesign.
  505. *
  506. * 1] This routine does a lot more than validate a Win32 handle.
  507. * It does some limited error checking on the Win32 handle,
  508. * to make sure its within a reasonable range. Then if a
  509. * Win16 handle table slot has already been allocated for
  510. * this Win32 handle it will return the Win16 handle that
  511. * was previously allocated. Alternatively, if a Win16
  512. * handle has not been previously allocated for a Win32
  513. * STOCK handle it will allocate a W16 handle and return the
  514. * Win16 handle. This function is called by FillRgn, FrameRgn
  515. * and SelectObject to allow lazy allocation of stock objects.
  516. *
  517. * 2] Input is a Win32 handle, either a stock or a non-stock
  518. * handle.
  519. *
  520. * 3] Output is a Win16 handle, this is the value in the
  521. * Win32-index of the piW32ToW16ObjectMap. If a stock object
  522. * does not exist, it will create one.
  523. *
  524. * 4] If there is an error a -1 is returned.
  525. **************************************************************************/
  526. INT iValidateHandle(PLOCALDC pLocalDC, INT ihW32)
  527. {
  528. INT ihW32Norm,
  529. ihW16 ;
  530. // Assume the worst.
  531. ihW16 = -1 ;
  532. // NOTE: Normalizing the W32 handles takes care of checking
  533. // for a reasonable W32 handle value.
  534. ihW32Norm = iNormalizeHandle(pLocalDC, ihW32) ;
  535. if (ihW32Norm == -1)
  536. goto error_exit ;
  537. // Check the W32ToW16 map, to determine if this W32 handle has
  538. // already been allocated a W16 slot.
  539. ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
  540. if (ihW16 == UNMAPPED)
  541. {
  542. // There is no mapping from W32 to W16. This implies
  543. // that the object in question does not exist. If this is
  544. // a stock object, then we will create the object at this time.
  545. // Alternatively, if this is a non-stock object then we have an
  546. // error condition.
  547. if ((DWORD) ihW32Norm <= STOCK_LAST)
  548. {
  549. if (bCreateStockObject(pLocalDC, ihW32))
  550. ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
  551. else
  552. ihW16 = -1 ;
  553. }
  554. else
  555. {
  556. RIP("MF3216: iValidateHandle - Unmapped Standard Object\n") ;
  557. ihW16 = -1 ;
  558. }
  559. }
  560. error_exit:
  561. return (ihW16) ;
  562. }
  563. /***************************************************************************
  564. * DoDeleteObject - Win32 to Win16 Metafile Converter Entry Point
  565. *
  566. * CR1 - Most of this routine was rewritten to conform to the new
  567. * objects management system.
  568. *
  569. * 1] The object handle is checked for reasonable limits.
  570. * We will also make sure that the Win16 slot has a handle
  571. * allocated to it. If it does not then we will return an
  572. * error.
  573. *
  574. * 2] If this is a stock object we fail and return an error.
  575. *
  576. * 3] If this is a non-stock object we emit a Win16DeleteObject
  577. * record. Then we set pW16ObjHndlSlotStatus to
  578. * indicate that this slot is available. We also set
  579. * piW32ToW16ObjectMap to -1 (UNMAPPED).
  580. **************************************************************************/
  581. BOOL WINAPI DoDeleteObject
  582. (
  583. PLOCALDC pLocalDC,
  584. INT ihObject
  585. )
  586. {
  587. BOOL b ;
  588. INT ihW16,
  589. ihW32Norm;
  590. // Assume the worst.
  591. b = FALSE ;
  592. // Normalize the W32 handle.
  593. ihW32Norm = iNormalizeHandle(pLocalDC, ihObject) ;
  594. if (ihW32Norm == -1)
  595. goto error_exit ;
  596. // Make sure we're not deleting a stock object.
  597. if ((DWORD) ihW32Norm <= STOCK_LAST)
  598. {
  599. PUTS("MF3216: DoDeleteObject, attempt to delete a stock object\n") ;
  600. return(TRUE);
  601. }
  602. // If this is a palette, then we do not delete the win16 object.
  603. // We do delete our local version of the palette.
  604. if (pLocalDC->pW32hPal && pLocalDC->pW32hPal[ihObject])
  605. {
  606. b = DeleteObject(pLocalDC->pW32hPal[ihObject]);
  607. pLocalDC->pW32hPal[ihObject] = 0;
  608. if (b == FALSE)
  609. RIP("MF3216: DoDeleteObject - DeleteObject (hPalette) failed\n") ;
  610. return (b) ;
  611. }
  612. // Map the ihW32 to a ihW16 (object handle table slot).
  613. ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
  614. if (ihW16 == UNMAPPED)
  615. {
  616. RIP("MF3216: DoDeleteObject, attempt to delete a non-existent object\n");
  617. goto error_exit ;
  618. }
  619. // Make sure the object is one that we expect.
  620. // There is no region object or bitmap object in the enhanced metafiles.
  621. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH
  622. || pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN
  623. || pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_FONT,
  624. "MF3216: DoDeleteObject, Invalid Object Deletion\n") ;
  625. // If there was a Win32 handle associated with this Win16 handle
  626. // then the w32Handle field of the W16ObjHndlSlotStatus[ihW16]
  627. // entry in the handle slot status array will be non-null. If
  628. // it is non-null then we should delete the Win32 handle at this time.
  629. if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0)
  630. {
  631. if (!DeleteObject(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle))
  632. {
  633. ASSERTGDI(FALSE, "MF3216: DoDeleteObject, DeleteObject failed");
  634. }
  635. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle = 0 ;
  636. }
  637. // Mark the slot as available.
  638. // And set the map entry for the W32ToW16 map to unmapped.
  639. pLocalDC->pW16ObjHndlSlotStatus[ihW16].use = OPEN_AVAILABLE_SLOT ;
  640. pLocalDC->piW32ToW16ObjectMap[ihW32Norm] = UNMAPPED ;
  641. // Emit the delete drawing order.
  642. b = bEmitWin16DeleteObject(pLocalDC, LOWORD(ihW16)) ;
  643. error_exit:
  644. return (b) ;
  645. }
  646. /***************************************************************************
  647. * DoSelectObject - Win32 to Win16 Metafile Converter Entry Point
  648. *
  649. * CR1 - Major rewrite due to handle system redesign.
  650. *
  651. * DoSelectObject
  652. *
  653. * 1] For stock objects this is the workhorse routine.
  654. *
  655. * 2] For normal, non-stock, objects this routine will verify
  656. * that an object has been created for this Win32 object-index.
  657. * Then it will emit a Win16SelectObject metafile record.
  658. *
  659. * 3] For stock objects things get a little more complicated.
  660. * First this routine must make sure a Win16 object has been
  661. * created for this stock object. If a Win16 object has not
  662. * been created yet, then it will be. After a Win16 object
  663. * is created a Win16SelectObject record will be emitted for
  664. * the object.
  665. **************************************************************************/
  666. BOOL WINAPI DoSelectObject
  667. (
  668. PLOCALDC pLocalDC,
  669. LONG ihObject
  670. )
  671. {
  672. BOOL b ;
  673. INT ihW16;
  674. // Assume the worst.
  675. b = FALSE ;
  676. // Make sure that the W16 object exists before we emit the
  677. // SelectObject record. Stock objects may not have been created
  678. // and iValidateHandle will take care of creating them.
  679. ihW16 = iValidateHandle(pLocalDC, ihObject) ;
  680. if (ihW16 == -1)
  681. goto error_exit ;
  682. // Make sure the object is one that we expect.
  683. // There is no region object or bitmap object in the enhanced metafiles.
  684. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH
  685. || pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN
  686. || pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_FONT,
  687. "MF3216: DoSelectObject, Invalid Object Deletion\n") ;
  688. // Remember the currently selected pen. This is used in path and text.
  689. if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN)
  690. pLocalDC->lhpn32 = ihObject;
  691. // Remember the currently selected brush. This is used in text.
  692. if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH)
  693. pLocalDC->lhbr32 = ihObject;
  694. // If there was a Win32 handle associated with this Win16 handle
  695. // then the w32Handle field of the W16ObjHndlSlotStatus[ihW16]
  696. // entry in the handle slot status array will be non-null. If
  697. // it is non-null then we should select the W32 object into the
  698. // helper DC at this time.
  699. if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0)
  700. SelectObject(pLocalDC->hdcHelper,
  701. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle) ;
  702. b = bEmitWin16SelectObject(pLocalDC, LOWORD(ihW16)) ;
  703. error_exit:
  704. return(b) ;
  705. }
  706. /***************************************************************************
  707. * bCreateStockObject
  708. **************************************************************************/
  709. BOOL bCreateStockObject(PLOCALDC pLocalDC, INT ihW32)
  710. {
  711. BOOL b ;
  712. INT i ;
  713. ASSERTGDI((ihW32 & ENHMETA_STOCK_OBJECT) != 0,
  714. "MF3216: bCreateStockObject, invalid stock handle");
  715. switch (ihW32 & ~ENHMETA_STOCK_OBJECT)
  716. {
  717. case WHITE_BRUSH:
  718. case LTGRAY_BRUSH:
  719. case GRAY_BRUSH:
  720. case DKGRAY_BRUSH:
  721. case BLACK_BRUSH:
  722. case NULL_BRUSH:
  723. b = DoCreateBrushIndirect(pLocalDC, ihW32, &albStock[ihW32 & ~ENHMETA_STOCK_OBJECT]) ;
  724. break ;
  725. case WHITE_PEN:
  726. case BLACK_PEN:
  727. case NULL_PEN:
  728. i = (ihW32 & ~ENHMETA_STOCK_OBJECT) - WHITE_PEN ;
  729. b = DoCreatePen(pLocalDC, ihW32, (PLOGPEN) &alpnStock[i]) ;
  730. break ;
  731. case OEM_FIXED_FONT:
  732. case ANSI_FIXED_FONT:
  733. case ANSI_VAR_FONT:
  734. case SYSTEM_FONT:
  735. case DEVICE_DEFAULT_FONT:
  736. case SYSTEM_FIXED_FONT:
  737. b = bCreateStockFont(pLocalDC, ihW32) ;
  738. break ;
  739. case DEFAULT_PALETTE:
  740. default:
  741. // Logical palettes are handled in DoSelectPalette and should
  742. // not get here.
  743. RIP("MF3216: bCreateStockObject - Invalid Stock Object\n") ;
  744. b =FALSE ;
  745. break ;
  746. }
  747. return (b) ;
  748. }
  749. /***************************************************************************
  750. * bCreateStockFont
  751. **************************************************************************/
  752. BOOL bCreateStockFont(PLOCALDC pLocalDC, INT ihW32)
  753. {
  754. BOOL b ;
  755. INT i ;
  756. LOGFONTW LogFontW ;
  757. HANDLE hFont ;
  758. b = FALSE ;
  759. ASSERTGDI((ihW32 & ENHMETA_STOCK_OBJECT) != 0,
  760. "MF3216: bCreateStockObject, invalid stock handle");
  761. // Get a handle to this logfont.
  762. hFont = GetStockObject(ihW32 & ~ENHMETA_STOCK_OBJECT) ;
  763. if (hFont == (HANDLE) 0)
  764. {
  765. RIP("MF3216: bCreateStockFont, GetStockObject (font) failed\n") ;
  766. goto error_exit ;
  767. }
  768. // Get the logfont data. Assume we get at least one char in the
  769. // facename string.
  770. i = GetObjectW(hFont, sizeof(LOGFONTW), &LogFontW) ;
  771. if (i <= (INT) offsetof(LOGFONTW,lfFaceName[0]))
  772. {
  773. PUTS("MF3216: bCreateStockFont - GetObjectW failed\n") ;
  774. goto error_exit ;
  775. }
  776. // Zero out the remaining logfont structure.
  777. for ( ; i < sizeof(LOGFONTW); i++)
  778. ((PBYTE) &LogFontW)[i] = 0;
  779. // Create a LogFont for this stock font in the Win16 metafile.
  780. b = DoExtCreateFont(pLocalDC,
  781. ihW32,
  782. &LogFontW);
  783. error_exit:
  784. return (b) ;
  785. }
  786. /***************************************************************************
  787. * CreateBrushIndirect - Win32 to Win16 Metafile Converter Entry Point
  788. **************************************************************************/
  789. BOOL WINAPI DoCreateBrushIndirect
  790. (
  791. PLOCALDC pLocalDC,
  792. INT ihBrush,
  793. LPLOGBRUSH lpLogBrush
  794. )
  795. {
  796. WIN16LOGBRUSH Win16LogBrush ;
  797. BOOL b ;
  798. INT ihW16 ;
  799. LOGBRUSH LogBrush ;
  800. b = FALSE ;
  801. // Only 3 brush styles are allowed.
  802. if (lpLogBrush->lbStyle != BS_SOLID
  803. && lpLogBrush->lbStyle != BS_HATCHED
  804. && lpLogBrush->lbStyle != BS_HOLLOW)
  805. goto error_exit ;
  806. // Make a copy of the logical brush.
  807. LogBrush = *lpLogBrush;
  808. // The first 6 hatched styles map directly from Win32 to Win16.
  809. // The remaining hatched brushes are simulated using DIB pattern
  810. // brushes. Note that the background color of a hatched brush
  811. // is the current background color but that of a DIB pattern brush
  812. // is given at create time! We will use the current background color
  813. // in the DIB pattern brush when it is created. As a result, the
  814. // output of these brushes may look different!
  815. if (LogBrush.lbStyle == BS_HATCHED)
  816. {
  817. switch (LogBrush.lbHatch)
  818. {
  819. case HS_HORIZONTAL:
  820. case HS_VERTICAL:
  821. case HS_FDIAGONAL:
  822. case HS_BDIAGONAL:
  823. case HS_CROSS:
  824. case HS_DIAGCROSS:
  825. break;
  826. default:
  827. RIP("MF3216: Unknown hatched pattern\n");
  828. LogBrush.lbStyle = BS_SOLID;
  829. break;
  830. }
  831. }
  832. // Allocate the W16 handle.
  833. ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
  834. if (ihW16 == -1)
  835. goto error_exit ;
  836. // Create the w32 brush and store it in the w16 slot table.
  837. // This brush is needed by the helper DC for BitBlt simulations.
  838. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
  839. = CreateBrushIndirect(lpLogBrush) ;
  840. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
  841. "MF3216: CreateBrushIndirect failed");
  842. // Assign all the Win32 brush attributes to Win16 brush attributes.
  843. Win16LogBrush.lbStyle = (WORD) LogBrush.lbStyle ;
  844. Win16LogBrush.lbColor = LogBrush.lbColor ;
  845. Win16LogBrush.lbHatch = (SHORT) LogBrush.lbHatch ;
  846. // Call the Win16 routine to emit the brush to the metafile.
  847. b = bEmitWin16CreateBrushIndirect(pLocalDC, &Win16LogBrush) ;
  848. error_exit:
  849. return(b) ;
  850. }
  851. /******************************Public*Routine******************************\
  852. * CreateMonoDib
  853. *
  854. * This is the same as CreateBitmap except that the bits are assumed
  855. * to be DWORD aligned and that the scans start from the bottom of the bitmap.
  856. *
  857. * This routine is temporary until CreateDIBitmap supports monochrome bitmaps
  858. *
  859. * History:
  860. * Wed Jul 01 11:02:24 1992 -by- Hock San Lee [hockl]
  861. * Wrote it.
  862. \**************************************************************************/
  863. HBITMAP CreateMonoDib
  864. (
  865. LPBITMAPINFO pbmi,
  866. CONST BYTE * pjBits,
  867. UINT iUsage
  868. )
  869. {
  870. HBITMAP hbm;
  871. ASSERTGDI(pbmi->bmiHeader.biPlanes == 1, "CreateMonoDib: bad biPlanes value");
  872. ASSERTGDI(pbmi->bmiHeader.biBitCount == 1, "CreateMonoDib: bad biBitCount value");
  873. hbm = CreateBitmap((int) pbmi->bmiHeader.biWidth,
  874. (int) pbmi->bmiHeader.biHeight,
  875. (UINT) 1,
  876. (UINT) 1,
  877. (CONST VOID *) NULL);
  878. if (!hbm)
  879. return(hbm);
  880. SetDIBits((HDC) 0, hbm, 0, (UINT) pbmi->bmiHeader.biHeight,
  881. (CONST VOID *) pjBits, pbmi, iUsage);
  882. return(hbm);
  883. }
  884. /***************************************************************************
  885. * CreateMonoBrush - Win32 to Win16 Metafile Converter Entry Point
  886. **************************************************************************/
  887. BOOL WINAPI DoCreateMonoBrush
  888. (
  889. PLOCALDC pLocalDC,
  890. DWORD ihBrush,
  891. PBITMAPINFO pBitmapInfo,
  892. DWORD cbBitmapInfo,
  893. PBYTE pBits,
  894. DWORD cbBits,
  895. DWORD iUsage
  896. )
  897. {
  898. BOOL b ;
  899. INT ihW16;
  900. DWORD ul ;
  901. BYTE pbmi[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
  902. HBITMAP hbm;
  903. b = FALSE ;
  904. // Need to make a copy of the bitmap info header, for a few reasons
  905. // 1] the memory mapped file is write protected.
  906. // 2] the iUsage may be (is) use palatte indicies, and we need
  907. // use RGB colors.
  908. ((PBITMAPINFO) pbmi)->bmiHeader = pBitmapInfo->bmiHeader;
  909. // Need to make sure the iUsage is DIB_RGB_COLORS
  910. // and the palette is initialized to Black and White.
  911. ul = 0 ;
  912. ((PBITMAPINFO) pbmi)->bmiColors[0] = (*((RGBQUAD *) &(ul))) ;
  913. ul = 0x00ffffff ;
  914. ((PBITMAPINFO) pbmi)->bmiColors[1] = (*((RGBQUAD *) &(ul))) ;
  915. // Allocate the W16 handle.
  916. ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
  917. if (ihW16 == -1)
  918. goto error_exit ;
  919. // Create the w32 brush and store it in the w16 slot table.
  920. // This brush is needed by the helper DC for BitBlt simulations.
  921. if ((hbm = CreateMonoDib
  922. (
  923. pBitmapInfo,
  924. (CONST BYTE *) pBits,
  925. (UINT) iUsage
  926. )
  927. )
  928. )
  929. {
  930. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
  931. = CreatePatternBrush(hbm);
  932. if (!DeleteObject(hbm))
  933. ASSERTGDI(FALSE, "MF3216: DoCreateMonoBrush, DeleteObject failed");
  934. }
  935. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
  936. "MF3216: CreatePatternBrush failed");
  937. // Call the Win16 routine to emit the brush to the metafile.
  938. b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
  939. (PBITMAPINFO) pbmi,
  940. sizeof(pbmi),
  941. pBits,
  942. cbBits,
  943. (WORD) DIB_RGB_COLORS,
  944. (WORD) BS_PATTERN // Mono brush!
  945. ) ;
  946. error_exit:
  947. return(b) ;
  948. }
  949. /***************************************************************************
  950. * CreateDIPatternBrush - Win32 to Win16 Metafile Converter Entry Point
  951. **************************************************************************/
  952. BOOL WINAPI DoCreateDIBPatternBrush
  953. (
  954. PLOCALDC pLocalDC,
  955. DWORD ihBrush,
  956. PBITMAPINFO pBitmapInfo,
  957. DWORD cbBitmapInfo,
  958. PBYTE pBits,
  959. DWORD cbBits,
  960. DWORD iUsage
  961. )
  962. {
  963. BOOL b;
  964. INT ihW16;
  965. HBITMAP hbm;
  966. PBYTE pBits24;
  967. DWORD cbBits24;
  968. BITMAPINFOHEADER bmih;
  969. hbm = (HBITMAP) 0;
  970. pBits24 = (PBYTE) NULL;
  971. b = FALSE ;
  972. // Allocate the W16 handle.
  973. ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
  974. if (ihW16 == -1)
  975. goto error_exit ;
  976. // Create the w32 brush and store it in the w16 slot table.
  977. // We assume that the bitmap info is followed by the bits immediately,
  978. // i.e. it is a packed dib.
  979. // This brush is needed by the helper DC for BitBlt simulations.
  980. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
  981. = CreateDIBPatternBrushPt((LPVOID) pBitmapInfo, (UINT) iUsage);
  982. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
  983. "MF3216: CreateDIBPatternBrushPt failed");
  984. // We need to convert new bitmap info formats to the win3 formats.
  985. if (pBitmapInfo->bmiHeader.biPlanes != 1
  986. || pBitmapInfo->bmiHeader.biBitCount == 16
  987. || pBitmapInfo->bmiHeader.biBitCount == 32)
  988. {
  989. if (!(hbm = CreateDIBitmap(pLocalDC->hdcHelper,
  990. (LPBITMAPINFOHEADER) pBitmapInfo,
  991. CBM_INIT | CBM_CREATEDIB,
  992. pBits,
  993. (LPBITMAPINFO) pBitmapInfo,
  994. (UINT) iUsage)))
  995. goto error_exit ;
  996. bmih = *(PBITMAPINFOHEADER) pBitmapInfo;
  997. bmih.biPlanes = 1;
  998. bmih.biBitCount = 24;
  999. bmih.biCompression = BI_RGB;
  1000. bmih.biSizeImage = 0;
  1001. bmih.biClrUsed = 0;
  1002. bmih.biClrImportant = 0;
  1003. cbBits24 = CJSCAN(bmih.biWidth,bmih.biPlanes,bmih.biBitCount)
  1004. * ABS(bmih.biHeight);
  1005. pBits24 = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBits24);
  1006. if (pBits24 == (LPBYTE) NULL)
  1007. goto error_exit;
  1008. // Get bitmap info and bits in 24bpp.
  1009. if (!GetDIBits(pLocalDC->hdcHelper,
  1010. hbm,
  1011. 0,
  1012. (UINT) bmih.biHeight,
  1013. pBits24,
  1014. (LPBITMAPINFO) &bmih,
  1015. DIB_RGB_COLORS))
  1016. goto error_exit;
  1017. b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
  1018. (PBITMAPINFO) &bmih,
  1019. sizeof(bmih),
  1020. pBits24,
  1021. cbBits24,
  1022. (WORD) DIB_RGB_COLORS,
  1023. (WORD) BS_DIBPATTERN
  1024. ) ;
  1025. }
  1026. else
  1027. {
  1028. // Call the Win16 routine to emit the brush to the metafile.
  1029. b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
  1030. pBitmapInfo,
  1031. cbBitmapInfo,
  1032. pBits,
  1033. cbBits,
  1034. (WORD) iUsage,
  1035. (WORD) BS_DIBPATTERN
  1036. ) ;
  1037. }
  1038. error_exit:
  1039. if (hbm)
  1040. DeleteObject(hbm);
  1041. if (pBits24)
  1042. LocalFree((HANDLE) pBits24);
  1043. return(b) ;
  1044. }
  1045. /***************************************************************************
  1046. * CreatePen - Win32 to Win16 Metafile Converter Entry Point
  1047. **************************************************************************/
  1048. BOOL WINAPI DoCreatePen
  1049. (
  1050. PLOCALDC pLocalDC,
  1051. INT ihPen,
  1052. PLOGPEN pLogPen
  1053. )
  1054. {
  1055. EXTLOGPEN ExtLogPen ;
  1056. BOOL b ;
  1057. ExtLogPen.elpPenStyle = PS_GEOMETRIC | pLogPen->lopnStyle ;
  1058. ExtLogPen.elpWidth = (UINT) pLogPen->lopnWidth.x ;
  1059. ExtLogPen.elpBrushStyle = BS_SOLID ;
  1060. ExtLogPen.elpColor = pLogPen->lopnColor ;
  1061. ExtLogPen.elpNumEntries = 0 ;
  1062. // ExtLogPen.elpHatch = 0 ;
  1063. // ExtLogPen.elpStyleEntry[0] = 0;
  1064. b = DoExtCreatePen(pLocalDC, ihPen, &ExtLogPen) ;
  1065. return (b) ;
  1066. }
  1067. /***************************************************************************
  1068. * ExtCreatePen - Win32 to Win16 Metafile Converter Entry Point
  1069. **************************************************************************/
  1070. BOOL WINAPI DoExtCreatePen
  1071. (
  1072. PLOCALDC pLocalDC,
  1073. INT ihPen,
  1074. PEXTLOGPEN pExtLogPen
  1075. )
  1076. {
  1077. BOOL b ;
  1078. WORD iStyle ;
  1079. POINTS ptsWidth ;
  1080. INT ihW16 ;
  1081. UINT iPenStyle ;
  1082. POINTL ptlWidth ;
  1083. COLORREF crColor ;
  1084. b = FALSE;
  1085. // Get pen style.
  1086. iPenStyle = pExtLogPen->elpPenStyle & PS_STYLE_MASK ;
  1087. switch(iPenStyle)
  1088. {
  1089. case PS_SOLID:
  1090. case PS_DASH:
  1091. case PS_DOT:
  1092. case PS_DASHDOT:
  1093. case PS_DASHDOTDOT:
  1094. case PS_NULL:
  1095. case PS_INSIDEFRAME:
  1096. break ;
  1097. case PS_ALTERNATE:
  1098. iPenStyle = PS_DOT ;
  1099. break ;
  1100. case PS_USERSTYLE:
  1101. default:
  1102. // CR1: default to solid.
  1103. iPenStyle = PS_SOLID ;
  1104. break ;
  1105. }
  1106. // Get pen color.
  1107. switch (pExtLogPen->elpBrushStyle)
  1108. {
  1109. case BS_SOLID:
  1110. case BS_HATCHED:
  1111. crColor = pExtLogPen->elpColor ;
  1112. break;
  1113. // If the extended pen contains a hollow brush, then
  1114. // we will emit a NULL pen.
  1115. case BS_NULL: // BS_HOLLOW is the same as BS_NULL
  1116. iPenStyle = PS_NULL ;
  1117. crColor = 0 ;
  1118. break;
  1119. // Win3.x does not support pens with bitmap patterns.
  1120. // So we will just use solid pens here. Since we do not
  1121. // know what pen color to use, we choose the text color.
  1122. case BS_PATTERN:
  1123. case BS_DIBPATTERN:
  1124. case BS_DIBPATTERNPT:
  1125. default:
  1126. crColor = pLocalDC->crTextColor ;
  1127. break;
  1128. }
  1129. // Get pen width.
  1130. // If this is a cosmetic pen then the width is 0.
  1131. ptlWidth.y = 0 ;
  1132. if ((pExtLogPen->elpPenStyle & PS_TYPE_MASK) == PS_COSMETIC)
  1133. ptlWidth.x = 0 ;
  1134. else
  1135. ptlWidth.x = pExtLogPen->elpWidth ;
  1136. // Allocate the W16 handle.
  1137. ihW16 = iAllocateW16Handle(pLocalDC, ihPen, REALIZED_PEN);
  1138. if (ihW16 == -1)
  1139. goto error_exit ;
  1140. // This is where we need to create a pen for helper DC.
  1141. // We do not select it into the helper DC at this time.
  1142. pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
  1143. = CreatePen((int) iPenStyle, ptlWidth.x, crColor) ;
  1144. ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
  1145. "MF3216: DoExtCreatePen, CreatePen failed");
  1146. // Get pen width in play time page units.
  1147. ptlWidth.x = (LONG) iMagnitudeXform(pLocalDC, (INT) ptlWidth.x, CX_MAG);
  1148. // Set the Win16 pen attributes
  1149. iStyle = (WORD) iPenStyle ;
  1150. ptsWidth.x = (WORD) ptlWidth.x ;
  1151. ptsWidth.y = (WORD) ptlWidth.y ;
  1152. // Call the Win16 routine to emit the pen to the metafile.
  1153. b = bEmitWin16CreatePen(pLocalDC, iStyle, &ptsWidth, crColor) ;
  1154. error_exit:
  1155. return(b) ;
  1156. }