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.

5146 lines
140 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: textddi.cxx
  3. *
  4. * EngTextOut text drawing to DIBs
  5. *
  6. * Copyright (c) 1994-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. VOID vRectBlt(PBYTE, ULONG, LONG, LONG, LONG, LONG);
  10. VOID vRectBlt4(BYTE*,ULONG, LONG, LONG, LONG, LONG);
  11. VOID vRectBlt8(BYTE*,ULONG, LONG, LONG, LONG, LONG);
  12. class FRINGERECT
  13. {
  14. private:
  15. SURFACE *pSurf;
  16. PVOID pvBits; // see comment [1] below
  17. CLIPOBJ *pco;
  18. BRUSHOBJ *pboOpaque;
  19. int crcl; // Count of fringe rectangles to do.
  20. RECTL arcl[4];
  21. public:
  22. FRINGERECT(SURFACE *pSurf1,CLIPOBJ *pco1,BRUSHOBJ *pboOpaque1)
  23. {
  24. pSurf = pSurf1;
  25. if (pSurf1->iType() == STYPE_BITMAP)
  26. pvBits = pSurf1->pvBits();
  27. else
  28. pvBits = NULL;
  29. pco = pco1;
  30. pboOpaque = pboOpaque1;
  31. crcl = 0;
  32. }
  33. ~FRINGERECT()
  34. {
  35. //
  36. // We just assume the Rop is P according to the DDI.
  37. //
  38. if (pvBits)
  39. {
  40. while (--crcl >= 0)
  41. {
  42. vDIBSolidBlt(
  43. pSurf ,
  44. &arcl[crcl] ,
  45. pco ,
  46. pboOpaque->iSolidColor,
  47. FALSE
  48. );
  49. }
  50. }
  51. else
  52. {
  53. // this section was put in to support AntiAliased
  54. // text. It is possible that for the case of
  55. // antialiased text EngTextOut could be asked to
  56. // render to a device managed surface. In that
  57. // case, we use the device's BitBlt function to
  58. // render the rectangles
  59. POINTL ptlBrush = {0,0}; // it does not matter, it is solid color always
  60. RECTL *prcl;
  61. SURFOBJ *pso = pSurf->pSurfobj();
  62. PFN_DrvBitBlt pFnBitBlt = pSurf->pfnBitBlt();
  63. for (prcl = arcl; prcl < arcl + crcl; prcl++)
  64. {
  65. (*(pFnBitBlt))(
  66. pso , // psoTrg
  67. 0 , // psoSrc
  68. 0 , // psoMask
  69. pco , // pco
  70. 0 , // pxlo
  71. prcl , // prclTrg
  72. 0 , // pptlSrc
  73. 0 , // pptlMask
  74. pboOpaque , // pbo
  75. &ptlBrush , // pptlBrush
  76. 0x0000f0f0 // rop4
  77. );
  78. }
  79. }
  80. }
  81. VOID vAddRect(LONG left, LONG top, LONG right, LONG bottom)
  82. {
  83. arcl[crcl].left = left;
  84. arcl[crcl].top = top;
  85. arcl[crcl].right = right;
  86. arcl[crcl].bottom = bottom;
  87. crcl++;
  88. }
  89. };
  90. /***********************************************************************
  91. * [1] *
  92. * *
  93. * Before GDI provided support for antialiased text it would *
  94. * not have been possible to have a surface without a pointer *
  95. * to the DIB bits. However, in the case of antialiased text *
  96. * it is possible that we reached here by way of GreExtTextOutW() *
  97. * ( this case is signaled by pSurf->pdcoAA != 0 ). In this *
  98. * case, the original surface of the device may not be accessible *
  99. * by GDI. This case would be indicated by a zero value for *
  100. * pvBits. You might worry that this means that we cannot take *
  101. * care of the background rectangles. But this is not the case! *
  102. * The background rectangle will be taken care of by GreExtTextOutW. *
  103. * *
  104. ***********************************************************************/
  105. #define SO_MASK \
  106. ( \
  107. SO_FLAG_DEFAULT_PLACEMENT | \
  108. SO_ZERO_BEARINGS | \
  109. SO_CHAR_INC_EQUAL_BM_BASE | \
  110. SO_MAXEXT_EQUAL_BM_SIDE \
  111. )
  112. #define TEXT_BUFFER_SIZE 1024
  113. #define KERNEL_ALLOC_SIZE 65536
  114. //
  115. // accelerator masks for four canonical directions of
  116. // writing (multiples of 90 degrees)
  117. //
  118. #define SO_LTOR (SO_MASK | SO_HORIZONTAL)
  119. #define SO_RTOL (SO_LTOR | SO_REVERSED)
  120. #define SO_TTOB (SO_MASK | SO_VERTICAL)
  121. #define SO_BTOT (SO_TTOB | SO_REVERSED)
  122. //
  123. // Glyph copy Declarations
  124. //
  125. typedef VOID (*PFN_MASTERTEXTTYPE)(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  126. //
  127. // Temp buffer expansion Declarations
  128. //
  129. typedef VOID (*PFN_TEXTSRCCPY)(
  130. BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  131. VOID vExpandAndCopyText(
  132. SURFACE *,
  133. FONTOBJ * ,
  134. GLYPHPOS *,
  135. ULONG ,
  136. PBYTE,
  137. ULONG,
  138. ULONG,
  139. SURFACE *,
  140. SURFACE *,
  141. RECTL *,
  142. RECTL *,
  143. INT,
  144. INT,
  145. ULONG,
  146. RECTL *,
  147. RECTL *,
  148. ULONG,
  149. BRUSHOBJ *,
  150. POINTL *
  151. );
  152. extern "C" {
  153. VOID vFastText(
  154. GLYPHPOS *,
  155. ULONG ,
  156. PBYTE,
  157. ULONG,
  158. ULONG,
  159. SURFOBJ *,
  160. RECTL *,
  161. RECTL *,
  162. INT,
  163. INT,
  164. ULONG,
  165. RECTL *,
  166. RECTL *
  167. );
  168. VOID vSrcTranCopyError( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  169. VOID vSrcTranCopyS1D1( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  170. VOID vSrcTranCopyS1D4( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  171. VOID vSrcTranCopyS1D8( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  172. VOID vSrcTranCopyS1D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  173. VOID vSrcTranCopyS1D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  174. VOID vSrcTranCopyS1D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  175. VOID vSrcOpaqCopyS1D1( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  176. VOID vSrcOpaqCopyS1D4( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  177. VOID vSrcOpaqCopyS1D8( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  178. VOID vSrcOpaqCopyS1D8_64(BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  179. VOID vSrcOpaqCopyS1D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  180. VOID vSrcOpaqCopyS1D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  181. VOID vSrcOpaqCopyS1D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  182. VOID vSrcTranCopyS4D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  183. VOID vSrcTranCopyS4D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  184. VOID vSrcTranCopyS4D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  185. VOID vSrcOpaqCopyS4D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  186. VOID vSrcOpaqCopyS4D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  187. VOID vSrcOpaqCopyS4D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  188. VOID vSrcOpaqCopyS8D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  189. VOID vSrcOpaqCopyS8D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  190. VOID vSrcOpaqCopyS8D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  191. VOID vSrcTranCopyS8D16( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  192. VOID vSrcTranCopyS8D24( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  193. VOID vSrcTranCopyS8D32( BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*);
  194. VOID draw_f_tb_no_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  195. VOID draw_nf_tb_no_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  196. VOID draw_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  197. VOID draw_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  198. // grayscale routines
  199. VOID draw_gray_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  200. VOID draw_gray_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  201. // cleartype routines
  202. VOID draw_clrt_nf_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  203. VOID draw_clrt_f_ntb_o_to_temp_start(PGLYPHPOS,ULONG,PUCHAR,ULONG,ULONG,ULONG,ULONG);
  204. ULONG TextExpStartMask[] = {0xFFFFFFFF,
  205. 0xFFFFFF00,
  206. 0xFFFF0000,
  207. 0xFF000000
  208. };
  209. ULONG TextExpEndMask[] = {0xFFFFFFFF,
  210. 0x000000FF,
  211. 0x0000FFFF,
  212. 0x00FFFFFF
  213. };
  214. LONG TextExpStartByteCount[] = {0,3,2,1};
  215. }
  216. #define NO_TARGET 0
  217. #define FIFTEEN_BITS ((1 << 15)-1)
  218. #if DBG
  219. void vDump8bppDIB(SURFMEM& surfmem);
  220. #endif
  221. /******************************Public*Routine******************************\
  222. * Routine Name:
  223. *
  224. * EngTextOut
  225. *
  226. * Routine Description:
  227. *
  228. * This routine blts glyphs to a DIB.
  229. *
  230. * Arguments:
  231. *
  232. * pso - Surface object for destination surface
  233. * pstro - String object for enumerating glyphs
  234. * pfo - Font object of glyphs
  235. * pco - Clip object
  236. * prclExtra - Extra rectangles to draw with text
  237. * prclOpaque - Opaque rectangle
  238. * pboFore - Foreground brush
  239. * pboOpaque - Background brush
  240. * pptlOrg - Brush starting origin
  241. * mix - Equal to SRCCOPY for now
  242. *
  243. * Return Value:
  244. *
  245. * BOOL Status
  246. *
  247. \**************************************************************************/
  248. #define ETO_GRAY 8
  249. #define ETO_DEVICE_SURFACE 16
  250. #define ETO_CLEARTYPE_X 32
  251. #define ETO_CLEARTYPE_Y 64
  252. VOID EngTextOutBitBlt(
  253. SURFACE *pSurf,
  254. FONTOBJ *pfo,
  255. ULONG fDrawFlags,
  256. SURFOBJ *psoSrc,
  257. SURFOBJ *psoMsk,
  258. CLIPOBJ *pco,
  259. XLATEOBJ *plxo,
  260. RECTL *prclTrg,
  261. POINTL *pptlSrc,
  262. POINTL *pptlMsk,
  263. BRUSHOBJ *pbo,
  264. POINTL *pptlBrush,
  265. ROP4 rop4
  266. )
  267. {
  268. if (fDrawFlags & ETO_DEVICE_SURFACE)
  269. {
  270. RFONTTMPOBJ rfo(PFO_TO_PRF(pfo));
  271. TextOutBitBlt(pSurf, rfo, psoSrc, psoMsk, pco, plxo,
  272. prclTrg, pptlSrc, pptlMsk, pbo, pptlBrush, rop4);
  273. }
  274. else
  275. {
  276. EngBitBlt(pSurf->pSurfobj(), psoSrc, psoMsk, pco, plxo,
  277. prclTrg, pptlSrc, pptlMsk, pbo, pptlBrush, rop4);
  278. }
  279. }
  280. BOOL EngTextOut(
  281. SURFOBJ *pso,
  282. STROBJ *pstro,
  283. FONTOBJ *pfo,
  284. CLIPOBJ *pco,
  285. PRECTL prclExtra,
  286. PRECTL prclOpaque,
  287. BRUSHOBJ *pboFore,
  288. BRUSHOBJ *pboOpaque,
  289. PPOINTL pptlOrg,
  290. MIX mix
  291. )
  292. {
  293. ULONG iClip; // Clip object's complexity
  294. BOOL bMore; // Flag for clip enumeration
  295. CLIPENUMRECT txen; // Clip enumeration object
  296. GLYPHPOS *pgp; // pointer to the 1st glyph
  297. BOOL bMoreGlyphs; // Glyph enumeration flag
  298. ULONG cGlyph; // number of glyphs in one batch
  299. ULONG iSolidForeColor; // Solid foreground color
  300. ULONG iSolidBkColor; // Solid background color
  301. FLONG flStr = 0; // Accelator flag for DrvTextOut()
  302. FLONG flOption = 0; // Accelator flag for pfnBlt
  303. RECTL arclTmp[4]; // Temp storage for portions of
  304. // opaquing rect
  305. RECTL *prclClip; // ptr to list of clip rectangles
  306. ULONG ulBufferWidthInBytes = 0;
  307. ULONG ulBufferHeight;
  308. ULONG ulBufferBytes;
  309. BOOL bTextPerfectFit;
  310. ULONG fDrawFlags = 0;
  311. BYTE *pjTempBuffer;
  312. BOOL bTempAlloc;
  313. BOOL bKernelAlloc;
  314. BYTE szTextBuffer[TEXT_BUFFER_SIZE];
  315. ULONG Native64BitAccess = TRUE;
  316. ULONG iTrgType = 0;
  317. SURFACE *pSurfDraw;
  318. RECTL rcScreen; // intersection of Screen & DIB
  319. // in screen coordinates
  320. RECTL rcDIB; // intersection of Screen & DIB
  321. // in DIB coordinates
  322. XDCOBJ *pdco = 0; // equal to pSurf->pdcoAA
  323. // this is non-zero in the case
  324. // where the text in anti-aliased
  325. // and the device does not support
  326. // antialiased text directly. In such
  327. // a case we must be able to pass
  328. // information about the original
  329. // deivce surface
  330. SURFACE *pSurfDevice = 0; // pointer to original device surface
  331. // this is obtained via pdco
  332. // This hack, due to filtering needs to be put in textgdi.cxx
  333. // filtering leeks color one pixel to the left and one pixel to the right
  334. ASSERTGDI(pso != (SURFOBJ *) NULL, "ERROR: EngTextOut Surface\n");
  335. ASSERTGDI(pstro != (STROBJ *) NULL, "ERROR: EngTextOut String\n" );
  336. ASSERTGDI(pfo != (FONTOBJ *) NULL, "ERROR: EngTextOut Font\n" );
  337. // In order to support antialiasing text on devices that don't
  338. // support antialiasing GDI will first render the text to
  339. // a DIB then later copy the DIB to the original device surface.
  340. // In such a case pso represents the DIB surface and mix
  341. // contains a pointer to the original XDCOBJ which will
  342. // be needed in order to interpret the colors corectly. The
  343. // way that we recognize this situation is that
  344. // pSurf->pdcoAA is non-zero
  345. PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
  346. pSurfDraw = pSurf;
  347. if (pfo->flFontType & FO_GRAY16)
  348. {
  349. if ( pdco = pSurf->pdcoAA )
  350. {
  351. ASSERTGDI(pdco->dctp() != DCTYPE_INFO, "dctp == DCTYPE_INFO\n");
  352. pSurfDevice = pdco->pdc->ppdev()->pSurface;
  353. }
  354. else
  355. {
  356. pSurfDevice = pSurf;
  357. }
  358. if (pSurf->iType() != STYPE_BITMAP)
  359. {
  360. fDrawFlags |= ETO_DEVICE_SURFACE;
  361. }
  362. }
  363. if ((pfo->flFontType & DEVICE_FONTTYPE) != 0)
  364. {
  365. WARNING("Attempting EngTextOut with Device Font\n");
  366. return(FALSE);
  367. }
  368. //
  369. // Note that we don't synchronize with the device here (we do that in
  370. // vExpandAndCopyText after doing a bunch of work not involving the
  371. // frame buffer), but we do let the driver know we're going to be
  372. // calling Synchronize soon via FLUSH, to get it to empty its DMA
  373. // buffer.
  374. //
  375. // {
  376. // PDEVOBJ po(pSurf->hdev());
  377. // if (po.flGraphicsCaps2() & GCAPS2_SYNCFLUSH)
  378. // {
  379. // po.vSync(pso, NULL, DSS_FLUSH_EVENT);
  380. // }
  381. // }
  382. iClip = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
  383. iSolidForeColor = pboFore->iSolidColor;
  384. //
  385. // assume no opaque rectangle
  386. //
  387. iSolidBkColor = 0xFFFFFFFF;
  388. //
  389. // See if the temp buffer is big enough for the text; if not,
  390. // try to allocate enough memory.
  391. // Round up to the nearest dword multiple so that the alignment
  392. // will stay constant when blt to the destination surface.
  393. //
  394. if(pfo->flFontType & FO_GRAY16)
  395. {
  396. if (pSurf->iFormat() == BMF_8BPP)
  397. {
  398. if (pboOpaque->iSolidColor == -1L)
  399. {
  400. RIP("EngTextOut Error attempting anti-aliased text\n"
  401. "at 8bpp with a transparent background.\n");
  402. return(FALSE);
  403. }
  404. }
  405. fDrawFlags |= ETO_GRAY;
  406. if (pfo->flFontType & FO_CLEARTYPE_X)
  407. {
  408. //
  409. // This is the case 8-bpp antialiased text
  410. //
  411. // The strategy is to create a 8-bpp buffer representing
  412. // the entire string.
  413. //
  414. // The buffer shall be aligned with the destination. That
  415. // is, 32-bit boundaries in the buffer correspond to 32
  416. // bit boundaries in the destination surface and the text
  417. // in the buffer has the same relative alignment as the
  418. // destination. To do this, we bump boundaries of the buffer
  419. // such that the left and right boundaries of the buffer
  420. // land on 32-bit aligned postions. This is done in the
  421. // following way. We note that a DWORD is 32 bits, this
  422. // is enough information to specify 4 (8bpp) pixels. The
  423. // number aligned DWORD's needed to surround the nibbles
  424. // defining the text is calculated by finding the nearest
  425. // multiple of 4 above and below the x-boundaries of the
  426. // text. The difference between these two numbers is a
  427. // count of DWORD's. Then since each DWORD is made up
  428. // of 4 bytes, we multiply by 4 at the end to get a count
  429. // of bytes.
  430. //
  431. // buffer width in bytes = 4 * (ceiling((right+1)/4) - floor(left/4))
  432. //
  433. fDrawFlags |= ETO_CLEARTYPE_X;
  434. ulBufferWidthInBytes =
  435. ( ((pstro->rclBkGround.right + 4) >> 2)
  436. - ((pstro->rclBkGround.left ) >> 2) ) << 2;
  437. }
  438. else if (pfo->flFontType & FO_CLEARTYPE_Y)
  439. {
  440. RIP("FO_CLEARTYPE_Y, not supported yet\n");
  441. }
  442. else
  443. {
  444. //
  445. // This is the case 4-bpp antialiased text
  446. //
  447. // The strategy is to create a 4-bpp buffer representing
  448. // the entire string.
  449. //
  450. // The buffer shall be aligned with the destination. That
  451. // is, 32-bit boundaries in the buffer correspond to 32
  452. // bit boundaries in the destination surface and the text
  453. // in the buffer has the same relative alignment as the
  454. // destination. To do this, we bump boundaries of the buffer
  455. // such that the left and right boundaries of the buffer
  456. // land on 32-bit aligned postions. This is done in the
  457. // following way. We note that a DWORD is 32 bits, this
  458. // is enough information to specify 8 (4bpp) pixels. The
  459. // number aligned DWORD's needed to surround the nibbles
  460. // defining the text is calculated by finding the nearest
  461. // multiple of 8 above and below the x-boundaries of the
  462. // text. The difference between these two numbers is a
  463. // count of DWORD's. Then since each DWORD is made up
  464. // of 4 bytes, we multiply by 4 at the end to get a count
  465. // of bytes.
  466. //
  467. // buffer width in bytes = 4 * (ceiling((right+1)/8) - floor(left/8))
  468. //
  469. ulBufferWidthInBytes =
  470. ( ((pstro->rclBkGround.right + 8) >> 3)
  471. - ((pstro->rclBkGround.left ) >> 3) ) << 2;
  472. }
  473. }
  474. else
  475. {
  476. ulBufferWidthInBytes =
  477. ((((pstro->rclBkGround.right + 32) & ~31) -
  478. (pstro->rclBkGround.left & ~31)) >> 3);
  479. }
  480. ulBufferHeight = (ULONG)(pstro->rclBkGround.bottom - pstro->rclBkGround.top);
  481. if ((ulBufferWidthInBytes > FIFTEEN_BITS) ||
  482. (ulBufferHeight > FIFTEEN_BITS))
  483. {
  484. //
  485. // the math will have overflowed
  486. //
  487. return(FALSE);
  488. }
  489. ulBufferBytes = ulBufferWidthInBytes * ulBufferHeight;
  490. if (ulBufferBytes <= TEXT_BUFFER_SIZE)
  491. {
  492. //
  493. // The temp buffer on the stack is big enough, so we'll use it
  494. //
  495. pjTempBuffer = szTextBuffer;
  496. bTempAlloc = FALSE;
  497. }
  498. else
  499. {
  500. //
  501. // The temp buffer isn't big enough, so we'll try to allocate
  502. // enough memory
  503. //
  504. #if DBG
  505. if (ulBufferBytes >= (PAGE_SIZE * 10000))
  506. {
  507. WARNING("EngTextOut: temp buffer >= 10000 pages");
  508. return(FALSE);
  509. }
  510. #endif
  511. bKernelAlloc = (ulBufferBytes < KERNEL_ALLOC_SIZE);
  512. if (bKernelAlloc)
  513. {
  514. pjTempBuffer = (BYTE*) PALLOCNOZ(ulBufferBytes, 'oteG');
  515. }
  516. else
  517. {
  518. pjTempBuffer = (BYTE*) EngAllocUserMem(ulBufferBytes,'oteG');
  519. }
  520. if (pjTempBuffer == NULL)
  521. {
  522. return(FALSE);
  523. }
  524. //
  525. // Mark that we have to free the buffer when we're done
  526. //
  527. bTempAlloc = TRUE;
  528. }
  529. //
  530. // One way or another, we've found a buffer that's big enough; set up
  531. // for accelerated text drawing
  532. //
  533. // Set fixed pitch, overlap, and top & bottom Y alignment flags
  534. //
  535. if ((!(pstro->flAccel & SO_HORIZONTAL)) || (pstro->flAccel & SO_REVERSED))
  536. {
  537. ;
  538. }
  539. else
  540. {
  541. fDrawFlags |= ((pstro->ulCharInc != 0) |
  542. (
  543. (
  544. (pstro->flAccel & (SO_ZERO_BEARINGS |
  545. SO_FLAG_DEFAULT_PLACEMENT)) !=
  546. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)
  547. ) << 1
  548. ) |
  549. (
  550. ((pstro->flAccel & (SO_ZERO_BEARINGS |
  551. SO_FLAG_DEFAULT_PLACEMENT |
  552. SO_MAXEXT_EQUAL_BM_SIDE)) ==
  553. (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
  554. SO_MAXEXT_EQUAL_BM_SIDE)
  555. ) << 2
  556. )
  557. );
  558. }
  559. //
  560. // Handle the opaque rectangle if given.
  561. //
  562. // If the background brush is a pattern brush or the foreground brush is
  563. // a pattern brush (foreground pattern brush is not supported), we
  564. // will output the whole rectangle now.
  565. //
  566. // Otherwise, we will compute the fringe opaque area outside the text
  567. // rectangle and include the remaining rectangle in the text output.
  568. // The fringe rectangles will be output last to reduce flickering when
  569. // a string is "moved" continuously across the screen.
  570. //
  571. FRINGERECT fr(pSurf, pco, pboOpaque);
  572. if (prclOpaque != (PRECTL) NULL)
  573. {
  574. //
  575. // If we have a device managed surface then the pattern should be
  576. // laid down with the device's BitBlt function
  577. //
  578. iSolidBkColor = pboOpaque->iSolidColor;
  579. if ((iSolidBkColor == 0xFFFFFFFF) || // Background brush is pattern.
  580. (iSolidForeColor == 0xFFFFFFFF)) // Foreground brush is pattern.
  581. {
  582. //
  583. // Output the whole rectangle.
  584. //
  585. EngTextOutBitBlt(
  586. pSurf,
  587. pfo,
  588. fDrawFlags,
  589. (SURFOBJ *) NULL, // Source surface.
  590. (SURFOBJ *) NULL, // Mask surface.
  591. pco, // Clip object.
  592. NULL, // Palette translation object.
  593. prclOpaque, // Destination rectangle.
  594. (POINTL *) NULL, // Source origin.
  595. (POINTL *) NULL, // Mask origin.
  596. pboOpaque, // Realized opaque brush.
  597. pptlOrg, // brush origin
  598. 0x0000f0f0 // PATCOPY
  599. );
  600. }
  601. else
  602. {
  603. //
  604. // Compute the four fringe rectangles.
  605. //
  606. // According to the DDI, the opaque rectangle,
  607. // if given, always bounds the text to be drawn.
  608. //
  609. // (iClip == DC_RECT) added because display driver changes prclOpq
  610. // after intersecting the original prclOpq, rclBkGrnd and rclClip
  611. // iClip == DC_RECT if there is a clipping rectangle.
  612. //
  613. ASSERTGDI((iClip != DC_TRIVIAL) || ((ERECTL *) prclOpaque)->bContain(pstro->rclBkGround),
  614. "EngTextOut: opaque rectangle does not bound text background!");
  615. if (pstro->rclBkGround.top > prclOpaque->top)
  616. {
  617. fr.vAddRect(prclOpaque->left, prclOpaque->top,
  618. prclOpaque->right, pstro->rclBkGround.top);
  619. }
  620. if (pstro->rclBkGround.left > prclOpaque->left)
  621. {
  622. fr.vAddRect(prclOpaque->left, pstro->rclBkGround.top,
  623. pstro->rclBkGround.left, pstro->rclBkGround.bottom);
  624. }
  625. if (pstro->rclBkGround.right < prclOpaque->right)
  626. {
  627. fr.vAddRect(pstro->rclBkGround.right, pstro->rclBkGround.top,
  628. prclOpaque->right, pstro->rclBkGround.bottom);
  629. }
  630. if (pstro->rclBkGround.bottom < prclOpaque->bottom)
  631. {
  632. fr.vAddRect(prclOpaque->left, pstro->rclBkGround.bottom,
  633. prclOpaque->right, prclOpaque->bottom);
  634. }
  635. }
  636. }
  637. //
  638. // Draw the text into the temp buffer, and thence to the screen
  639. //
  640. //
  641. // IF (a device surface) THEN BEGIN
  642. // create a DIB;
  643. // IF (allocation was not successful) THEN return(FAILURE);
  644. // IF (transparent text) THEN
  645. // copy the surface bits to the DIB;
  646. // END
  647. //
  648. SURFMEM surfmem;
  649. DEVBITMAPINFO dbmi;
  650. if (fDrawFlags & ETO_DEVICE_SURFACE)
  651. {
  652. ASSERTGDI(fDrawFlags & ETO_GRAY,
  653. "Device surface but not antialiased text\n");
  654. // Rectangles of interest (in screen coordinates)
  655. //
  656. // 1. screen
  657. //
  658. // left_s = 0
  659. // top_s = 0
  660. // right_s = pso->sizlBitmap.cx
  661. // bottom_s = pso->sizlBitmap.cy
  662. //
  663. // 2. text
  664. //
  665. // left_t = prcl->left
  666. // top_t = prcl->top
  667. // right_t = prcl->right
  668. // bottom_t = prcl->bottom
  669. //
  670. // 3. buffer
  671. //
  672. // left_b = left_t & ~7
  673. // top_b = top_t
  674. // right_b = (right_t + 7) & ~7
  675. // bottom_b = bottom_t
  676. //
  677. // 4. dib
  678. //
  679. // left_d = left_b
  680. // top_d = top_b
  681. // right_d = right_t
  682. // bottom_d = bottom_t
  683. //
  684. // The intersection of the screen and dib rectangles
  685. // have screen coordinates
  686. //
  687. // 5. interesection of the screen and text rectangles
  688. // (screen coordinates)
  689. //
  690. // left_st = max(left_t, left_s )
  691. // top_st = max(top_t, top_s )
  692. // right_st = min(right_t, right_s )
  693. // bottom_st = min(bottom_t, bottom_s)
  694. //
  695. // 6. intersection of the screen and text coordinates
  696. // (DIB coordinates)
  697. //
  698. // left_st' = left_st - left_d
  699. // top_st' = top_st - top_d
  700. // right_st' = right_st - left_d
  701. // bottom_st' = bottom_st - top_d
  702. //
  703. // Make the DIB aligned with the buffer on the left
  704. // and aligned with the text on the right
  705. //
  706. // Actually, I could have been less aggressive in allocating
  707. // memory. There is actually no reason to allocate memory
  708. // that is larger than the screen. However, if I did that
  709. // I would have to watch for the end of the dib while I
  710. // processed the glyphs which would slow things down.
  711. //
  712. long left = pstro->rclBkGround.left & ~7; // left of DIB (screen coordinates)
  713. if (fDrawFlags & ETO_CLEARTYPE_X)
  714. left = pstro->rclBkGround.left & ~3;
  715. long top = pstro->rclBkGround.top; // top of DIB (screen coordinates)
  716. dbmi.iFormat = pSurf->iFormat();
  717. dbmi.cxBitmap = pstro->rclBkGround.right - left;
  718. dbmi.cyBitmap = pstro->rclBkGround.bottom - top;
  719. dbmi.hpal = 0;
  720. dbmi.fl = BMF_TOPDOWN;
  721. if (pSurf->bUMPD())
  722. dbmi.fl |= UMPD_SURFACE;
  723. if (!surfmem.bCreateDIB(&dbmi,0))
  724. {
  725. WARNING("EngTextOut: surfmem.bCreateDIB failed\n");
  726. if (bTempAlloc)
  727. {
  728. if (bKernelAlloc)
  729. VFREEMEM(pjTempBuffer);
  730. else
  731. EngFreeUserMem(pjTempBuffer);
  732. }
  733. return(FALSE);
  734. }
  735. pSurfDraw = surfmem.ps;
  736. //
  737. // Compute the source surface origin, taking into account multi-mon
  738. // and negative offsets:
  739. //
  740. LONG xOrigin = 0;
  741. LONG yOrigin = 0;
  742. PDEVOBJ pdoSrc(pSurf->hdev());
  743. ASSERTGDI(pdoSrc.bValid(),"Invalid pdoSrc I\n");
  744. if (pdoSrc.bPrimary(pSurf) && pdoSrc.bMetaDriver())
  745. {
  746. xOrigin = pdoSrc.pptlOrigin()->x;
  747. yOrigin = pdoSrc.pptlOrigin()->y;
  748. }
  749. //
  750. // rcScreen = screen & text intersection (screen coordinates)
  751. //
  752. rcDIB = pstro->rclBkGround;
  753. rcScreen.left = max(xOrigin, pstro->rclBkGround.left);
  754. rcScreen.top = max(yOrigin, pstro->rclBkGround.top );
  755. rcScreen.right = min(xOrigin + pso->sizlBitmap.cx, pstro->rclBkGround.right );
  756. rcScreen.bottom = min(yOrigin + pso->sizlBitmap.cy, pstro->rclBkGround.bottom);
  757. //
  758. // The DDI guarantees the driver that 'pco->rclBounds' is guaranteed
  759. // to intersect with 'prclDst' on a DrvCopyBits call. Later on, we
  760. // will use 'pco' and 'rcScreen' in a DrvCopyBits call, so check for
  761. // no drawing here:
  762. //
  763. if ((iClip != DC_TRIVIAL) && !bIntersect(&rcScreen, &pco->rclBounds))
  764. {
  765. if (bTempAlloc)
  766. {
  767. if (bKernelAlloc)
  768. VFREEMEM(pjTempBuffer);
  769. else
  770. EngFreeUserMem(pjTempBuffer);
  771. }
  772. return(TRUE);
  773. }
  774. //
  775. // rcDIB = screen & text intersection (DIB coordinates)
  776. //
  777. rcDIB = rcScreen;
  778. rcDIB.left -= left;
  779. rcDIB.top -= top;
  780. rcDIB.right -= left;
  781. rcDIB.bottom -= top;
  782. if (iSolidBkColor == (ULONG) -1)
  783. {
  784. //
  785. // background is transparent copy bits from surface to DIB
  786. //
  787. if (rcScreen.left < rcScreen.right && rcScreen.top < rcScreen.bottom)
  788. {
  789. (*PPFNGET(pdoSrc,CopyBits,pSurf->flags())) (
  790. surfmem.pSurfobj(),
  791. pSurf->pSurfobj(),
  792. 0,
  793. &xloIdent,
  794. &rcDIB,
  795. (POINTL*) &rcScreen);
  796. }
  797. }
  798. }
  799. //
  800. // Some drivers do banking meaning they will call EngTextOut multiple times
  801. // per TextOut call. Most of the time all the GLYPH positions in the STROBJ will
  802. // be valid meaning it doesn't matter that you call STROBJ_vEnumStart. But if
  803. // they aren't, it does matter. This is always true in the case of linked text out
  804. // calls.
  805. //
  806. STROBJ_vEnumStart(pstro);
  807. //
  808. // clear buffer for opaque mode
  809. //
  810. if (iSolidBkColor != -1L)
  811. RtlFillMemoryUlong((ULONG*) pjTempBuffer, ulBufferBytes, 0);
  812. do
  813. {
  814. //
  815. // Get the next batch of glyphs
  816. //
  817. //
  818. // clear buffer, transparent mode, we need to clean the buffer in the while loop to get the font linking
  819. // with antialiazing work right
  820. //
  821. if (iSolidBkColor == -1L)
  822. RtlFillMemoryUlong((ULONG*) pjTempBuffer, ulBufferBytes, 0);
  823. if (pstro->pgp != NULL)
  824. {
  825. //
  826. // There's only the one batch of glyphs, so save ourselves a call
  827. //
  828. pgp = pstro->pgp;
  829. cGlyph = pstro->cGlyphs;
  830. bMoreGlyphs = FALSE;
  831. }
  832. else
  833. {
  834. bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp);
  835. }
  836. //
  837. // No glyph, no work!
  838. //
  839. if (cGlyph)
  840. {
  841. arclTmp[0].left = LONG_MIN;
  842. arclTmp[0].top = LONG_MIN;
  843. arclTmp[0].right = LONG_MAX;
  844. arclTmp[0].bottom = LONG_MAX;
  845. arclTmp[1].bottom = 0;
  846. prclClip = &arclTmp[0];
  847. {
  848. switch (iClip)
  849. {
  850. case DC_RECT:
  851. arclTmp[0] = pco->rclBounds; // copy clip rect to arclTmp[0]
  852. arclTmp[1].bottom = 0; // make arclTmp[1] a null rect
  853. //
  854. // falling through !
  855. //
  856. case DC_TRIVIAL:
  857. vExpandAndCopyText(pSurf,
  858. pfo,
  859. pgp,
  860. cGlyph,
  861. (PBYTE)pjTempBuffer,
  862. ulBufferWidthInBytes,
  863. pstro->ulCharInc,
  864. pSurfDraw,
  865. pSurfDevice,
  866. &pstro->rclBkGround,
  867. prclOpaque,
  868. iSolidForeColor,
  869. iSolidBkColor,
  870. fDrawFlags,
  871. prclClip,
  872. prclExtra,
  873. Native64BitAccess,
  874. pboFore,
  875. pptlOrg);
  876. break;
  877. case DC_COMPLEX:
  878. prclClip = &txen.arcl[0];
  879. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  880. do
  881. {
  882. bMore = CLIPOBJ_bEnum(pco,
  883. (ULONG) (sizeof(txen) - sizeof(RECT)),
  884. (PULONG) &txen);
  885. txen.arcl[txen.c].bottom = 0; // terminate txen.arcl[]
  886. // with a null rect
  887. vExpandAndCopyText(pSurf,
  888. pfo,
  889. pgp,
  890. cGlyph,
  891. (PBYTE)pjTempBuffer,
  892. ulBufferWidthInBytes,
  893. pstro->ulCharInc,
  894. pSurfDraw,
  895. pSurfDevice,
  896. &pstro->rclBkGround,
  897. prclOpaque,
  898. iSolidForeColor,
  899. iSolidBkColor,
  900. fDrawFlags,
  901. prclClip,
  902. prclExtra,
  903. Native64BitAccess,
  904. pboFore,
  905. pptlOrg);
  906. } while (bMore);
  907. break;
  908. }
  909. }
  910. }
  911. } while (bMoreGlyphs);
  912. if (fDrawFlags & ETO_DEVICE_SURFACE)
  913. {
  914. PDEVOBJ pdoSrc(pSurf->hdev());
  915. ASSERTGDI(pdoSrc.bValid(), "Invalid pdoSrc II\n");
  916. (*PPFNGET(pdoSrc,CopyBits,pSurf->flags())) (
  917. pSurf->pSurfobj(),
  918. surfmem.pSurfobj(),
  919. pco,
  920. 0,
  921. &rcScreen,
  922. (POINTL*) &rcDIB);
  923. }
  924. //
  925. // Free up any memory we allocated for the temp buffer
  926. //
  927. if (bTempAlloc)
  928. {
  929. if (bKernelAlloc)
  930. VFREEMEM(pjTempBuffer);
  931. else
  932. EngFreeUserMem(pjTempBuffer);
  933. }
  934. return(TRUE);
  935. }
  936. //
  937. // lookup tables for character drawing and temp buffer expansion
  938. //
  939. #if !defined (_X86_)
  940. PVOID MastertextTypeTabel[] = {
  941. draw_nf_ntb_o_to_temp_start,
  942. draw_f_ntb_o_to_temp_start,
  943. draw_nf_ntb_o_to_temp_start,
  944. draw_f_ntb_o_to_temp_start,
  945. draw_nf_tb_no_to_temp_start,
  946. draw_f_tb_no_to_temp_start,
  947. draw_nf_ntb_o_to_temp_start,
  948. draw_f_ntb_o_to_temp_start,
  949. draw_gray_nf_ntb_o_to_temp_start,
  950. draw_gray_f_ntb_o_to_temp_start,
  951. draw_gray_nf_ntb_o_to_temp_start,
  952. draw_gray_f_ntb_o_to_temp_start,
  953. draw_gray_nf_ntb_o_to_temp_start,
  954. draw_gray_f_ntb_o_to_temp_start,
  955. draw_gray_nf_ntb_o_to_temp_start,
  956. draw_gray_f_ntb_o_to_temp_start
  957. };
  958. #endif
  959. //
  960. // MIPS has separate code for 8bpp destination depending
  961. // on whether the driver supports the GCAPS_64BITMEMACCESS flag.
  962. // This is because on some MIPS systems, 64 bit memory accesses
  963. // the video space are truncated to 32. These systems must use the
  964. // 32 bit version of 8 bpp output.
  965. //
  966. // SrcCopyTextFunctionTable is an array of 32 pointers to functions
  967. // takeing BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*
  968. // as arguments and returning a VOID.
  969. #if !defined (_MIPS_)
  970. VOID (*(SrcCopyTextFunctionTable[48]))
  971. (BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*) = {
  972. vSrcTranCopyError, // 0 opaque
  973. vSrcOpaqCopyS1D1, // 1
  974. vSrcOpaqCopyS1D4, // 2
  975. vSrcOpaqCopyS1D8, // 3
  976. vSrcOpaqCopyS1D16, // 4
  977. vSrcOpaqCopyS1D24, // 5
  978. vSrcOpaqCopyS1D32, // 6
  979. vSrcTranCopyError, // 7
  980. vSrcTranCopyError, // 8 transparent
  981. vSrcTranCopyS1D1, // 9
  982. vSrcTranCopyS1D4, // a
  983. vSrcTranCopyS1D8, // b
  984. vSrcTranCopyS1D16, // c
  985. vSrcTranCopyS1D24, // d
  986. vSrcTranCopyS1D32, // e
  987. vSrcTranCopyError, // f
  988. // gray pixels
  989. vSrcTranCopyError, // 10 opaque
  990. vSrcTranCopyError, // 11
  991. vSrcTranCopyError, // 12
  992. vSrcTranCopyError, // 13
  993. vSrcOpaqCopyS4D16, // 14
  994. vSrcOpaqCopyS4D24, // 15
  995. vSrcOpaqCopyS4D32, // 16
  996. vSrcTranCopyError, // 17
  997. vSrcTranCopyError, // 18 transparent
  998. vSrcTranCopyError, // 19
  999. vSrcTranCopyError, // 1a
  1000. vSrcTranCopyError, // 1b
  1001. vSrcTranCopyS4D16, // 1c
  1002. vSrcTranCopyS4D24, // 1d
  1003. vSrcTranCopyS4D32, // 1e
  1004. vSrcTranCopyError, // 1f
  1005. // CLEARTYPE_X
  1006. vSrcTranCopyError, // 20 opaque
  1007. vSrcTranCopyError, // 21
  1008. vSrcTranCopyError, // 22
  1009. vSrcTranCopyError, // 23
  1010. vSrcOpaqCopyS8D16, // 24
  1011. vSrcOpaqCopyS8D24, // 25
  1012. vSrcOpaqCopyS8D32, // 26
  1013. vSrcTranCopyError, // 27
  1014. vSrcTranCopyError, // 28 transparent
  1015. vSrcTranCopyError, // 29
  1016. vSrcTranCopyError, // 2a
  1017. vSrcTranCopyError, // 2b
  1018. vSrcTranCopyS8D16, // 24
  1019. vSrcTranCopyS8D24, // 25
  1020. vSrcTranCopyS8D32, // 26
  1021. vSrcTranCopyError, // 2f
  1022. };
  1023. #else
  1024. VOID (*(SrcCopyTextFunctionTable[48]))
  1025. (BYTE*,LONG,LONG,BYTE*,LONG,LONG,LONG,LONG,ULONG,ULONG,SURFACE*) = {
  1026. vSrcOpaqCopyS1D8, // 0 opaque
  1027. vSrcOpaqCopyS1D1, // 1
  1028. vSrcOpaqCopyS1D4, // 2
  1029. vSrcOpaqCopyS1D8_64, // 3
  1030. vSrcOpaqCopyS1D16, // 4
  1031. vSrcOpaqCopyS1D24, // 5
  1032. vSrcOpaqCopyS1D32, // 6
  1033. vSrcTranCopyError, // 7
  1034. vSrcTranCopyError, // 8 transparent
  1035. vSrcTranCopyS1D1, // 9
  1036. vSrcTranCopyS1D4, // a
  1037. vSrcTranCopyS1D8, // b
  1038. vSrcTranCopyS1D16, // c
  1039. vSrcTranCopyS1D24, // d
  1040. vSrcTranCopyS1D32, // e
  1041. vSrcTranCopyError, // f
  1042. // gray pixels
  1043. vSrcTranCopyError, // 10 opaque
  1044. vSrcTranCopyError, // 11
  1045. vSrcTranCopyError, // 12
  1046. vSrcTranCopyError, // 13
  1047. vSrcOpaqCopyS4D16, // 14
  1048. vSrcOpaqCopyS4D24, // 15
  1049. vSrcOpaqCopyS4D32, // 16
  1050. vSrcTranCopyError, // 17
  1051. vSrcTranCopyError, // 18 transparent
  1052. vSrcTranCopyError, // 19
  1053. vSrcTranCopyError, // 1a
  1054. vSrcTranCopyError, // 1b
  1055. vSrcTranCopyS4D16, // 1c
  1056. vSrcTranCopyS4D24, // 1d
  1057. vSrcTranCopyS4D32, // 1e
  1058. vSrcTranCopyError, // 1f
  1059. // CLEARTYPE_X
  1060. vSrcTranCopyError, // 20 opaque
  1061. vSrcTranCopyError, // 21
  1062. vSrcTranCopyError, // 22
  1063. vSrcTranCopyError, // 23
  1064. vSrcOpaqCopyS8D16, // 24
  1065. vSrcOpaqCopyS8D24, // 25
  1066. vSrcOpaqCopyS8D32, // 26
  1067. vSrcTranCopyError, // 27
  1068. vSrcTranCopyError, // 28 transparent
  1069. vSrcTranCopyError, // 29
  1070. vSrcTranCopyError, // 2a
  1071. vSrcTranCopyError, // 2b
  1072. vSrcTranCopyS8D16, // 2c
  1073. vSrcTranCopyS8D24, // 2d
  1074. vSrcTranCopyS8D32, // 2e
  1075. vSrcTranCopyError, // 2f
  1076. };
  1077. #endif
  1078. /******************************Public*Routine******************************\
  1079. *
  1080. * Routine Name
  1081. *
  1082. * vExpandAndCopyText
  1083. *
  1084. * Routine Description:
  1085. *
  1086. * Break down glyph drawing into several classes, based on
  1087. * pitch, alignment and overlap, and in this loop dispatch to
  1088. * highly specialized glyph drawing routines based on width
  1089. * and bit rotation.
  1090. *
  1091. * Arguments:
  1092. *
  1093. * pGlyphPos - Pointer to first in list of GLYPHPOS structs
  1094. * cGlyph - Number of glyphs to draw
  1095. * pjTempBuffer - temp 1BPP [4BPP] buffer to draw into
  1096. * ulBufferWidthInBytes - Delta for temp buffer
  1097. * ulCharInc - pstro->ulCharInc, increment for fixed pitch
  1098. * pSurf - surface obj, for drawing on actual surface
  1099. * pSurfDevice - surface object for original device
  1100. * (for antialiased text on devices that
  1101. * don't support antialiased text natively).
  1102. * prclText - bounding rectangle on dest surface
  1103. * prclOpaque - boundary of opaque rect
  1104. * iSolidForeColor - foreground color when drawing on dest surface
  1105. * iSolidBkColor - background color when drawing on dest surface
  1106. * fDrawFlags - special flags to allow for table lookup of routines
  1107. * prclClip - clipping rect
  1108. * prclExtra - extra rects to draw
  1109. * Native64BitAccess - can use 64 bit accesses
  1110. *
  1111. * Return Value:
  1112. *
  1113. * None
  1114. *
  1115. \**************************************************************************/
  1116. VOID vExpandAndCopyText(
  1117. SURFACE* pSurface,
  1118. FONTOBJ* pfo,
  1119. GLYPHPOS *pGlyphPos,
  1120. ULONG cGlyph,
  1121. BYTE *pjTempBuffer,
  1122. ULONG ulBufferWidthInBytes,
  1123. ULONG ulCharInc,
  1124. SURFACE *pSurf,
  1125. SURFACE *pSurfDevice,
  1126. RECTL *prclText,
  1127. RECTL *prclOpaque,
  1128. INT iSolidForeColor,
  1129. INT iSolidBkColor,
  1130. ULONG fDrawFlags,
  1131. RECTL *prclClip,
  1132. RECTL *prclExtra,
  1133. ULONG Native64BitAccess,
  1134. BRUSHOBJ *pboFore,
  1135. POINTL *pptlOrg
  1136. )
  1137. {
  1138. PFN_MASTERTEXTTYPE pfnMasterType;
  1139. BLTINFO SrcCopyBltInfo;
  1140. PFN_TEXTSRCCPY pfnTextSrcCopy;
  1141. EXLATEOBJ exlo;
  1142. XLATE *pxlo = NULL;
  1143. RECTL *pCurrentRect;
  1144. ULONG BufferAlign;
  1145. ULONG BufferOffset;
  1146. ULONG ulSrcCopyFlag;
  1147. ULONG ulTempTop;
  1148. #if DBG
  1149. /**/void vDumpGrayBuffer(BYTE *, ULONG, RECTL*);
  1150. #endif
  1151. GLYPHPOS *pGPosTmp = pGlyphPos;
  1152. //
  1153. // pGlyphPos->pgdf->pgb must not be NULL.
  1154. // But if there is printer a driver bug and GetGlyphMode() returns FO_HGLYPHS
  1155. // instead of FO_GLYPHBITS, then it can be NULL and crash system.
  1156. // To protect from this situation, vExpandAndCopyText() just return without copying
  1157. // in this case.
  1158. //
  1159. for(ULONG i=0; i<cGlyph; i++, pGPosTmp++){
  1160. if(pGPosTmp->pgdf->pgb == NULL){
  1161. WARNING("pGlyphPos->pgdf->pgb is NULL. Possibly GetGlyphMode() bug of Printer Driver\n");
  1162. return;
  1163. }
  1164. }
  1165. //
  1166. // XP bug #352368
  1167. // Due to bad design of LTOFX and FXToL, overflow will alway happen when >0x7ffffff or <0xf8000000
  1168. // At worst case, there can be big jump in the middle among the returned long values and will cause AV in vFastText
  1169. // To avoid this, if the difference of pGlyphPos between the first char and last char is too big
  1170. // We reject it.
  1171. //
  1172. if( !(fDrawFlags & 1) && cGlyph > 1){
  1173. pGPosTmp=pGlyphPos+(cGlyph-1);
  1174. if((pGlyphPos->ptl.x - pGPosTmp->ptl.x) > 0x8000000 || (pGlyphPos->ptl.x - pGPosTmp->ptl.x) < -0x8000000 ){
  1175. WARNING("Big jump among pGlyphPos.ptl.x. Mustbe LToFx overflow");
  1176. return;
  1177. }
  1178. }
  1179. // UMPD NtGdiEngTextOut holding RFONT cache semaphore.
  1180. // vExpandAndCopyText might call back into user mode.
  1181. BOOL bSem = FALSE;
  1182. ULONG fl = 0, numLinks = 0;
  1183. BOOL aFaceLink[UMPD_MAX_FONTFACELINK], *pFaceLink = aFaceLink;
  1184. //
  1185. // Release rfont semaphores, otherwise holding rfont semaphores can
  1186. // disable APC queue while calling to the user mode.
  1187. //
  1188. //
  1189. // WINBUG #214225 tessiew 10-27-2000 Blackcomb: re-visit the RFONT.hsemCache acquiring/releasing issue
  1190. // Need to revisit the font semaphore problem in Blackcomb
  1191. // It seems that a thread doesn't need to hold the font caching semaphore
  1192. // during the whole GreExtTextOutWLocked call.
  1193. //
  1194. PDEVOBJ po(pSurface->hdev());
  1195. RFONTTMPOBJ rfo(PFO_TO_PRF(pfo));
  1196. if (po.bValid() && po.bPrinter() && po.bUMPD() && rfo.bValid())
  1197. {
  1198. bSem = UMPDReleaseRFONTSem(rfo, NULL, &fl, &numLinks, &pFaceLink);
  1199. }
  1200. //
  1201. // save global params
  1202. //
  1203. ulTempTop = prclText->top;
  1204. //
  1205. // DWORD Align temp buffer to DST.
  1206. //
  1207. // For 1Bpp addresses, left[31:05] = DWORD Address
  1208. // left[04:03] = Byte in DWORD
  1209. // left[02:00] = Pixel in Byte
  1210. //
  1211. // To optimize 1bpp drawing, both buffers must be DWORD aligned,
  1212. // this makes the temp buffer starting point is left[04:00].
  1213. //
  1214. // This means that the glyph offset in the temporary buffer is xPos - left[31:05]
  1215. //
  1216. //
  1217. // BufferOffset = x-position of nearest pixel to the left of the text rectangle
  1218. // whose address is on a 32-bit boundary in the glyph source
  1219. // which is either monchrome (1bpp) or gray (4bpp). This
  1220. // is also the position of the first pixel position on
  1221. // a temporary DIB buffer provided for anti-aliased text
  1222. // simulation.
  1223. //
  1224. // BufferAlign = number of pixels the left portion of the text is
  1225. // offset to the right from BufferOffset
  1226. //
  1227. // prclText = BufferOffset + BufferAlign
  1228. //
  1229. // monochrome text
  1230. //
  1231. // BufferOffset = prclText->left & ~31
  1232. // BufferAlign = prclText->left & 31
  1233. //
  1234. // gray (4bpp) text
  1235. //
  1236. // BufferOffset = prclText->left & ~7
  1237. // BufferAlign = prclText->left & 7
  1238. //
  1239. // clear type 8bpp text
  1240. //
  1241. // BufferOffset = prclText->left & ~3
  1242. // BufferAlign = prclText->left & 3
  1243. //
  1244. #if DBG
  1245. if (gflFontDebug & DEBUG_AA)
  1246. {
  1247. if (fDrawFlags & ETO_GRAY)
  1248. {
  1249. GLYPHPOS *pgp, *pgpBad;
  1250. DbgPrint(
  1251. "vExpandAndCopyText(\n"
  1252. " GLYPHPOS *pGlyphPos = %-#x\n"
  1253. " ULONG cGlyph = %u\n"
  1254. " BYTE *pjTempBuffer = %-#x\n"
  1255. " ULONG ulBufferWidthInBytes = %u\n"
  1256. " ULONG ulCharInc = %u\n"
  1257. " SURFACE *pSurf = %-#x\n"
  1258. " SURFACE *pSurfDevice = %-#x\n"
  1259. , pGlyphPos
  1260. , cGlyph
  1261. , pjTempBuffer
  1262. , ulBufferWidthInBytes
  1263. , ulCharInc
  1264. , pSurf
  1265. , pSurfDevice
  1266. );
  1267. DbgPrint(
  1268. " RECTL *prclText = %-#x\n"
  1269. " RECTL *prclOpaque = %-#x\n"
  1270. " INT iSolidForeColor = %-#x\n"
  1271. " INT iSolidBkColor = %-#x\n"
  1272. , prclText
  1273. , prclOpaque
  1274. , iSolidForeColor
  1275. , iSolidBkColor
  1276. );
  1277. DbgPrint(
  1278. " RECTL *prclClip = %-#x\n"
  1279. " RECTL *prclExtra = %-#x\n"
  1280. " ULONG Native64BitAccess = %-#x\n"
  1281. , prclClip
  1282. , prclExtra
  1283. , Native64BitAccess
  1284. );
  1285. DbgPrint(
  1286. " ULONG fDrawFlags = %-#x\n"
  1287. , fDrawFlags
  1288. );
  1289. if (fDrawFlags & 1)
  1290. {
  1291. DbgPrint("\t\t\t\t\tETO_FIXED_PITCH\n");
  1292. }
  1293. if (fDrawFlags & 2)
  1294. {
  1295. DbgPrint(
  1296. "\t\t\t\t\tETO_NOT_DEFAULT\n"
  1297. );
  1298. }
  1299. if (fDrawFlags & ETO_GRAY)
  1300. {
  1301. DbgPrint("\t\t\t\t\tETO_GRAY\n");
  1302. }
  1303. if (fDrawFlags & ETO_DEVICE_SURFACE)
  1304. {
  1305. DbgPrint("\t\t\t\t\tETO_DEVICE_SURFACE\n");
  1306. }
  1307. DbgPrint(")\n");
  1308. DbgPrint("---\n");
  1309. pSurf->vDump();
  1310. if (pSurfDevice)
  1311. pSurfDevice->vDump();
  1312. DbgBreakPoint();
  1313. }
  1314. }
  1315. #endif
  1316. //
  1317. // pSurfDevice is an argument given to the SrcTextCopy function
  1318. // It must be non-zero in order to get information about the
  1319. // device palette
  1320. //
  1321. if (!pSurfDevice)
  1322. {
  1323. pSurfDevice = pSurf;
  1324. }
  1325. // This is a wasted calculation for the case of a device surface
  1326. // but what the heck, a branch costs too
  1327. BufferAlign = prclText->left & ((fDrawFlags & ETO_GRAY) ? ((fDrawFlags & ETO_CLEARTYPE_X) ? 3 : 7) : 31);
  1328. BufferOffset = prclText->left - BufferAlign;
  1329. if(!(fDrawFlags & ETO_CLEARTYPE_X))
  1330. {
  1331. #if !defined (_X86_)
  1332. //
  1333. // select and jump to appropriate glyph dispatch
  1334. // routine
  1335. //
  1336. pfnMasterType =
  1337. (PFN_MASTERTEXTTYPE)MastertextTypeTabel[
  1338. fDrawFlags & ~(ETO_DEVICE_SURFACE | ETO_CLEARTYPE_X)
  1339. ];
  1340. pfnMasterType(
  1341. pGlyphPos
  1342. , cGlyph
  1343. , pjTempBuffer
  1344. , BufferOffset
  1345. , ulBufferWidthInBytes
  1346. , ulCharInc
  1347. , ulTempTop
  1348. );
  1349. #else
  1350. //
  1351. // call x86 version for glyph copy
  1352. //
  1353. vFastText(
  1354. pGlyphPos,
  1355. cGlyph,
  1356. pjTempBuffer + ((prclText->left >> 3) & 3),
  1357. ulBufferWidthInBytes,
  1358. ulCharInc,
  1359. pSurf->pSurfobj(),
  1360. prclText,
  1361. prclOpaque,
  1362. iSolidForeColor,
  1363. iSolidBkColor,
  1364. fDrawFlags & ~(ETO_DEVICE_SURFACE | ETO_CLEARTYPE_X),
  1365. prclClip,
  1366. prclExtra
  1367. );
  1368. #endif
  1369. }
  1370. else // cleartype
  1371. {
  1372. PVOID MastertextClearTypeTable[] = {
  1373. draw_clrt_nf_ntb_o_to_temp_start,
  1374. draw_clrt_f_ntb_o_to_temp_start,
  1375. };
  1376. pfnMasterType =
  1377. (PFN_MASTERTEXTTYPE)MastertextClearTypeTable[fDrawFlags & 1];
  1378. pfnMasterType(
  1379. pGlyphPos
  1380. , cGlyph
  1381. , pjTempBuffer
  1382. , BufferOffset
  1383. , ulBufferWidthInBytes
  1384. , ulCharInc
  1385. , ulTempTop
  1386. );
  1387. }
  1388. //
  1389. // draw extra rects (if any)
  1390. //
  1391. if (prclExtra != (PRECTL) NULL)
  1392. {
  1393. //
  1394. // intersect extra rects with temp buffer, draw any
  1395. // that intersect
  1396. //
  1397. VOID (*pfn)(PBYTE, ULONG, LONG, LONG, LONG, LONG);
  1398. pfn = (fDrawFlags & ETO_GRAY) ? ((fDrawFlags & ETO_CLEARTYPE_X) ? vRectBlt8 : vRectBlt4) : vRectBlt;
  1399. while (prclExtra->left != prclExtra->right) {
  1400. LONG xleft, xright, ytop, ybottom;
  1401. xleft = max(prclExtra->left, prclText->left) - BufferOffset;
  1402. xright = min(prclExtra->right, prclText->right) - BufferOffset;
  1403. ytop = max(prclExtra->top, prclText->top) - prclText->top;
  1404. ybottom = min(prclExtra->bottom, prclText->bottom) - prclText->top;
  1405. //
  1406. // Render the clipped 'extra' rectangle into the mono dib.
  1407. //
  1408. if (xleft < xright && ytop < ybottom) {
  1409. (*pfn)(pjTempBuffer,ulBufferWidthInBytes, xleft, ytop, xright, ybottom);
  1410. }
  1411. prclExtra++;
  1412. }
  1413. }
  1414. //
  1415. // draw/expand 1bpp temp buffer onto target surface
  1416. //
  1417. ASSERTGDI(pSurf->iFormat() > 0,"Error in DIB format");
  1418. ASSERTGDI(pSurf->iFormat() <= BMF_32BPP,"Error in DIB format");
  1419. ULONG iFormat = pSurf->iFormat();
  1420. #if defined (_MIPS_)
  1421. //
  1422. // special check for MIPS 64 bit opaque,
  1423. // set format to 0 (use 32 bit opaque routine)
  1424. //
  1425. if
  1426. (
  1427. (iFormat == BMF_8BPP) &&
  1428. (!Native64BitAccess) &&
  1429. (iSolidBkColor != 0xFFFFFFFF)
  1430. )
  1431. {
  1432. iFormat = 0;
  1433. }
  1434. #endif
  1435. //
  1436. // Get a pointer to the appropriate function
  1437. //
  1438. {
  1439. int i = iFormat;
  1440. ASSERTGDI(i < 8, "bad index");
  1441. if (iSolidBkColor == -1L)
  1442. {
  1443. i += 8; // transparent background
  1444. }
  1445. if (ETO_GRAY & fDrawFlags)
  1446. {
  1447. i += 16; // anti-aliased text
  1448. if (ETO_CLEARTYPE_X & fDrawFlags)
  1449. i += 16;
  1450. }
  1451. pfnTextSrcCopy = SrcCopyTextFunctionTable[i];
  1452. }
  1453. //
  1454. // blt each clip rectangle
  1455. //
  1456. for (pCurrentRect=prclClip; pCurrentRect->bottom; pCurrentRect++)
  1457. {
  1458. LONG Left = max(prclText->left , pCurrentRect->left );
  1459. LONG Right = min(prclText->right , pCurrentRect->right );
  1460. LONG Top = max(prclText->top , pCurrentRect->top );
  1461. LONG Bottom = min(prclText->bottom, pCurrentRect->bottom);
  1462. ULONG dX = (ULONG) (Left - prclText->left);
  1463. ULONG dY = (ULONG) (Top - prclText->top );
  1464. if (fDrawFlags & ETO_DEVICE_SURFACE)
  1465. {
  1466. // Left = position of first pixel relative to the left
  1467. // hand edge of the temporary 4bpp buffer
  1468. Left -= BufferOffset;
  1469. Right -= BufferOffset;
  1470. Top -= prclText->top;
  1471. Bottom -= prclText->top;
  1472. #if DBG
  1473. if (gflFontDebug & DEBUG_AA)
  1474. {
  1475. DbgPrint(
  1476. "*pCurrentRect = 0x%lx 0x%lx 0x%lx 0x%lx\n"
  1477. "*prclText = 0x%lx 0x%lx 0x%lx 0x%lx\n"
  1478. " intersection = 0x%lx 0x%lx 0x%lx 0x%lx\n"
  1479. " BuffOffset BuffAlign = 0x%lx 0x%lx \n"
  1480. " dX dY = 0x%lx 0x%lx \n"
  1481. , pCurrentRect->left
  1482. , pCurrentRect->top
  1483. , pCurrentRect->right
  1484. , pCurrentRect->bottom
  1485. , prclText->left
  1486. , prclText->top
  1487. , prclText->right
  1488. , prclText->bottom
  1489. , Left
  1490. , Top
  1491. , Right
  1492. , Bottom
  1493. , BufferOffset, BufferAlign
  1494. , dX,dY
  1495. );
  1496. }
  1497. #endif
  1498. }
  1499. else
  1500. {
  1501. //
  1502. // Synchronize with the driver
  1503. //
  1504. PDEVOBJ poSurf(pSurf->hdev());
  1505. poSurf.vSync(pSurf->pSurfobj(), NULL, 0);
  1506. }
  1507. if ((Left < Right) && (Top < Bottom))
  1508. {
  1509. if (iSolidForeColor == 0xffffffff)
  1510. {
  1511. //
  1512. // Our (*pfnTextSrcCopy) routines can only expand solid
  1513. // colors, so if the foreground color is a dither we fall
  1514. // back to our slower MaskBlt support. We set the mask
  1515. // to the monochrome text bitmap and do a masked PatBlt
  1516. // using the dithered brush.
  1517. //
  1518. // Note that we've already laid down the opaquing rectangle,
  1519. // so this is now effectively a "transparent" textout
  1520. // operation.
  1521. //
  1522. ASSERTGDI(!(fDrawFlags & ETO_GRAY),
  1523. "Can't do dithered anti-aliased text");
  1524. RECTL rclDst;
  1525. SURFACE surfMask;
  1526. POINTL ptlMask;
  1527. rclDst.left = Left;
  1528. rclDst.top = Top;
  1529. rclDst.right = Right;
  1530. rclDst.bottom = Bottom;
  1531. surfMask.iFormat(BMF_1BPP);
  1532. surfMask.iType(STYPE_BITMAP);
  1533. surfMask.pvScan0(pjTempBuffer);
  1534. surfMask.lDelta(ulBufferWidthInBytes);
  1535. surfMask.sizl().cx = 8 * ulBufferWidthInBytes;
  1536. surfMask.sizl().cy = prclText->bottom - prclText->top;
  1537. ptlMask.x = dX + BufferAlign;
  1538. ptlMask.y = dY;
  1539. BltLnk(pSurf,
  1540. NULL,
  1541. &surfMask,
  1542. NULL,
  1543. NULL,
  1544. &rclDst,
  1545. NULL,
  1546. &ptlMask,
  1547. pboFore,
  1548. pptlOrg,
  1549. 0xaaf0);
  1550. }
  1551. else
  1552. {
  1553. // The brush is a solid color, so use our optimized monochrome
  1554. // solid color expansion routines.
  1555. __try
  1556. {
  1557. PBYTE pjSrc = (PBYTE)pjTempBuffer
  1558. + dY * ulBufferWidthInBytes;
  1559. PBYTE pjDst = (PBYTE)pSurf->pvScan0()
  1560. + Top * pSurf->lDelta();
  1561. (*pfnTextSrcCopy)(
  1562. pjSrc,
  1563. BufferAlign + dX,
  1564. ulBufferWidthInBytes,
  1565. pjDst,
  1566. Left,
  1567. Right,
  1568. pSurf->lDelta(),
  1569. Bottom - Top,
  1570. iSolidForeColor,
  1571. iSolidBkColor,
  1572. pSurfDevice
  1573. );
  1574. }
  1575. __except(EXCEPTION_EXECUTE_HANDLER)
  1576. {
  1577. WARNING("pfnTextSrcCopy: exception raised!!!");
  1578. }
  1579. }
  1580. }
  1581. }
  1582. // acquire the font semaphore(s)
  1583. if (bSem)
  1584. {
  1585. UMPDAcquireRFONTSem(rfo, NULL, fl, numLinks, pFaceLink);
  1586. if (pFaceLink && pFaceLink != aFaceLink)
  1587. {
  1588. VFREEMEM(pFaceLink);
  1589. }
  1590. }
  1591. }
  1592. /******************************Public*Routine******************************\
  1593. *
  1594. * Routine Name
  1595. *
  1596. * vSrcTranCopyS1D1
  1597. *
  1598. * Routine Description:
  1599. *
  1600. * Transparent blt of 1BPP src to all destination format
  1601. * src bits that are "1" are copied to the dest as foreground color,
  1602. * src bits that are "0" are not copied
  1603. *
  1604. * Arguments:
  1605. *
  1606. * pjSrcIn - pointer to beginning of current scan line of src buffer
  1607. * SrcLeft - left (starting) pixel in src rectangle
  1608. * DeltaSrcIn - bytes from one src scan line to next
  1609. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  1610. * DstLeft - left(first) dst pixel
  1611. * DstRight - right(last) dst pixel
  1612. * DeltaDstIn - bytes from one Dst scan line to next
  1613. * cy - number of scan lines
  1614. * uF - Foreground color
  1615. * uB - Background color
  1616. * pSurf - not used
  1617. *
  1618. * Return Value:
  1619. *
  1620. * None
  1621. *
  1622. \**************************************************************************/
  1623. #if !defined (_X86_)
  1624. VOID
  1625. vSrcTranCopyS1D1(
  1626. PBYTE pjSrcIn,
  1627. LONG SrcLeft,
  1628. LONG DeltaSrcIn,
  1629. PBYTE pjDstIn,
  1630. LONG DstLeft,
  1631. LONG DstRight,
  1632. LONG DeltaDstIn,
  1633. LONG cy,
  1634. ULONG uF,
  1635. ULONG uB,
  1636. SURFACE *pSurf
  1637. )
  1638. {
  1639. //
  1640. // DWORD version
  1641. //
  1642. // if uF == 1 then Dst |= Src
  1643. //
  1644. // if uF == 0 then Dst &= ~Src
  1645. //
  1646. //
  1647. LONG cx = DstRight - DstLeft;
  1648. LONG lStartCase = SrcLeft;
  1649. LONG lEndCase = SrcLeft + cx;
  1650. ULONG uStartMask = (ULONG)~0;
  1651. ULONG uEndMask = (ULONG)~0;
  1652. LONG lEndOffset;
  1653. LONG lSrcStride = DeltaSrcIn;
  1654. LONG lDstStride = DeltaDstIn;
  1655. PBYTE pjSrc;
  1656. PBYTE pjDst;
  1657. PBYTE pjSrcEnd;
  1658. PBYTE pjSrcEndY;
  1659. lStartCase = lStartCase & 0x1F;
  1660. lEndCase = lEndCase & 0x1F;
  1661. //
  1662. // big endian masks
  1663. //
  1664. if (lStartCase) {
  1665. uStartMask >>= lStartCase;
  1666. //
  1667. // convert to little
  1668. // // 0 1 2 3
  1669. ULONG u0 = uStartMask << 24; // 3 - - -
  1670. ULONG u1 = uStartMask >> 24; // - - - 0
  1671. ULONG u2 = (uStartMask >> 8) & 0xFF00; // - - 1 -
  1672. uStartMask = (uStartMask & 0xFF00) << 8; // - 2 - -
  1673. uStartMask |= u0 | u1 | u2;
  1674. }
  1675. if (lEndCase) {
  1676. uEndMask <<= (32 - lEndCase);
  1677. //
  1678. // convert to little
  1679. // // 0 1 2 3
  1680. ULONG u0 = uEndMask << 24; // 3 - - -
  1681. ULONG u1 = uEndMask >> 24; // - - - 0
  1682. ULONG u2 = (uEndMask >> 8) & 0xFF00; // - - 1 -
  1683. uEndMask = (uEndMask & 0xFF00) << 8; // - 2 - -
  1684. uEndMask |= u0 | u1 | u2;
  1685. }
  1686. //
  1687. // calc starting and ending addresses (DWORD aligned)
  1688. //
  1689. pjDst = pjDstIn + ((DstLeft >> 5) << 2);
  1690. pjSrc = pjSrcIn + ((SrcLeft >> 5) << 2);
  1691. pjSrcEnd = pjSrcIn + (((SrcLeft+cx) >> 5) << 2);
  1692. // Sundown safe truncation
  1693. lEndOffset = (ULONG)((ULONG_PTR)pjSrcEnd - (ULONG_PTR)pjSrc);
  1694. pjSrcEndY = pjSrc + cy * lSrcStride;
  1695. if (uF) {
  1696. if (pjSrc != pjSrcEnd) {
  1697. //
  1698. // start and stop are not in same byte
  1699. //
  1700. lDstStride -= lEndOffset;
  1701. lSrcStride -= lEndOffset;
  1702. do {
  1703. pjSrcEnd = pjSrc + lEndOffset;
  1704. if (lStartCase) {
  1705. *(PULONG)pjDst |= *(PULONG)pjSrc & uStartMask;
  1706. pjDst+=4;
  1707. pjSrc+=4;
  1708. }
  1709. while (pjSrc != pjSrcEnd) {
  1710. *(PULONG)pjDst |= *(PULONG)pjSrc;
  1711. pjSrc +=4;
  1712. pjDst +=4;
  1713. }
  1714. if (lEndCase) {
  1715. *(PULONG)pjDst |= *(PULONG)pjSrc & uEndMask;
  1716. }
  1717. pjSrc += lSrcStride;
  1718. pjDst += lDstStride;
  1719. } while (pjSrc != pjSrcEndY);
  1720. } else {
  1721. //
  1722. // start and stop are in same byte
  1723. //
  1724. uStartMask &= uEndMask;
  1725. do {
  1726. *(PULONG)pjDst |= *(PULONG)pjSrc & uStartMask;
  1727. pjSrc += lSrcStride;
  1728. pjDst += lDstStride;
  1729. } while (pjSrc != pjSrcEndY);
  1730. }
  1731. } else {
  1732. //
  1733. // uF == 0, Dst &= ~Src
  1734. //
  1735. if (pjSrc != pjSrcEnd) {
  1736. //
  1737. // start and stop are not in same byte
  1738. //
  1739. lDstStride -= lEndOffset;
  1740. lSrcStride -= lEndOffset;
  1741. do {
  1742. pjSrcEnd = pjSrc + lEndOffset;
  1743. if (lStartCase) {
  1744. *(PULONG)pjDst &= ~(*(PULONG)pjSrc & uStartMask);
  1745. pjDst+=4;
  1746. pjSrc+=4;
  1747. }
  1748. while (pjSrc != pjSrcEnd) {
  1749. *(PULONG)pjDst &= ~(*(PULONG)pjSrc);
  1750. pjSrc +=4;
  1751. pjDst +=4;
  1752. }
  1753. if (lEndCase) {
  1754. *(PULONG)pjDst &= ~(*(PULONG)pjSrc & uEndMask);
  1755. }
  1756. pjSrc += lSrcStride;
  1757. pjDst += lDstStride;
  1758. } while (pjSrc != pjSrcEndY);
  1759. } else {
  1760. //
  1761. // start and stop are in same byte
  1762. //
  1763. uStartMask &= uEndMask;
  1764. do {
  1765. *(PULONG)pjDst &= ~(*(PULONG)pjSrc & uStartMask);
  1766. pjSrc += lSrcStride;
  1767. pjDst += lDstStride;
  1768. } while (pjSrc != pjSrcEndY);
  1769. }
  1770. }
  1771. }
  1772. #endif
  1773. /******************************Public*Routine******************************\
  1774. *
  1775. * Routine Name
  1776. *
  1777. * vSrcTranCopyS1D4
  1778. *
  1779. * Routine Description:
  1780. *
  1781. * Transparent blt of 1BPP src to all destination format
  1782. * src bits that are "1" are copied to the dest as foreground color,
  1783. * src bits that are "0" are not copied
  1784. *
  1785. * Arguments:
  1786. *
  1787. * pjSrcIn - pointer to beginning of current scan line of src buffer
  1788. * SrcLeft - left (starting) pixel in src rectangle
  1789. * DeltaSrcIn - bytes from one src scan line to next
  1790. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  1791. * DstLeft - left(first) dst pixel
  1792. * DstRight - right(last) dst pixel
  1793. * DeltaDstIn - bytes from one Dst scan line to next
  1794. * cy - number of scan lines
  1795. * uF - Foreground color
  1796. * uB - Background color
  1797. *
  1798. * Return Value:
  1799. *
  1800. * None
  1801. *
  1802. \**************************************************************************/
  1803. VOID vSrcTranCopyS1D4(
  1804. PBYTE pjSrcIn,
  1805. LONG SrcLeft,
  1806. LONG DeltaSrcIn,
  1807. PBYTE pjDstIn,
  1808. LONG DstLeft,
  1809. LONG DstRight,
  1810. LONG DeltaDstIn,
  1811. LONG cy,
  1812. ULONG uF,
  1813. ULONG uB,
  1814. SURFACE *pSurf
  1815. )
  1816. {
  1817. //
  1818. // Warning, noot optimized. It is not expected that 4 bit text
  1819. // will be handled by the negine
  1820. //
  1821. LONG cx = DstRight - DstLeft;
  1822. BYTE jF = (BYTE)uF;
  1823. BYTE jB = (BYTE)uB;
  1824. BYTE TextExpMask[4] = {0x00,0x0f,0xf0,0xff};
  1825. //
  1826. // build byte of replicate foreground
  1827. //
  1828. BYTE Accum = jF | (jF << 4);
  1829. LONG SrcRight = SrcLeft + cx;
  1830. LONG lStartCase = SrcLeft & 0x07;
  1831. LONG lEndCase = SrcRight & 0x07;
  1832. PBYTE pjSrc = pjSrcIn + ((SrcLeft + 7) >> 3);
  1833. PBYTE pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  1834. PBYTE pjSrcEnd;
  1835. LONG lSrcStartOffset = (8 - lStartCase);
  1836. LONG lSrcStride;
  1837. PBYTE pjDst;
  1838. BYTE jSrc;
  1839. BYTE Mask;
  1840. if (lStartCase == 0) {
  1841. lSrcStartOffset = 0;
  1842. }
  1843. cx = cx - lSrcStartOffset - (SrcRight & 0x07);
  1844. if (cx > 0) {
  1845. LONG lDstStride = DeltaDstIn - (cx >> 1);
  1846. lSrcStride = DeltaSrcIn - (cx >> 3);
  1847. pjDst = pjDstIn + ((DstLeft + lSrcStartOffset) >> 1);
  1848. do {
  1849. pjSrcEnd = pjSrc + (cx >> 3);
  1850. //
  1851. // aligned middle
  1852. //
  1853. do {
  1854. jSrc = *pjSrc;
  1855. Mask = TextExpMask[(jSrc & 0xC0) >> 6];
  1856. *pjDst = (*pjDst & ~Mask ) | (Accum & Mask);
  1857. Mask = TextExpMask[(jSrc & 0x30) >> 4];
  1858. *(pjDst+1) = (*(pjDst+1) & ~Mask ) | (Accum & Mask);
  1859. Mask = TextExpMask[(jSrc & 0x0C) >> 2];
  1860. *(pjDst+2) = (*(pjDst+2) & ~Mask ) | (Accum & Mask);
  1861. Mask = TextExpMask[(jSrc & 0x03) ];
  1862. *(pjDst+3) = (*(pjDst+3) & ~Mask ) | (Accum & Mask);
  1863. pjDst += 4;
  1864. pjSrc ++;
  1865. } while (pjSrc != pjSrcEnd);
  1866. pjDst += lDstStride;
  1867. pjSrc += lSrcStride;
  1868. } while (pjSrc != pjSrcEndY);
  1869. }
  1870. //
  1871. // start case
  1872. //
  1873. if (lStartCase) {
  1874. //
  1875. // check for start and stop in same src byte
  1876. //
  1877. BOOL bSameByte = ((SrcLeft) & ~0x07) == ((SrcRight) & ~0x07);
  1878. if (bSameByte) {
  1879. //
  1880. // start and stop in same src byte
  1881. //
  1882. PBYTE pjDstEnd2;
  1883. PBYTE pjDstScan = pjDstIn + ((DstLeft >> 1));
  1884. LONG lTextWidth = lEndCase - lStartCase;
  1885. //
  1886. // check for bad width
  1887. //
  1888. if (lTextWidth <= 0) {
  1889. return;
  1890. }
  1891. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1892. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  1893. do {
  1894. pjDst = pjDstScan;
  1895. jSrc = *pjSrc << lStartCase;
  1896. LONG ix = lTextWidth;
  1897. //
  1898. // partial nibble on left edge
  1899. //
  1900. if (lStartCase & 0x01) {
  1901. if (jSrc & 0x80) {
  1902. *pjDst = (*pjDst & 0xF0) | (Accum & 0x0F);
  1903. }
  1904. jSrc <<= 1;
  1905. pjDst++;
  1906. ix--;
  1907. }
  1908. //
  1909. // bytes
  1910. //
  1911. while (ix >= 2) {
  1912. Mask = TextExpMask[(jSrc & 0xc0) >> 6];
  1913. *(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask);
  1914. jSrc<<=2;
  1915. ix -= 2;
  1916. pjDst++;
  1917. }
  1918. //
  1919. // last nibble on right edge
  1920. //
  1921. if (ix & 0x01) {
  1922. if (jSrc & 0x80) {
  1923. *pjDst = (*pjDst & 0x0F) | (Accum & 0xF0);
  1924. }
  1925. }
  1926. pjSrc += DeltaSrcIn;
  1927. pjDstScan += DeltaDstIn;
  1928. } while (pjSrc != pjSrcEndY);
  1929. //
  1930. // make sure end case doesn't run
  1931. //
  1932. lEndCase = 0;
  1933. } else {
  1934. //
  1935. // start case
  1936. //
  1937. pjSrc = pjSrcIn + (SrcLeft >> 3);
  1938. pjDst = pjDstIn + ((DstLeft >> 1));
  1939. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  1940. LONG lDstStride = DeltaDstIn - ((9 - lStartCase) >> 1);
  1941. do {
  1942. jSrc = *pjSrc << lStartCase;
  1943. LONG ix = 8 - lStartCase;
  1944. //
  1945. // partial
  1946. //
  1947. if (ix & 0x01) {
  1948. if (jSrc & 0x80) {
  1949. *pjDst = (*pjDst & 0xF0) | (Accum & 0x0F);
  1950. }
  1951. jSrc <<= 1;
  1952. pjDst++;
  1953. ix--;
  1954. }
  1955. //
  1956. // bytes
  1957. //
  1958. while (ix != 0) {
  1959. Mask = TextExpMask[(jSrc & 0xc0) >> 6];
  1960. *(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask);
  1961. jSrc<<=2;
  1962. ix-=2;
  1963. pjDst++;
  1964. }
  1965. pjSrc += DeltaSrcIn;
  1966. pjDst += lDstStride;
  1967. } while (pjSrc != pjSrcEndY);
  1968. }
  1969. }
  1970. //
  1971. // end case
  1972. //
  1973. if (lEndCase) {
  1974. pjSrc = pjSrcIn + (SrcRight >> 3);
  1975. pjDst = pjDstIn + ((DstRight - lEndCase) >> 1);
  1976. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  1977. LONG lDstStride = DeltaDstIn - ((lEndCase + 1) >> 1);
  1978. do {
  1979. jSrc = *pjSrc;
  1980. LONG ix = lEndCase;
  1981. //
  1982. // bytes
  1983. //
  1984. while (ix >= 2) {
  1985. Mask = TextExpMask[(jSrc & 0xC0) >> 6];
  1986. *(pjDst) = (*(pjDst) & ~Mask ) | (Accum & Mask);
  1987. jSrc <<= 2;
  1988. ix -= 2;
  1989. pjDst ++;
  1990. }
  1991. //
  1992. // last partial
  1993. //
  1994. if (ix) {
  1995. if (jSrc & 0x80) {
  1996. *pjDst = (*pjDst & 0x0F) | (Accum & 0xF0);
  1997. }
  1998. pjDst++;
  1999. }
  2000. pjSrc += DeltaSrcIn;
  2001. pjDst += lDstStride;
  2002. } while (pjSrc != pjSrcEndY);
  2003. }
  2004. }
  2005. #if !defined(_MIPS_)
  2006. const ULONG TranTable [] =
  2007. {
  2008. 0x00000000,
  2009. 0xff000000,
  2010. 0x00ff0000,
  2011. 0xffff0000,
  2012. 0x0000ff00,
  2013. 0xff00ff00,
  2014. 0x00ffff00,
  2015. 0xffffff00,
  2016. 0x000000ff,
  2017. 0xff0000ff,
  2018. 0x00ff00ff,
  2019. 0xffff00ff,
  2020. 0x0000ffff,
  2021. 0xff00ffff,
  2022. 0x00ffffff,
  2023. 0xffffffff
  2024. };
  2025. /******************************Public*Routine******************************\
  2026. *
  2027. * Routine Name
  2028. *
  2029. * vSrcTranCopyS1D8
  2030. *
  2031. * Routine Description:
  2032. *
  2033. * Transparent blt of 1BPP src to all destination format
  2034. * src bits that are "1" are copied to the dest as foreground color,
  2035. * src bits that are "0" are not copied
  2036. *
  2037. * Arguments:
  2038. *
  2039. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2040. * SrcLeft - left (starting) pixel in src rectangle
  2041. * DeltaSrcIn - bytes from one src scan line to next
  2042. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2043. * DstLeft - left(first) dst pixel
  2044. * DstRight - right(last) dst pixel
  2045. * DeltaDstIn - bytes from one Dst scan line to next
  2046. * cy - number of scan lines
  2047. * uF - Foreground color
  2048. * uB - Background color
  2049. *
  2050. * Return Value:
  2051. *
  2052. * None
  2053. *
  2054. \**************************************************************************/
  2055. VOID
  2056. vSrcTranCopyS1D8(
  2057. PBYTE pjSrcIn,
  2058. LONG SrcLeft,
  2059. LONG DeltaSrcIn,
  2060. PBYTE pjDstIn,
  2061. LONG DstLeft,
  2062. LONG DstRight,
  2063. LONG DeltaDstIn,
  2064. LONG cy,
  2065. ULONG uF,
  2066. ULONG uB,
  2067. SURFACE *pSurf
  2068. )
  2069. {
  2070. //
  2071. // start at 8-byte aligned left edge
  2072. //
  2073. ULONG uExpand = uF | (uF << 8);
  2074. ULONG LeftAln = (DstLeft & ~0x07);
  2075. ULONG LeftEdgeMask = 0xFF >> (DstLeft & 0x07);
  2076. ULONG RightAln = (DstRight & ~0x07);
  2077. ULONG EndOffset = RightAln - LeftAln;
  2078. LONG DeltaDst;
  2079. LONG DeltaSrc;
  2080. PBYTE pjDstEndY;
  2081. PBYTE pjSrc;
  2082. PBYTE pjDst;
  2083. uExpand = uExpand | (uExpand << 16);
  2084. //
  2085. // calc addresses and strides
  2086. //
  2087. pjDst = pjDstIn + LeftAln;
  2088. pjDstEndY = pjDst + cy * DeltaDstIn;
  2089. pjSrc = pjSrcIn + (SrcLeft >> 3);
  2090. DeltaSrc = DeltaSrcIn - (EndOffset >> 3);
  2091. DeltaDst = DeltaDstIn - EndOffset;
  2092. //
  2093. // make sure at least 1 QWORD needs copied
  2094. //
  2095. if (RightAln != LeftAln) {
  2096. do {
  2097. PBYTE pjDstEnd = pjDst + EndOffset;
  2098. //
  2099. // and first src byte to cover left edge
  2100. //
  2101. BYTE c0 = *pjSrc & (BYTE)LeftEdgeMask;
  2102. if (c0 != 0) {
  2103. ULONG MaskLow = TranTable[c0 >> 4];
  2104. ULONG MaskHi = TranTable[c0 & 0x0F];
  2105. ULONG d0 = *(PULONG)pjDst;
  2106. ULONG d1 = *(PULONG)(pjDst + 4);
  2107. d0 = (d0 & ~MaskLow) | (uExpand & MaskLow);
  2108. d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
  2109. *(PULONG)pjDst = d0;
  2110. *(PULONG)(pjDst + 4) = d1;
  2111. }
  2112. pjSrc ++;
  2113. pjDst += 8;
  2114. while (pjDst != pjDstEnd) {
  2115. c0 = *pjSrc;
  2116. if (c0 != 0) {
  2117. ULONG MaskLow = TranTable[c0 >> 4];
  2118. ULONG MaskHi = TranTable[c0 & 0x0F];
  2119. ULONG d0 = *(PULONG)pjDst;
  2120. ULONG d1 = *(PULONG)(pjDst + 4);
  2121. d0 = (d0 & ~MaskLow) | (uExpand & MaskLow);
  2122. d1 = (d1 & ~MaskHi) | (uExpand & MaskHi);
  2123. *(PULONG)pjDst = d0;
  2124. *(PULONG)(pjDst + 4) = d1;
  2125. }
  2126. pjSrc ++;
  2127. pjDst += 8;
  2128. };
  2129. pjDst += DeltaDst;
  2130. pjSrc += DeltaSrc;
  2131. } while (pjDst != pjDstEndY);
  2132. }
  2133. RightAln = DstRight & 0x07;
  2134. if (RightAln) {
  2135. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight) & ~0x07);
  2136. //
  2137. // if left and right edges are in same qword handle with masked
  2138. // read-modify-write
  2139. //
  2140. if (bSameQWord) {
  2141. LeftAln = DstLeft & 0x07;
  2142. LONG xCount = RightAln - LeftAln;
  2143. //
  2144. // assert ic xCount < 0
  2145. //
  2146. if (xCount <= 0) {
  2147. return;
  2148. }
  2149. LONG lDeltaDst = DeltaDstIn - xCount;
  2150. PBYTE pjDstEnd;
  2151. pjDst = pjDstIn + DstLeft;
  2152. pjDstEndY = pjDst + cy * DeltaDstIn;
  2153. pjSrc = pjSrcIn + (SrcLeft >> 3);
  2154. //
  2155. // expand, one src byte is all that's required
  2156. //
  2157. BYTE jSrc;
  2158. do {
  2159. //
  2160. // load src and shift into place
  2161. //
  2162. jSrc = *pjSrc;
  2163. jSrc <<= LeftAln;
  2164. pjDstEnd = pjDst + xCount;
  2165. do {
  2166. if (jSrc & 0x80) {
  2167. *pjDst = (BYTE)uF;
  2168. }
  2169. jSrc <<=1;
  2170. pjDst++;
  2171. } while (pjDst != pjDstEnd);
  2172. pjDst += lDeltaDst;
  2173. pjSrc += DeltaSrcIn;
  2174. } while (pjDst != pjDstEndY);
  2175. return;
  2176. } else {
  2177. ULONG ul0,ul1;
  2178. BYTE jSrc;
  2179. LONG lDeltaDst = DeltaDstIn - RightAln;
  2180. PBYTE pjDstEnd;
  2181. pjDst = pjDstIn + (DstRight & ~0x07);
  2182. pjDstEndY = pjDst + cy * DeltaDstIn;
  2183. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  2184. do {
  2185. //
  2186. // read src
  2187. //
  2188. jSrc = *pjSrc;
  2189. if (jSrc != 0) {
  2190. pjDstEnd = pjDst + RightAln;
  2191. do {
  2192. if (jSrc & 0x80) {
  2193. *pjDst = (BYTE)uF;
  2194. }
  2195. jSrc <<=1;
  2196. pjDst++;
  2197. } while (pjDst != pjDstEnd);
  2198. } else {
  2199. //
  2200. // short cut for zero
  2201. //
  2202. pjDst += RightAln;
  2203. }
  2204. pjDst += lDeltaDst;
  2205. pjSrc += DeltaSrcIn;
  2206. } while (pjDst != pjDstEndY);
  2207. }
  2208. }
  2209. }
  2210. #endif
  2211. /******************************Public*Routine******************************\
  2212. *
  2213. * Routine Name
  2214. *
  2215. * vSrcTranCopyS1D16
  2216. *
  2217. * Routine Description:
  2218. *
  2219. * Transparent blt of 1BPP src to all destination format
  2220. * src bits that are "1" are copied to the dest as foreground color,
  2221. * src bits that are "0" are not copied
  2222. *
  2223. * Arguments:
  2224. *
  2225. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2226. * SrcLeft - left (starting) pixel in src rectangle
  2227. * DeltaSrcIn - bytes from one src scan line to next
  2228. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2229. * DstLeft - left(first) dst pixel
  2230. * DstRight - right(last) dst pixel
  2231. * DeltaDstIn - bytes from one Dst scan line to next
  2232. * cy - number of scan lines
  2233. * uF - Foreground color
  2234. * uB - Background color
  2235. *
  2236. * Return Value:
  2237. *
  2238. * None
  2239. *
  2240. \**************************************************************************/
  2241. VOID
  2242. vSrcTranCopyS1D16(
  2243. PBYTE pjSrcIn,
  2244. LONG SrcLeft,
  2245. LONG DeltaSrcIn,
  2246. PBYTE pjDstIn,
  2247. LONG DstLeft,
  2248. LONG DstRight,
  2249. LONG DeltaDstIn,
  2250. LONG cy,
  2251. ULONG uF,
  2252. ULONG uB,
  2253. SURFACE *pSurf
  2254. )
  2255. {
  2256. BYTE jSrc;
  2257. LONG ixStart = SrcLeft & 0x07;
  2258. PUSHORT pusEnd;
  2259. PUSHORT pusEnd8;
  2260. PUSHORT pusDst = (PUSHORT)pjDstIn + DstLeft;
  2261. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  2262. LONG cx = DstRight - DstLeft;
  2263. LONG lDstStride = DeltaDstIn - (cx << 1);
  2264. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  2265. PUSHORT pusEndY = (PUSHORT)((PBYTE)pusDst + DeltaDstIn * cy);
  2266. LONG StartOffset = min(cx, (8 - ixStart));
  2267. do {
  2268. pusEnd = pusDst + cx;
  2269. //
  2270. // do starting pixels
  2271. //
  2272. if (ixStart) {
  2273. jSrc = *pjSrc << ixStart;
  2274. pjSrc++;
  2275. PUSHORT pusEndSt = pusDst + StartOffset;
  2276. do {
  2277. if (jSrc & 0x80) {
  2278. *pusDst = (USHORT)uF;
  2279. }
  2280. pusDst++;
  2281. jSrc <<=1;
  2282. } while (pusDst != pusEndSt);
  2283. }
  2284. //
  2285. // number of full bytes that can be expanded
  2286. //
  2287. pusEnd8 = (PUSHORT)((PBYTE)pusDst + (((ULONG_PTR)pusEnd - (ULONG_PTR)pusDst) & ~0x0F));
  2288. //
  2289. // expand full bytes
  2290. //
  2291. while (pusDst != pusEnd8) {
  2292. jSrc = *pjSrc;
  2293. if (jSrc & 0x80) {
  2294. *(pusDst+0) = (USHORT)uF;
  2295. }
  2296. if (jSrc & 0x40) {
  2297. *(pusDst+1) = (USHORT)uF;
  2298. }
  2299. if (jSrc & 0x20) {
  2300. *(pusDst+2) = (USHORT)uF;
  2301. }
  2302. if (jSrc & 0x10) {
  2303. *(pusDst+3) = (USHORT)uF;
  2304. }
  2305. if (jSrc & 0x08) {
  2306. *(pusDst+4) = (USHORT)uF;
  2307. }
  2308. if (jSrc & 0x04) {
  2309. *(pusDst+5) = (USHORT)uF;
  2310. }
  2311. if (jSrc & 0x02) {
  2312. *(pusDst+6) = (USHORT)uF;
  2313. }
  2314. if (jSrc & 0x01) {
  2315. *(pusDst+7) = (USHORT)uF;
  2316. }
  2317. pjSrc++;
  2318. pusDst += 8;
  2319. }
  2320. //
  2321. // finish off scan line if needed
  2322. //
  2323. if (pusDst != pusEnd) {
  2324. jSrc = *pjSrc++;
  2325. do {
  2326. if (jSrc & 0x80) {
  2327. *pusDst = (USHORT)uF;
  2328. }
  2329. jSrc<<=1;
  2330. pusDst++;
  2331. } while (pusDst != pusEnd);
  2332. }
  2333. pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride);
  2334. pjSrc += lSrcStride;
  2335. } while(pusDst != pusEndY);
  2336. }
  2337. /******************************Public*Routine******************************\
  2338. *
  2339. * Routine Name
  2340. *
  2341. * vSrcTranCopyS1D24
  2342. *
  2343. * Routine Description:
  2344. *
  2345. * Transparent blt of 1BPP src to all destination format
  2346. * src bits that are "1" are copied to the dest as foreground color,
  2347. * src bits that are "0" are not copied
  2348. *
  2349. * Arguments:
  2350. *
  2351. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2352. * SrcLeft - left (starting) pixel in src rectangle
  2353. * DeltaSrcIn - bytes from one src scan line to next
  2354. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2355. * DstLeft - left(first) dst pixel
  2356. * DstRight - right(last) dst pixel
  2357. * DeltaDstIn - bytes from one Dst scan line to next
  2358. * cy - number of scan lines
  2359. * uF - Foreground color
  2360. * uB - Background color
  2361. *
  2362. * Return Value:
  2363. *
  2364. * None
  2365. *
  2366. \**************************************************************************/
  2367. VOID
  2368. vSrcTranCopyS1D24(
  2369. PBYTE pjSrcIn,
  2370. LONG SrcLeft,
  2371. LONG DeltaSrcIn,
  2372. PBYTE pjDstIn,
  2373. LONG DstLeft,
  2374. LONG DstRight,
  2375. LONG DeltaDstIn,
  2376. LONG cy,
  2377. ULONG uF,
  2378. ULONG uB,
  2379. SURFACE *pSurf
  2380. )
  2381. {
  2382. BYTE jSrc;
  2383. BYTE jF0 = (BYTE)uF;
  2384. BYTE jF1 = (BYTE)(uF >> 8);
  2385. BYTE jF2 = (BYTE)(uF >> 16);
  2386. LONG ixStart = SrcLeft & 0x07;
  2387. PBYTE pjEnd;
  2388. PBYTE pjEnd8;
  2389. PBYTE pjDst = (PBYTE)pjDstIn + 3 * DstLeft;
  2390. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  2391. LONG cx = DstRight - DstLeft;
  2392. LONG lDstStride = DeltaDstIn - 3* cx;
  2393. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  2394. PBYTE pjEndY = (PBYTE)((PBYTE)pjDst + DeltaDstIn * cy);
  2395. LONG StartOffset = 3 * min(cx, (8 - ixStart));
  2396. do {
  2397. pjEnd = pjDst + 3 * cx;
  2398. //
  2399. // do starting pixels
  2400. //
  2401. if (ixStart) {
  2402. jSrc = *pjSrc << ixStart;
  2403. pjSrc++;
  2404. PBYTE pjEndSt = pjDst + StartOffset;
  2405. do {
  2406. if (jSrc & 0x80) {
  2407. *pjDst = jF0;
  2408. *(pjDst+1) = jF1;
  2409. *(pjDst+2) = jF2;
  2410. }
  2411. pjDst += 3;
  2412. jSrc <<=1;
  2413. } while (pjDst != pjEndSt);
  2414. }
  2415. //
  2416. // number of full bytes that can be expanded
  2417. //
  2418. pjEnd8 = (PBYTE)((PBYTE)pjDst + ( 24 * (((ULONG_PTR)(pjEnd - pjDst))/24)));
  2419. //
  2420. // expand full bytes
  2421. //
  2422. while (pjDst != pjEnd8) {
  2423. jSrc = *pjSrc;
  2424. if (jSrc & 0x80) {
  2425. *(pjDst+0) = jF0;
  2426. *(pjDst+1) = jF1;
  2427. *(pjDst+2) = jF2;
  2428. }
  2429. if (jSrc & 0x40) {
  2430. *(pjDst+3) = jF0;
  2431. *(pjDst+4) = jF1;
  2432. *(pjDst+5) = jF2;
  2433. }
  2434. if (jSrc & 0x20) {
  2435. *(pjDst+6) = jF0;
  2436. *(pjDst+7) = jF1;
  2437. *(pjDst+8) = jF2;
  2438. }
  2439. if (jSrc & 0x10) {
  2440. *(pjDst+9) = jF0;
  2441. *(pjDst+10) = jF1;
  2442. *(pjDst+11) = jF2;
  2443. }
  2444. if (jSrc & 0x08) {
  2445. *(pjDst+12) = jF0;
  2446. *(pjDst+13) = jF1;
  2447. *(pjDst+14) = jF2;
  2448. }
  2449. if (jSrc & 0x04) {
  2450. *(pjDst+15) = jF0;
  2451. *(pjDst+16) = jF1;
  2452. *(pjDst+17) = jF2;
  2453. }
  2454. if (jSrc & 0x02) {
  2455. *(pjDst+18) = jF0;
  2456. *(pjDst+19) = jF1;
  2457. *(pjDst+20) = jF2;
  2458. }
  2459. if (jSrc & 0x01) {
  2460. *(pjDst+21) = jF0;
  2461. *(pjDst+22) = jF1;
  2462. *(pjDst+23) = jF2;
  2463. }
  2464. pjSrc++;
  2465. pjDst += 3*8;
  2466. }
  2467. //
  2468. // finish off scan line if needed
  2469. //
  2470. if (pjDst != pjEnd) {
  2471. jSrc = *pjSrc++;
  2472. do {
  2473. if (jSrc & 0x80) {
  2474. *(pjDst+0) = jF0;
  2475. *(pjDst+1) = jF1;
  2476. *(pjDst+2) = jF2;
  2477. }
  2478. jSrc <<= 1;
  2479. pjDst += 3;
  2480. } while (pjDst != pjEnd);
  2481. }
  2482. pjDst = (PBYTE)((PBYTE)pjDst + lDstStride);
  2483. pjSrc += lSrcStride;
  2484. } while(pjDst != pjEndY);
  2485. }
  2486. /******************************Public*Routine******************************\
  2487. *
  2488. * Routine Name
  2489. *
  2490. * vSrcTranCopyS1D32
  2491. *
  2492. * Routine Description:
  2493. *
  2494. * Transparent blt of 1BPP src to all destination format
  2495. * src bits that are "1" are copied to the dest as foreground color,
  2496. * src bits that are "0" are not copied
  2497. *
  2498. * Arguments:
  2499. *
  2500. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2501. * SrcLeft - left (starting) pixel in src rectangle
  2502. * DeltaSrcIn - bytes from one src scan line to next
  2503. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2504. * DstLeft - left(first) dst pixel
  2505. * DstRight - right(last) dst pixel
  2506. * DeltaDstIn - bytes from one Dst scan line to next
  2507. * cy - number of scan lines
  2508. * uF - Foreground color
  2509. * uB - Background color
  2510. *
  2511. * Return Value:
  2512. *
  2513. * None
  2514. *
  2515. \**************************************************************************/
  2516. VOID
  2517. vSrcTranCopyS1D32(
  2518. PBYTE pjSrcIn,
  2519. LONG SrcLeft,
  2520. LONG DeltaSrcIn,
  2521. PBYTE pjDstIn,
  2522. LONG DstLeft,
  2523. LONG DstRight,
  2524. LONG DeltaDstIn,
  2525. LONG cy,
  2526. ULONG uF,
  2527. ULONG uB,
  2528. SURFACE *pSurf
  2529. )
  2530. {
  2531. BYTE jSrc;
  2532. LONG ixStart = SrcLeft & 0x07;
  2533. PULONG pulEnd;
  2534. PULONG pulEnd8;
  2535. PULONG pulDst = (PULONG)pjDstIn + DstLeft;
  2536. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  2537. LONG cx = DstRight - DstLeft;
  2538. LONG lDstStride = DeltaDstIn - (cx << 2);
  2539. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  2540. PULONG pulEndY = (PULONG)((PBYTE)pulDst + DeltaDstIn * cy);
  2541. LONG StartOffset = min(cx, (8 - ixStart));
  2542. do {
  2543. pulEnd = pulDst + cx;
  2544. //
  2545. // do starting pixels
  2546. //
  2547. if (ixStart) {
  2548. jSrc = *pjSrc << ixStart;
  2549. pjSrc++;
  2550. PULONG pulEndSt = pulDst + StartOffset;
  2551. do {
  2552. if (jSrc & 0x80) {
  2553. *pulDst = uF;
  2554. }
  2555. pulDst++;
  2556. jSrc <<=1;
  2557. } while (pulDst != pulEndSt);
  2558. }
  2559. //
  2560. // number of full bytes that can be expanded
  2561. //
  2562. pulEnd8 = (PULONG)((PBYTE)pulDst + (((ULONG_PTR)pulEnd - (ULONG_PTR)pulDst) & ~0x1F));
  2563. //
  2564. // expand full bytes
  2565. //
  2566. while (pulDst != pulEnd8) {
  2567. jSrc = *pjSrc;
  2568. if (jSrc & 0x80) {
  2569. *(pulDst+0) = uF;
  2570. }
  2571. if (jSrc & 0x40) {
  2572. *(pulDst+1) = uF;
  2573. }
  2574. if (jSrc & 0x20) {
  2575. *(pulDst+2) = uF;
  2576. }
  2577. if (jSrc & 0x10) {
  2578. *(pulDst+3) = uF;
  2579. }
  2580. if (jSrc & 0x08) {
  2581. *(pulDst+4) = uF;
  2582. }
  2583. if (jSrc & 0x04) {
  2584. *(pulDst+5) = uF;
  2585. }
  2586. if (jSrc & 0x02) {
  2587. *(pulDst+6) = uF;
  2588. }
  2589. if (jSrc & 0x01) {
  2590. *(pulDst+7) = uF;
  2591. }
  2592. pjSrc++;
  2593. pulDst += 8;
  2594. }
  2595. //
  2596. // finish off scan line if needed
  2597. //
  2598. if (pulDst != pulEnd) {
  2599. jSrc = *pjSrc++;
  2600. do {
  2601. if (jSrc & 0x80) {
  2602. *pulDst = uF;
  2603. }
  2604. jSrc<<=1;
  2605. pulDst++;
  2606. } while (pulDst != pulEnd);
  2607. }
  2608. pulDst = (PULONG)((PBYTE)pulDst + lDstStride);
  2609. pjSrc += lSrcStride;
  2610. } while(pulDst != pulEndY);
  2611. }
  2612. /******************************Public*Routine******************************\
  2613. *
  2614. * Routine Name
  2615. *
  2616. * vSrcOpaqCopyS1D1
  2617. *
  2618. * Routine Description:
  2619. *
  2620. * Opaque blt of 1BPP src to destination format
  2621. *
  2622. *
  2623. * Arguments:
  2624. *
  2625. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2626. * SrcLeft - left (starting) pixel in src rectangle
  2627. * DeltaSrcIn - bytes from one src scan line to next
  2628. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2629. * DstLeft - left(first) dst pixel
  2630. * DstRight - right(last) dst pixel
  2631. * DeltaDstIn - bytes from one Dst scan line to next
  2632. * cy - number of scan lines
  2633. * uF - Foreground color
  2634. * uB - Background color
  2635. *
  2636. * Return Value:
  2637. *
  2638. * None
  2639. *
  2640. \**************************************************************************/
  2641. #if !defined (_X86_)
  2642. VOID
  2643. vSrcOpaqCopyS1D1(
  2644. PBYTE pjSrcIn,
  2645. LONG SrcLeft,
  2646. LONG DeltaSrcIn,
  2647. PBYTE pjDstIn,
  2648. LONG DstLeft,
  2649. LONG DstRight,
  2650. LONG DeltaDstIn,
  2651. LONG cy,
  2652. ULONG uF,
  2653. ULONG uB,
  2654. SURFACE *pSurf
  2655. )
  2656. {
  2657. //
  2658. // DWORD version
  2659. //
  2660. //
  2661. // build and and xor mask
  2662. //
  2663. // and mask is set to 0x00 if uF == uB, so that
  2664. // this routine acts like a solid fill. (although src is not needed!)
  2665. //
  2666. // The xor mask is set to 0xFF if inversion is needed:
  2667. // either uF == uB == 1, for solid fill 1s or
  2668. // uF = 0, uB = 1 for inverted text
  2669. //
  2670. uF &= 1;
  2671. uB &= 1;
  2672. LONG cx = DstRight - DstLeft;
  2673. LONG lStartCase = SrcLeft;
  2674. LONG lEndCase = SrcLeft + cx;
  2675. ULONG uStartMask = (ULONG)~0;
  2676. ULONG uEndMask = (ULONG)~0;
  2677. LONG lEndOffset;
  2678. LONG lSrcStride = DeltaSrcIn;
  2679. LONG lDstStride = DeltaDstIn;
  2680. PBYTE pjSrc;
  2681. PBYTE pjDst;
  2682. PBYTE pjSrcEnd;
  2683. PBYTE pjSrcEndY;
  2684. lStartCase = lStartCase & 0x1F;
  2685. lEndCase = lEndCase & 0x1F;
  2686. //
  2687. // big endian masks
  2688. //
  2689. if (lStartCase) {
  2690. uStartMask >>= lStartCase;
  2691. //
  2692. // convert to little
  2693. // // 0 1 2 3
  2694. ULONG u0 = uStartMask << 24; // 3 - - -
  2695. ULONG u1 = uStartMask >> 24; // - - - 0
  2696. ULONG u2 = (uStartMask >> 8) & 0xFF00; // - - 1 -
  2697. uStartMask = (uStartMask & 0xFF00) << 8; // - 2 - -
  2698. uStartMask |= u0 | u1 | u2;
  2699. }
  2700. if (lEndCase) {
  2701. uEndMask <<= (32 - lEndCase);
  2702. //
  2703. // convert to little
  2704. // // 0 1 2 3
  2705. ULONG u0 = uEndMask << 24; // 3 - - -
  2706. ULONG u1 = uEndMask >> 24; // - - - 0
  2707. ULONG u2 = (uEndMask >> 8) & 0xFF00; // - - 1 -
  2708. uEndMask = (uEndMask & 0xFF00) << 8; // - 2 - -
  2709. uEndMask |= u0 | u1 | u2;
  2710. }
  2711. //
  2712. // calc starting and ending full dword addresses (DWORD aligned)
  2713. //
  2714. pjDst = pjDstIn + (((DstLeft) >> 3) & ~0x03);
  2715. pjSrc = pjSrcIn + (((SrcLeft) >> 3) & ~0x03);
  2716. pjSrcEnd = pjSrcIn + (((SrcLeft+cx) >> 3) & ~0x03);
  2717. //Sundown safe truncation
  2718. lEndOffset = (ULONG)((ULONG_PTR)pjSrcEnd - (ULONG_PTR)pjSrc);
  2719. pjSrcEndY = pjSrc + cy * lSrcStride;
  2720. //
  2721. // special case uF = 1 and uB = 0
  2722. //
  2723. if (uF && !uB) {
  2724. //
  2725. // special case direct copy
  2726. //
  2727. if (pjSrc != pjSrcEnd) {
  2728. //
  2729. // start and stop are not in same byte
  2730. //
  2731. lDstStride -= lEndOffset;
  2732. lSrcStride -= lEndOffset;
  2733. do {
  2734. pjSrcEnd = pjSrc + lEndOffset;
  2735. if (lStartCase) {
  2736. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (*(PULONG)pjSrc & uStartMask);
  2737. pjDst+=4;
  2738. pjSrc+=4;
  2739. }
  2740. while (pjSrc != pjSrcEnd) {
  2741. *(PULONG)pjDst = *(PULONG)pjSrc;
  2742. pjSrc +=4;
  2743. pjDst +=4;
  2744. }
  2745. if (lEndCase) {
  2746. *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (*(PULONG)pjSrc & uEndMask);
  2747. }
  2748. pjSrc += lSrcStride;
  2749. pjDst += lDstStride;
  2750. } while (pjSrc != pjSrcEndY);
  2751. } else {
  2752. //
  2753. // start and stop are in same byte
  2754. //
  2755. uStartMask &= uEndMask;
  2756. do {
  2757. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (*(PULONG)pjSrc & uStartMask);
  2758. pjSrc += lSrcStride;
  2759. pjDst += lDstStride;
  2760. } while (pjSrc != pjSrcEndY);
  2761. }
  2762. //
  2763. // special case uF = 0 and uB = 1 (invert)
  2764. //
  2765. } else if (!uF && uB) {
  2766. //
  2767. // dst = ~Src
  2768. //
  2769. if (pjSrc != pjSrcEnd) {
  2770. //
  2771. // start and stop are not in same byte
  2772. //
  2773. lDstStride -= lEndOffset;
  2774. lSrcStride -= lEndOffset;
  2775. do {
  2776. pjSrcEnd = pjSrc + lEndOffset;
  2777. if (lStartCase) {
  2778. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (~(*(PULONG)pjSrc) & uStartMask);
  2779. pjDst+=4;
  2780. pjSrc+=4;
  2781. }
  2782. while (pjSrc != pjSrcEnd) {
  2783. *(PULONG)pjDst = ~(*(PULONG)pjSrc);
  2784. pjSrc +=4;
  2785. pjDst +=4;
  2786. }
  2787. if (lEndCase) {
  2788. *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (~(*(PULONG)pjSrc) & uEndMask);
  2789. }
  2790. pjSrc += lSrcStride;
  2791. pjDst += lDstStride;
  2792. } while (pjSrc != pjSrcEndY);
  2793. } else {
  2794. //
  2795. // start and stop are in same byte
  2796. //
  2797. uStartMask &= uEndMask;
  2798. do {
  2799. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (~(*(PULONG)pjSrc) & uStartMask);
  2800. pjSrc += lSrcStride;
  2801. pjDst += lDstStride;
  2802. } while (pjSrc != pjSrcEndY);
  2803. }
  2804. } else {
  2805. ULONG AndMask = (uF == uB) ? 0x00 : 0xFF;
  2806. AndMask |= AndMask << 8;
  2807. AndMask |= AndMask << 16;
  2808. ULONG XorMask = (uB == 1) ? 0xFF : 0x00;
  2809. XorMask |= XorMask << 8;
  2810. XorMask |= XorMask << 16;
  2811. if (pjSrc != pjSrcEnd) {
  2812. //
  2813. // start and stop are not in same byte
  2814. //
  2815. lDstStride -= lEndOffset;
  2816. lSrcStride -= lEndOffset;
  2817. do {
  2818. pjSrcEnd = pjSrc + lEndOffset;
  2819. if (lStartCase) {
  2820. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uStartMask);
  2821. pjDst+=4;
  2822. pjSrc+=4;
  2823. }
  2824. while (pjSrc != pjSrcEnd) {
  2825. *(PULONG)pjDst = *(PULONG)pjSrc & AndMask ^ XorMask;
  2826. pjSrc +=4;
  2827. pjDst +=4;
  2828. }
  2829. if (lEndCase) {
  2830. *(PULONG)pjDst = (*(PULONG)pjDst & ~uEndMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uEndMask);
  2831. }
  2832. pjSrc += lSrcStride;
  2833. pjDst += lDstStride;
  2834. } while (pjSrc != pjSrcEndY);
  2835. } else {
  2836. //
  2837. // start and stop are in same byte
  2838. //
  2839. uStartMask &= uEndMask;
  2840. do {
  2841. *(PULONG)pjDst = (*(PULONG)pjDst & ~uStartMask) | (((*(PULONG)pjSrc & AndMask) ^ XorMask) & uStartMask);
  2842. pjSrc += lSrcStride;
  2843. pjDst += lDstStride;
  2844. } while (pjSrc != pjSrcEndY);
  2845. }
  2846. }
  2847. }
  2848. #endif
  2849. /******************************Public*Routine******************************\
  2850. *
  2851. * Routine Name
  2852. *
  2853. * vSrcOpaqCopyS1D4
  2854. *
  2855. * Routine Description:
  2856. *
  2857. * Opaque blt of 1BPP src to destination format
  2858. *
  2859. * Arguments:
  2860. *
  2861. * pjSrcIn - pointer to beginning of current scan line of src buffer
  2862. * SrcLeft - left (starting) pixel in src rectangle
  2863. * DeltaSrcIn - bytes from one src scan line to next
  2864. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  2865. * DstLeft - left(first) dst pixel
  2866. * DstRight - right(last) dst pixel
  2867. * DeltaDstIn - bytes from one Dst scan line to next
  2868. * cy - number of scan lines
  2869. * uF - Foreground color
  2870. * uB - Background color
  2871. *
  2872. * Return Value:
  2873. *
  2874. * None
  2875. *
  2876. \**************************************************************************/
  2877. VOID vSrcOpaqCopyS1D4(
  2878. PBYTE pjSrcIn,
  2879. LONG SrcLeft,
  2880. LONG DeltaSrcIn,
  2881. PBYTE pjDstIn,
  2882. LONG DstLeft,
  2883. LONG DstRight,
  2884. LONG DeltaDstIn,
  2885. LONG cy,
  2886. ULONG uF,
  2887. ULONG uB,
  2888. SURFACE *pSurf
  2889. )
  2890. {
  2891. //
  2892. // Warning, this 4bit code is not optimized, it is not expected that
  2893. // we will draw many 4bpp engine bitmaps.
  2894. //
  2895. //
  2896. // check for quick out?
  2897. //
  2898. BYTE jF = (BYTE)uF;
  2899. BYTE jB = (BYTE)uB;
  2900. BYTE TextExpTable[4];
  2901. LONG cx = DstRight - DstLeft;
  2902. //
  2903. // build small table
  2904. //
  2905. BYTE Accum = jB | (jB << 4);
  2906. TextExpTable[0] = Accum; // 0 0
  2907. Accum <<= 4;
  2908. Accum |= jF;
  2909. TextExpTable[1] = Accum; // 0 1
  2910. Accum <<= 4;
  2911. Accum |= jF;
  2912. TextExpTable[3] = Accum; // 1 1
  2913. Accum <<= 4;
  2914. Accum |= jB;
  2915. TextExpTable[2] = Accum; // 1 0
  2916. LONG lStartCase = SrcLeft & 0x07;
  2917. LONG SrcRight = SrcLeft+cx;
  2918. LONG lEndCase = SrcRight & 0x07;
  2919. PBYTE pjSrc = pjSrcIn + ((SrcLeft + 7) >> 3);
  2920. PBYTE pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  2921. PBYTE pjSrcEnd;
  2922. LONG lSrcStartOffset = (8 - lStartCase);
  2923. LONG lSrcStride;
  2924. PBYTE pjDst;
  2925. BYTE jSrc;
  2926. if (lStartCase == 0) {
  2927. lSrcStartOffset = 0;
  2928. }
  2929. cx = cx - lSrcStartOffset - lEndCase;
  2930. if (cx > 0) {
  2931. LONG lDstStride = DeltaDstIn - (cx >> 1);
  2932. lSrcStride = DeltaSrcIn - (cx >> 3);
  2933. pjDst = pjDstIn + ((DstLeft + lSrcStartOffset) >> 1);
  2934. do {
  2935. pjSrcEnd = pjSrc + (cx >> 3);
  2936. //
  2937. // aligned middle
  2938. //
  2939. do {
  2940. jSrc = *pjSrc;
  2941. *pjDst = TextExpTable[(jSrc & 0xC0) >> 6];
  2942. *(pjDst+1) = TextExpTable[(jSrc & 0x30) >> 4];
  2943. *(pjDst+2) = TextExpTable[(jSrc & 0x0C) >> 2];
  2944. *(pjDst+3) = TextExpTable[ jSrc & 0x03 ];
  2945. pjDst += 4;
  2946. pjSrc ++;
  2947. } while (pjSrc != pjSrcEnd);
  2948. pjDst += lDstStride;
  2949. pjSrc += lSrcStride;
  2950. } while (pjSrc != pjSrcEndY);
  2951. }
  2952. //
  2953. // start case
  2954. //
  2955. if (lStartCase) {
  2956. //
  2957. // are start and stop in same src byte
  2958. //
  2959. BOOL bSameByte = ((SrcLeft) & ~0x07) == ((SrcRight) & ~0x07);
  2960. if (bSameByte) {
  2961. //
  2962. // start and stop in same byte
  2963. //
  2964. PBYTE pjDstScan = pjDstIn + ((DstLeft >> 1));
  2965. PBYTE pjDstEnd2;
  2966. LONG lTextWidth = lEndCase - lStartCase;
  2967. //
  2968. // check for bad width
  2969. //
  2970. if (lTextWidth <= 0) {
  2971. return;
  2972. }
  2973. pjSrc = pjSrcIn + (SrcLeft >> 3);
  2974. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  2975. do {
  2976. pjDst = pjDstScan;
  2977. jSrc = *pjSrc << (lStartCase & ~0x01);
  2978. LONG ix = lTextWidth;
  2979. //
  2980. // starting odd nibble
  2981. //
  2982. if (lStartCase & 0x01) {
  2983. *pjDst = (*pjDst & 0xF0) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0x0F);
  2984. jSrc <<= 2;
  2985. pjDst++;
  2986. ix--;
  2987. }
  2988. //
  2989. // full byte nibble pairs
  2990. //
  2991. while (ix >= 2) {
  2992. *(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6];
  2993. jSrc<<=2;
  2994. pjDst++;
  2995. ix -= 2;
  2996. }
  2997. //
  2998. // last nibble
  2999. //
  3000. if (ix) {
  3001. *(pjDst) = (*(pjDst) & 0x0F) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0xF0);
  3002. }
  3003. pjSrc += DeltaSrcIn;
  3004. pjDstScan += DeltaDstIn;
  3005. } while (pjSrc != pjSrcEndY);
  3006. //
  3007. // make sure end case doesn't run
  3008. //
  3009. lEndCase = 0;
  3010. } else {
  3011. pjSrc = pjSrcIn + (SrcLeft >> 3);
  3012. pjDst = pjDstIn + ((DstLeft >> 1));
  3013. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  3014. LONG lDstStride = DeltaDstIn - ((9 - lStartCase) >> 1); // ((8 - lStartCase) + 1) / 2
  3015. do {
  3016. jSrc = *pjSrc << (lStartCase & ~0x01);
  3017. LONG ix = 8 - lStartCase;
  3018. //
  3019. // partial
  3020. //
  3021. if (ix & 0x01) {
  3022. *pjDst = (*pjDst & 0xF0) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0x0F);
  3023. jSrc <<= 2;
  3024. pjDst++;
  3025. ix--;
  3026. }
  3027. //
  3028. // bytes
  3029. //
  3030. while (ix != 0) {
  3031. *(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6];
  3032. jSrc<<=2;
  3033. ix-=2;
  3034. pjDst++;
  3035. }
  3036. pjSrc += DeltaSrcIn;
  3037. pjDst += lDstStride;
  3038. } while (pjSrc != pjSrcEndY);
  3039. }
  3040. }
  3041. //
  3042. // end case
  3043. //
  3044. if (lEndCase) {
  3045. pjSrc = pjSrcIn + (SrcRight >> 3);
  3046. pjDst = pjDstIn + ((DstRight - lEndCase) >> 1);
  3047. pjSrcEndY = pjSrc + cy * DeltaSrcIn;
  3048. LONG lDstStride = DeltaDstIn - ((lEndCase + 1) >> 1);
  3049. do {
  3050. jSrc = *pjSrc;
  3051. LONG ix = lEndCase;
  3052. //
  3053. // bytes
  3054. //
  3055. while (ix >= 2) {
  3056. *(pjDst) = TextExpTable[(jSrc & 0xC0) >> 6];
  3057. jSrc <<= 2;
  3058. ix -= 2;
  3059. pjDst ++;
  3060. }
  3061. //
  3062. // last partial
  3063. //
  3064. if (ix) {
  3065. *(pjDst) = (*(pjDst) & 0x0F) | (TextExpTable[(jSrc & 0xc0) >> 6] & 0xF0);
  3066. pjDst++;
  3067. }
  3068. pjSrc += DeltaSrcIn;
  3069. pjDst += lDstStride;
  3070. } while (pjSrc != pjSrcEndY);
  3071. }
  3072. }
  3073. //
  3074. // edge mask for 8 bit expansion
  3075. //
  3076. extern "C" {
  3077. ULONG gTextLeftMask[8][2] = {
  3078. {0xffffffff,0xffffffff},
  3079. {0xffffff00,0xffffffff},
  3080. {0xffff0000,0xffffffff},
  3081. {0xff000000,0xffffffff},
  3082. {0x00000000,0xffffffff},
  3083. {0x00000000,0xffffff00},
  3084. {0x00000000,0xffff0000},
  3085. {0x00000000,0xff000000}
  3086. };
  3087. ULONG gTextRightMask[8][2] = {
  3088. {0xffffffff,0xffffffff},
  3089. {0x000000ff,0x00000000},
  3090. {0x0000ffff,0x00000000},
  3091. {0x00ffffff,0x00000000},
  3092. {0xffffffff,0x00000000},
  3093. {0xffffffff,0x000000ff},
  3094. {0xffffffff,0x0000ffff},
  3095. {0xffffffff,0x00ffffff}
  3096. };
  3097. }
  3098. /******************************Public*Routine******************************\
  3099. *
  3100. * Routine Name
  3101. *
  3102. * vSrcOpaqCopyS1D8
  3103. *
  3104. * Routine Description:
  3105. *
  3106. * Opaque blt of 1BPP src to destination format
  3107. *
  3108. * Arguments:
  3109. *
  3110. * pjSrcIn - pointer to beginning of current scan line of src buffer
  3111. * SrcLeft - left (starting) pixel in src rectangle
  3112. * DeltaSrcIn - bytes from one src scan line to next
  3113. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  3114. * DstLeft - left(first) dst pixel
  3115. * DstRight - right(last) dst pixel
  3116. * DeltaDstIn - bytes from one Dst scan line to next
  3117. * cy - number of scan lines
  3118. * uF - Foreground color
  3119. * uB - Background color
  3120. *
  3121. * Return Value:
  3122. *
  3123. * None
  3124. *
  3125. \**************************************************************************/
  3126. VOID
  3127. vSrcOpaqCopyS1D8(
  3128. PBYTE pjSrcIn,
  3129. LONG SrcLeft,
  3130. LONG DeltaSrcIn,
  3131. PBYTE pjDstIn,
  3132. LONG DstLeft,
  3133. LONG DstRight,
  3134. LONG DeltaDstIn,
  3135. LONG cy,
  3136. ULONG uF,
  3137. ULONG uB,
  3138. SURFACE *pSurf
  3139. )
  3140. {
  3141. //
  3142. // Aligned portion
  3143. //
  3144. ULONG LeftAln = ((DstLeft + 7) & ~0x07);
  3145. ULONG RightAln = ((DstRight) & ~0x07);
  3146. ULONG EndOffset = RightAln - LeftAln;
  3147. ULONG EndOffset4 = EndOffset & ~0x0F;
  3148. ULONG EndOffset8 = EndOffset & ~0x1F;
  3149. LONG DeltaDst;
  3150. LONG DeltaSrc;
  3151. PBYTE pjDstEndY;
  3152. PBYTE pjSrc;
  3153. PBYTE pjDst;
  3154. ULONG TextExpTable[16];
  3155. //
  3156. // Generate text expasion table
  3157. //
  3158. ULONG Accum = uB;
  3159. Accum = Accum | (Accum << 8);
  3160. Accum = Accum | (Accum << 16);
  3161. TextExpTable[0] = Accum; // 0 0 0 0
  3162. Accum <<= 8;
  3163. Accum |= uF;
  3164. TextExpTable[8] = Accum; // 0 0 0 1
  3165. Accum <<= 8;
  3166. Accum |= uB;
  3167. TextExpTable[4] = Accum; // 0 0 1 0
  3168. Accum <<= 8;
  3169. Accum |= uF;
  3170. TextExpTable[10] = Accum; // 0 1 0 1
  3171. Accum <<= 8;
  3172. Accum |= uB;
  3173. TextExpTable[5] = Accum; // 1 0 1 0
  3174. Accum <<= 8;
  3175. Accum |= uB;
  3176. TextExpTable[ 2] = Accum; // 0 1 0 0
  3177. Accum <<= 8;
  3178. Accum |= uF;
  3179. TextExpTable[ 9] = Accum; // 1 0 0 1
  3180. Accum <<= 8;
  3181. Accum |= uF;
  3182. TextExpTable[12] = Accum; // 0 0 1 1
  3183. Accum <<= 8;
  3184. Accum |= uF;
  3185. TextExpTable[14] = Accum; // 0 1 1 1
  3186. Accum <<= 8;
  3187. Accum |= uF;
  3188. TextExpTable[15] = Accum; // 1 1 1 1
  3189. Accum <<= 8;
  3190. Accum |= uB;
  3191. TextExpTable[ 7] = Accum; // 1 1 1 0
  3192. Accum <<= 8;
  3193. Accum |= uF;
  3194. TextExpTable[11] = Accum; // 1 1 0 1
  3195. Accum <<= 8;
  3196. Accum |= uF;
  3197. TextExpTable[13] = Accum; // 1 0 1 1
  3198. Accum <<= 8;
  3199. Accum |= uB;
  3200. TextExpTable[06] = Accum; // 0 1 1 0
  3201. Accum <<= 8;
  3202. Accum |= uB;
  3203. TextExpTable[ 3] = Accum; // 1 1 0 0
  3204. Accum <<= 8;
  3205. Accum |= uB;
  3206. TextExpTable[ 1] = Accum; // 1 0 0 0
  3207. //
  3208. // calc addresses and strides
  3209. //
  3210. pjDst = pjDstIn + LeftAln;
  3211. pjDstEndY = pjDst + cy * DeltaDstIn;
  3212. pjSrc = pjSrcIn + ((SrcLeft+7) >> 3);
  3213. DeltaSrc = DeltaSrcIn - (EndOffset >> 3);
  3214. DeltaDst = DeltaDstIn - EndOffset;
  3215. //
  3216. // make sure at least 1 QWORD needs copied
  3217. //
  3218. if (RightAln > LeftAln) {
  3219. //
  3220. // expand buffer
  3221. //
  3222. do {
  3223. PBYTE pjDstEnd = pjDst + EndOffset;
  3224. PBYTE pjDstEnd4 = pjDst + EndOffset4;
  3225. PBYTE pjDstEnd8 = pjDst + EndOffset8;
  3226. //
  3227. // 4 times unrolled
  3228. //
  3229. while (pjDst != pjDstEnd8) {
  3230. BYTE c0 = *(pjSrc + 0);
  3231. BYTE c1 = *(pjSrc + 1);
  3232. BYTE c2 = *(pjSrc + 2);
  3233. BYTE c3 = *(pjSrc + 3);
  3234. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  3235. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  3236. *(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4];
  3237. *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
  3238. *(PULONG)(pjDst +16) = TextExpTable[c2 >> 4];
  3239. *(PULONG)(pjDst +20) = TextExpTable[c2 & 0x0F];
  3240. *(PULONG)(pjDst +24) = TextExpTable[c3 >> 4];
  3241. *(PULONG)(pjDst +28) = TextExpTable[c3 & 0x0F];
  3242. pjSrc += 4;
  3243. pjDst += 32;
  3244. }
  3245. //
  3246. // 2 times unrolled
  3247. //
  3248. while (pjDst != pjDstEnd4) {
  3249. BYTE c0 = *(pjSrc + 0);
  3250. BYTE c1 = *(pjSrc + 1);
  3251. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  3252. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  3253. *(PULONG)(pjDst + 8) = TextExpTable[c1 >> 4];
  3254. *(PULONG)(pjDst +12) = TextExpTable[c1 & 0x0F];
  3255. pjSrc += 2;
  3256. pjDst += 16;
  3257. }
  3258. //
  3259. // 1 byte expansion loop
  3260. //
  3261. while (pjDst != pjDstEnd) {
  3262. BYTE c0 = *(pjSrc + 0);
  3263. *(PULONG)(pjDst + 0) = TextExpTable[c0 >> 4];
  3264. *(PULONG)(pjDst + 4) = TextExpTable[c0 & 0x0F];
  3265. pjSrc++;
  3266. pjDst += 8;
  3267. }
  3268. pjDst += DeltaDst;
  3269. pjSrc += DeltaSrc;
  3270. } while (pjDst != pjDstEndY);
  3271. }
  3272. //
  3273. // Starting alignment case: at most 1 src byte is required.
  3274. // Start and end may occur in same Quadword.
  3275. //
  3276. //
  3277. // Left Right
  3278. // 0 1 2 3�4 5 6 7 0 1 2 3�4 5 6 7
  3279. // ���������������Ŀ �������ĺ������Ŀ
  3280. // 1 � �x�x�x�x�x�x�x� 1 �x� � � � � � � �
  3281. // �������ĺ������Ĵ �������ĺ������Ĵ
  3282. // 2 � � �x�x�x�x�x�x� 2 �x�x� � � � � � �
  3283. // �������ĺ������Ĵ �������ĺ������Ĵ
  3284. // 3 � � � �x�x�x�x�x� 3 �x�x�x� � � � � �
  3285. // �������ĺ������Ĵ �������ĺ������Ĵ
  3286. // 4 � � � � �x�x�x�x� 4 �x�x�x�x� � � � �
  3287. // �������ĺ������Ĵ �������ĺ������Ĵ
  3288. // 5 � � � � � �x�x�x� 5 �x�x�x�x�x� � � �
  3289. // �������ĺ������Ĵ �������ĺ������Ĵ
  3290. // 6 � � � � � � �x�x� 6 �x�x�x�x�x�x� � �
  3291. // �������ĺ������Ĵ �������ĺ������Ĵ
  3292. // 7 � � � � � � � �x� 7 �x�x�x�x�x�x�x� �
  3293. // ����������������� ��������������
  3294. //
  3295. LeftAln = DstLeft & 0x07;
  3296. RightAln = DstRight & 0x07;
  3297. if (LeftAln) {
  3298. BYTE jSrc;
  3299. BOOL bSameDWord = ((DstLeft) & ~0x03) == ((DstRight-1) & ~0x03);
  3300. BOOL bSameQWord = ((DstLeft) & ~0x07) == ((DstRight-1) & ~0x07);
  3301. ULONG ul0,ul1;
  3302. ASSERTGDI (DstLeft < DstRight, "vSrcOpaqCopyS1D8: null rectangle passed in.");
  3303. // if left and right edges are in the same dword or the same qword,
  3304. // handle with masked read-modify-write
  3305. if (bSameDWord) {
  3306. ULONG Mask0;
  3307. Mask0 = gTextLeftMask[LeftAln & 3][0] &
  3308. gTextRightMask[RightAln & 3][0];
  3309. pjDst = pjDstIn + (DstLeft & ~0x03);
  3310. pjDstEndY = pjDst + cy * DeltaDstIn;
  3311. // (SrcLeft >> 3) is the number of bytes to offset by
  3312. // (1 BPP in the src buffer).
  3313. pjSrc = pjSrcIn + (SrcLeft >> 3);
  3314. // expand
  3315. do {
  3316. jSrc = *pjSrc;
  3317. if (LeftAln < 4)
  3318. ul0 = TextExpTable[jSrc >> 4];
  3319. else
  3320. ul0 = TextExpTable[jSrc & 0xf];
  3321. *(PULONG)pjDst = (*(PULONG)pjDst & ~Mask0) | (ul0 & Mask0);
  3322. pjDst += DeltaDstIn;
  3323. pjSrc += DeltaSrcIn;
  3324. } while (pjDst != pjDstEndY);
  3325. return;
  3326. } else if (bSameQWord) {
  3327. ULONG Mask0,Mask1;
  3328. Mask0 = gTextLeftMask[LeftAln][0] & gTextRightMask[RightAln][0];
  3329. Mask1 = gTextLeftMask[LeftAln][1] & gTextRightMask[RightAln][1];
  3330. pjDst = pjDstIn + (DstLeft & ~0x07);
  3331. pjDstEndY = pjDst + cy * DeltaDstIn;
  3332. // (SrcLeft >> 3) is the number of bytes to offset by
  3333. // (1 BPP in the src buffer).
  3334. pjSrc = pjSrcIn + (SrcLeft >> 3);
  3335. //
  3336. // expand
  3337. //
  3338. do {
  3339. jSrc = *pjSrc;
  3340. ul0 = TextExpTable[jSrc >> 4];
  3341. ul1 = TextExpTable[jSrc & 0x0F];
  3342. *(PULONG)(pjDst) = (*(PULONG)(pjDst) & ~Mask0) | (ul0 & Mask0);
  3343. *(PULONG)(pjDst+4) = (*(PULONG)(pjDst+4) & ~Mask1) | (ul1 & Mask1);
  3344. pjDst += DeltaDstIn;
  3345. pjSrc += DeltaSrcIn;
  3346. } while (pjDst != pjDstEndY);
  3347. return;
  3348. }
  3349. //
  3350. // Left edge only, handle with special write-only loops
  3351. //
  3352. pjDst = pjDstIn + (DstLeft & ~0x07);
  3353. pjDstEndY = pjDst + cy * DeltaDstIn;
  3354. pjSrc = pjSrcIn + (SrcLeft >> 3);
  3355. switch (LeftAln) {
  3356. case 1:
  3357. do {
  3358. jSrc = *pjSrc;
  3359. ul0 = TextExpTable[jSrc >> 4];
  3360. ul1 = TextExpTable[jSrc & 0x0F];
  3361. *(pjDst+1) = (BYTE)(ul0 >> 8);
  3362. *((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16);
  3363. *((PULONG)(pjDst+4)) = ul1;
  3364. pjDst += DeltaDstIn;
  3365. pjSrc += DeltaSrcIn;
  3366. } while (pjDst != pjDstEndY);
  3367. break;
  3368. case 2:
  3369. do {
  3370. jSrc = *pjSrc;
  3371. ul0 = TextExpTable[jSrc >> 4];
  3372. ul1 = TextExpTable[jSrc & 0x0F];
  3373. *((PUSHORT)(pjDst+2)) = (USHORT)(ul0 >> 16);
  3374. *((PULONG)(pjDst+4)) = ul1;
  3375. pjDst += DeltaDstIn;
  3376. pjSrc += DeltaSrcIn;
  3377. } while (pjDst != pjDstEndY);
  3378. break;
  3379. case 3:
  3380. do {
  3381. jSrc = *pjSrc;
  3382. ul0 = TextExpTable[jSrc >> 4];
  3383. ul1 = TextExpTable[jSrc & 0x0F];
  3384. *(pjDst+3) = (BYTE)(ul0 >> 24);
  3385. *((PULONG)(pjDst+4)) = ul1;
  3386. pjDst += DeltaDstIn;
  3387. pjSrc += DeltaSrcIn;
  3388. } while (pjDst != pjDstEndY);
  3389. break;
  3390. case 4:
  3391. do {
  3392. jSrc = *pjSrc;
  3393. ul1 = TextExpTable[jSrc & 0x0F];
  3394. *((PULONG)(pjDst+4)) = ul1;
  3395. pjDst += DeltaDstIn;
  3396. pjSrc += DeltaSrcIn;
  3397. } while (pjDst != pjDstEndY);
  3398. break;
  3399. case 5:
  3400. do {
  3401. jSrc = *pjSrc;
  3402. ul1 = TextExpTable[jSrc & 0x0F];
  3403. *(pjDst+5) = (BYTE)(ul1 >> 8);
  3404. *((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
  3405. pjDst += DeltaDstIn;
  3406. pjSrc += DeltaSrcIn;
  3407. } while (pjDst != pjDstEndY);
  3408. break;
  3409. case 6:
  3410. do {
  3411. jSrc = *pjSrc;
  3412. ul1 = TextExpTable[jSrc & 0x0F];
  3413. *((PUSHORT)(pjDst+6)) = (USHORT)(ul1 >> 16);
  3414. pjDst += DeltaDstIn;
  3415. pjSrc += DeltaSrcIn;
  3416. } while (pjDst != pjDstEndY);
  3417. break;
  3418. case 7:
  3419. do {
  3420. jSrc = *pjSrc;
  3421. ul1 = TextExpTable[jSrc & 0x0F];
  3422. *(pjDst+7) = (BYTE)(ul1 >> 24);
  3423. pjDst += DeltaDstIn;
  3424. pjSrc += DeltaSrcIn;
  3425. } while (pjDst != pjDstEndY);
  3426. break;
  3427. }
  3428. }
  3429. //
  3430. // handle right edge only, use special write-only loops for each case
  3431. //
  3432. if (RightAln) {
  3433. ULONG ul0,ul1;
  3434. BYTE jSrc;
  3435. pjDst = pjDstIn + (DstRight & ~0x07);
  3436. pjDstEndY = pjDst + cy * DeltaDstIn;
  3437. pjSrc = pjSrcIn + ((SrcLeft + (DstRight - DstLeft)) >> 3);
  3438. //
  3439. // select right case
  3440. //
  3441. switch (RightAln) {
  3442. case 1:
  3443. do {
  3444. jSrc = *pjSrc;
  3445. ul0 = TextExpTable[jSrc >> 4];
  3446. *(pjDst) = (BYTE)ul0;
  3447. pjDst += DeltaDstIn;
  3448. pjSrc += DeltaSrcIn;
  3449. } while (pjDst != pjDstEndY);
  3450. break;
  3451. case 2:
  3452. do {
  3453. jSrc = *pjSrc;
  3454. ul0 = TextExpTable[jSrc >> 4];
  3455. *(PUSHORT)(pjDst) = (USHORT)ul0;
  3456. pjDst += DeltaDstIn;
  3457. pjSrc += DeltaSrcIn;
  3458. } while (pjDst != pjDstEndY);
  3459. break;
  3460. case 3:
  3461. do {
  3462. jSrc = *pjSrc;
  3463. ul0 = TextExpTable[jSrc >> 4];
  3464. *(PUSHORT)(pjDst) = (USHORT)ul0;
  3465. *(pjDst+2) = (BYTE)(ul0 >> 16);
  3466. pjDst += DeltaDstIn;
  3467. pjSrc += DeltaSrcIn;
  3468. } while (pjDst != pjDstEndY);
  3469. break;
  3470. case 4:
  3471. do {
  3472. jSrc = *pjSrc;
  3473. ul0 = TextExpTable[jSrc >> 4];
  3474. *(PULONG)(pjDst) = ul0;
  3475. pjDst += DeltaDstIn;
  3476. pjSrc += DeltaSrcIn;
  3477. } while (pjDst != pjDstEndY);
  3478. break;
  3479. case 5:
  3480. do {
  3481. jSrc = *pjSrc;
  3482. ul0 = TextExpTable[jSrc >> 4];
  3483. ul1 = TextExpTable[jSrc & 0x0F];
  3484. *(PULONG)(pjDst) = ul0;
  3485. *(pjDst+4) = (BYTE)ul1;
  3486. pjDst += DeltaDstIn;
  3487. pjSrc += DeltaSrcIn;
  3488. } while (pjDst != pjDstEndY);
  3489. break;
  3490. case 6:
  3491. do {
  3492. jSrc = *pjSrc;
  3493. ul0 = TextExpTable[jSrc >> 4];
  3494. ul1 = TextExpTable[jSrc & 0x0F];
  3495. *(PULONG)(pjDst) = ul0;
  3496. *(PUSHORT)(pjDst+4) = (USHORT)ul1;
  3497. pjDst += DeltaDstIn;
  3498. pjSrc += DeltaSrcIn;
  3499. } while (pjDst != pjDstEndY);
  3500. break;
  3501. case 7:
  3502. do {
  3503. jSrc = *pjSrc;
  3504. ul0 = TextExpTable[jSrc >> 4];
  3505. ul1 = TextExpTable[jSrc & 0x0F];
  3506. *(PULONG)(pjDst) = ul0;
  3507. *(PUSHORT)(pjDst+4) = (USHORT)ul1;
  3508. *(pjDst+6) = (BYTE)(ul1 >> 16);
  3509. pjDst += DeltaDstIn;
  3510. pjSrc += DeltaSrcIn;
  3511. } while (pjDst != pjDstEndY);
  3512. break;
  3513. }
  3514. }
  3515. }
  3516. /******************************Public*Routine******************************\
  3517. *
  3518. * Routine Name
  3519. *
  3520. * vSrcOpaqCopyS1D16
  3521. *
  3522. * Routine Description:
  3523. *
  3524. * Opaque blt of 1BPP src to destination format
  3525. *
  3526. * Arguments:
  3527. *
  3528. * pjSrcIn - pointer to beginning of current scan line of src buffer
  3529. * SrcLeft - left (starting) pixel in src rectangle
  3530. * DeltaSrcIn - bytes from one src scan line to next
  3531. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  3532. * DstLeft - left(first) dst pixel
  3533. * DstRight - right(last) dst pixel
  3534. * DeltaDstIn - bytes from one Dst scan line to next
  3535. * cy - number of scan lines
  3536. * uF - Foreground color
  3537. * uB - Background color
  3538. *
  3539. * Return Value:
  3540. *
  3541. * None
  3542. *
  3543. \**************************************************************************/
  3544. VOID
  3545. vSrcOpaqCopyS1D16(
  3546. PBYTE pjSrcIn,
  3547. LONG SrcLeft,
  3548. LONG DeltaSrcIn,
  3549. PBYTE pjDstIn,
  3550. LONG DstLeft,
  3551. LONG DstRight,
  3552. LONG DeltaDstIn,
  3553. LONG cy,
  3554. ULONG uF,
  3555. ULONG uB,
  3556. SURFACE *pSurf
  3557. )
  3558. {
  3559. BYTE jSrc;
  3560. LONG ixStart = SrcLeft & 0x07;
  3561. PUSHORT pusEnd;
  3562. PUSHORT pusEnd8;
  3563. PUSHORT pusDst = (PUSHORT)pjDstIn + DstLeft;
  3564. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  3565. LONG cx = DstRight - DstLeft;
  3566. LONG lDstStride = DeltaDstIn - (cx << 1);
  3567. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  3568. UCHAR ExpTable[4];
  3569. PUSHORT pusEndY = (PUSHORT)((PBYTE)pusDst + DeltaDstIn * cy);
  3570. LONG StartOffset = min(cx, (8 - ixStart));
  3571. //
  3572. // build exp table
  3573. //
  3574. *(PUSHORT)ExpTable = (USHORT)uB;
  3575. *(PUSHORT)(ExpTable+2) = (USHORT)uF;
  3576. do {
  3577. pusEnd = pusDst + cx;
  3578. //
  3579. // do starting pixels
  3580. //
  3581. if (ixStart) {
  3582. jSrc = *pjSrc << ixStart;
  3583. pjSrc++;
  3584. PUSHORT pusEndSt = pusDst + StartOffset;
  3585. do {
  3586. *pusDst = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1)));
  3587. pusDst++;
  3588. jSrc <<=1;
  3589. } while (pusDst != pusEndSt);
  3590. }
  3591. //
  3592. // number of full bytes that can be expanded
  3593. //
  3594. pusEnd8 = (PUSHORT)((PBYTE)pusDst + (((ULONG_PTR)pusEnd - (ULONG_PTR)pusDst) & ~0x0F));
  3595. //
  3596. // expand full bytes
  3597. //
  3598. while (pusDst != pusEnd8) {
  3599. jSrc = *pjSrc;
  3600. *(pusDst + 0) = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1)));
  3601. *(pusDst + 1) = *(PUSHORT)(ExpTable + ((jSrc & 0x40) >> (6-1)));
  3602. *(pusDst + 2) = *(PUSHORT)(ExpTable + ((jSrc & 0x20) >> (5-1)));
  3603. *(pusDst + 3) = *(PUSHORT)(ExpTable + ((jSrc & 0x10) >> (4-1)));
  3604. *(pusDst + 4) = *(PUSHORT)(ExpTable + ((jSrc & 0x08) >> (3-1)));
  3605. *(pusDst + 5) = *(PUSHORT)(ExpTable + ((jSrc & 0x04) >> (2-1)));
  3606. *(pusDst + 6) = *(PUSHORT)(ExpTable + ((jSrc & 0x02) >> (1-1)));
  3607. *(pusDst + 7) = *(PUSHORT)(ExpTable + ((jSrc & 0x01) << 1));
  3608. pjSrc++;
  3609. pusDst += 8;
  3610. }
  3611. //
  3612. // finish off scan line if needed
  3613. //
  3614. if (pusDst != pusEnd) {
  3615. jSrc = *pjSrc++;
  3616. do {
  3617. *pusDst = *(PUSHORT)(ExpTable + ((jSrc & 0x80) >> (7-1)));
  3618. jSrc<<=1;
  3619. pusDst++;
  3620. } while (pusDst != pusEnd);
  3621. }
  3622. pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride);
  3623. pjSrc += lSrcStride;
  3624. } while(pusDst != pusEndY);
  3625. }
  3626. /******************************Public*Routine******************************\
  3627. *
  3628. * Routine Name
  3629. *
  3630. * vSrcOpaqCopyS1D24
  3631. *
  3632. * Routine Description:
  3633. *
  3634. * Opaque blt of 1BPP src to destination format
  3635. *
  3636. * Arguments:
  3637. *
  3638. * pjSrcIn - pointer to beginning of current scan line of src buffer
  3639. * SrcLeft - left (starting) pixel in src rectangle
  3640. * DeltaSrcIn - bytes from one src scan line to next
  3641. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  3642. * DstLeft - left(first) dst pixel
  3643. * DstRight - right(last) dst pixel
  3644. * DeltaDstIn - bytes from one Dst scan line to next
  3645. * cy - number of scan lines
  3646. * uF - Foreground color
  3647. * uB - Background color
  3648. *
  3649. * Return Value:
  3650. *
  3651. * None
  3652. *
  3653. \**************************************************************************/
  3654. VOID
  3655. vSrcOpaqCopyS1D24(
  3656. PBYTE pjSrcIn,
  3657. LONG SrcLeft,
  3658. LONG DeltaSrcIn,
  3659. PBYTE pjDstIn,
  3660. LONG DstLeft,
  3661. LONG DstRight,
  3662. LONG DeltaDstIn,
  3663. LONG cy,
  3664. ULONG uF,
  3665. ULONG uB,
  3666. SURFACE *pSurf
  3667. )
  3668. {
  3669. BYTE jSrc;
  3670. BYTE F0,F1,F2;
  3671. BYTE B0,B1,B2;
  3672. LONG ixStart = SrcLeft & 0x07;
  3673. PBYTE pjEnd;
  3674. PBYTE pjEnd8;
  3675. PBYTE pjDst = pjDstIn + 3 * DstLeft;
  3676. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  3677. LONG cx = DstRight - DstLeft;
  3678. LONG lDstStride = DeltaDstIn - (cx * 3);
  3679. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  3680. UCHAR ExpTable[8];
  3681. PBYTE pjEndY = pjDst + DeltaDstIn * cy;
  3682. LONG StartOffset = 3 * (min(cx, (8 - ixStart)));
  3683. PBYTE pTable;
  3684. //
  3685. // build exp table
  3686. //
  3687. *(PULONG)ExpTable = uB;
  3688. *(PULONG)(ExpTable+4) = uF;
  3689. do {
  3690. pjEnd = pjDst + 3 * cx;
  3691. //
  3692. // do starting pixels
  3693. //
  3694. if (ixStart) {
  3695. jSrc = *pjSrc << ixStart;
  3696. pjSrc++;
  3697. PBYTE pjEndSt = pjDst + StartOffset;
  3698. do {
  3699. pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
  3700. *pjDst = *pTable;
  3701. *(pjDst+1) = *(pTable+1);
  3702. *(pjDst+2) = *(pTable+2);
  3703. pjDst += 3;
  3704. jSrc <<=1;
  3705. } while (pjDst != pjEndSt);
  3706. }
  3707. //
  3708. // number of full bytes that can be expanded
  3709. //
  3710. pjEnd8 = pjDst + (24 * (((ULONG_PTR)pjEnd - (ULONG_PTR)pjDst)/24));
  3711. //
  3712. // expand full bytes
  3713. //
  3714. while (pjDst != pjEnd8) {
  3715. jSrc = *pjSrc;
  3716. pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
  3717. *(pjDst + 0) = *pTable;
  3718. *(pjDst + 1) = *(pTable+1);
  3719. *(pjDst + 2) = *(pTable+2);
  3720. pTable = ExpTable + ((jSrc & 0x40) >> (6-2));
  3721. *(pjDst + 3) = *pTable;
  3722. *(pjDst + 4) = *(pTable+1);
  3723. *(pjDst + 5) = *(pTable+2);
  3724. pTable = ExpTable + ((jSrc & 0x20) >> (5-2));
  3725. *(pjDst + 6) = *pTable;
  3726. *(pjDst + 7) = *(pTable+1);
  3727. *(pjDst + 8) = *(pTable+2);
  3728. pTable = ExpTable + ((jSrc & 0x10) >> (4-2));
  3729. *(pjDst + 9) = *pTable;
  3730. *(pjDst + 10) = *(pTable+1);
  3731. *(pjDst + 11) = *(pTable+2);
  3732. pTable = ExpTable + ((jSrc & 0x08) >> (3-2));
  3733. *(pjDst + 12) = *pTable;
  3734. *(pjDst + 13) = *(pTable+1);
  3735. *(pjDst + 14) = *(pTable+2);
  3736. pTable = ExpTable + (jSrc & 0x04);
  3737. *(pjDst + 15) = *pTable;
  3738. *(pjDst + 16) = *(pTable+1);
  3739. *(pjDst + 17) = *(pTable+2);
  3740. pTable = ExpTable + ((jSrc & 0x02) << 1);
  3741. *(pjDst + 18) = *pTable;
  3742. *(pjDst + 19) = *(pTable+1);
  3743. *(pjDst + 20) = *(pTable+2);
  3744. pTable = ExpTable + ((jSrc & 0x01) << 2);
  3745. *(pjDst + 21) = *pTable;
  3746. *(pjDst + 22) = *(pTable+1);
  3747. *(pjDst + 23) = *(pTable+2);
  3748. pjSrc++;
  3749. pjDst += (3*8);
  3750. }
  3751. //
  3752. // finish off scan line if needed
  3753. //
  3754. if (pjDst != pjEnd) {
  3755. jSrc = *pjSrc++;
  3756. do {
  3757. pTable = ExpTable + ((jSrc & 0x80) >> (7-2));
  3758. *(pjDst + 0) = *pTable;
  3759. *(pjDst + 1) = *(pTable+1);
  3760. *(pjDst + 2) = *(pTable+2);
  3761. jSrc<<=1;
  3762. pjDst+= 3;
  3763. } while (pjDst != pjEnd);
  3764. }
  3765. pjDst = (PBYTE)((PBYTE)pjDst + lDstStride);
  3766. pjSrc += lSrcStride;
  3767. } while(pjDst != pjEndY);
  3768. }
  3769. /******************************Public*Routine******************************\
  3770. *
  3771. * Routine Name
  3772. *
  3773. * vSrcOpaqCopyS1D32
  3774. *
  3775. * Routine Description:
  3776. *
  3777. * Opaque blt of 1BPP src to destination format
  3778. *
  3779. * Arguments:
  3780. *
  3781. * pjSrcIn - pointer to beginning of current scan line of src buffer
  3782. * SrcLeft - left (starting) pixel in src rectangle
  3783. * DeltaSrcIn - bytes from one src scan line to next
  3784. * pjDstIn - pointer to beginning of current scan line of Dst buffer
  3785. * DstLeft - left(first) dst pixel
  3786. * DstRight - right(last) dst pixel
  3787. * DeltaDstIn - bytes from one Dst scan line to next
  3788. * cy - number of scan lines
  3789. * uF - Foreground color
  3790. * uB - Background color
  3791. *
  3792. * Return Value:
  3793. *
  3794. * None
  3795. *
  3796. \**************************************************************************/
  3797. VOID
  3798. vSrcOpaqCopyS1D32(
  3799. PBYTE pjSrcIn,
  3800. LONG SrcLeft,
  3801. LONG DeltaSrcIn,
  3802. PBYTE pjDstIn,
  3803. LONG DstLeft,
  3804. LONG DstRight,
  3805. LONG DeltaDstIn,
  3806. LONG cy,
  3807. ULONG uF,
  3808. ULONG uB,
  3809. SURFACE *pSurf
  3810. )
  3811. {
  3812. BYTE jSrc;
  3813. LONG ixStart = SrcLeft & 0x07;
  3814. PULONG pulEnd;
  3815. PULONG pulEnd8;
  3816. PULONG pulDst = (PULONG)pjDstIn + DstLeft;
  3817. PBYTE pjSrc = pjSrcIn + (SrcLeft >> 3);
  3818. LONG cx = DstRight - DstLeft;
  3819. LONG lDstStride = DeltaDstIn - (cx << 2);
  3820. LONG lSrcStride = DeltaSrcIn - ((cx + ixStart + 7) >> 3);
  3821. UCHAR ExpTable[8];
  3822. PULONG pulEndY = (PULONG)((PBYTE)pulDst + DeltaDstIn * cy);
  3823. LONG StartOffset = min(cx, (8 - ixStart));
  3824. //
  3825. // build exp table
  3826. //
  3827. *(PULONG)ExpTable = uB;
  3828. *(PULONG)(ExpTable+4) = uF;
  3829. do {
  3830. pulEnd = pulDst + cx;
  3831. //
  3832. // do starting pixels
  3833. //
  3834. if (ixStart) {
  3835. jSrc = *pjSrc << ixStart;
  3836. pjSrc++;
  3837. PULONG pulEndSt = pulDst + StartOffset;
  3838. do {
  3839. *pulDst = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2)));
  3840. pulDst++;
  3841. jSrc <<=1;
  3842. } while (pulDst != pulEndSt);
  3843. }
  3844. //
  3845. // number of full bytes that can be expanded
  3846. //
  3847. pulEnd8 = (PULONG)((PBYTE)pulDst + (((ULONG_PTR)pulEnd - (ULONG_PTR)pulDst) & ~0x1F));
  3848. //
  3849. // expand full bytes
  3850. //
  3851. while (pulDst != pulEnd8) {
  3852. jSrc = *pjSrc;
  3853. *(pulDst + 0) = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2)));
  3854. *(pulDst + 1) = *(PULONG)(ExpTable + ((jSrc & 0x40) >> (6-2)));
  3855. *(pulDst + 2) = *(PULONG)(ExpTable + ((jSrc & 0x20) >> (5-2)));
  3856. *(pulDst + 3) = *(PULONG)(ExpTable + ((jSrc & 0x10) >> (4-2)));
  3857. *(pulDst + 4) = *(PULONG)(ExpTable + ((jSrc & 0x08) >> (3-2)));
  3858. *(pulDst + 5) = *(PULONG)(ExpTable + ((jSrc & 0x04) >> (2-2)));
  3859. *(pulDst + 6) = *(PULONG)(ExpTable + ((jSrc & 0x02) << 1));
  3860. *(pulDst + 7) = *(PULONG)(ExpTable + ((jSrc & 0x01) << 2));
  3861. pjSrc++;
  3862. pulDst += 8;
  3863. }
  3864. //
  3865. // finish off scan line if needed
  3866. //
  3867. if (pulDst != pulEnd) {
  3868. jSrc = *pjSrc++;
  3869. do {
  3870. *pulDst = *(PULONG)(ExpTable + ((jSrc & 0x80) >> (7-2)));
  3871. jSrc<<=1;
  3872. pulDst++;
  3873. } while (pulDst != pulEnd);
  3874. }
  3875. pulDst = (PULONG)((PBYTE)pulDst + lDstStride);
  3876. pjSrc += lSrcStride;
  3877. } while(pulDst != pulEndY);
  3878. }
  3879. VOID vSrcTranCopyError(
  3880. PBYTE pjSrcIn,
  3881. LONG SrcLeft,
  3882. LONG DeltaSrcIn,
  3883. PBYTE pjDstIn,
  3884. LONG DstLeft,
  3885. LONG DstRight,
  3886. LONG DeltaDstIn,
  3887. LONG cy,
  3888. ULONG uF,
  3889. ULONG uB,
  3890. SURFACE *pSurf
  3891. )
  3892. {
  3893. /**/WARNING("!!vSrcTranCopyError!!\n");
  3894. }
  3895. /******************************Public*Routine******************************\
  3896. * vRectBlt
  3897. *
  3898. * 'Extra' rectangle on a monochrome dib.
  3899. *
  3900. * History:
  3901. * Thu Dec 03 11:22:21 1992 -by- Hock San Lee [hockl]
  3902. * Wrote it.
  3903. \**************************************************************************/
  3904. VOID vRectBlt
  3905. (
  3906. PBYTE pjMonoDib,
  3907. ULONG cjScanMono,
  3908. LONG xleft,
  3909. LONG ytop,
  3910. LONG xright,
  3911. LONG ybottom
  3912. )
  3913. {
  3914. PWORD pwDst;
  3915. ULONG cy = (ULONG) (ybottom - ytop);
  3916. //
  3917. // Left mask
  3918. //
  3919. static WORD awMaskL[16] = {
  3920. 0x0000, 0x0080, 0x00C0, 0x00E0, 0x00F0, 0x00F8, 0x00FC, 0x00FE,
  3921. 0x00FF, 0x80FF, 0xC0FF, 0xE0FF, 0xF0FF, 0xF8FF, 0xFCFF, 0xFEFF};
  3922. //
  3923. // Right mask
  3924. //
  3925. static WORD awMaskR[16] = {
  3926. 0xFFFF, 0xFF7F, 0xFF3F, 0xFF1F, 0xFF0F, 0xFF07, 0xFF03, 0xFF01,
  3927. 0xFF00, 0x7F00, 0x3F00, 0x1F00, 0x0F00, 0x0700, 0x0300, 0x0100};
  3928. ASSERTGDI(xleft < xright && ytop < ybottom, "vRectBlt: bad rectangle");
  3929. pjMonoDib += (ytop * cjScanMono);
  3930. pjMonoDib += (xleft >> 4 << 1);
  3931. //
  3932. // Since the mono dib is word-aligned, we will set one word at a time
  3933. // in the main loop.
  3934. //
  3935. LONG cWords = (xright >> 4) - ((xleft + 0xF) >> 4);
  3936. do {
  3937. pwDst = (PWORD) pjMonoDib;
  3938. pjMonoDib += cjScanMono;
  3939. //
  3940. // Handle the special case where both xleft and xright are in
  3941. // the same word and ((xleft & 0xF) != 0) and ((xright & 0xF) != 0).
  3942. //
  3943. if (cWords < 0)
  3944. {
  3945. WORD wMask = awMaskR[xleft & 0xF] & awMaskL[xright & 0xF];
  3946. *pwDst = *pwDst | wMask;
  3947. continue;
  3948. }
  3949. //
  3950. // Handle the first partial source word.
  3951. //
  3952. if (xleft & 0xF)
  3953. {
  3954. *pwDst = *pwDst | awMaskR[xleft & 0xF];
  3955. pwDst++;
  3956. }
  3957. //
  3958. // Handle the main loop for each source word.
  3959. //
  3960. for (LONG i = cWords; i > 0; i--) {
  3961. *pwDst++ = (WORD) ~0;
  3962. }
  3963. //
  3964. // Handle the last partial source word.
  3965. //
  3966. if (xright & 0xF) {
  3967. *pwDst = *pwDst | awMaskL[xright & 0xF];
  3968. }
  3969. } while (--cy);
  3970. }
  3971. VOID vRectBlt4
  3972. (
  3973. PBYTE pj4bpp,
  3974. ULONG cjScanMono,
  3975. LONG xleft,
  3976. LONG ytop,
  3977. LONG xright,
  3978. LONG ybottom
  3979. )
  3980. {
  3981. // Put in a rectangle by hand. This is a matter of setting each
  3982. // of the appropriate nibbles to 0xf
  3983. }
  3984. VOID vRectBlt8
  3985. (
  3986. PBYTE pj8bpp,
  3987. ULONG cjScanMono,
  3988. LONG xleft,
  3989. LONG ytop,
  3990. LONG xright,
  3991. LONG ybottom
  3992. )
  3993. {
  3994. // Put in a rectangle by hand. This is a matter of setting each
  3995. // of the appropriate pixels to ????
  3996. RIP("cleartype vRectBlt8 \n");
  3997. }
  3998. /******************************Public*Routine******************************\
  3999. * STROBJ_dwGetCodePage
  4000. *
  4001. * Code page corresponding to the current TextOut
  4002. *
  4003. * History:
  4004. * Wed Jan 24 11:09:21 1996 -by- Tessie Wu [tessiew]
  4005. * Wrote it.
  4006. \**************************************************************************/
  4007. extern "C" DWORD STROBJ_dwGetCodePage( STROBJ* pstro)
  4008. {
  4009. return ( ((ESTROBJ*)pstro)->dwCodePage );
  4010. }
  4011. /******************************Public*Routine******************************\
  4012. *
  4013. * more accelerators for ps driver:
  4014. *
  4015. * FIX APIENTRY STROBJ_fxCharacterExtra(STROBJ *pstro)
  4016. * FIX APIENTRY STROBJ_fxBreakExtra(STROBJ *pstro)
  4017. * Effects:
  4018. *
  4019. * History:
  4020. * 25-Oct-1996 -by- Bodin Dresevic [BodinD]
  4021. * Wrote it.
  4022. \**************************************************************************/
  4023. extern "C" FIX APIENTRY STROBJ_fxCharacterExtra(STROBJ *pstro)
  4024. {
  4025. if (((ESTROBJ*)pstro)->flAccel & SO_CHARACTER_EXTRA)
  4026. return ((ESTROBJ*)pstro)->xExtra;
  4027. else
  4028. return 0;
  4029. }
  4030. extern "C" FIX APIENTRY STROBJ_fxBreakExtra(STROBJ *pstro)
  4031. {
  4032. if (((ESTROBJ*)pstro)->flAccel & SO_BREAK_EXTRA)
  4033. return ((ESTROBJ*)pstro)->xBreakExtra;
  4034. else
  4035. return 0;
  4036. }