|
|
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.