103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 1998 Keith Packard 303b705cfSriastradh * Copyright © 2012 Intel Corporation 403b705cfSriastradh * 503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its 603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that 703b705cfSriastradh * the above copyright notice appear in all copies and that both that 803b705cfSriastradh * copyright notice and this permission notice appear in supporting 903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in 1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without 1103b705cfSriastradh * specific, written prior permission. Keith Packard makes no 1203b705cfSriastradh * representations about the suitability of this software for any purpose. It 1303b705cfSriastradh * is provided "as is" without express or implied warranty. 1403b705cfSriastradh * 1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE. 2203b705cfSriastradh */ 2303b705cfSriastradh 2403b705cfSriastradh#include "fb.h" 2503b705cfSriastradh#include <X11/fonts/fontstruct.h> 2603b705cfSriastradh#include <dixfontstr.h> 2703b705cfSriastradh 2803b705cfSriastradh#define GLYPH fbGlyph8 2903b705cfSriastradh#define BITS BYTE 3003b705cfSriastradh#define BITS2 CARD16 3103b705cfSriastradh#define BITS4 CARD32 3203b705cfSriastradh#include "fbglyphbits.h" 3303b705cfSriastradh#undef BITS 3403b705cfSriastradh#undef BITS2 3503b705cfSriastradh#undef BITS4 3603b705cfSriastradh#undef GLYPH 3703b705cfSriastradh 3803b705cfSriastradh#define GLYPH fbGlyph16 3903b705cfSriastradh#define BITS CARD16 4003b705cfSriastradh#define BITS2 CARD32 4103b705cfSriastradh#include "fbglyphbits.h" 4203b705cfSriastradh#undef BITS 4303b705cfSriastradh#undef BITS2 4403b705cfSriastradh#undef GLYPH 4503b705cfSriastradh 4603b705cfSriastradh#define GLYPH fbGlyph32 4703b705cfSriastradh#define BITS CARD32 4803b705cfSriastradh#include "fbglyphbits.h" 4903b705cfSriastradh#undef BITS 5003b705cfSriastradh#undef GLYPH 5103b705cfSriastradh 5203b705cfSriastradhstatic bool 5303b705cfSriastradhfbGlyphIn(GCPtr gc, int x, int y, int width, int height) 5403b705cfSriastradh{ 5503b705cfSriastradh BoxRec box; 5603b705cfSriastradh BoxPtr extents = RegionExtents(gc->pCompositeClip); 5703b705cfSriastradh 5803b705cfSriastradh /* 5903b705cfSriastradh * Check extents by hand to avoid 16 bit overflows 6003b705cfSriastradh */ 6103b705cfSriastradh if (x < (int) extents->x1 || (int) extents->x2 < x + width) 6203b705cfSriastradh return FALSE; 6303b705cfSriastradh if (y < (int) extents->y1 || (int) extents->y2 < y + height) 6403b705cfSriastradh return FALSE; 6503b705cfSriastradh 6603b705cfSriastradh box.x1 = x; 6703b705cfSriastradh box.x2 = x + width; 6803b705cfSriastradh box.y1 = y; 6903b705cfSriastradh box.y2 = y + height; 7003b705cfSriastradh return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN; 7103b705cfSriastradh} 7203b705cfSriastradh 7303b705cfSriastradh#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg) 7403b705cfSriastradh#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg) 7503b705cfSriastradh#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg) 7603b705cfSriastradh 7703b705cfSriastradh/* 7803b705cfSriastradh * This is a bit tricky, but it's brief. Write 12 bytes worth 7903b705cfSriastradh * of dest, which is four pixels, at a time. This gives constant 8003b705cfSriastradh * code for each pattern as they're always aligned the same 8103b705cfSriastradh * 8203b705cfSriastradh * a b c d a b c d a b c d bytes 8303b705cfSriastradh * A B C A B C A B C A B C pixels 8403b705cfSriastradh * 8503b705cfSriastradh * f0 f1 f2 8603b705cfSriastradh * A B C A B C A B C A B C pixels LSB 8703b705cfSriastradh * C A B C A B C A B C A B pixels MSB 8803b705cfSriastradh * 8903b705cfSriastradh * LSB MSB 9003b705cfSriastradh * A f0 f1 9103b705cfSriastradh * B f1 f2 9203b705cfSriastradh * C f2 f0 9303b705cfSriastradh * A B f0 f2 9403b705cfSriastradh * B C f1 f0 9503b705cfSriastradh * C A f2 f1 9603b705cfSriastradh * A B C A f0 f1 9703b705cfSriastradh * B C A B f1 f2 9803b705cfSriastradh * C A B C f2 f0 9903b705cfSriastradh */ 10003b705cfSriastradh 10103b705cfSriastradh#undef _A 10203b705cfSriastradh#undef _B 10303b705cfSriastradh#undef _C 10403b705cfSriastradh#undef _AB 10503b705cfSriastradh#undef _BC 10603b705cfSriastradh#undef _CA 10703b705cfSriastradh#undef _ABCA 10803b705cfSriastradh#undef _BCAB 10903b705cfSriastradh#undef _CABC 11003b705cfSriastradh 11103b705cfSriastradh#define _A f0 11203b705cfSriastradh#define _B f1 11303b705cfSriastradh#define _C f2 11403b705cfSriastradh#define _AB f0 11503b705cfSriastradh#define _BC f1 11603b705cfSriastradh#define _CA f2 11703b705cfSriastradh#define _ABCA f0 11803b705cfSriastradh#define _BCAB f1 11903b705cfSriastradh#define _CABC f2 12003b705cfSriastradh#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) 12103b705cfSriastradh 12203b705cfSriastradhvoid 12303b705cfSriastradhfbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc, 12403b705cfSriastradh int x, int y, 12503b705cfSriastradh unsigned int nglyph, CharInfoPtr * ppci, pointer glyphs) 12603b705cfSriastradh{ 12703b705cfSriastradh FbGCPrivPtr pgc = fb_gc(gc); 12803b705cfSriastradh CharInfoPtr pci; 12903b705cfSriastradh unsigned char *pglyph; /* pointer bits in glyph */ 13003b705cfSriastradh int gx, gy; 13103b705cfSriastradh int gWidth, gHeight; /* width and height of glyph */ 13203b705cfSriastradh FbStride gStride; /* stride of glyph */ 13303b705cfSriastradh void (*raster) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); 13403b705cfSriastradh FbBits *dst = 0; 13503b705cfSriastradh FbStride dstStride = 0; 13603b705cfSriastradh int dstBpp = 0; 13703b705cfSriastradh int dstXoff = 0, dstYoff = 0; 13803b705cfSriastradh 13903b705cfSriastradh DBG(("%s x %d\n", __FUNCTION__, nglyph)); 14003b705cfSriastradh 14103b705cfSriastradh raster = 0; 14203b705cfSriastradh if (gc->fillStyle == FillSolid && pgc->and == 0) { 14303b705cfSriastradh dstBpp = drawable->bitsPerPixel; 14403b705cfSriastradh switch (dstBpp) { 14503b705cfSriastradh case 8: 14603b705cfSriastradh raster = fbGlyph8; 14703b705cfSriastradh break; 14803b705cfSriastradh case 16: 14903b705cfSriastradh raster = fbGlyph16; 15003b705cfSriastradh break; 15103b705cfSriastradh case 32: 15203b705cfSriastradh raster = fbGlyph32; 15303b705cfSriastradh break; 15403b705cfSriastradh } 15503b705cfSriastradh } 15603b705cfSriastradh x += drawable->x; 15703b705cfSriastradh y += drawable->y; 15803b705cfSriastradh 15903b705cfSriastradh while (nglyph--) { 16003b705cfSriastradh pci = *ppci++; 16103b705cfSriastradh pglyph = FONTGLYPHBITS(glyphs, pci); 16203b705cfSriastradh gWidth = GLYPHWIDTHPIXELS(pci); 16303b705cfSriastradh gHeight = GLYPHHEIGHTPIXELS(pci); 16403b705cfSriastradh if (gWidth && gHeight) { 16503b705cfSriastradh gx = x + pci->metrics.leftSideBearing; 16603b705cfSriastradh gy = y - pci->metrics.ascent; 16703b705cfSriastradh if (raster && gWidth <= sizeof(FbStip) * 8 && 16803b705cfSriastradh fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { 16903b705cfSriastradh fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, 17003b705cfSriastradh dstYoff); 17103b705cfSriastradh raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 17203b705cfSriastradh (FbStip *) pglyph, pgc->xor, gx + dstXoff, gHeight); 17303b705cfSriastradh } else { 17403b705cfSriastradh gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 17503b705cfSriastradh fbPushImage(drawable, gc, 17603b705cfSriastradh (FbStip *)pglyph, 17703b705cfSriastradh gStride, 0, gx, gy, gWidth, gHeight); 17803b705cfSriastradh } 17903b705cfSriastradh } 18003b705cfSriastradh x += pci->metrics.characterWidth; 18103b705cfSriastradh } 18203b705cfSriastradh} 18303b705cfSriastradh 18403b705cfSriastradhvoid 18503b705cfSriastradhfbImageGlyphBlt(DrawablePtr drawable, GCPtr gc, 18603b705cfSriastradh int x, int y, 18703b705cfSriastradh unsigned int nglyph, CharInfoPtr * ppciInit, pointer glyphs) 18803b705cfSriastradh{ 18903b705cfSriastradh FbGCPrivPtr pgc = fb_gc(gc); 19003b705cfSriastradh CharInfoPtr *ppci; 19103b705cfSriastradh CharInfoPtr pci; 19203b705cfSriastradh unsigned char *pglyph; /* pointer bits in glyph */ 19303b705cfSriastradh int gWidth, gHeight; /* width and height of glyph */ 19403b705cfSriastradh FbStride gStride; /* stride of glyph */ 19503b705cfSriastradh bool opaque; 19603b705cfSriastradh int n; 19703b705cfSriastradh int gx, gy; 19803b705cfSriastradh void (*raster)(FbBits *, FbStride, int, FbStip *, FbBits, int, int); 19903b705cfSriastradh FbBits *dst = 0; 20003b705cfSriastradh FbStride dstStride = 0; 20103b705cfSriastradh int dstBpp = 0; 20203b705cfSriastradh int dstXoff = 0, dstYoff = 0; 20303b705cfSriastradh 20403b705cfSriastradh DBG(("%s x %d\n", __FUNCTION__, nglyph)); 20503b705cfSriastradh 20603b705cfSriastradh raster = 0; 20703b705cfSriastradh if (pgc->and == 0) { 20803b705cfSriastradh dstBpp = drawable->bitsPerPixel; 20903b705cfSriastradh switch (dstBpp) { 21003b705cfSriastradh case 8: 21103b705cfSriastradh raster = fbGlyph8; 21203b705cfSriastradh break; 21303b705cfSriastradh case 16: 21403b705cfSriastradh raster = fbGlyph16; 21503b705cfSriastradh break; 21603b705cfSriastradh case 32: 21703b705cfSriastradh raster = fbGlyph32; 21803b705cfSriastradh break; 21903b705cfSriastradh } 22003b705cfSriastradh } 22103b705cfSriastradh 22203b705cfSriastradh x += drawable->x; 22303b705cfSriastradh y += drawable->y; 22403b705cfSriastradh 22503b705cfSriastradh if (TERMINALFONT(gc->font) && !raster) { 22603b705cfSriastradh opaque = TRUE; 22703b705cfSriastradh } else { 22803b705cfSriastradh int xBack, widthBack; 22903b705cfSriastradh int yBack, heightBack; 23003b705cfSriastradh 23103b705cfSriastradh ppci = ppciInit; 23203b705cfSriastradh n = nglyph; 23303b705cfSriastradh widthBack = 0; 23403b705cfSriastradh while (n--) 23503b705cfSriastradh widthBack += (*ppci++)->metrics.characterWidth; 23603b705cfSriastradh 23703b705cfSriastradh xBack = x; 23803b705cfSriastradh if (widthBack < 0) { 23903b705cfSriastradh xBack += widthBack; 24003b705cfSriastradh widthBack = -widthBack; 24103b705cfSriastradh } 24203b705cfSriastradh yBack = y - FONTASCENT(gc->font); 24303b705cfSriastradh heightBack = FONTASCENT(gc->font) + FONTDESCENT(gc->font); 24403b705cfSriastradh fbSolidBoxClipped(drawable, gc, 24503b705cfSriastradh xBack, yBack, 24603b705cfSriastradh xBack + widthBack, 24703b705cfSriastradh yBack + heightBack); 24803b705cfSriastradh opaque = FALSE; 24903b705cfSriastradh } 25003b705cfSriastradh 25103b705cfSriastradh ppci = ppciInit; 25203b705cfSriastradh while (nglyph--) { 25303b705cfSriastradh pci = *ppci++; 25403b705cfSriastradh pglyph = FONTGLYPHBITS(glyphs, pci); 25503b705cfSriastradh gWidth = GLYPHWIDTHPIXELS(pci); 25603b705cfSriastradh gHeight = GLYPHHEIGHTPIXELS(pci); 25703b705cfSriastradh if (gWidth && gHeight) { 25803b705cfSriastradh gx = x + pci->metrics.leftSideBearing; 25903b705cfSriastradh gy = y - pci->metrics.ascent; 26003b705cfSriastradh if (raster && gWidth <= sizeof(FbStip) * 8 && 26103b705cfSriastradh fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { 26203b705cfSriastradh fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, 26303b705cfSriastradh dstYoff); 26403b705cfSriastradh raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 26503b705cfSriastradh (FbStip *) pglyph, pgc->fg, gx + dstXoff, gHeight); 26603b705cfSriastradh } else { 26703b705cfSriastradh gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 26803b705cfSriastradh fbPutXYImage(drawable, gc, 26903b705cfSriastradh pgc->fg, pgc->bg, pgc->pm, 27003b705cfSriastradh GXcopy, opaque, 27103b705cfSriastradh gx, gy, gWidth, gHeight, 27203b705cfSriastradh (FbStip *) pglyph, gStride, 0); 27303b705cfSriastradh } 27403b705cfSriastradh } 27503b705cfSriastradh x += pci->metrics.characterWidth; 27603b705cfSriastradh } 27703b705cfSriastradh} 278