|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24: /* $Header: mfbplygblt.c,v 1.15 87/09/01 16:53:00 toddb Exp $ */
25:
26: #include "X.h"
27: #include "Xmd.h"
28: #include "Xproto.h"
29: #include "fontstruct.h"
30: #include "dixfontstr.h"
31: #include "gcstruct.h"
32: #include "windowstr.h"
33: #include "pixmapstr.h"
34: #include "scrnintstr.h"
35: #include "regionstr.h"
36: #include "mfb.h"
37: #include "maskbits.h"
38: #include "miscstruct.h"
39:
40:
41: /*
42: we should eventually special-case fixed-width fonts, although
43: its more important for ImageText, which is meant for terminal
44: emulators.
45:
46: this works for fonts with glyphs <= 32 bits wide.
47:
48: the clipping calculations are done for worst-case fonts.
49: we make no assumptions about the heights, widths, or bearings
50: of the glyphs. if we knew that the glyphs are all the same height,
51: we could clip the tops and bottoms per clipping box, rather
52: than per character per clipping box. if we knew that the glyphs'
53: left and right bearings were well-behaved, we could clip a single
54: character at the start, output until the last unclipped
55: character, and then clip the last one. this is all straightforward
56: to determine based on max-bounds and min-bounds from the font.
57: there is some inefficiency introduced in the per-character
58: clipping to make what's going on clearer.
59:
60: (it is possible, for example, for a font to be defined in which the
61: next-to-last character in a font would be clipped out, but the last
62: one wouldn't. the code below deals with this.)
63:
64: PolyText looks at the fg color and the rasterop; mfbValidateGC
65: swaps in the right routine after looking at the reduced ratserop
66: in the private field of the GC.
67:
68: the register allocations are provisional; in particualr startmask and
69: endmask might not be the right things. pglyph, xoff, pdst, and tmpSrc
70: are fairly obvious, though.
71:
72: to avoid source proliferation, this file is compiled
73: three times:
74: MFBPOLYGLYPHBLT OPEQ
75: mfbPolyGlyphBltWhite |=
76: mfbPolyGlyphBltBlack &=~
77: mfbPolyGlyphBltInvert ^=
78: */
79:
80: void
81: MFBPOLYGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
82: DrawablePtr pDrawable;
83: GCPtr pGC;
84: int x, y;
85: unsigned int nglyph;
86: CharInfoPtr *ppci; /* array of character info */
87: unsigned char *pglyphBase; /* start of array of glyphs */
88: {
89: ExtentInfoRec info; /* used by QueryGlyphExtents() */
90: BoxRec bbox; /* string's bounding box */
91:
92: CharInfoPtr pci;
93: int xorg, yorg; /* origin of drawable in bitmap */
94: int widthDst; /* width of dst in longwords */
95:
96: /* these keep track of the character origin */
97: unsigned int *pdstBase;
98: /* points to longword with character origin */
99: int xchar; /* xorigin of char (mod 32) */
100:
101: /* these are used for placing the glyph */
102: register int xoff; /* x offset of left edge of glyph (mod 32) */
103: register unsigned int *pdst;
104: /* pointer to current longword in dst */
105:
106: int w; /* width of glyph in bits */
107: int h; /* height of glyph */
108: int widthGlyph; /* width of glyph, in bytes */
109: register unsigned char *pglyph;
110: /* pointer to current row of glyph */
111:
112: /* used for putting down glyph */
113: register int startmask;
114: register int endmask;
115: int nFirst; /* bits of glyph in current longword */
116: register unsigned int tmpSrc;
117: /* for getting bits from glyph */
118:
119: if (!(pGC->planemask & 1))
120: return;
121:
122: if (pDrawable->type == DRAWABLE_WINDOW)
123: {
124: xorg = ((WindowPtr)pDrawable)->absCorner.x;
125: yorg = ((WindowPtr)pDrawable)->absCorner.y;
126: pdstBase = (unsigned int *)
127: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devPrivate);
128: widthDst = (int)
129: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devKind) >> 2;
130: }
131: else
132: {
133: xorg = 0;
134: yorg = 0;
135: pdstBase = (unsigned int *)(((PixmapPtr)pDrawable)->devPrivate);
136: widthDst = (int)(((PixmapPtr)pDrawable)->devKind) >> 2;
137: }
138:
139: x += xorg;
140: y += yorg;
141:
142: QueryGlyphExtents(pGC->font, ppci, nglyph, &info);
143: bbox.x1 = x + info.overallLeft;
144: bbox.x2 = x + info.overallRight;
145: bbox.y1 = y - info.overallAscent;
146: bbox.y2 = y + info.overallDescent;
147:
148: switch ((*pGC->pScreen->RectIn)(
149: ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip, &bbox))
150: {
151: case rgnOUT:
152: break;
153: case rgnIN:
154: pdstBase = pdstBase + (widthDst * y) + (x >> 5);
155: xchar = x & 0x1f;
156:
157: while(nglyph--)
158: {
159: pci = *ppci;
160: pglyph = pglyphBase + pci->byteOffset;
161: w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
162: h = pci->metrics.ascent + pci->metrics.descent;
163: widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
164:
165: /* start at top scanline of glyph */
166: pdst = pdstBase - (pci->metrics.ascent * widthDst);
167:
168: /* find correct word in scanline and x offset within it
169: for left edge of glyph
170: */
171: xoff = xchar + pci->metrics.leftSideBearing;
172: if (xoff > 31)
173: {
174: pdst++;
175: xoff &= 0x1f;
176: }
177: else if (xoff < 0)
178: {
179: xoff += 32;
180: pdst--;
181: }
182:
183: if ((xoff + w) <= 32)
184: {
185: /* glyph all in one longword */
186: maskpartialbits(xoff, w, startmask);
187: while (h--)
188: {
189: getleftbits(pglyph, w, tmpSrc);
190: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
191: pglyph += widthGlyph;
192: pdst += widthDst;
193: }
194: }
195: else
196: {
197: /* glyph crosses longword boundary */
198: mask32bits(xoff, w, startmask, endmask);
199: nFirst = 32 - xoff;
200: while (h--)
201: {
202: getleftbits(pglyph, w, tmpSrc);
203: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
204: *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
205: pglyph += widthGlyph;
206: pdst += widthDst;
207: }
208: } /* glyph crosses longwords boundary */
209:
210: /* update character origin */
211: x += pci->metrics.characterWidth;
212: xchar += pci->metrics.characterWidth;
213: if (xchar > 31)
214: {
215: xchar -= 32;
216: pdstBase++;
217: }
218: else if (xchar < 0)
219: {
220: xchar += 32;
221: pdstBase--;
222: }
223: ppci++;
224: } /* while nglyph-- */
225: break;
226: case rgnPART:
227: {
228: TEXTPOS *ppos;
229: int nbox;
230: BoxPtr pbox;
231: int xpos; /* x position of char origin */
232: int i;
233: BoxRec clip;
234: int leftEdge, rightEdge;
235: int topEdge, bottomEdge;
236: int glyphRow; /* first row of glyph not wholly
237: clipped out */
238: int glyphCol; /* leftmost visible column of glyph */
239:
240: if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS))))
241: return;
242:
243: pdstBase = pdstBase + (widthDst * y) + (x >> 5);
244: xpos = x;
245: xchar = xpos & 0x1f;
246:
247: for (i=0; i<nglyph; i++)
248: {
249: pci = ppci[i];
250:
251: ppos[i].xpos = xpos;
252: ppos[i].xchar = xchar;
253: ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing;
254: ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing;
255: ppos[i].topEdge = y - pci->metrics.ascent;
256: ppos[i].bottomEdge = y + pci->metrics.descent;
257: ppos[i].pdstBase = pdstBase;
258: ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
259:
260: xpos += pci->metrics.characterWidth;
261: xchar += pci->metrics.characterWidth;
262: if (xchar > 31)
263: {
264: xchar &= 0x1f;
265: pdstBase++;
266: }
267: else if (xchar < 0)
268: {
269: xchar += 32;
270: pdstBase--;
271: }
272: }
273:
274: pbox = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->rects;
275: nbox = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->numRects;
276:
277: /* HACK ALERT
278: since we continue out of the loop below so often, it
279: is easier to increment pbox at the top than at the end.
280: don't try this at home.
281: */
282: pbox--;
283: while(nbox--)
284: {
285: pbox++;
286: clip.x1 = max(bbox.x1, pbox->x1);
287: clip.y1 = max(bbox.y1, pbox->y1);
288: clip.x2 = min(bbox.x2, pbox->x2);
289: clip.y2 = min(bbox.y2, pbox->y2);
290: if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1))
291: continue;
292:
293: for(i=0; i<nglyph; i++)
294: {
295: pci = ppci[i];
296: xchar = ppos[i].xchar;
297:
298: /* clip the left and right edges */
299: if (ppos[i].leftEdge < clip.x1)
300: leftEdge = clip.x1;
301: else
302: leftEdge = ppos[i].leftEdge;
303:
304: if (ppos[i].rightEdge > clip.x2)
305: rightEdge = clip.x2;
306: else
307: rightEdge = ppos[i].rightEdge;
308:
309: w = rightEdge - leftEdge;
310: if (w <= 0)
311: continue;
312:
313: /* clip the top and bottom edges */
314: if (ppos[i].topEdge < clip.y1)
315: topEdge = clip.y1;
316: else
317: topEdge = ppos[i].topEdge;
318:
319: if (ppos[i].bottomEdge > clip.y2)
320: bottomEdge = clip.y2;
321: else
322: bottomEdge = ppos[i].bottomEdge;
323:
324: h = bottomEdge - topEdge;
325: if (h <= 0)
326: continue;
327:
328: glyphRow = (topEdge - y) + pci->metrics.ascent;
329: widthGlyph = ppos[i].widthGlyph;
330: pglyph = pglyphBase + pci->byteOffset;
331: pglyph += (glyphRow * widthGlyph);
332:
333: pdst = ppos[i].pdstBase - ((y-topEdge) * widthDst);
334:
335: glyphCol = (leftEdge - ppos[i].xpos) -
336: (pci->metrics.leftSideBearing);
337: xoff = xchar + (leftEdge - ppos[i].xpos);
338: if (xoff > 31)
339: {
340: xoff &= 0x1f;
341: pdst++;
342: }
343: else if (xoff < 0)
344: {
345: xoff += 32;
346: pdst--;
347: }
348:
349: if ((xoff + w) <= 32)
350: {
351: maskpartialbits(xoff, w, startmask);
352: while (h--)
353: {
354: getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
355: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
356: pglyph += widthGlyph;
357: pdst += widthDst;
358: }
359: }
360: else
361: {
362: mask32bits(xoff, w, startmask, endmask);
363: nFirst = 32 - xoff;
364: while (h--)
365: {
366: getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
367: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
368: *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
369: pglyph += widthGlyph;
370: pdst += widthDst;
371: }
372: }
373: } /* for each glyph */
374: } /* while nbox-- */
375: DEALLOCATE_LOCAL(ppos);
376: break;
377: }
378: default:
379: break;
380: }
381: }
382:
383:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.