|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1991-1992 Microsoft Corporation
4:
5: Module Name:
6:
7: Text.c
8:
9: Abstract:
10:
11: This module attempts to cache fonts on the VXL video board and draw glyphs
12: using hardware acceleration,
13: If the font cannot be cached the Engine is called to draw the glyphs.
14:
15: Environment:
16:
17:
18: Revision History:
19:
20: --*/
21:
22: #include "driver.h"
23: #include "jzvxl484.h"
24:
25: //
26: // The following macro is the hash function for computing the cache
27: // index from a Glyph Handle and FontId.
28: //
29:
30: #define HASH_FUNCTION(GlyphHandle,FontId) \
31: ((GlyphHandle & 0x7FF) << 1) + \
32: FontId + \
33: (FontId << 7)
34:
35:
36:
37: //#define CACHE_STATS
38:
39: //
40: // Define string object accelerator masks.
41: //
42:
43: #define SO_MASK \
44: (SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \
45: SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE)
46:
47: #define SO_LTOR (SO_MASK | SO_HORIZONTAL)
48: #define SO_RTOL (SO_LTOR | SO_REVERSED)
49: #define SO_TTOB (SO_MASK | SO_VERTICAL)
50: #define SO_BTOT (SO_TTOB | SO_REVERSED)
51:
52: static ULONG TextForegroundColor = 0xFFFFFFFF;
53: static ULONG TextBackgroundColor = 0xFFFFFFFF;
54:
55: #ifdef CACHE_STATS
56: static ULONG CacheUnused = Vxl.CacheSize;
57: static ULONG CharCount = 0;
58: static ULONG CacheMisses = 0;
59: static ULONG CacheReplacement = 0;
60: static ULONG ReplacementTotal = 0;
61: static ULONG CharTotal = 0;
62: static ULONG MissTotal = 0;
63: static ULONG HigherFontId = 0;
64: static ULONG HigherGlyphHandle = 0;
65: #endif
66:
67: static UCHAR ToBigEndian[256] = {
68: 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
69: 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
70: 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
71: 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
72: 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
73: 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
74: 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
75: 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
76: 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
77: 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
78: 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
79: 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
80: 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
81: 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
82: 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
83: 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
84: };
85:
86:
87:
88: BOOL
89: DrvTextOut
90: (
91: IN SURFOBJ *pso,
92: IN STROBJ *pstro,
93: IN FONTOBJ *pfo,
94: IN CLIPOBJ *pco,
95: IN RECTL *prclExtra,
96: IN RECTL *prclOpaque,
97: IN BRUSHOBJ *pboFore,
98: IN BRUSHOBJ *pboOpaque,
99: IN POINTL *pptlOrg,
100: IN MIX mix
101: )
102: /*++
103:
104: Routine Description:
105:
106: This function will cache fonts on the VXL video board and use accelerator
107: hardware to draw each glyph. An attemp is made to use opaque mode
108: text output to draw text and background color at the same time. If this
109: cannot be done then glyph forground and backgrounds are drawn spearately.
110:
111: Arguments:
112:
113: MIX is not checked. Since the GCAPS_ARBMIXTEXT capability bit is not
114: set, mix mode is always R2_COPYPEN.
115:
116: Return Value:
117:
118:
119: --*/
120:
121: {
122: BOOL bMoreGlyphs;
123: LONG LineIndex;
124: ULONG ByteIndex;
125: PGLYPHPOS GlyphPosList;
126: ULONG GlyphCount;
127: ULONG GlyphHandle;
128: ULONG CacheIndex;
129: ULONG FontId;
130: GLYPHBITS *FontBitMap;
131: PBYTE BitMapPtr;
132: ULONG X,Y;
133: BOOL Allocate;
134: PULONG CacheData;
135: ULONG BitMapData;
136: ULONG SrcAdr,DstAdr,XYCmd,Cmd;
137: PGLYPHPOS GlyphEnd;
138: PGLYPHPOS GlyphStart;
139: LONG GlyphStride;
140: RECTL OpaqueRectl;
141: ULONG GlyphBytesPerScan,ShiftAmount;
142:
143: //
144: // Make sure the surface is the screen.
145: //
146:
147: if (pso->pvBits != (PVOID)Vxl.ScreenBase) {
148: goto DevFailTextOut;
149: }
150:
151: //
152: // If the width of the glyph is bigger than what the accelerator supports
153: // The font is non cacheable
154: // Clipping is not trivial OR
155: // SolidColor is a brush.
156: // call GDI to draw the text.
157: //
158:
159:
160: if ((pfo->cxMax > 32) ||
161: (pfo->flFontType & DEVICE_FONTTYPE) ||
162: (pco->iDComplexity != DC_TRIVIAL) ||
163: (pboFore->iSolidColor == 0xFFFFFFFFL)) {
164:
165: goto DevFailTextOut;
166: }
167:
168: //
169: // Set Jaguar foreground color only if it changed since the
170: // previous call. Changing Foreground/Background color requires
171: // synchronization.
172: //
173:
174: if (TextForegroundColor != pboFore->iSolidColor) {
175: TextForegroundColor = pboFore->iSolidColor;
176: DevSetFgColor(TextForegroundColor);
177: }
178:
179: //
180: // Check that the Background color is solid.
181: // Set Jaguar Background color if it changed.
182: //
183:
184: if (prclOpaque != (PRECTL) NULL) {
185: if (pboOpaque->iSolidColor == 0xFFFFFFFFL) {
186: goto DevFailTextOut;
187: }
188: if (TextBackgroundColor != pboOpaque->iSolidColor) {
189: TextBackgroundColor = pboOpaque->iSolidColor;
190: DevSetBgColor(TextBackgroundColor);
191: }
192: }
193:
194: //
195: // enumerate the string psto into glyphs (GLYPHPOS), then send a draw
196: // command for each. Deal with clipping later.
197: //
198:
199: FontId = pfo->iUniq;
200: #ifdef CACHE_STATS
201: if (FontId > HigherFontId) {
202: HigherFontId = FontId;
203: }
204: #endif
205: if (((pstro->flAccel == SO_LTOR) || (pstro->flAccel == SO_RTOL) ||
206: (pstro->flAccel == SO_TTOB) || (pstro->flAccel == SO_BTOT)) &&
207: (prclOpaque != NULL)) {
208:
209: //
210: // If the top of the opaque rectangle is less than the top of the
211: // background rectangle, then fill the region between the top of
212: // opaque rectangle and the top of the background rectangle and
213: // reduce the size of the opaque rectangle.
214: //
215:
216: OpaqueRectl = *prclOpaque;
217: if (OpaqueRectl.top < pstro->rclBkGround.top) {
218: OpaqueRectl.bottom = pstro->rclBkGround.top;
219: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
220: OpaqueRectl.top = pstro->rclBkGround.top;
221: OpaqueRectl.bottom = prclOpaque->bottom;
222: }
223:
224: //
225: // If the bottom of the opaque rectangle is greater than the bottom
226: // of the background rectangle, then fill the region between the
227: // bottom of the background rectangle and the bottom of the opaque
228: // rectangle and reduce the size of the opaque rectangle.
229: //
230:
231: if (OpaqueRectl.bottom > pstro->rclBkGround.bottom) {
232: OpaqueRectl.top = pstro->rclBkGround.bottom;
233: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
234: OpaqueRectl.top = pstro->rclBkGround.top;
235: OpaqueRectl.bottom = pstro->rclBkGround.bottom;
236: }
237:
238: //
239: // If the left of the opaque rectangle is less than the left of
240: // the background rectangle, then fill the region between the
241: // left of the opaque rectangle and the left of the background
242: // rectangle.
243: //
244:
245: if (OpaqueRectl.left < pstro->rclBkGround.left) {
246: OpaqueRectl.right = pstro->rclBkGround.left;
247: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
248: OpaqueRectl.right = prclOpaque->right;
249: }
250:
251: //
252: // If the right of the opaque rectangle is greater than the right
253: // of the background rectangle, then fill the region between the
254: // right of the opaque rectangle and the right of the background
255: // rectangle.
256: //
257:
258: if (OpaqueRectl.right > pstro->rclBkGround.right) {
259: OpaqueRectl.left = pstro->rclBkGround.right;
260: DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
261: }
262:
263: Cmd = JAGUAR_TEXT_OPAQUE << XYCMD_CMD_SHIFT;
264:
265: } else {
266:
267: //
268: // We now have a cacheable font and drawable rectangles, first clip and draw
269: // all opaque rectangles.
270: //
271:
272: if (prclOpaque != (PRECTL)NULL) {
273:
274: DrvpFillRectangle(prclOpaque,pboOpaque->iSolidColor);
275:
276: }
277: Cmd = JAGUAR_TEXT_TRANSPARENT << XYCMD_CMD_SHIFT;
278: }
279:
280: //
281: // If the font is fixed pitch, then optimize the computation of
282: // x and y coordinate values. Otherwise, compute the x and y values
283: // for each glyph.
284: //
285:
286: if (pstro->ulCharInc != 0) {
287:
288: //
289: // The font is fixed pitch. Capture the glyph dimensions and
290: // compute the starting display address.
291: //
292:
293: if (pstro->pgp == NULL) {
294: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList);
295:
296: } else {
297: GlyphCount = pstro->cGlyphs;
298: GlyphPosList = pstro->pgp;
299: bMoreGlyphs = FALSE;
300: }
301:
302: #ifdef CACHE_STATS
303: CharCount += GlyphCount;
304: #endif
305:
306: FontBitMap = GlyphPosList->pgdf->pgb;
307: X = FontBitMap->sizlBitmap.cx;
308: Y = FontBitMap->sizlBitmap.cy;
309:
310: DstAdr = ((GlyphPosList->ptl.y + FontBitMap->ptlOrigin.y) * Vxl.JaguarScreenX) +
311: ((GlyphPosList->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift) ;
312:
313: //
314: // Compute the glyph stride.
315: //
316:
317: GlyphStride = ((pstro->ulCharInc) << Vxl.ColorModeShift);
318: if ((pstro->flAccel & SO_VERTICAL) != 0) {
319: GlyphStride *= Vxl.JaguarScreenX;
320: }
321:
322: //
323: // If the direction of drawing is reversed, then the stride is
324: // negative.
325: //
326:
327: if ((pstro->flAccel & SO_REVERSED) != 0) {
328: GlyphStride = -GlyphStride;
329: }
330:
331: //
332: // Output the set of glyphs.
333: //
334:
335: do {
336: GlyphEnd = &GlyphPosList[GlyphCount];
337: GlyphStart = GlyphPosList;
338: do {
339:
340: GlyphHandle = (ULONG) (GlyphStart->hg);
341:
342: CacheIndex = HASH_FUNCTION(GlyphHandle,FontId);
343:
344: CacheIndex &= Vxl.CacheIndexMask;
345:
346: //
347: // Get glyph info
348: //
349:
350: FontBitMap = GlyphStart->pgdf->pgb;
351:
352: //
353: // If FontId or GlyphHandle don't match, cache this glyph.
354: //
355:
356: if (Vxl.CacheTag[CacheIndex].FontId != FontId) {
357: Allocate = TRUE;
358: } else {
359: if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) {
360: Allocate = TRUE;
361: } else {
362: Allocate = FALSE;
363: }
364: }
365: if (Allocate) {
366:
367: //
368: // Wait for the accelerator to be idle to ensure
369: // that the glyph being replaced is not in use.
370: //
371:
372: WaitForJaguarIdle();
373:
374: #ifdef CACHE_STATS
375: CacheMisses++;
376:
377: if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) {
378: CacheUnused--;
379: } else {
380: CacheReplacement++;
381: }
382:
383: if (Vxl.CacheTag[CacheIndex].FontId == FontId) {
384: DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n",
385: Vxl.CacheTag[CacheIndex].FontId,
386: FontId));
387: }
388:
389: if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) {
390: DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n",
391: GlyphHandle,
392: Vxl.CacheTag[CacheIndex].FontId,
393: FontId));
394: }
395:
396: if (GlyphHandle > HigherGlyphHandle) {
397: HigherGlyphHandle = GlyphHandle;
398: }
399: #endif
400: //
401: // if the entry that needs to be replaced
402: // is used as extension for a glyph > 32 lines
403: // go backwards and clear the Id so that if the
404: // glyph > 32 is used again it'll miss in the cache
405: //
406: //
407:
408: LineIndex = CacheIndex;
409: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
410: LineIndex--;
411: Vxl.CacheTag[LineIndex].FontId = FreeTag;
412: }
413:
414: //
415: // Clear the entries used by the big glyph that follows the one
416: // that needs to be replaced
417: //
418:
419: LineIndex = CacheIndex+1;
420: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
421: Vxl.CacheTag[LineIndex].FontId = FreeTag;
422: LineIndex++;
423: }
424:
425: //
426: // Store the tag for the current glyph.
427: //
428:
429: Vxl.CacheTag[CacheIndex].FontId = FontId;
430: Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle;
431:
432: CacheData = Vxl.FontCacheBase + (CacheIndex << 5);
433:
434: //
435: // Fix the bit ordering and store the bitmap
436: // in off screen video memory.
437: //
438:
439: BitMapPtr = FontBitMap->aj;
440: GlyphBytesPerScan = (X+7) >> 3;
441: ShiftAmount = (GlyphBytesPerScan-1) << 3;
442:
443:
444: for (LineIndex=0;LineIndex < Y; LineIndex ++) {
445: BitMapData = 0;
446:
447:
448: for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) {
449: BitMapData >>= 8;
450: BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount;
451: }
452: *CacheData++ = BitMapData;
453: }
454:
455: //
456: // If Y is bigger than 32 lines, the glyph that was just cached
457: // took more than one entry. Fix the CacheTags.
458: //
459:
460: for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) {
461: Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended;
462: LineIndex -=32;
463: }
464: }
465:
466: //
467: // Find out where to draw the glyph and the glyph's starting address
468: //
469:
470: SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7);
471:
472: XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X;
473:
474: FifoWrite(DstAdr,SrcAdr,XYCmd);
475:
476: DstAdr += GlyphStride;
477: GlyphStart += 1;
478: } while (GlyphStart != GlyphEnd);
479:
480: if (bMoreGlyphs) {
481: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList);
482: #ifdef CACHE_STATS
483: CharCount += GlyphCount;
484: #endif
485:
486: } else {
487: break;
488: }
489: } while (TRUE);
490:
491: } else {
492:
493: //
494: // The font is not fixed pitch. Compute the x and y values for
495: // each glyph individually.
496: //
497:
498: do {
499:
500: //
501: // Get each glyph handle, find the physical address and send the
502: // draw command to the accelerator. Don't worry about clipping yet.
503: //
504:
505: bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount,&GlyphPosList);
506:
507: #ifdef CACHE_STATS
508: CharCount += GlyphCount;
509: #endif
510:
511: GlyphEnd = &GlyphPosList[GlyphCount];
512: GlyphStart = GlyphPosList;
513: do {
514:
515: GlyphHandle = (ULONG) (GlyphStart->hg);
516:
517: CacheIndex = HASH_FUNCTION(GlyphHandle,FontId);
518:
519: CacheIndex &= Vxl.CacheIndexMask;
520:
521: //
522: // Get glyph info
523: //
524:
525: FontBitMap = GlyphStart->pgdf->pgb;
526: X = FontBitMap->sizlBitmap.cx;
527: Y = FontBitMap->sizlBitmap.cy;
528:
529: //
530: // If FontId or GlyphHandle don't match, cache this glyph.
531: //
532:
533:
534: if (Vxl.CacheTag[CacheIndex].FontId != FontId) {
535: Allocate = TRUE;
536: } else {
537: if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) {
538: Allocate = TRUE;
539: } else {
540: Allocate = FALSE;
541: }
542: }
543:
544: if (Allocate) {
545:
546: //
547: // Wait for the accelerator to be idle to ensure
548: // that the glyph being replaced is not in use.
549: //
550: WaitForJaguarIdle();
551:
552: #ifdef CACHE_STATS
553: CacheMisses++;
554: #endif
555:
556: //
557: // The Glyph that has to be replaced is from the same font,
558: // wait for the accelerator to be idle before caching the
559: // glyph.
560: //
561:
562: #ifdef CACHE_STATS
563: if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) {
564: CacheUnused--;
565: } else {
566: CacheReplacement++;
567: }
568:
569: if (Vxl.CacheTag[CacheIndex].FontId == FontId) {
570: DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n",
571: Vxl.CacheTag[CacheIndex].FontId,
572: FontId));
573: }
574:
575: if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) {
576: DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n",
577: GlyphHandle,
578: Vxl.CacheTag[CacheIndex].FontId,
579: FontId));
580: }
581:
582: if (GlyphHandle > HigherGlyphHandle) {
583: HigherGlyphHandle = GlyphHandle;
584: }
585: #endif
586:
587: //
588: // if the entry that needs to be replaced
589: // is used as extension for a glyph > 32 lines
590: // go backwards and clear the Id so that if the
591: // glyph > 32 is used again it'll miss in the cache
592: //
593:
594: LineIndex = CacheIndex;
595: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
596: LineIndex--;
597: Vxl.CacheTag[LineIndex].FontId = FreeTag;
598: }
599:
600: //
601: // Clear the entries used by the big glyph that follows the one
602: // that needs to be replaced
603: //
604:
605: LineIndex = CacheIndex+1;
606: while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
607: Vxl.CacheTag[LineIndex].FontId = FreeTag;
608: LineIndex++;
609: }
610:
611: //
612: // Store the tag for the current glyph.
613: //
614:
615: Vxl.CacheTag[CacheIndex].FontId = FontId;
616: Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle;
617:
618: CacheData = Vxl.FontCacheBase + (CacheIndex << 5);
619:
620: BitMapPtr = FontBitMap->aj;
621: GlyphBytesPerScan = (X+7) >> 3;
622: ShiftAmount = (GlyphBytesPerScan-1) << 3;
623:
624: for (LineIndex=0;LineIndex < Y; LineIndex ++) {
625: BitMapData = 0;
626: for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) {
627:
628: BitMapData >>= 8;
629: BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount;
630: }
631: *CacheData++ = BitMapData;
632: }
633:
634: //
635: // If Y is bigger than 32 lines, the glyph we just cached
636: // took more than one entry. Fix the CacheTags.
637: //
638:
639: for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) {
640: Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended;
641: LineIndex -=32;
642: }
643:
644: }
645:
646: SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7);
647:
648: DstAdr = Vxl.JaguarScreenX * (GlyphStart->ptl.y + FontBitMap->ptlOrigin.y) +
649: ((GlyphStart->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift);
650:
651: XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X;
652:
653: FifoWrite(DstAdr,SrcAdr,XYCmd);
654: GlyphStart += 1;
655: } while (GlyphStart != GlyphEnd);
656: } while (bMoreGlyphs);
657: }
658:
659: //
660: // Draw extra rectangles using foreground brush
661: //
662:
663: if (prclExtra != (PRECTL)NULL) {
664: DrvpFillRectangle(prclExtra,pboFore->iSolidColor);
665: }
666:
667: #ifdef CACHE_STATS
668: if (CharCount >= 10000) {
669: ReplacementTotal += CacheReplacement;
670: CharTotal += CharCount;
671: MissTotal += CacheMisses;
672: DISPDBG((3, "Cache Statistics for last %ld chars\n",CharCount));
673: DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld\n",
674: CacheMisses,
675: (CacheMisses*100)/CharCount,
676: CacheReplacement));
677:
678: DISPDBG((3, "Cache Statistics since begining. Total of %ld chars\n",CharTotal));
679: DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld Unused entries = %ld\n",
680: MissTotal,
681: (MissTotal*100)/CharTotal,
682: ReplacementTotal,
683: CacheUnused));
684: DISPDBG((3, "HigherFontId = %x HigherGlyphHandle = %x\n",HigherFontId,HigherGlyphHandle));
685: CharCount = 0;
686: CacheMisses = 0;
687: CacheReplacement = 0;
688: }
689:
690: #endif
691:
692: //
693: // Done with call, return
694: //
695:
696: return(TRUE);
697:
698: //
699: // Could not execute this TextOut call, pass to engine.
700: // No need to synchronize here since Eng routine will call DrvSynchronize.
701: //
702:
703:
704: DevFailTextOut:
705:
706: return(EngTextOut(pso,
707: pstro,
708: pfo,
709: pco,
710: prclExtra,
711: prclOpaque,
712: pboFore,
713: pboOpaque,
714: pptlOrg,
715: mix));
716:
717: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.