1/* 2 * Copyright © 1998 Keith Packard 3 * Copyright © 2012 Intel Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#include "fb.h" 25#include <X11/fonts/fontstruct.h> 26#include <dixfontstr.h> 27 28#define GLYPH fbGlyph8 29#define BITS BYTE 30#define BITS2 CARD16 31#define BITS4 CARD32 32#include "fbglyphbits.h" 33#undef BITS 34#undef BITS2 35#undef BITS4 36#undef GLYPH 37 38#define GLYPH fbGlyph16 39#define BITS CARD16 40#define BITS2 CARD32 41#include "fbglyphbits.h" 42#undef BITS 43#undef BITS2 44#undef GLYPH 45 46#define GLYPH fbGlyph32 47#define BITS CARD32 48#include "fbglyphbits.h" 49#undef BITS 50#undef GLYPH 51 52static bool 53fbGlyphIn(GCPtr gc, int x, int y, int width, int height) 54{ 55 BoxRec box; 56 BoxPtr extents = RegionExtents(gc->pCompositeClip); 57 58 /* 59 * Check extents by hand to avoid 16 bit overflows 60 */ 61 if (x < (int) extents->x1 || (int) extents->x2 < x + width) 62 return FALSE; 63 if (y < (int) extents->y1 || (int) extents->y2 < y + height) 64 return FALSE; 65 66 box.x1 = x; 67 box.x2 = x + width; 68 box.y1 = y; 69 box.y2 = y + height; 70 return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN; 71} 72 73#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg) 74#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg) 75#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg) 76 77/* 78 * This is a bit tricky, but it's brief. Write 12 bytes worth 79 * of dest, which is four pixels, at a time. This gives constant 80 * code for each pattern as they're always aligned the same 81 * 82 * a b c d a b c d a b c d bytes 83 * A B C A B C A B C A B C pixels 84 * 85 * f0 f1 f2 86 * A B C A B C A B C A B C pixels LSB 87 * C A B C A B C A B C A B pixels MSB 88 * 89 * LSB MSB 90 * A f0 f1 91 * B f1 f2 92 * C f2 f0 93 * A B f0 f2 94 * B C f1 f0 95 * C A f2 f1 96 * A B C A f0 f1 97 * B C A B f1 f2 98 * C A B C f2 f0 99 */ 100 101#undef _A 102#undef _B 103#undef _C 104#undef _AB 105#undef _BC 106#undef _CA 107#undef _ABCA 108#undef _BCAB 109#undef _CABC 110 111#define _A f0 112#define _B f1 113#define _C f2 114#define _AB f0 115#define _BC f1 116#define _CA f2 117#define _ABCA f0 118#define _BCAB f1 119#define _CABC f2 120#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) 121 122void 123fbPolyGlyphBlt(DrawablePtr drawable, GCPtr gc, 124 int x, int y, 125 unsigned int nglyph, CharInfoPtr * ppci, pointer glyphs) 126{ 127 FbGCPrivPtr pgc = fb_gc(gc); 128 CharInfoPtr pci; 129 unsigned char *pglyph; /* pointer bits in glyph */ 130 int gx, gy; 131 int gWidth, gHeight; /* width and height of glyph */ 132 FbStride gStride; /* stride of glyph */ 133 void (*raster) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); 134 FbBits *dst = 0; 135 FbStride dstStride = 0; 136 int dstBpp = 0; 137 int dstXoff = 0, dstYoff = 0; 138 139 DBG(("%s x %d\n", __FUNCTION__, nglyph)); 140 141 raster = 0; 142 if (gc->fillStyle == FillSolid && pgc->and == 0) { 143 dstBpp = drawable->bitsPerPixel; 144 switch (dstBpp) { 145 case 8: 146 raster = fbGlyph8; 147 break; 148 case 16: 149 raster = fbGlyph16; 150 break; 151 case 32: 152 raster = fbGlyph32; 153 break; 154 } 155 } 156 x += drawable->x; 157 y += drawable->y; 158 159 while (nglyph--) { 160 pci = *ppci++; 161 pglyph = FONTGLYPHBITS(glyphs, pci); 162 gWidth = GLYPHWIDTHPIXELS(pci); 163 gHeight = GLYPHHEIGHTPIXELS(pci); 164 if (gWidth && gHeight) { 165 gx = x + pci->metrics.leftSideBearing; 166 gy = y - pci->metrics.ascent; 167 if (raster && gWidth <= sizeof(FbStip) * 8 && 168 fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { 169 fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, 170 dstYoff); 171 raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 172 (FbStip *) pglyph, pgc->xor, gx + dstXoff, gHeight); 173 } else { 174 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 175 fbPushImage(drawable, gc, 176 (FbStip *)pglyph, 177 gStride, 0, gx, gy, gWidth, gHeight); 178 } 179 } 180 x += pci->metrics.characterWidth; 181 } 182} 183 184void 185fbImageGlyphBlt(DrawablePtr drawable, GCPtr gc, 186 int x, int y, 187 unsigned int nglyph, CharInfoPtr * ppciInit, pointer glyphs) 188{ 189 FbGCPrivPtr pgc = fb_gc(gc); 190 CharInfoPtr *ppci; 191 CharInfoPtr pci; 192 unsigned char *pglyph; /* pointer bits in glyph */ 193 int gWidth, gHeight; /* width and height of glyph */ 194 FbStride gStride; /* stride of glyph */ 195 bool opaque; 196 int n; 197 int gx, gy; 198 void (*raster)(FbBits *, FbStride, int, FbStip *, FbBits, int, int); 199 FbBits *dst = 0; 200 FbStride dstStride = 0; 201 int dstBpp = 0; 202 int dstXoff = 0, dstYoff = 0; 203 204 DBG(("%s x %d\n", __FUNCTION__, nglyph)); 205 206 raster = 0; 207 if (pgc->and == 0) { 208 dstBpp = drawable->bitsPerPixel; 209 switch (dstBpp) { 210 case 8: 211 raster = fbGlyph8; 212 break; 213 case 16: 214 raster = fbGlyph16; 215 break; 216 case 32: 217 raster = fbGlyph32; 218 break; 219 } 220 } 221 222 x += drawable->x; 223 y += drawable->y; 224 225 if (TERMINALFONT(gc->font) && !raster) { 226 opaque = TRUE; 227 } else { 228 int xBack, widthBack; 229 int yBack, heightBack; 230 231 ppci = ppciInit; 232 n = nglyph; 233 widthBack = 0; 234 while (n--) 235 widthBack += (*ppci++)->metrics.characterWidth; 236 237 xBack = x; 238 if (widthBack < 0) { 239 xBack += widthBack; 240 widthBack = -widthBack; 241 } 242 yBack = y - FONTASCENT(gc->font); 243 heightBack = FONTASCENT(gc->font) + FONTDESCENT(gc->font); 244 fbSolidBoxClipped(drawable, gc, 245 xBack, yBack, 246 xBack + widthBack, 247 yBack + heightBack); 248 opaque = FALSE; 249 } 250 251 ppci = ppciInit; 252 while (nglyph--) { 253 pci = *ppci++; 254 pglyph = FONTGLYPHBITS(glyphs, pci); 255 gWidth = GLYPHWIDTHPIXELS(pci); 256 gHeight = GLYPHHEIGHTPIXELS(pci); 257 if (gWidth && gHeight) { 258 gx = x + pci->metrics.leftSideBearing; 259 gy = y - pci->metrics.ascent; 260 if (raster && gWidth <= sizeof(FbStip) * 8 && 261 fbGlyphIn(gc, gx, gy, gWidth, gHeight)) { 262 fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, 263 dstYoff); 264 raster(dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 265 (FbStip *) pglyph, pgc->fg, gx + dstXoff, gHeight); 266 } else { 267 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 268 fbPutXYImage(drawable, gc, 269 pgc->fg, pgc->bg, pgc->pm, 270 GXcopy, opaque, 271 gx, gy, gWidth, gHeight, 272 (FbStip *) pglyph, gStride, 0); 273 } 274 } 275 x += pci->metrics.characterWidth; 276 } 277} 278