|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: text.c ! 3: * ! 4: * Optimized TextOut for the MIPS. Reduces the total number of memory writes ! 5: * required to output a glyph which significantly improves performance when ! 6: * using slower video memory. ! 7: * ! 8: * Copyright (c) 1992 Microsoft Corporation ! 9: \**************************************************************************/ ! 10: ! 11: #include "driver.h" ! 12: ! 13: // ! 14: // Define string object accelerator masks. ! 15: // ! 16: ! 17: #define SO_MASK \ ! 18: (SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \ ! 19: SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE) ! 20: ! 21: #define SO_LTOR (SO_MASK | SO_HORIZONTAL) ! 22: #define SO_RTOL (SO_LTOR | SO_REVERSED) ! 23: #define SO_TTOB (SO_MASK | SO_VERTICAL) ! 24: #define SO_BTOT (SO_TTOB | SO_REVERSED) ! 25: ! 26: // ! 27: // Define enumeration structure. ! 28: // ! 29: ! 30: #define BB_RECT_LIMIT 20 ! 31: ! 32: typedef struct _ENUMRECTLIST { ! 33: ULONG c; ! 34: RECTL arcl[BB_RECT_LIMIT]; ! 35: } ENUMRECTLIST; ! 36: ! 37: // ! 38: // Define function prototype for glyph output routines. ! 39: // ! 40: ! 41: typedef ! 42: VOID ! 43: (*PDRVP_GLYPHOUT_ROUTINE) ( ! 44: IN PBYTE DrawPoint, ! 45: IN PULONG GlyphBits, ! 46: IN ULONG GlyphWidth, ! 47: IN ULONG GlyphHeight ! 48: ); ! 49: ! 50: VOID ! 51: DrvpOutputGlyphTransparent ( ! 52: IN PBYTE DrawPoint, ! 53: IN PBYTE GlyphBitmap, ! 54: IN ULONG GlyphWidth, ! 55: IN ULONG GlyphHeight ! 56: ); ! 57: ! 58: // ! 59: // Define big endian color mask table conversion table. ! 60: // ! 61: ! 62: const ULONG DrvpColorMask[16] = { ! 63: 0x00000000, // 0000 -> 0000 ! 64: 0xff000000, // 0001 -> 1000 ! 65: 0x00ff0000, // 0010 -> 0100 ! 66: 0xffff0000, // 0011 -> 1100 ! 67: 0x0000ff00, // 0100 -> 0010 ! 68: 0xff00ff00, // 0101 -> 1010 ! 69: 0x00ffff00, // 0110 -> 0110 ! 70: 0xffffff00, // 0111 -> 1110 ! 71: 0x000000ff, // 1000 -> 0001 ! 72: 0xff0000ff, // 1001 -> 1001 ! 73: 0x00ff00ff, // 1010 -> 0101 ! 74: 0xffff00ff, // 1011 -> 1101 ! 75: 0x0000ffff, // 1100 -> 0011 ! 76: 0xff00ffff, // 1101 -> 1011 ! 77: 0x00ffffff, // 1110 -> 0111 ! 78: 0xffffffff}; // 1111 -> 1111 ! 79: ! 80: // ! 81: // Define draw color table that is generated for text output. ! 82: // ! 83: ! 84: ULONG DrvpDrawColorTable[16]; ! 85: ! 86: // ! 87: // Define foreground color for transparent output. ! 88: // ! 89: ! 90: ULONG DrvpForeGroundColor; ! 91: ! 92: // ! 93: // Define scanline width value. ! 94: // ! 95: ! 96: ULONG DrvpScanLineWidth; ! 97: ! 98: // ! 99: // Define global opaque glyph output routine address table. ! 100: // ! 101: ! 102: extern PDRVP_GLYPHOUT_ROUTINE DrvpOpaqueTable[8]; ! 103: ! 104: /******************************Public*Routine******************************\ ! 105: * DrvpIntersectRect ! 106: * ! 107: * This routine checks to see if the two specified retangles intersect. ! 108: * ! 109: * A value of TRUE is returned if the rectangles intersect. Otherwise, ! 110: * a value of FALSE is returned. ! 111: * ! 112: \**************************************************************************/ ! 113: ! 114: BOOL DrvpIntersectRect ( ! 115: IN PRECTL Rectl1, ! 116: IN PRECTL Rectl2, ! 117: OUT PRECTL DestRectl) ! 118: ! 119: { ! 120: ! 121: // ! 122: // Compute the maximum left edge and the minimum right edge. ! 123: // ! 124: ! 125: DestRectl->left = max(Rectl1->left, Rectl2->left); ! 126: DestRectl->right = min(Rectl1->right, Rectl2->right); ! 127: ! 128: // ! 129: // If the minimum right edge is greater than the maximum left edge, ! 130: // then the rectanges may intersect. Otherwise, they do not intersect. ! 131: // ! 132: ! 133: if (DestRectl->left < DestRectl->right) { ! 134: ! 135: // ! 136: // Compute the maximum top edge and the minimum bottom edge. ! 137: // ! 138: ! 139: DestRectl->top = max(Rectl1->top, Rectl2->top); ! 140: DestRectl->bottom = min(Rectl1->bottom, Rectl2->bottom); ! 141: ! 142: // ! 143: // If the minimum bottom edge is greater than the maximum top ! 144: // edge, then the rectanges intersect. Otherwise, they do not ! 145: // intersect. ! 146: // ! 147: ! 148: if (DestRectl->top < DestRectl->bottom) { ! 149: return TRUE; ! 150: } ! 151: } ! 152: ! 153: return FALSE; ! 154: } ! 155: ! 156: /******************************Public*Routine******************************\ ! 157: * DrvpSolidColorFill ! 158: * ! 159: * Routine Description: ! 160: * ! 161: * This routine fills a rectangle with a solid color. ! 162: * ! 163: * Arguments: ! 164: * ! 165: * Rectangle - Supplies a pointer to a rectangle. ! 166: * ! 167: * FillColor - Supplies the fill color. ! 168: * ! 169: * ! 170: * Return Value: ! 171: * ! 172: * None. ! 173: * ! 174: \**************************************************************************/ ! 175: ! 176: VOID DrvpSolidColorFill ( ! 177: IN SURFOBJ *pso, ! 178: IN PRECTL Rectangle, ! 179: IN ULONG FillColor) ! 180: ! 181: { ! 182: ! 183: PUCHAR Destination; ! 184: ULONG Index; ! 185: ULONG Length; ! 186: LONG lDelta = pso->lDelta; ! 187: ! 188: // ! 189: // Compute rectangle fill parameters and fill rectangle with solid color. ! 190: // ! 191: ! 192: Destination = ((PBYTE) pso->pvScan0) + (Rectangle->top * lDelta) + Rectangle->left; ! 193: Length = Rectangle->right - Rectangle->left; ! 194: for (Index = 0; Index < (Rectangle->bottom - Rectangle->top); Index += 1) { ! 195: RtlFillMemory((PVOID)Destination, Length, FillColor); ! 196: Destination += lDelta; ! 197: } ! 198: ! 199: return; ! 200: } ! 201: ! 202: /******************************Public*Routine******************************\ ! 203: * DrvpEqualRectangle ! 204: * ! 205: * This routine compares two rectangles for equality. ! 206: * ! 207: \**************************************************************************/ ! 208: ! 209: BOOL DrvpEqualRectangle ( ! 210: IN RECTL *prcl1, ! 211: IN RECTL *prcl2) ! 212: ! 213: { ! 214: ! 215: if ((prcl1->left == prcl2->left) && (prcl1->right == prcl2->right) && ! 216: (prcl1->bottom == prcl2->bottom) && (prcl1->top == prcl2->top)) { ! 217: return TRUE; ! 218: ! 219: } else { ! 220: return FALSE; ! 221: } ! 222: } ! 223: ! 224: /******************************Public*Routine******************************\ ! 225: * DrvpFillRectangle ! 226: * ! 227: * This routine fills a rectangle with clipping. ! 228: * ! 229: \**************************************************************************/ ! 230: ! 231: VOID DrvpFillRectangle ( ! 232: IN SURFOBJ *pso, ! 233: IN CLIPOBJ *pco, ! 234: IN RECTL *prcl, ! 235: IN BRUSHOBJ *pbo) ! 236: ! 237: { ! 238: ! 239: ENUMRECTLIST ClipEnum; ! 240: RECTL Region; ! 241: ULONG Index; ! 242: BOOL More; ! 243: ULONG iDComplexity; ! 244: ! 245: if (pco) { ! 246: iDComplexity = pco->iDComplexity; ! 247: ! 248: } else { ! 249: iDComplexity = DC_TRIVIAL; ! 250: } ! 251: ! 252: ! 253: // ! 254: // Clip and fill the rectangle with the specified color. ! 255: // ! 256: ! 257: switch(iDComplexity) { ! 258: case DC_TRIVIAL: ! 259: DrvpSolidColorFill(pso, prcl, pbo->iSolidColor); ! 260: return; ! 261: ! 262: case DC_RECT: ! 263: More = FALSE; ! 264: ClipEnum.c = 1; ! 265: ClipEnum.arcl[0] = pco->rclBounds; ! 266: break; ! 267: ! 268: case DC_COMPLEX: ! 269: More = TRUE; ! 270: CLIPOBJ_cEnumStart(pco, ! 271: FALSE, ! 272: CT_RECTANGLES, ! 273: CD_LEFTWARDS, ! 274: BB_RECT_LIMIT); ! 275: ! 276: break; ! 277: } ! 278: ! 279: // ! 280: // Do a solid color fill for each nonclipped region. ! 281: // ! 282: ! 283: do { ! 284: ! 285: // ! 286: // If more clip regions is TRUE, then get the next batch of ! 287: // clipping regions. ! 288: // ! 289: ! 290: if (More != FALSE) { ! 291: More = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum); ! 292: } ! 293: ! 294: // ! 295: // If the clipping is not trival, then do the clipping for the ! 296: // next region and do the solid fill. Otherwise, do the solid ! 297: // fill with no clipping. ! 298: // ! 299: ! 300: for (Index = 0; Index < ClipEnum.c; Index += 1) { ! 301: if (DrvpIntersectRect(&ClipEnum.arcl[Index], ! 302: prcl, ! 303: &Region)) { ! 304: DrvpSolidColorFill(pso, &Region, pbo->iSolidColor); ! 305: } ! 306: } ! 307: ! 308: } while (More); ! 309: return; ! 310: } ! 311: ! 312: /******************************Public*Routine******************************\ ! 313: * DrvTextOut ! 314: * ! 315: * This routine outputs text to the screen. ! 316: * ! 317: * History: ! 318: * 07-Jul-1992 -by- David N. Cutler [davec] ! 319: * Wrote it. ! 320: \**************************************************************************/ ! 321: ! 322: BOOL DrvTextOut ( ! 323: IN SURFOBJ *pso, ! 324: IN STROBJ *pstro, ! 325: IN FONTOBJ *pfo, ! 326: IN CLIPOBJ *pco, ! 327: IN RECTL *prclExtra, ! 328: IN RECTL *prclOpaque, ! 329: IN BRUSHOBJ *pboFore, ! 330: IN BRUSHOBJ *pboOpaque, ! 331: IN POINTL *pptlOrg, ! 332: IN MIX mix) ! 333: ! 334: { ! 335: ! 336: ULONG BackGroundColor; ! 337: PBYTE DrawPoint; ! 338: FONTINFO FontInformation; ! 339: ULONG ForeGroundColor; ! 340: ULONG GlyphCount; ! 341: PGLYPHPOS GlyphEnd; ! 342: ULONG GlyphHeight; ! 343: PGLYPHPOS GlyphList; ! 344: PDRVP_GLYPHOUT_ROUTINE GlyphOutputRoutine; ! 345: PGLYPHPOS GlyphStart; ! 346: ULONG GlyphWidth; ! 347: LONG GlyphStride; ! 348: ULONG Index; ! 349: BOOL More; ! 350: RECTL OpaqueRectl; ! 351: LONG OriginX; ! 352: LONG OriginY; ! 353: PBYTE pjScreenBase; ! 354: GLYPHBITS *pgb; ! 355: ! 356: // ! 357: // DrvTextOut will only get called with solid color brushes and ! 358: // the mix mode being the simplest R2_COPYPEN. The driver must ! 359: // set a capabilities bit to get called with more complicated ! 360: // mix brushes. ! 361: // ! 362: ! 363: // ASSERT(pboFore->iSolidColor != 0xffffffff); ! 364: // ASSERT(pboOpaque->iSolidColor != 0xffffffff); ! 365: // ASSERT(mix == ((R2_COPYPEN << 8) | R2_COPYPEN)); ! 366: ! 367: // ! 368: // If the complexity of the clipping is not trival, then let GDI ! 369: // process the request. ! 370: // ! 371: ! 372: if (pco->iDComplexity != DC_TRIVIAL) { ! 373: return(EngTextOut(pso, ! 374: pstro, ! 375: pfo, ! 376: pco, ! 377: prclExtra, ! 378: prclOpaque, ! 379: pboFore, ! 380: pboOpaque, ! 381: pptlOrg, ! 382: mix)); ! 383: } ! 384: ! 385: // ! 386: // The foreground color is used for the text and extra rectangle ! 387: // if it specified. The background color is used for the opaque ! 388: // rectangle. If the foreground color is not a solid color brush ! 389: // or the opaque rectangle is specified and is not a solid color ! 390: // brush, then let GDI process the request. ! 391: // ! 392: ! 393: DrvpScanLineWidth = pso->lDelta; ! 394: pjScreenBase = pso->pvScan0; ! 395: ! 396: // ! 397: // Check if the background and foreground can be draw at the same time. ! 398: // ! 399: ! 400: ForeGroundColor = pboFore->iSolidColor; ! 401: ForeGroundColor |= (ForeGroundColor << 8); ! 402: ForeGroundColor |= (ForeGroundColor << 16); ! 403: if (((pstro->flAccel == SO_LTOR) || (pstro->flAccel == SO_RTOL) || ! 404: (pstro->flAccel == SO_TTOB) || (pstro->flAccel == SO_BTOT)) && ! 405: (prclOpaque != NULL) && (pfo->cxMax <= 32)) { ! 406: ! 407: // ! 408: // The background and the foreground can be draw at the same ! 409: // time. Generate the drawing color table and draw the text ! 410: // opaquely. ! 411: // ! 412: ! 413: BackGroundColor = pboOpaque->iSolidColor; ! 414: BackGroundColor |= (BackGroundColor << 8); ! 415: BackGroundColor |= (BackGroundColor << 16); ! 416: for (Index = 0; Index < 16; Index += 1) { ! 417: DrvpDrawColorTable[Index] = ! 418: (ForeGroundColor & DrvpColorMask[Index]) | ! 419: (BackGroundColor & (~DrvpColorMask[Index])); ! 420: } ! 421: ! 422: // ! 423: // If the top of the opaque rectangle is less than the top of the ! 424: // background rectangle, then fill the region between the top of ! 425: // opaque rectangle and the top of the background rectangle and ! 426: // reduce the size of the opaque rectangle. ! 427: // ! 428: ! 429: OpaqueRectl = *prclOpaque; ! 430: if (OpaqueRectl.top < pstro->rclBkGround.top) { ! 431: OpaqueRectl.bottom = pstro->rclBkGround.top; ! 432: DrvpFillRectangle(pso,pco, &OpaqueRectl, pboOpaque); ! 433: OpaqueRectl.top = pstro->rclBkGround.top; ! 434: OpaqueRectl.bottom = prclOpaque->bottom; ! 435: } ! 436: ! 437: // ! 438: // If the bottom of the opaque rectangle is greater than the bottom ! 439: // of the background rectangle, then fill the region between the ! 440: // bottom of the background rectangle and the bottom of the opaque ! 441: // rectangle and reduce the size of the opaque rectangle. ! 442: // ! 443: ! 444: if (OpaqueRectl.bottom > pstro->rclBkGround.bottom) { ! 445: OpaqueRectl.top = pstro->rclBkGround.bottom; ! 446: DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque); ! 447: OpaqueRectl.top = pstro->rclBkGround.top; ! 448: OpaqueRectl.bottom = pstro->rclBkGround.bottom; ! 449: } ! 450: ! 451: // ! 452: // If the left of the opaque rectangle is less than the left of ! 453: // the background rectangle, then fill the region between the ! 454: // left of the opaque rectangle and the left of the background ! 455: // rectangle. ! 456: // ! 457: ! 458: if (OpaqueRectl.left < pstro->rclBkGround.left) { ! 459: OpaqueRectl.right = pstro->rclBkGround.left; ! 460: DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque); ! 461: OpaqueRectl.right = prclOpaque->right; ! 462: } ! 463: ! 464: // ! 465: // If the right of the opaque rectangle is greater than the right ! 466: // of the background rectangle, then fill the region between the ! 467: // right of the opaque rectangle and the right of the background ! 468: // rectangle. ! 469: // ! 470: ! 471: if (OpaqueRectl.right > pstro->rclBkGround.right) { ! 472: OpaqueRectl.left = pstro->rclBkGround.right; ! 473: DrvpFillRectangle(pso, pco, &OpaqueRectl, pboOpaque); ! 474: } ! 475: ! 476: // ! 477: // If the font is fixed pitch, then optimize the computation of ! 478: // x and y coordinate values. Otherwise, compute the x and y values ! 479: // for each glyph. ! 480: // ! 481: ! 482: if (pstro->ulCharInc != 0) { ! 483: ! 484: // ! 485: // The font is fixed pitch. Capture the glyph dimensions and ! 486: // compute the starting display address. ! 487: // ! 488: ! 489: if (pstro->pgp == NULL) { ! 490: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 491: ! 492: } else { ! 493: GlyphCount = pstro->cGlyphs; ! 494: GlyphList = pstro->pgp; ! 495: More = FALSE; ! 496: } ! 497: ! 498: pgb = GlyphList->pgdf->pgb; ! 499: GlyphWidth = pgb->sizlBitmap.cx; ! 500: GlyphHeight = pgb->sizlBitmap.cy; ! 501: OriginX = GlyphList->ptl.x + pgb->ptlOrigin.x; ! 502: OriginY = GlyphList->ptl.y + pgb->ptlOrigin.y; ! 503: DrawPoint = pjScreenBase + ((OriginY * DrvpScanLineWidth) + OriginX); ! 504: ! 505: // ! 506: // Compute the glyph stride. ! 507: // ! 508: ! 509: GlyphStride = pstro->ulCharInc; ! 510: if ((pstro->flAccel & SO_VERTICAL) != 0) { ! 511: GlyphStride *= DrvpScanLineWidth; ! 512: } ! 513: ! 514: // ! 515: // If the direction of drawing is reversed, then the stride is ! 516: // negative. ! 517: // ! 518: ! 519: if ((pstro->flAccel & SO_REVERSED) != 0) { ! 520: GlyphStride = - GlyphStride; ! 521: } ! 522: ! 523: // ! 524: // Output the initial set of glyphs. ! 525: // ! 526: ! 527: GlyphOutputRoutine = DrvpOpaqueTable[(GlyphWidth - 1) >> 2]; ! 528: GlyphEnd = &GlyphList[GlyphCount]; ! 529: GlyphStart = GlyphList; ! 530: do { ! 531: pgb = GlyphStart->pgdf->pgb; ! 532: (GlyphOutputRoutine)(DrawPoint, ! 533: (PULONG)&pgb->aj[0], ! 534: GlyphWidth, ! 535: GlyphHeight); ! 536: ! 537: DrawPoint += GlyphStride; ! 538: GlyphStart += 1; ! 539: } while (GlyphStart != GlyphEnd); ! 540: ! 541: // ! 542: // Output the subsequent set of glyphs. ! 543: // ! 544: ! 545: while (More) { ! 546: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 547: GlyphEnd = &GlyphList[GlyphCount]; ! 548: GlyphStart = GlyphList; ! 549: do { ! 550: pgb = GlyphStart->pgdf->pgb; ! 551: (GlyphOutputRoutine)(DrawPoint, ! 552: (PULONG)&pgb->aj[0], ! 553: GlyphWidth, ! 554: GlyphHeight); ! 555: ! 556: DrawPoint += GlyphStride; ! 557: GlyphStart += 1; ! 558: } while (GlyphStart != GlyphEnd); ! 559: } ! 560: ! 561: } else { ! 562: ! 563: // ! 564: // The font is not fixed pitch. Compute the x and y values for ! 565: // each glyph individually. ! 566: // ! 567: ! 568: do { ! 569: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 570: GlyphEnd = &GlyphList[GlyphCount]; ! 571: GlyphStart = GlyphList; ! 572: do { ! 573: pgb = GlyphStart->pgdf->pgb; ! 574: OriginX = GlyphStart->ptl.x + pgb->ptlOrigin.x; ! 575: OriginY = GlyphStart->ptl.y + pgb->ptlOrigin.y; ! 576: DrawPoint = pjScreenBase + ! 577: ((OriginY * DrvpScanLineWidth) + OriginX); ! 578: ! 579: GlyphWidth = pgb->sizlBitmap.cx; ! 580: GlyphOutputRoutine = DrvpOpaqueTable[(GlyphWidth - 1) >> 2]; ! 581: (GlyphOutputRoutine)(DrawPoint, ! 582: (PULONG)&pgb->aj[0], ! 583: GlyphWidth, ! 584: pgb->sizlBitmap.cy); ! 585: ! 586: GlyphStart += 1; ! 587: } while(GlyphStart != GlyphEnd); ! 588: } while(More); ! 589: } ! 590: ! 591: } else { ! 592: ! 593: // ! 594: // The background and the foreground cannot be draw at the same ! 595: // time. Set the foreground color and fill the background rectangle, ! 596: // if specified, and then draw the text transparently. ! 597: // ! 598: ! 599: DrvpForeGroundColor = ForeGroundColor; ! 600: if (prclOpaque != NULL) { ! 601: DrvpFillRectangle(pso, pco, prclOpaque, pboOpaque); ! 602: } ! 603: ! 604: // ! 605: // If the font is fixed pitch, then optimize the computation of ! 606: // x and y coordinate values. Otherwise, compute the x and y values ! 607: // for each glyph. ! 608: // ! 609: ! 610: if (pstro->ulCharInc != 0) { ! 611: ! 612: // ! 613: // The font is fixed pitch. Capture the glyph dimensions and ! 614: // compute the starting display address. ! 615: // ! 616: ! 617: if (pstro->pgp == NULL) { ! 618: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 619: ! 620: } else { ! 621: GlyphCount = pstro->cGlyphs; ! 622: GlyphList = pstro->pgp; ! 623: More = FALSE; ! 624: } ! 625: ! 626: pgb = GlyphList->pgdf->pgb; ! 627: GlyphWidth = pgb->sizlBitmap.cx; ! 628: GlyphHeight = pgb->sizlBitmap.cy; ! 629: OriginX = GlyphList->ptl.x + pgb->ptlOrigin.x; ! 630: OriginY = GlyphList->ptl.y + pgb->ptlOrigin.y; ! 631: DrawPoint = pjScreenBase + ((OriginY * DrvpScanLineWidth) + OriginX); ! 632: ! 633: // ! 634: // Compute the glyph stride. ! 635: // ! 636: ! 637: GlyphStride = pstro->ulCharInc; ! 638: if ((pstro->flAccel & SO_VERTICAL) != 0) { ! 639: GlyphStride *= DrvpScanLineWidth; ! 640: } ! 641: ! 642: // ! 643: // If the direction of drawing is reversed, then the stride is ! 644: // negative. ! 645: // ! 646: ! 647: if ((pstro->flAccel & SO_REVERSED) != 0) { ! 648: GlyphStride = -GlyphStride; ! 649: } ! 650: ! 651: // ! 652: // Output the initial set of glyphs. ! 653: // ! 654: ! 655: GlyphEnd = &GlyphList[GlyphCount]; ! 656: GlyphStart = GlyphList; ! 657: do { ! 658: pgb = GlyphStart->pgdf->pgb; ! 659: DrvpOutputGlyphTransparent(DrawPoint, ! 660: &pgb->aj[0], ! 661: GlyphWidth, ! 662: GlyphHeight); ! 663: ! 664: DrawPoint += GlyphStride; ! 665: GlyphStart += 1; ! 666: } while (GlyphStart != GlyphEnd); ! 667: ! 668: // ! 669: // Output the subsequent set of glyphs. ! 670: // ! 671: ! 672: while (More) { ! 673: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 674: GlyphEnd = &GlyphList[GlyphCount]; ! 675: GlyphStart = GlyphList; ! 676: do { ! 677: pgb = GlyphStart->pgdf->pgb; ! 678: DrvpOutputGlyphTransparent(DrawPoint, ! 679: &pgb->aj[0], ! 680: GlyphWidth, ! 681: GlyphHeight); ! 682: ! 683: DrawPoint += GlyphStride; ! 684: GlyphStart += 1; ! 685: } while (GlyphStart != GlyphEnd); ! 686: } ! 687: ! 688: } else { ! 689: ! 690: // ! 691: // The font is not fixed pitch. Compute the x and y values for ! 692: // each glyph individually. ! 693: // ! 694: ! 695: do { ! 696: More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList); ! 697: GlyphEnd = &GlyphList[GlyphCount]; ! 698: GlyphStart = GlyphList; ! 699: do { ! 700: pgb = GlyphStart->pgdf->pgb; ! 701: OriginX = GlyphStart->ptl.x + pgb->ptlOrigin.x; ! 702: OriginY = GlyphStart->ptl.y + pgb->ptlOrigin.y; ! 703: DrawPoint = pjScreenBase + ! 704: ((OriginY * DrvpScanLineWidth) + OriginX); ! 705: ! 706: DrvpOutputGlyphTransparent(DrawPoint, ! 707: &pgb->aj[0], ! 708: pgb->sizlBitmap.cx, ! 709: pgb->sizlBitmap.cy); ! 710: ! 711: GlyphStart += 1; ! 712: } while(GlyphStart != GlyphEnd); ! 713: } while(More); ! 714: } ! 715: } ! 716: ! 717: // ! 718: // Fill the extra rectangles if specified. ! 719: // ! 720: ! 721: if (prclExtra != (PRECTL)NULL) { ! 722: while (prclExtra->left != prclExtra->right) { ! 723: DrvpFillRectangle(pso, pco, prclExtra, pboFore); ! 724: prclExtra += 1; ! 725: } ! 726: } ! 727: ! 728: return(TRUE); ! 729: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.