|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: TextOut.c
3: *
4: * Text
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: *
8: \**************************************************************************/
9:
10: #include "driver.h"
11:
12: BOOL vFastText(PDEV *, GLYPHPOS *, ULONG, PBYTE, ULONG, ULONG, RECTL *,
13: RECTL *, INT, INT, ULONG);
14: VOID lclFillRect(CLIPOBJ *, ULONG, PRECTL, PPDEV, INT);
15:
16: /****************************************************************************
17: * DrvTextOut
18: ***************************************************************************/
19:
20: BOOL DrvTextOut(
21: SURFOBJ* pso,
22: STROBJ* pstro,
23: FONTOBJ* pfo,
24: CLIPOBJ* pco,
25: RECTL* prclExtra,
26: RECTL* prclOpaque,
27: BRUSHOBJ* pboFore,
28: BRUSHOBJ* pboOpaque,
29: POINTL* pptlOrg,
30: MIX mix)
31: {
32: BOOL b;
33: PPDEV ppdev;
34: INT iClip; // clip object's complexity
35: ULONG iSolidForeColor; // Solid foreground color
36: ULONG iSolidBkColor; // Solid background color
37: RECTL arclTmp[4]; // Temp storage for portions of opaquing rect
38: ULONG culRcl; // Temp rectangle count
39:
40: ppdev = (PPDEV) pso->dhpdev;
41:
42:
43: //---------------------------------------------------------------------
44: // Get information about clip object.
45: //---------------------------------------------------------------------
46:
47: iClip = DC_TRIVIAL;
48:
49: if (pco != NULL) {
50: iClip = pco->iDComplexity;
51: }
52:
53: //---------------------------------------------------------------------
54: // Get text color.
55: //---------------------------------------------------------------------
56:
57: iSolidForeColor = pboFore->iSolidColor;
58:
59: //---------------------------------------------------------------------
60: // See if this is text we can handle faster with special-case code.
61: //---------------------------------------------------------------------
62:
63: if (((ppdev->fl & DRIVER_PLANAR_CAPABLE) ||
64: (prclOpaque == (PRECTL) NULL)) && // opaque only if planar for now
65: // LATER implement fast non-planar
66: // opaque
67: (iClip == DC_TRIVIAL) && // no clipping for now
68: ((pstro->rclBkGround.right & ~0x03) >
69: ((pstro->rclBkGround.left + 3) & ~0x03)) &&
70: // not if no full nibbles spanned
71: // for now @@@
72: (pstro->pgp != NULL) && // no glyph enumeration for now
73: (prclExtra == NULL) && // no extra rects for now
74: ((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) ==
75: SO_HORIZONTAL)) { // only left-to-right text for now
76:
77: ULONG ulBufferWidthInBytes;
78: ULONG ulBufferBytes;
79: BOOL bTextPerfectFit;
80: ULONG fDrawFlags;
81:
82: // It's the type of text we can special-case; see if the temp buffer is
83: // big enough for the text.
84:
85: ulBufferWidthInBytes = ((((pstro->rclBkGround.right + 7) & ~0x07) -
86: (pstro->rclBkGround.left & ~0x07)) >> 3);
87: ulBufferBytes = ulBufferWidthInBytes *
88: (pstro->rclBkGround.bottom - pstro->rclBkGround.top);
89:
90: if (ulBufferBytes <= TMP_BUFFER_SIZE) {
91:
92: // It's big enough; set up for the accelerator
93:
94: // Set fixed pitch, overlap, and top & bottom Y alignment flags
95: fDrawFlags = ((pstro->ulCharInc != 0) ? 0x01 : 0) |
96: (((pstro->flAccel & (SO_ZERO_BEARINGS |
97: SO_FLAG_DEFAULT_PLACEMENT)) !=
98: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT))
99: ? 0x02 : 0) |
100: (((pstro->flAccel & (SO_ZERO_BEARINGS |
101: SO_FLAG_DEFAULT_PLACEMENT |
102: SO_MAXEXT_EQUAL_BM_SIDE)) ==
103: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
104: SO_MAXEXT_EQUAL_BM_SIDE)) ? 0x04 : 0);
105:
106: // If there's an opaque rectangle, we'll do as much opaquing as
107: // possible as we do the text. If the opaque rectangle is larger
108: // than the text rectangle, then we'll do the fringe areas right
109: // now, and the text and associated background areas together,
110: // later.
111: if (prclOpaque != (PRECTL) NULL) {
112:
113: // This driver only handles solid brushes
114: iSolidBkColor = pboOpaque->iSolidColor;
115:
116: // See if we have fringe areas to do. If so, build a list of
117: // rectangles to fill, in rightdown order
118:
119: culRcl = 0;
120:
121: // Top fragment
122: if (pstro->rclBkGround.top > prclOpaque->top) {
123: arclTmp[culRcl].top = prclOpaque->top;
124: arclTmp[culRcl].left = prclOpaque->left;
125: arclTmp[culRcl].right = prclOpaque->right;
126: arclTmp[culRcl++].bottom = pstro->rclBkGround.top;
127: }
128:
129: // Left fragment
130: if (pstro->rclBkGround.left > prclOpaque->left) {
131: arclTmp[culRcl].top = pstro->rclBkGround.top;
132: arclTmp[culRcl].left = prclOpaque->left;
133: arclTmp[culRcl].right = pstro->rclBkGround.left;
134: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom;
135: }
136:
137: // Right fragment
138: if (pstro->rclBkGround.right < prclOpaque->right) {
139: arclTmp[culRcl].top = pstro->rclBkGround.top;
140: arclTmp[culRcl].right = prclOpaque->right;
141: arclTmp[culRcl].left = pstro->rclBkGround.right;
142: arclTmp[culRcl++].bottom = pstro->rclBkGround.bottom;
143: }
144:
145: // Bottom fragment
146: if (pstro->rclBkGround.bottom < prclOpaque->bottom) {
147: arclTmp[culRcl].bottom = prclOpaque->bottom;
148: arclTmp[culRcl].left = prclOpaque->left;
149: arclTmp[culRcl].right = prclOpaque->right;
150: arclTmp[culRcl++].top = pstro->rclBkGround.bottom;
151: }
152:
153: if (culRcl != 0) {
154: if (iClip == DC_TRIVIAL) {
155: vTrgBlt(ppdev, culRcl, arclTmp, R2_COPYPEN,
156: *((RBRUSH_COLOR*) &iSolidBkColor), NULL);
157: } else {
158: lclFillRect(pco, culRcl, arclTmp, ppdev,
159: iSolidBkColor);
160: }
161: }
162: }
163:
164: // We're done with separate opaquing; any further opaquing will
165: // happen as part of the text drawing
166:
167: // Clear the buffer if the text isn't going to set every bit
168: // BUGBUG do I have to pay attention to ulCharInc?
169: bTextPerfectFit = (pstro->flAccel & (SO_ZERO_BEARINGS |
170: SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE |
171: SO_CHAR_INC_EQUAL_BM_BASE)) ==
172: (SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT |
173: SO_MAXEXT_EQUAL_BM_SIDE | SO_CHAR_INC_EQUAL_BM_BASE);
174:
175: if (!bTextPerfectFit) {
176: vClearMemDword(ppdev->pvTmp, (ulBufferBytes + 3) >> 2);
177: }
178:
179: // Draw the text into the temp buffer, and thence to the screen
180: vFastText(ppdev,
181: pstro->pgp,
182: pstro->cGlyphs,
183: ppdev->pvTmp,
184: ulBufferWidthInBytes,
185: pstro->ulCharInc,
186: &pstro->rclBkGround,
187: prclOpaque,
188: iSolidForeColor,
189: iSolidBkColor,
190: fDrawFlags);
191:
192: return(TRUE);
193:
194: }
195: }
196:
197: // Can't special-case; let the engine draw the text
198:
199: pso = ppdev->pSurfObj;
200:
201: // It may be that the opaquing rectangle is larger than the text rectangle,
202: // so we'll want to use that to tell the bank manager which banks to
203: // enumerate:
204:
205: pco = pcoBankStart(ppdev,
206: (prclOpaque != NULL) ? prclOpaque : &pstro->rclBkGround,
207: pso,
208: pco);
209:
210: do {
211: b = EngTextOut(pso,
212: pstro,
213: pfo,
214: pco,
215: prclExtra,
216: prclOpaque,
217: pboFore,
218: pboOpaque,
219: pptlOrg,
220: mix);
221:
222: } while (b && bBankEnum(ppdev, pso, pco));
223:
224: return(b);
225: }
226:
227: //--------------------------------------------------------------------------
228: // Fills the specified rectangles on the specified surface with the
229: // specified color, honoring the requested clipping. No more than four
230: // rectangles should be passed in. Intended for drawing the areas of the
231: // opaquing rectangle that extended beyond the text box. The rectangles must
232: // be in left to right, top to bottom order. Assumes there is at least one
233: // rectangle in the list.
234: //--------------------------------------------------------------------------
235:
236: VOID lclFillRect(
237: CLIPOBJ *pco,
238: ULONG culRcl,
239: PRECTL prcl,
240: PPDEV ppdev,
241: INT iColor)
242: {
243: BOOL bMore; // Flag for clip enumeration
244: TEXTENUM txen; // Clip enumeration object
245: ULONG i, j;
246: RECTL arclTmp[4];
247: ULONG culRclTmp;
248: RECTL *prclTmp, *prclClipTmp;
249: INT iLastBottom;
250: RECTL *pClipRcl;
251: INT iClip;
252:
253: iClip = DC_TRIVIAL;
254:
255: if (pco != NULL) {
256: iClip = pco->iDComplexity;
257: }
258:
259: switch ( iClip ) {
260:
261: case DC_TRIVIAL:
262:
263: vTrgBlt(ppdev, culRcl, prcl, R2_COPYPEN,
264: *((RBRUSH_COLOR*) &iColor), NULL);
265:
266: break;
267:
268: case DC_RECT:
269:
270: prclTmp = &pco->rclBounds;
271:
272: // Generate a list of clipped rects
273: for (culRclTmp=0, i=0; i<culRcl; i++, prcl++) {
274:
275: // Intersect fill and clip rectangles
276: if (bIntersectRect(&arclTmp[culRclTmp], prcl, prclTmp)) {
277:
278: // Add to list if anything's left to draw
279: culRclTmp++;
280: }
281: }
282:
283: // Draw the clipped rects
284: if (culRclTmp != 0) {
285: vTrgBlt(ppdev, culRclTmp, arclTmp, R2_COPYPEN,
286: *((RBRUSH_COLOR*) &iColor), NULL);
287: }
288:
289: break;
290:
291: case DC_COMPLEX:
292:
293: // Bottom of last rectangle to fill
294: iLastBottom = prcl[culRcl-1].bottom;
295:
296: // Initialize the clip rectangle enumeration to rightdown so we can
297: // take advantage of the rectangle list being rightdown
298: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN,
299: TO_RECT_LIMIT);
300:
301: // Scan through all the clip rectangles, looking for intersects
302: // of fill areas with region rectangles
303: do {
304:
305: // Get a batch of region rectangles
306: bMore = CLIPOBJ_bEnum(pco, (ULONG)sizeof(txen), (PVOID)&txen);
307:
308: // Clip the rect list to each region rect
309: for (j = txen.c, pClipRcl = txen.arcl; j-- > 0; pClipRcl++) {
310:
311: // Since the rectangles and the region enumeration are both
312: // rightdown, we can zip through the region until we reach
313: // the first fill rect, and are done when we've passed the
314: // last fill rect.
315:
316: if (pClipRcl->top >= iLastBottom) {
317: // Past last fill rectangle; nothing left to do
318: return;
319: }
320:
321: // Do intersection tests only if we've reached the top of
322: // the first rectangle to fill
323: if (pClipRcl->bottom > prcl->top) {
324:
325: // We've reached the top Y scan of the first rect, so
326: // it's worth bothering checking for intersection
327:
328: // Generate a list of the rects clipped to this region
329: // rect
330: prclTmp = prcl;
331: prclClipTmp = arclTmp;
332: for (i = culRcl, culRclTmp=0; i-- > 0; prclTmp++) {
333:
334: // Intersect fill and clip rectangles
335: if (bIntersectRect(prclClipTmp, prclTmp,
336: pClipRcl)) {
337:
338: // Add to list if anything's left to draw
339: culRclTmp++;
340: prclClipTmp++;
341: }
342: }
343:
344: // Draw the clipped rects
345: if (culRclTmp != 0) {
346: vTrgBlt(ppdev, culRclTmp, arclTmp, R2_COPYPEN,
347: *((RBRUSH_COLOR*) &iColor), NULL);
348: }
349: }
350: }
351: } while (bMore);
352:
353: break;
354: }
355:
356: }
357:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.