|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: textout.c
3: *
4: * VGA DrvTextOut Entry point
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: \**************************************************************************/
8: #include "driver.h"
9: #include "textout.h"
10:
11: #define SO_MASK \
12: ( \
13: SO_FLAG_DEFAULT_PLACEMENT | \
14: SO_ZERO_BEARINGS | \
15: SO_CHAR_INC_EQUAL_BM_BASE | \
16: SO_MAXEXT_EQUAL_BM_SIDE \
17: )
18:
19: // accelerator masks for four canonical directions of
20: // writing (multiples of 90 degrees)
21:
22: #define SO_LTOR (SO_MASK | SO_HORIZONTAL)
23: #define SO_RTOL (SO_LTOR | SO_REVERSED)
24: #define SO_TTOB (SO_MASK | SO_VERTICAL)
25: #define SO_BTOT (SO_TTOB | SO_REVERSED)
26:
27: /**************************************************************************\
28: * Function Declarations
29: \**************************************************************************/
30:
31: VOID vGlyphBlt (PDEVSURF,PRECTL,ULONG,PGLYPHPOS,ULONG,ULONG,ULONG,FLONG);
32: VOID vStringBlt(PDEVSURF,PRECTL,ULONG,PGLYPHPOS,ULONG,ULONG,ULONG,FLONG);
33: ULONG ulSetXParentRegs(ROP4,PULONG,BOOL);
34: VOID vResetVGARegs(void);
35: BOOL bIdenticalRect(PRECTL,PRECTL);
36: FLONG flClipRect(PRECTL,PRECTL,PRECTL);
37: VOID lclFillRect(CLIPOBJ *pco, ULONG culRcl, PRECTL prcl, PDEVSURF pdsurf,
38: INT iColor);
39: BOOL DrvIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2);
40: VOID vFastText(GLYPHPOS *, ULONG, PBYTE, ULONG, ULONG, DEVSURF *, RECTL *,
41: RECTL *, INT, INT, ULONG, RECTL *);
42:
43: /**************************************************************************\
44: * Mix mode-Rop4 Mapping Table
45: \**************************************************************************/
46:
47: static ROP4 arop4[] = { // !!! This table needs serious fixing
48: 0x0000, /* 0 */
49: 0x0000, /* DPon */
50: 0x0000, /* DPna */
51: 0x0f0f, /* Pn */
52: 0x0000, /* PDna */
53: 0x5555, /* Dn */
54: 0x0000, /* DPx */
55: 0x0000, /* DPan */
56: 0x0000, /* DPa */
57: 0x0000, /* DPxn */
58: 0x0000, /* D */
59: 0x0000, /* DPno */
60: 0xf0f0, /* P */
61: 0x0000, /* PDno */
62: 0x0000, /* DPo */
63: 0xffff /* 1 */
64: };
65:
66: #define B_ORDERED_RECT(prcl) (((prcl) == (PRECTL)NULL) ? 1 : (((prcl)->left <= (prcl)->right) && ((prcl)->top <= (prcl)->bottom)))
67:
68:
69: /******************************Public*Routine******************************\
70: * BOOL DrvTextOut(pso,pstro,pfo,pco,prclExtra,prcOpaque,
71: * pvFore,pvBack,pptOrg,r2Fore,r2Back)
72: *
73: \**************************************************************************/
74:
75: BOOL DrvTextOut(
76: SURFOBJ *pso,
77: STROBJ *pstro,
78: FONTOBJ *pfo,
79: CLIPOBJ *pco,
80: PRECTL prclExtra,
81: PRECTL prclOpaque,
82: BRUSHOBJ *pboFore,
83: BRUSHOBJ *pboOpaque,
84: PPOINTL pptlOrg,
85: MIX mix)
86: {
87: PDEVSURF pdsurf; // Pointer to device surface
88:
89: ULONG iClip; // Clip object's complexity
90: ULONG iClipTmp; // Clip object's complexity
91: ULONG ircl; // index to current clip rect
92: BOOL bMore; // Flag for clip enumeration
93: RECT_ENUM txen; // Clip enumeration object
94:
95: GLYPHPOS *pgp; // pointer to the 1st glyph
96: GLYPHBITS *pgb; // pointer to glyph bits.
97:
98: BOOL bMoreGlyphs; // Glyph enumeration flag
99: ULONG cGlyph; // number of glyphs in one batch
100: ULONG iGlyph; // index to current glyph
101: RECTL rclGlyph; // string/glyph cell
102: RECTL rclTmp; // Temporary rectangle
103: RECTL rclBankTmp; // Temporary rectangle when bank
104: // clipping
105:
106: ROP4 rop4; // Rop tranlated from mix mode
107: ULONG iSolidTextColor; // Solid foreground text color
108: ULONG iSolidForeColor; // Solid foreground color
109: ULONG iSolidBkColor; // Solid background color
110:
111: FLONG flStr = 0; // Accelator flag for DrvTextOut()
112:
113: ULONG ulMixMode; // Glyph mix mode
114: PFN pfnBlt; // function to output glyph/string
115: FLONG flOption = 0; // Accelator flag for pfnBlt
116: FLONG flOptionTemp; // Working version of flOption
117:
118: RECTL arclTmp[4]; // Temp storage for portions of
119: // opaquing rect
120: ULONG culRcl; // Temp rectangle count
121:
122: //---------------------------------------------------------------------
123: // Get the target surface information
124: //---------------------------------------------------------------------
125:
126: // Now find out if the target is the screen
127: pdsurf = (PDEVSURF) pso->dhsurf;
128:
129: //---------------------------------------------------------------------
130: // Get information about clip object.
131: //---------------------------------------------------------------------
132:
133: iClip = DC_TRIVIAL;
134:
135: if (pco != NULL) {
136: iClip = pco->iDComplexity;
137: }
138:
139: //---------------------------------------------------------------------
140: // Get text color.
141: //---------------------------------------------------------------------
142:
143: iSolidForeColor = iSolidTextColor = pboFore->iSolidColor;
144:
145: //---------------------------------------------------------------------
146: // See if this is text we can handle faster with special-case code.
147: //---------------------------------------------------------------------
148:
149: if ((((prclOpaque != NULL) && (iClip != DC_COMPLEX)) ||
150: // handle opaque both non-clipped &
151: // rectangle-clipped
152: ((prclOpaque == NULL) && (iClip == DC_TRIVIAL))) &&
153: // handle xpar non-clipped only
154: // for now
155: (pstro->pgp != NULL) && // no glyph enumeration for now
156: (prclExtra == NULL) && // no extra rects for now
157: ((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) ==
158: SO_HORIZONTAL)) { // only left-to-right text for now
159:
160: ULONG ulBufferWidthInBytes;
161: ULONG ulBufferBytes;
162: BOOL bTextPerfectFit;
163: ULONG fDrawFlags;
164: BYTE *pjTempBuffer;
165: BOOL bTempAlloc;
166:
167: // It's the type of text we can special-case; see if the temp buffer is
168: // big enough for the text; if not, try to allocate enough memory.
169: // Round up to the nearest dword multiple.
170:
171: ulBufferWidthInBytes = ((((pstro->rclBkGround.right + 15) & ~0x0F) -
172: (pstro->rclBkGround.left & ~0x0F)) >> 3);
173: ulBufferBytes = ((ulBufferWidthInBytes *
174: (pstro->rclBkGround.bottom - pstro->rclBkGround.top)) + 3)
175: & ~0x03;
176:
177: if (ulBufferBytes <= pdsurf->ulTempBufferSize) {
178: // The temp buffer is big enough, so we'll use it
179: pjTempBuffer = pdsurf->pvBankBufferPlane0;
180: bTempAlloc = FALSE;
181: } else {
182: // The temp buffer isn't big enough, so we'll try to allocate
183: // enough memory
184: if ((pjTempBuffer =
185: LocalAlloc(LMEM_FIXED, ulBufferBytes)) == NULL) {
186: // We couldn't get enough memory, so fall back to the general,
187: // slow code
188: goto NoFastText;
189: }
190:
191: // Mark that we have to free the buffer when we're done
192: bTempAlloc = TRUE;
193: }
194:
195: // One way or another, we've found a buffer that's big enough; set up
196: // for accelerated text drawing
197:
198: // Set fixed pitch, overlap, and top & bottom Y alignment flags
199: fDrawFlags = ((pstro->ulCharInc != 0) ? 0x01 : 0) |
200: (((pstro->flAccel & (SO_ZERO_BEARINGS |
201: SO_FLAG_DEFAULT_PLACEMENT)) !=
202: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT))
203: ? 0x02 : 0) |
204: (((pstro->flAccel & (SO_ZERO_BEARINGS |
205: SO_FLAG_DEFAULT_PLACEMENT |
206: SO_MAXEXT_EQUAL_BM_SIDE)) ==
207: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
208: SO_MAXEXT_EQUAL_BM_SIDE)) ? 0x04 : 0);
209:
210: // If there's an opaque rectangle, we'll do as much opaquing as
211: // possible as we do the text. If the opaque rectangle is larger than
212: // the text rectangle, then we'll do the fringe areas right now, and
213: // the text and associated background areas together later
214: if (prclOpaque != (PRECTL) NULL) {
215:
216: // This driver only handles solid brushes
217: iSolidBkColor = pboOpaque->iSolidColor;
218:
219: // See if we have fringe areas to do. If so, build a list of
220: // rectangles to fill, in rightdown order
221:
222: culRcl = 0;
223:
224: // Top fragment
225: if (pstro->rclBkGround.top > prclOpaque->top) {
226: arclTmp[culRcl].top = prclOpaque->top;
227: arclTmp[culRcl].left = prclOpaque->left;
228: arclTmp[culRcl].right = prclOpaque->right;
229: arclTmp[culRcl++].bottom = pstro->rclBkGround.top;
230: }
231:
232: // Left fragment
233: if (pstro->rclBkGround.left > prclOpaque->left) {
234: arclTmp[culRcl].top = pstro->rclBkGround.top;
235: arclTmp[culRcl].left = prclOpaque->left;
236: arclTmp[culRcl].right = pstro->rclBkGround.left;
237: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom;
238: }
239:
240: // Right fragment
241: if (pstro->rclBkGround.right < prclOpaque->right) {
242: arclTmp[culRcl].top = pstro->rclBkGround.top;
243: arclTmp[culRcl].right = prclOpaque->right;
244: arclTmp[culRcl].left = pstro->rclBkGround.right;
245: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom;
246: }
247:
248: // Bottom fragment
249: if (pstro->rclBkGround.bottom < prclOpaque->bottom) {
250: arclTmp[culRcl].bottom = prclOpaque->bottom;
251: arclTmp[culRcl].left = prclOpaque->left;
252: arclTmp[culRcl].right = prclOpaque->right;
253: arclTmp[culRcl++].top = pstro->rclBkGround.bottom;
254: }
255:
256: // Fill any fringe rectangles we found
257: if (culRcl != 0) {
258: if (iClip == DC_TRIVIAL) {
259: vTrgBlt(pdsurf, culRcl, arclTmp, R2_COPYPEN,
260: iSolidBkColor);
261: } else {
262: lclFillRect(pco, culRcl, arclTmp, pdsurf,
263: iSolidBkColor);
264: }
265: }
266: }
267:
268: // We're done with separate opaquing; any further opaquing will happen
269: // as part of the text drawing
270:
271: // Clear the buffer if the text isn't going to set every bit
272: bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
273: SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
274: SO_CHAR_INC_EQUAL_BM_BASE)) ==
275: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
276: SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
277:
278: if (!bTextPerfectFit) {
279: // Note that we already rounded up to a dword multiple size.
280: vClearMemDword((ULONG *)pjTempBuffer, ulBufferBytes >> 2);
281: }
282:
283: // Draw the text into the temp buffer, and thence to the screen
284: vFastText(pstro->pgp,
285: pstro->cGlyphs,
286: ((PBYTE) pjTempBuffer) +
287: ((pstro->rclBkGround.left & 0x08) ? 1 : 0),
288: ulBufferWidthInBytes,
289: pstro->ulCharInc,
290: pdsurf,
291: &pstro->rclBkGround,
292: prclOpaque,
293: iSolidForeColor,
294: iSolidBkColor,
295: fDrawFlags,
296: (iClip == DC_TRIVIAL) ? NULL : &pco->rclBounds);
297:
298: // Free up any memory we allocated for the temp buffer
299: if (bTempAlloc) {
300: LocalFree(pjTempBuffer);
301: }
302:
303: return(TRUE);
304:
305: }
306:
307: NoFastText:
308:
309: //--------------------------------------------------------------------------
310: // Get the foreground and background colors
311: //--------------------------------------------------------------------------
312:
313: rop4 = arop4[(mix & 255) - R2_BLACK]; // Get ROP4 from mix mode
314:
315: // This driver only handles solid brushes
316:
317: // If no background rectangle, we need to paint only the glyph foreground.
318: // Set VGA registers for the current rop and foreground color at once and
319: // maintain them while blting the glyphs.
320:
321: if (prclOpaque == (PRECTL) NULL)
322: {
323: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, TRUE);
324: flStr |= TO_NO_OPAQUE_RECT;
325: } else {
326:
327: // This driver only handles solid brushes
328: iSolidBkColor = pboOpaque->iSolidColor;
329: // ASSERT ( iSolidBkColor != 0xFFFFFFFFL, "Non solid opaque brush\n" );
330: }
331:
332: //--------------------------------------------------------------------------
333: // Enumerate glyphs for the string, and output to screen one batch at a time.
334: // Here is how we will output background rectangle and glyphs:-
335: //
336: // if glyphs are non-justified and horizontally aligned
337: // if opaque background rectangle doesn't exactly match the string bound
338: // Paint portions of background that are outside text cells
339: // Output the string one batch at a time, drawing both fg & bg in cells
340: // else
341: // Paint opaque rectangle only once
342: // Output to screen one glyph at a time
343: //
344: //--------------------------------------------------------------------------
345:
346: // Set up the STROBJ for enumerating the glyphs
347:
348: // STROBJ_vEnumStart(pstro); // This is automatic.
349:
350: if ((pstro->flAccel == SO_LTOR) && (pstro->ulCharInc != 0))
351: {
352: flStr |= TO_FIXED_PITCH;
353: if ((pstro->ulCharInc & 7) == 0)
354: flStr |= TO_MULTIPLE_BYTE;
355: }
356:
357: do {
358:
359: // Get the next batch of glyphs
360:
361: if (pstro->pgp != NULL) {
362: // There's only the one batch of glyphs, so save ourselves a call
363: pgp = pstro->pgp;
364: cGlyph = pstro->cGlyphs;
365: bMoreGlyphs = FALSE;
366: } else {
367: bMoreGlyphs = STROBJ_bEnum(pstro,&cGlyph,&pgp);
368: }
369:
370: //--------------------------------------------------------------------
371: // No glyph, no work!
372: //--------------------------------------------------------------------
373:
374: if ( cGlyph ) {
375: // Collect information about the string.
376:
377: pgb = pgp->pgdf->pgb; // Locate the bitmap info.
378:
379: if ((flStr & TO_MULTIPLE_BYTE) &&
380: ((pgb->ptlOrigin.x + pgp->ptl.x) & 7) == 0) {
381: flStr |= TO_BYTE_ALIGNED;
382: }
383:
384: if ((pstro->flAccel == SO_LTOR) &&
385: (pgb->sizlBitmap.cy <= MAX_GLYPH_HEIGHT)) {
386: // We can blt horizontally aligned string with non-justified
387: // text at once.
388:
389: pfnBlt = (PFN)vStringBlt;
390: flOption |= VGB_ENTIRE_STRING_BLT;
391:
392: // we can special-case an aligned byte-size string
393:
394: flOption |= (flStr & (VGB_BYTE_ALIGNED | VGB_MULTIPLE_BYTE));
395:
396: // If there's an opaque rectangle, then if the opaque
397: // rectangle exactly matches the text rectangle, we'll do the
398: // opaque rectangle as we do the text. If the opaque rectangle
399: // is larger than the text rectangle, then we'll do the fringe
400: // areas right now, and the text and associated background
401: // areas together, later.
402: if (!(flStr & TO_NO_OPAQUE_RECT)) {
403:
404: // See if we have fringe areas to do. If so, build a
405: // list of rectangles to fill, in rightdown order
406:
407: culRcl = 0;
408:
409: // Top fragment
410: if (pstro->rclBkGround.top > prclOpaque->top) {
411: arclTmp[culRcl].top = prclOpaque->top;
412: arclTmp[culRcl].left = prclOpaque->left;
413: arclTmp[culRcl].right = prclOpaque->right;
414: arclTmp[culRcl++].bottom = pstro->rclBkGround.top;
415: }
416:
417: // Left fragment
418: if (pstro->rclBkGround.left > prclOpaque->left) {
419: arclTmp[culRcl].top = pstro->rclBkGround.top;
420: arclTmp[culRcl].left = prclOpaque->left;
421: arclTmp[culRcl].right = pstro->rclBkGround.left;
422: arclTmp[culRcl++].bottom =
423: pstro->rclBkGround.bottom;
424: }
425:
426: // Right fragment
427: if (pstro->rclBkGround.right < prclOpaque->right) {
428: arclTmp[culRcl].top = pstro->rclBkGround.top;
429: arclTmp[culRcl].right = prclOpaque->right;
430: arclTmp[culRcl].left = pstro->rclBkGround.right;
431: arclTmp[culRcl++].bottom =
432: pstro->rclBkGround.bottom;
433: }
434:
435: // Bottom fragment
436: if (pstro->rclBkGround.bottom < prclOpaque->bottom) {
437: arclTmp[culRcl].bottom = prclOpaque->bottom;
438: arclTmp[culRcl].left = prclOpaque->left;
439: arclTmp[culRcl].right = prclOpaque->right;
440: arclTmp[culRcl++].top = pstro->rclBkGround.bottom;
441: }
442:
443: // Fill any fringe rectangles we found
444: if (culRcl > 0) {
445: if (iClip == DC_TRIVIAL) {
446: vTrgBlt(pdsurf, culRcl, arclTmp, R2_COPYPEN,
447: iSolidBkColor);
448: } else {
449: lclFillRect(pco, culRcl, arclTmp, pdsurf,
450: iSolidBkColor);
451: }
452: }
453:
454:
455: // The opaque rectangle exactly matches the text
456: // background cells. We can simultaneously paint it
457: // with the glyph. Then, pretend no background
458: // rectangle.
459:
460: flStr |= TO_NO_OPAQUE_RECT;
461: flOption |= VGB_OPAQUE_BKGRND;
462:
463: // Although we do not want to set the VGA regs, we
464: // need to know their mode when we actually blt.
465:
466: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, FALSE);
467:
468: }
469:
470: // It is foolishly assumed in the clipping vStrBlt that GDI
471: // puts all positions in the GLYPHPOS array even when the font
472: // is fixed pitch.
473:
474: if (pstro->ulCharInc != 0) {
475: UINT ii;
476: LONG x,y;
477:
478: x = pgp[0].ptl.x;
479: y = pgp[0].ptl.y;
480:
481: for (ii=1; ii<cGlyph; ii++) {
482: x += pstro->ulCharInc;
483: pgp[ii].ptl.x = x;
484: pgp[ii].ptl.y = y;
485: }
486: }
487: } else {
488: // We need to output one glyph at a time.
489:
490: pfnBlt = (PFN) vGlyphBlt;
491:
492: // It is foolishly assumed in vGlyphBlt that GDI puts all
493: // positions in the GLYPHPOS array even when the font is
494: // fixed pitch.
495:
496: if (pstro->ulCharInc != 0) {
497: UINT ii;
498: LONG x,y;
499:
500: x = pgp[0].ptl.x;
501: y = pgp[0].ptl.y;
502: for (ii=1; ii<cGlyph; ii++) {
503: x += pstro->ulCharInc;
504: pgp[ii].ptl.x = x;
505: pgp[ii].ptl.y = y;
506: }
507: }
508: }
509: }
510:
511: //------------------------------------------------------------------
512: // Paint background rectangle if exists.
513: //------------------------------------------------------------------
514:
515: if (!(flStr & TO_NO_OPAQUE_RECT))
516: {
517: switch ( iClip )
518: {
519: case DC_RECT:
520:
521: // Intersect opaque and clip rectangles
522:
523: flClipRect(&rclTmp, prclOpaque, &pco->rclBounds);
524:
525: if (BINVALIDRECT(rclTmp))
526: {
527: break;
528: };
529: prclOpaque = &rclTmp;
530:
531: case DC_TRIVIAL:
532: vTrgBlt(pdsurf, 1, prclOpaque, R2_COPYPEN, iSolidBkColor);
533: break;
534:
535: case DC_COMPLEX:
536:
537: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY,
538: ENUM_RECT_LIMIT);
539: bMore = TRUE;
540:
541: do
542: {
543: if (bMore) {
544: bMore = CLIPOBJ_bEnum(pco, (ULONG)
545: sizeof(txen), (PVOID) &txen);
546: }
547:
548: for (ircl = 0; ircl < txen.c; ircl++)
549: {
550:
551: // Clip only if we have clipping region
552:
553: flClipRect ( &rclTmp, prclOpaque, &txen.arcl[ircl] );
554:
555: if (!(BINVALIDRECT(rclTmp)))
556: {
557: // rop4 <--> PATCOPY
558:
559: vTrgBlt(pdsurf, 1, &rclTmp,
560: R2_COPYPEN, iSolidBkColor);
561: };
562: }
563:
564: } while (bMore);
565: break;
566: }
567:
568: // We need to paint the background only once. So pretend it
569: // does not exist anymore.
570:
571: flStr |= TO_NO_OPAQUE_RECT;
572:
573: // Set VGA registers for transparent glyphs.
574:
575: ulMixMode = ulSetXParentRegs(rop4, &iSolidForeColor, TRUE);
576:
577: }
578:
579: //----------------------------------------------------------------------
580: // We are ready to output glyphs to screen. By now either the background
581: // rectangle (if any) was painted or we will paint it while outputting
582: // each glyph/string.
583: //----------------------------------------------------------------------
584:
585: for (iGlyph = 0; iGlyph < cGlyph; iGlyph++)
586: {
587: pgb = pgp[iGlyph].pgdf->pgb;
588: iClipTmp = iClip;
589:
590: if (!(flOption & VGB_ENTIRE_STRING_BLT))
591: {
592: pgp[iGlyph].ptl.x += pgb->ptlOrigin.x;
593: pgp[iGlyph].ptl.y += pgb->ptlOrigin.y;
594:
595: rclGlyph.left = pgp[iGlyph].ptl.x;
596: rclGlyph.right = rclGlyph.left + pgb->sizlBitmap.cx;
597: rclGlyph.top = pgp[iGlyph].ptl.y;
598: rclGlyph.bottom = rclGlyph.top + pgb->sizlBitmap.cy;
599:
600: if ((iClipTmp == DC_TRIVIAL) &&
601: ((rclGlyph.left < pco->rclBounds.left) ||
602: (rclGlyph.top < pco->rclBounds.top) ||
603: (rclGlyph.right > pco->rclBounds.right) ||
604: (rclGlyph.bottom > pco->rclBounds.bottom)))
605: iClipTmp = DC_RECT;
606: } else {
607: // Build the correct bounding box for the current batch of
608: // glyphs (the bounding box in the STROBJ is for the entire
609: // string, not on a per-batch basis)
610: rclGlyph.left = pgp[iGlyph].ptl.x;
611: rclGlyph.right = pgp[iGlyph + cGlyph - 1].ptl.x +
612: pgp[iGlyph + cGlyph - 1].pgdf->pgb->sizlBitmap.cx;
613: rclGlyph.top = pstro->rclBkGround.top;
614: rclGlyph.bottom = pstro->rclBkGround.bottom;
615: }
616:
617: flOption &= ~(VGB_VERT_CLIPPED_GLYPH | VGB_HORIZ_CLIPPED_GLYPH);
618:
619: switch ( iClipTmp )
620: {
621: case DC_RECT:
622:
623: // Intersect glyph and clip rectangles
624:
625: flOption |= flClipRect(&rclGlyph, &rclGlyph, &pco->rclBounds);
626: if (BINVALIDRECT(rclGlyph))
627: break;
628:
629: case DC_TRIVIAL:
630: // Cycle through all banks that the (possibly clipped)
631: // glpyh rect spans
632:
633: // If the proper bank for the top scan line of
634: // the clipped glyph isn't mapped in, map it in
635: if ((rclGlyph.top < pdsurf->rcl1WindowClip.top) ||
636: (rclGlyph.top >= pdsurf->rcl1WindowClip.bottom)) {
637:
638: // Map in the bank containing the top (possibly
639: // clipped) glyph line
640: pdsurf->pfnBankControl(pdsurf,
641: rclGlyph.top,
642: JustifyTop);
643: }
644:
645: // Now draw the part of the rect that's in each
646: // bank
647:
648: for (;;) {
649:
650: flOptionTemp = flOption |
651: flClipRect(&rclBankTmp, &rclGlyph,
652: &pdsurf->rcl1WindowClip);
653:
654: (*pfnBlt)(pdsurf, &rclBankTmp, cGlyph,
655: &pgp[iGlyph], iSolidForeColor, iSolidBkColor,
656: ulMixMode, flOptionTemp);
657:
658: // Done if this bank contains the last line
659: // of the fill
660: if (rclGlyph.bottom <= pdsurf->rcl1WindowClip.bottom) {
661: break;
662: }
663:
664: // Map in the next bank
665: pdsurf->pfnBankControl(pdsurf,
666: pdsurf->rcl1WindowClip.bottom,
667: JustifyTop);
668:
669: }
670:
671: break;
672:
673: case DC_COMPLEX:
674: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY,
675: ENUM_RECT_LIMIT);
676: bMore = TRUE;
677:
678: do
679: {
680: if (bMore) {
681: // Enumerate more clip rects
682: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(txen),
683: (PVOID) &txen);
684: }
685:
686: // Draw the portion of the glyph that intersects each
687: // clip rect in turn
688: for (ircl = 0; ircl < txen.c; ircl++)
689: {
690: // Clip the glyph to the next clip rect, and set
691: // our clipping flags
692: flOption |= flClipRect ( &rclTmp, &rclGlyph,
693: &txen.arcl[ircl] );
694:
695: // If we have a valid rectangle to draw, draw it
696: if (!(BINVALIDRECT(rclTmp))) {
697: // Cycle through all banks that the clipped
698: // glpyh rect spans
699:
700: // If the proper bank for the top scan line of
701: // the clipped glyph isn't mapped in, map it in
702: if ((rclTmp.top <
703: pdsurf->rcl1WindowClip.top) ||
704: (rclTmp.top >=
705: pdsurf->rcl1WindowClip.bottom)) {
706:
707: // Map in the bank containing the top
708: // clipped glyph line
709: pdsurf->pfnBankControl(pdsurf,
710: rclTmp.top,
711: JustifyTop);
712: }
713:
714: // Now draw the part of the rect that's in each
715: // bank
716:
717: for (;;) {
718:
719: flOptionTemp = flOption |
720: flClipRect(&rclBankTmp, &rclTmp,
721: &pdsurf->rcl1WindowClip);
722:
723:
724: (*pfnBlt)(pdsurf, &rclBankTmp, cGlyph,
725: &pgp[iGlyph], iSolidForeColor,
726: iSolidBkColor, ulMixMode,
727: flOptionTemp);
728:
729: // Done if this bank contains the last line
730: // of the fill
731: if (rclTmp.bottom <=
732: pdsurf->rcl1WindowClip.bottom) {
733: break;
734: }
735:
736: // Map in the next bank
737: pdsurf->pfnBankControl(pdsurf,
738: pdsurf->rcl1WindowClip.bottom,
739: JustifyTop);
740:
741: }
742: }
743:
744: flOption &= ~(VGB_VERT_CLIPPED_GLYPH |
745: VGB_HORIZ_CLIPPED_GLYPH);
746: }
747: } while (bMore);
748: break;
749: }
750:
751: // We might have blted the entire string.
752:
753: if (flOption & VGB_ENTIRE_STRING_BLT)
754: break;
755: }
756:
757: } while (bMoreGlyphs);
758:
759: // Reset VGA registers
760:
761: vResetVGARegs();
762:
763: //--------------------------------------------------------------------------
764: // Now handle the 'extra' rectangles.
765: //--------------------------------------------------------------------------
766:
767: if (prclExtra != (PRECTL) NULL)
768: {
769: while (prclExtra->left != prclExtra->right)
770: {
771: switch ( iClip )
772: {
773: case DC_TRIVIAL:
774: vTrgBlt(pdsurf, 1, prclExtra, mix, iSolidTextColor);
775: break;
776:
777: case DC_RECT:
778:
779: // Intersect opaque and clip rectangles
780:
781: flClipRect ( &rclTmp, prclExtra, &pco->rclBounds );
782:
783: if (BINVALIDRECT(rclTmp))
784: break;
785:
786: vTrgBlt(pdsurf, 1, &rclTmp, mix, iSolidTextColor);
787: break;
788:
789: case DC_COMPLEX:
790: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY,
791: ENUM_RECT_LIMIT);
792: bMore = TRUE;
793:
794: do
795: {
796: if (bMore) {
797: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(txen),
798: (PVOID) &txen);
799: }
800:
801: for (ircl = 0; ircl < txen.c; ircl++)
802: {
803: flClipRect ( &rclTmp, prclExtra, &txen.arcl[ircl] );
804:
805: if (!(BINVALIDRECT(rclTmp)))
806: {
807: vTrgBlt(pdsurf, 1, &rclTmp,
808: mix, iSolidTextColor);
809: };
810: }
811: } while (bMore);
812: break;
813: };
814:
815: prclExtra++; // Advance to next extra rectangle
816: }
817: }
818:
819: //--------------------------------------------------------------------------
820: // Clean up the surface
821: //--------------------------------------------------------------------------
822:
823: pptlOrg;
824: return(TRUE);
825: }
826:
827:
828: //--------------------------------------------------------------------------
829: // Fills the specified rectangles on the specified surface with the
830: // specified color, honoring the requested clipping. No more than four
831: // rectangles should be passed in. Intended for drawing the areas of the
832: // opaquing rectangle that extended beyond the text box. The rectangles must
833: // be in left to right, top to bottom order. Assumes there is at least one
834: // rectangle in the list.
835: //--------------------------------------------------------------------------
836:
837: VOID lclFillRect(
838: CLIPOBJ *pco,
839: ULONG culRcl,
840: PRECTL prcl,
841: PDEVSURF pdsurf,
842: INT iColor)
843: {
844: BOOL bMore; // Flag for clip enumeration
845: RECT_ENUM txen; // Clip enumeration object
846: ULONG i, j;
847: RECTL arclTmp[4];
848: ULONG culRclTmp;
849: RECTL *prclTmp, *prclClipTmp;
850: INT iLastBottom;
851: RECTL *pClipRcl;
852: INT iClip;
853:
854: // ASSERT(culRcl <= 4, "Too many rects");
855:
856: iClip = DC_TRIVIAL;
857:
858: if (pco != NULL) {
859: iClip = pco->iDComplexity;
860: }
861:
862: switch ( iClip ) {
863:
864: case DC_TRIVIAL:
865:
866: vTrgBlt(pdsurf, culRcl, prcl, R2_COPYPEN, iColor);
867:
868: break;
869:
870: case DC_RECT:
871:
872: prclTmp = &pco->rclBounds;
873:
874: // Generate a list of clipped rects
875: for (culRclTmp=0, i=0; i<culRcl; i++, prcl++) {
876:
877: // Intersect fill and clip rectangles
878: if (DrvIntersectRect(&arclTmp[culRclTmp], prcl, prclTmp)) {
879:
880: // Add to list if anything's left to draw
881: culRclTmp++;
882: }
883: }
884:
885: // Draw the clipped rects
886: if (culRclTmp != 0) {
887: vTrgBlt(pdsurf, culRclTmp, arclTmp, R2_COPYPEN, iColor);
888: }
889:
890: break;
891:
892: case DC_COMPLEX:
893:
894: // Bottom of last rectangle to fill
895: iLastBottom = prcl[culRcl-1].bottom;
896:
897: // Initialize the clip rectangle enumeration to rightdown so we can
898: // take advantage of the rectangle list being rightdown
899: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN,
900: ENUM_RECT_LIMIT);
901:
902: // Scan through all the clip rectangles, looking for intersects
903: // of fill areas with region rectangles
904: do {
905:
906: // Get a batch of region rectangles
907: bMore = CLIPOBJ_bEnum(pco, (ULONG)sizeof(txen), (PVOID)&txen);
908:
909: // Clip the rect list to each region rect
910: for (j = txen.c, pClipRcl = txen.arcl; j-- > 0; pClipRcl++) {
911:
912: // Since the rectangles and the region enumeration are both
913: // rightdown, we can zip through the region until we reach
914: // the first fill rect, and are done when we've passed the
915: // last fill rect.
916:
917: if (pClipRcl->top >= iLastBottom) {
918: // Past last fill rectangle; nothing left to do
919: return;
920: }
921:
922: // Do intersection tests only if we've reached the top of
923: // the first rectangle to fill
924: if (pClipRcl->bottom > prcl->top) {
925:
926: // We've reached the top Y scan of the first rect, so
927: // it's worth bothering checking for intersection
928:
929: // Generate a list of the rects clipped to this region
930: // rect
931: prclTmp = prcl;
932: prclClipTmp = arclTmp;
933: for (i = culRcl, culRclTmp=0; i-- > 0; prclTmp++) {
934:
935: // Intersect fill and clip rectangles
936: if (DrvIntersectRect(prclClipTmp, prclTmp,
937: pClipRcl)) {
938:
939: // Add to list if anything's left to draw
940: culRclTmp++;
941: prclClipTmp++;
942: }
943: }
944:
945: // Draw the clipped rects
946: if (culRclTmp != 0) {
947: vTrgBlt(pdsurf, culRclTmp, arclTmp, R2_COPYPEN,
948: iColor);
949: }
950: }
951: }
952: } while (bMore);
953:
954: break;
955: }
956:
957: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.