|
|
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: mfbimggblt.c,v 1.4 87/09/08 10:03:47 toddb Exp $ */
25: #include "X.h"
26: #include "Xmd.h"
27: #include "Xproto.h"
28: #include "fontstruct.h"
29: #include "dixfontstr.h"
30: #include "gcstruct.h"
31: #include "windowstr.h"
32: #include "scrnintstr.h"
33: #include "pixmapstr.h"
34: #include "regionstr.h"
35: #include "mfb.h"
36: #include "maskbits.h"
37:
38:
39: /*
40: we should eventually special-case fixed-width fonts for ImageText.
41:
42: this works for fonts with glyphs <= 32 bits wide.
43:
44: the clipping calculations are done for worst-case fonts.
45: we make no assumptions about the heights, widths, or bearings
46: of the glyphs. if we knew that the glyphs are all the same height,
47: we could clip the tops and bottoms per clipping box, rather
48: than per character per clipping box. if we knew that the glyphs'
49: left and right bearings were wlle-behaved, we could clip a single
50: character at the start, output until the last unclipped
51: character, and then clip the last one. this is all straightforward
52: to determine based on max-bounds and min-bounds from the font.
53: there is some inefficiency introduced in the per-character
54: clipping to make what's going on clearer.
55:
56: (it is possible, for example, for a font to be defined in which the
57: next-to-last character in a font would be clipped out, but the last
58: one wouldn't. the code below deals with this.)
59:
60: Image text looks at the bits in the glyph and the fg and bg in the
61: GC. it paints a rectangle, as defined in the protocol dcoument,
62: and the paints the characters.
63:
64: to avoid source proliferation, this file is compiled
65: three times:
66: MFBIMAGEGLYPHBLT OPEQ
67: mfbImageGlyphBltWhite |=
68: mfbImageGlyphBltBlack &=~
69:
70: the register allocations for startmask and endmask may not
71: be the right thing. are there two other deserving candidates?
72: xoff, pdst, pglyph, and tmpSrc seem like the right things, though.
73: */
74:
75: void
76: MFBIMAGEGLYPHBLT(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
77: DrawablePtr pDrawable;
78: GC *pGC;
79: int x, y;
80: unsigned int nglyph;
81: CharInfoPtr *ppci; /* array of character info */
82: unsigned char *pglyphBase; /* start of array of glyphs */
83: {
84: ExtentInfoRec info; /* used by QueryGlyphExtents() */
85: BoxRec bbox; /* string's bounding box */
86: xRectangle backrect;/* backing rectangle to paint.
87: in the general case, NOT necessarily
88: the same as the string's bounding box
89: */
90:
91: CharInfoPtr pci;
92: int xorg, yorg; /* origin of drawable in bitmap */
93: int widthDst; /* width of dst in longwords */
94:
95: /* these keep track of the character origin */
96: unsigned int *pdstBase;
97: /* points to longword with character origin */
98: int xchar; /* xorigin of char (mod 32) */
99:
100: /* these are used for placing the glyph */
101: register int xoff; /* x offset of left edge of glyph (mod 32) */
102: register unsigned int *pdst;
103: /* pointer to current longword in dst */
104:
105: int w; /* width of glyph in bits */
106: int h; /* height of glyph */
107: int widthGlyph; /* width of glyph, in bytes */
108: register unsigned char *pglyph;
109: /* pointer to current row of glyph */
110:
111: /* used for putting down glyph */
112: register int startmask;
113: register int endmask;
114:
115: int nFirst; /* bits of glyph in current longword */
116: register unsigned int tmpSrc;
117: /* for getting bits from glyph */
118: void (* oldFillArea)();
119: /* we might temporarily usurp this
120: field in devPriv */
121:
122: if (!(pGC->planemask & 1))
123: return;
124:
125: if (pDrawable->type == DRAWABLE_WINDOW)
126: {
127: xorg = ((WindowPtr)pDrawable)->absCorner.x;
128: yorg = ((WindowPtr)pDrawable)->absCorner.y;
129: pdstBase = (unsigned int *)
130: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devPrivate);
131: widthDst = (int)
132: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devKind) >> 2;
133: }
134: else
135: {
136: xorg = 0;
137: yorg = 0;
138: pdstBase = (unsigned int *)(((PixmapPtr)pDrawable)->devPrivate);
139: widthDst = (int)(((PixmapPtr)pDrawable)->devKind) >> 2;
140: }
141:
142: QueryGlyphExtents(pGC->font, ppci, nglyph, &info);
143:
144: backrect.x = x;
145: backrect.y = y - pGC->font->pFI->fontAscent;
146: backrect.width = info.overallWidth;
147: backrect.height = pGC->font->pFI->fontAscent +
148: pGC->font->pFI->fontDescent;
149:
150: x += xorg;
151: y += yorg;
152:
153: bbox.x1 = x + info.overallLeft;
154: bbox.x2 = x + info.overallRight;
155: bbox.y1 = y - info.overallAscent;
156: bbox.y2 = y + info.overallDescent;
157:
158: /* UNCLEAN CODE
159: we know the mfbPolyFillRect uses only three fields in
160: devPriv, two of which (ppPixmap and ropFillArea) are
161: irrelevant for solid filling, so we just poke the FillArea
162: field. the GC is now in an inconsistent state, but we'll fix
163: it as soon as PolyFillRect returns. fortunately, the server
164: is single threaded.
165:
166: NOTE:
167: if you are not using the standard mfbFillRectangle code, you
168: need to poke any fields in the GC the rectangle stuff need
169: (probably alu, fgPixel, and fillStyle) and in devPriv
170: (probably rop or ropFillArea.) You could just call ValidateGC,
171: but that is usually not a cheap thing to do.
172: */
173:
174: oldFillArea = ((mfbPrivGC *)(pGC->devPriv))->FillArea;
175:
176: /* pcc doesn't like this. why?
177: ((mfbPrivGC *)(pGC->devPriv))->FillArea =
178: (pGC->bgPixel ? mfbSolidWhiteArea : mfbSolidBlackArea);
179: */
180: if (pGC->bgPixel)
181: ((mfbPrivGC *)(pGC->devPriv))->FillArea = mfbSolidWhiteArea;
182: else
183: ((mfbPrivGC *)(pGC->devPriv))->FillArea = mfbSolidBlackArea;
184:
185: mfbPolyFillRect(pDrawable, pGC, 1, &backrect);
186: ((mfbPrivGC *)(pGC->devPriv))->FillArea = oldFillArea;
187:
188: /* the faint-hearted can open their eyes now */
189: switch ((*pGC->pScreen->RectIn)(
190: ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip, &bbox))
191: {
192: case rgnOUT:
193: break;
194: case rgnIN:
195: pdstBase = pdstBase + (widthDst * y) + (x >> 5);
196: xchar = x & 0x1f;
197:
198: while(nglyph--)
199: {
200: pci = *ppci;
201: pglyph = pglyphBase + pci->byteOffset;
202: w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
203: h = pci->metrics.ascent + pci->metrics.descent;
204: widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
205:
206: /* start at top scanline of glyph */
207: pdst = pdstBase - (pci->metrics.ascent * widthDst);
208:
209: /* find correct word in scanline and x offset within it
210: for left edge of glyph
211: */
212: xoff = xchar + pci->metrics.leftSideBearing;
213: if (xoff > 31)
214: {
215: pdst++;
216: xoff &= 0x1f;
217: }
218: else if (xoff < 0)
219: {
220: xoff += 32;
221: pdst--;
222: }
223:
224: if ((xoff + w) <= 32)
225: {
226: /* glyph all in one longword */
227: maskpartialbits(xoff, w, startmask);
228: while (h--)
229: {
230: getleftbits(pglyph, w, tmpSrc);
231: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
232: pglyph += widthGlyph;
233: pdst += widthDst;
234: }
235: }
236: else
237: {
238: /* glyph crosses longword boundary */
239: mask32bits(xoff, w, startmask, endmask);
240: nFirst = 32 - xoff;
241: while (h--)
242: {
243: getleftbits(pglyph, w, tmpSrc);
244: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
245: *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
246: pglyph += widthGlyph;
247: pdst += widthDst;
248: }
249: } /* glyph crosses longwords boundary */
250:
251: /* update character origin */
252: x += pci->metrics.characterWidth;
253: xchar += pci->metrics.characterWidth;
254: if (xchar > 31)
255: {
256: xchar -= 32;
257: pdstBase++;
258: }
259: else if (xchar < 0)
260: {
261: xchar += 32;
262: pdstBase--;
263: }
264: ppci++;
265: } /* while nglyph-- */
266: break;
267: case rgnPART:
268: {
269: TEXTPOS *ppos;
270: int nbox;
271: BoxPtr pbox;
272: int xpos; /* x position of char origin */
273: int i;
274: BoxRec clip;
275: int leftEdge, rightEdge;
276: int topEdge, bottomEdge;
277: int glyphRow; /* first row of glyph not wholly
278: clipped out */
279: int glyphCol; /* leftmost visible column of glyph */
280:
281: if(!(ppos = (TEXTPOS *)ALLOCATE_LOCAL(nglyph * sizeof(TEXTPOS))))
282: return;
283:
284: pdstBase = pdstBase + (widthDst * y) + (x >> 5);
285: xpos = x;
286: xchar = xpos & 0x1f;
287:
288: for (i=0; i<nglyph; i++)
289: {
290: pci = ppci[i];
291:
292: ppos[i].xpos = xpos;
293: ppos[i].xchar = xchar;
294: ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing;
295: ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing;
296: ppos[i].topEdge = y - pci->metrics.ascent;
297: ppos[i].bottomEdge = y + pci->metrics.descent;
298: ppos[i].pdstBase = pdstBase;
299: ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci);
300:
301: xpos += pci->metrics.characterWidth;
302: xchar += pci->metrics.characterWidth;
303: if (xchar > 31)
304: {
305: xchar &= 0x1f;
306: pdstBase++;
307: }
308: else if (xchar < 0)
309: {
310: xchar += 32;
311: pdstBase--;
312: }
313: }
314:
315: pbox = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->rects;
316: nbox = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->numRects;
317:
318: /* HACK ALERT
319: since we continue out of the loop below so often, it
320: is easier to increment pbox at the top than at the end.
321: don't try this at home.
322: */
323: pbox--;
324: while(nbox--)
325: {
326: pbox++;
327: clip.x1 = max(bbox.x1, pbox->x1);
328: clip.y1 = max(bbox.y1, pbox->y1);
329: clip.x2 = min(bbox.x2, pbox->x2);
330: clip.y2 = min(bbox.y2, pbox->y2);
331: if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1))
332: continue;
333:
334: for(i=0; i<nglyph; i++)
335: {
336: pci = ppci[i];
337: xchar = ppos[i].xchar;
338:
339: /* clip the left and right edges */
340: if (ppos[i].leftEdge < clip.x1)
341: leftEdge = clip.x1;
342: else
343: leftEdge = ppos[i].leftEdge;
344:
345: if (ppos[i].rightEdge > clip.x2)
346: rightEdge = clip.x2;
347: else
348: rightEdge = ppos[i].rightEdge;
349:
350: w = rightEdge - leftEdge;
351: if (w <= 0)
352: continue;
353:
354: /* clip the top and bottom edges */
355: if (ppos[i].topEdge < clip.y1)
356: topEdge = clip.y1;
357: else
358: topEdge = ppos[i].topEdge;
359:
360: if (ppos[i].bottomEdge > clip.y2)
361: bottomEdge = clip.y2;
362: else
363: bottomEdge = ppos[i].bottomEdge;
364:
365: h = bottomEdge - topEdge;
366: if (h <= 0)
367: continue;
368:
369: glyphRow = (topEdge - y) + pci->metrics.ascent;
370: widthGlyph = ppos[i].widthGlyph;
371: pglyph = pglyphBase + pci->byteOffset;
372: pglyph += (glyphRow * widthGlyph);
373:
374: pdst = ppos[i].pdstBase - ((y-topEdge) * widthDst);
375:
376: glyphCol = (leftEdge - ppos[i].xpos) -
377: (pci->metrics.leftSideBearing);
378: xoff = xchar + (leftEdge - ppos[i].xpos);
379: if (xoff > 31)
380: {
381: xoff &= 0x1f;
382: pdst++;
383: }
384: else if (xoff < 0)
385: {
386: xoff += 32;
387: pdst--;
388: }
389:
390: if ((xoff + w) <= 32)
391: {
392: maskpartialbits(xoff, w, startmask);
393: while (h--)
394: {
395: getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
396: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
397: pglyph += widthGlyph;
398: pdst += widthDst;
399: }
400: }
401: else
402: {
403: mask32bits(xoff, w, startmask, endmask);
404: nFirst = 32 - xoff;
405: while (h--)
406: {
407: getshiftedleftbits(pglyph, glyphCol, w, tmpSrc);
408: *pdst OPEQ (SCRRIGHT(tmpSrc, xoff) & startmask);
409: *(pdst+1) OPEQ (SCRLEFT(tmpSrc, nFirst) & endmask);
410: pglyph += widthGlyph;
411: pdst += widthDst;
412: }
413: }
414: } /* for each glyph */
415: } /* while nbox-- */
416: DEALLOCATE_LOCAL(ppos);
417: break;
418: }
419: default:
420: break;
421: }
422: }
423:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.