diff options
Diffstat (limited to 'ilbm/ilbmplygblt.c')
-rw-r--r-- | ilbm/ilbmplygblt.c | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/ilbm/ilbmplygblt.c b/ilbm/ilbmplygblt.c new file mode 100644 index 000000000..a7dca5756 --- /dev/null +++ b/ilbm/ilbmplygblt.c @@ -0,0 +1,465 @@ +/* $XFree86: xc/programs/Xserver/ilbm/ilbmplygblt.c,v 3.1 1998/03/20 21:08:03 hohndel Exp $ */ +/* Combined Purdue/PurduePlus patches, level 2.0, 1/17/89 */ +/*********************************************************** + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XConsortium: ilbmimggblt.c,v 5.17 94/04/17 20:28:25 dpw Exp $ */ + +/* Modified jun 95 by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) + to use interleaved bitplanes instead of normal bitplanes */ + +#include "X.h" +#include "Xmd.h" +#include "Xproto.h" +#include "ilbm.h" +#include "fontstruct.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "maskbits.h" + +/* + this works for fonts with glyphs <= 32 bits wide. + + the clipping calculations are done for worst-case fonts. +we make no assumptions about the heights, widths, or bearings +of the glyphs. if we knew that the glyphs are all the same height, +we could clip the tops and bottoms per clipping box, rather +than per character per clipping box. if we knew that the glyphs' +left and right bearings were wlle-behaved, we could clip a single +character at the start, output until the last unclipped +character, and then clip the last one. this is all straightforward +to determine based on max-bounds and min-bounds from the font. + there is some inefficiency introduced in the per-character +clipping to make what's going on clearer. + + (it is possible, for example, for a font to be defined in which the +next-to-last character in a font would be clipped out, but the last +one wouldn't. the code below deals with this.) + +*/ + +void +ilbmPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) + DrawablePtr pDrawable; + GC *pGC; + int x, y; + unsigned int nglyph; + CharInfoPtr *ppci; /* array of character info */ + pointer pglyphBase; /* start of array of glyphs */ +{ + ExtentInfoRec info; /* used by QueryGlyphExtents() */ + BoxRec bbox; /* string's bounding box */ + xRectangle backrect; /* backing rectangle to paint. + in the general case, NOT necessarily + the same as the string's bounding box + */ + + CharInfoPtr pci; + int xorg, yorg; /* origin of drawable in bitmap */ + int widthDst; /* width of dst in longwords */ + + /* these keep track of the character origin */ + PixelType *pdstBase; + /* points to longword with character origin */ + int xchar; /* xorigin of char (mod 32) */ + + /* these are used for placing the glyph */ + register int xoff; /* x offset of left edge of glyph (mod 32) */ + register PixelType *pdst; /* pointer to current longword in dst */ + + register int d; + int depthDst; + int auxDst; + int hSave; + int w; /* width of glyph in bits */ + int h; /* height of glyph */ + int widthGlyph; /* width of glyph, in bytes */ + unsigned char *rrops; + register unsigned char *pglyph; + /* pointer to current row of glyph */ + unsigned char *pglyphSave; + + /* used for putting down glyph */ + register PixelType tmpSrc; + /* for getting bits from glyph */ + register PixelType startmask; + register PixelType endmask; + + register int nFirst; /* bits of glyph in current longword */ + PixelType *pdstSave; + + xorg = pDrawable->x; + yorg = pDrawable->y; + ilbmGetPixelWidthAuxDepthAndPointer(pDrawable, widthDst, auxDst, depthDst, + pdstBase); + + QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info); + + x += xorg; + y += yorg; + + bbox.x1 = x + info.overallLeft; + bbox.x2 = x + info.overallRight; + bbox.y1 = y - info.overallAscent; + bbox.y2 = y + info.overallDescent; + + rrops = ((ilbmPrivGCPtr) pGC->devPrivates[ilbmGCPrivateIndex].ptr)->rrops; + + switch (RECT_IN_REGION(pGC->pScreen, pGC->pCompositeClip, &bbox)) { + case rgnOUT: + break; + case rgnIN: + pdstBase = ilbmScanlineNoBankSwitch(pdstBase, x, y, auxDst); + xchar = x & PIM; + + while (nglyph--) { + pci = *ppci; + pglyphSave = FONTGLYPHBITS(pglyphBase, pci); + w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; + hSave = pci->metrics.ascent + pci->metrics.descent; + widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + /* start at top scanline of glyph */ + pdstSave = ilbmScanlineDelta(pdstBase, -pci->metrics.ascent, + auxDst); + + /* find correct word in scanline and x offset within it + for left edge of glyph + */ + xoff = xchar + pci->metrics.leftSideBearing; + if (xoff > PLST) { + pdstSave++; + xoff &= PIM; + } else if (xoff < 0) { + xoff += PPW; + pdstSave--; + } + + for (d = 0; d < depthDst; d++) { + h = hSave; + pdst = pdstSave; + pdstSave += widthDst; /* @@@ NEXT PLANE @@@ */ + pglyph = pglyphSave; + + if ((xoff + w) <= PPW) { + /* glyph all in one longword */ + maskpartialbits(xoff, w, startmask); + switch (rrops[d]) { + case RROP_WHITE: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst |= (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_BLACK: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_INVERT: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst ^= (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + } + } else { + /* glyph crosses longword boundary */ + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + switch (rrops[d]) { + case RROP_WHITE: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst |= (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) |= (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_BLACK: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) &= ~(SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_INVERT: + while (h--) { + getleftbits(pglyph, w, tmpSrc); + *pdst ^= (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) ^= (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + } + } /* glyph crosses longwords boundary */ + } /* depth loop */ + /* update character origin */ + x += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) { + xchar -= PPW; + pdstBase++; + } else if (xchar < 0) { + xchar += PPW; + pdstBase--; + } + ppci++; + } /* while nglyph-- */ + break; + case rgnPART: + { + ilbmTEXTPOS *ppos; + int nbox; + BoxPtr pbox; + RegionPtr cclip; + int xpos; /* x position of char origin */ + int i; + BoxRec clip; + int leftEdge, rightEdge; + int topEdge, bottomEdge; + int glyphRow; /* first row of glyph not wholly + clipped out */ + int glyphCol; /* leftmost visible column of glyph */ + int getWidth; /* bits to get from glyph */ + + if (!(ppos = (ilbmTEXTPOS *)ALLOCATE_LOCAL(nglyph * + sizeof(ilbmTEXTPOS)))) + return; + + pdstBase = ilbmScanlineNoBankSwitch(pdstBase, x, y, auxDst); + xpos = x; + xchar = xpos & PIM; + + for (i = 0; i < nglyph; i++) { + pci = ppci[i]; + + ppos[i].xpos = xpos; + ppos[i].xchar = xchar; + ppos[i].leftEdge = xpos + pci->metrics.leftSideBearing; + ppos[i].rightEdge = xpos + pci->metrics.rightSideBearing; + ppos[i].topEdge = y - pci->metrics.ascent; + ppos[i].bottomEdge = y + pci->metrics.descent; + ppos[i].pdstBase = pdstBase; + ppos[i].widthGlyph = GLYPHWIDTHBYTESPADDED(pci); + + xpos += pci->metrics.characterWidth; + xchar += pci->metrics.characterWidth; + if (xchar > PLST) { + xchar &= PIM; + pdstBase++; + } else if (xchar < 0) { + xchar += PPW; + pdstBase--; + } + } + + cclip = pGC->pCompositeClip; + pbox = REGION_RECTS(cclip); + nbox = REGION_NUM_RECTS(cclip); + + /* HACK ALERT + since we continue out of the loop below so often, it + is easier to increment pbox at the top than at the end. + don't try this at home. + */ + pbox--; + while (nbox--) { + pbox++; + clip.x1 = max(bbox.x1, pbox->x1); + clip.y1 = max(bbox.y1, pbox->y1); + clip.x2 = min(bbox.x2, pbox->x2); + clip.y2 = min(bbox.y2, pbox->y2); + if ((clip.x2<=clip.x1) || (clip.y2<=clip.y1)) + continue; + + for (i = 0; i<nglyph; i++) { + pci = ppci[i]; + xchar = ppos[i].xchar; + + /* clip the left and right edges */ + if (ppos[i].leftEdge < clip.x1) + leftEdge = clip.x1; + else + leftEdge = ppos[i].leftEdge; + + if (ppos[i].rightEdge > clip.x2) + rightEdge = clip.x2; + else + rightEdge = ppos[i].rightEdge; + + w = rightEdge - leftEdge; + if (w <= 0) + continue; + + /* clip the top and bottom edges */ + if (ppos[i].topEdge < clip.y1) + topEdge = clip.y1; + else + topEdge = ppos[i].topEdge; + + if (ppos[i].bottomEdge > clip.y2) + bottomEdge = clip.y2; + else + bottomEdge = ppos[i].bottomEdge; + + hSave = bottomEdge - topEdge; + if (hSave <= 0) + continue; + + glyphRow = (topEdge - y) + pci->metrics.ascent; + widthGlyph = ppos[i].widthGlyph; + pglyphSave = FONTGLYPHBITS(pglyphBase, pci); + pglyphSave += (glyphRow * widthGlyph); + + glyphCol = (leftEdge - ppos[i].xpos) - + (pci->metrics.leftSideBearing); + getWidth = w + glyphCol; + + pdstSave = ilbmScanlineDelta(ppos[i].pdstBase, -(y-topEdge), + auxDst); + xoff = xchar + (leftEdge - ppos[i].xpos); + if (xoff > PLST) { + xoff &= PIM; + pdstSave++; + } else if (xoff < 0) { + xoff += PPW; + pdstSave--; + } + + for (d = 0; d < depthDst; d++) { + h = hSave; + pdst = pdstSave; + pdstSave += widthDst; /* @@@ NEXT PLANE @@@ */ + pglyph = pglyphSave; + + if ((xoff + w) <= PPW) { + maskpartialbits(xoff, w, startmask); + switch (rrops[d]) { + case RROP_WHITE: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst |= (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_BLACK: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_INVERT: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst ^= (SCRRIGHT(tmpSrc, xoff) & startmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + } + } else { + maskPPWbits(xoff, w, startmask, endmask); + nFirst = PPW - xoff; + switch (rrops[d]) { + case RROP_WHITE: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst |= (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) |= (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_BLACK: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst &= ~(SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) &= ~(SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + case RROP_INVERT: + while (h--) { + getshiftedleftbits(pglyph, glyphCol, getWidth, tmpSrc); + *pdst ^= (SCRRIGHT(tmpSrc, xoff) & startmask); + *(pdst+1) ^= (SCRLEFT(tmpSrc, nFirst) & endmask); + pglyph += widthGlyph; + ilbmScanlineInc(pdst, auxDst); + } + break; + } + } + } /* depth */ + } /* for each glyph */ + } /* while nbox-- */ + DEALLOCATE_LOCAL(ppos); + break; + } + + default: + break; + } +} |