1/* 2 * 3 * Copyright © 1998 Keith Packard 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#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28#include "fb.h" 29#include <X11/fonts/fontstruct.h> 30#include "dixfontstr.h" 31 32static Bool 33fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height) 34{ 35 BoxRec box; 36 BoxPtr pExtents = RegionExtents(pRegion); 37 38 /* 39 * Check extents by hand to avoid 16 bit overflows 40 */ 41 if (x < (int) pExtents->x1) 42 return FALSE; 43 if ((int) pExtents->x2 < x + width) 44 return FALSE; 45 if (y < (int) pExtents->y1) 46 return FALSE; 47 if ((int) pExtents->y2 < y + height) 48 return FALSE; 49 box.x1 = x; 50 box.x2 = x + width; 51 box.y1 = y; 52 box.y2 = y + height; 53 return RegionContainsRect(pRegion, &box) == rgnIN; 54} 55 56void 57fbPolyGlyphBlt(DrawablePtr pDrawable, 58 GCPtr pGC, 59 int x, 60 int y, 61 unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase) 62{ 63 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 64 CharInfoPtr pci; 65 unsigned char *pglyph; /* pointer bits in glyph */ 66 int gx, gy; 67 int gWidth, gHeight; /* width and height of glyph */ 68 FbStride gStride; /* stride of glyph */ 69 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); 70 FbBits *dst = 0; 71 FbStride dstStride = 0; 72 int dstBpp = 0; 73 int dstXoff = 0, dstYoff = 0; 74 75 glyph = 0; 76 if (pGC->fillStyle == FillSolid && pPriv->and == 0) { 77 dstBpp = pDrawable->bitsPerPixel; 78 switch (dstBpp) { 79 case 8: 80 glyph = fbGlyph8; 81 break; 82 case 16: 83 glyph = fbGlyph16; 84 break; 85 case 32: 86 glyph = fbGlyph32; 87 break; 88 } 89 } 90 x += pDrawable->x; 91 y += pDrawable->y; 92 93 while (nglyph--) { 94 pci = *ppci++; 95 pglyph = FONTGLYPHBITS(pglyphBase, pci); 96 gWidth = GLYPHWIDTHPIXELS(pci); 97 gHeight = GLYPHHEIGHTPIXELS(pci); 98 if (gWidth && gHeight) { 99 gx = x + pci->metrics.leftSideBearing; 100 gy = y - pci->metrics.ascent; 101 if (glyph && gWidth <= sizeof(FbStip) * 8 && 102 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { 103 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, 104 dstYoff); 105 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 106 (FbStip *) pglyph, pPriv->xor, gx + dstXoff, gHeight); 107 fbFinishAccess(pDrawable); 108 } 109 else { 110 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 111 fbPushImage(pDrawable, 112 pGC, 113 (FbStip *) pglyph, 114 gStride, 0, gx, gy, gWidth, gHeight); 115 } 116 } 117 x += pci->metrics.characterWidth; 118 } 119} 120 121void 122fbImageGlyphBlt(DrawablePtr pDrawable, 123 GCPtr pGC, 124 int x, 125 int y, 126 unsigned int nglyph, CharInfoPtr * ppciInit, void *pglyphBase) 127{ 128 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 129 CharInfoPtr *ppci; 130 CharInfoPtr pci; 131 unsigned char *pglyph; /* pointer bits in glyph */ 132 int gWidth, gHeight; /* width and height of glyph */ 133 FbStride gStride; /* stride of glyph */ 134 Bool opaque; 135 int n; 136 int gx, gy; 137 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int); 138 FbBits *dst = 0; 139 FbStride dstStride = 0; 140 int dstBpp = 0; 141 int dstXoff = 0, dstYoff = 0; 142 143 glyph = 0; 144 if (pPriv->and == 0) { 145 dstBpp = pDrawable->bitsPerPixel; 146 switch (dstBpp) { 147 case 8: 148 glyph = fbGlyph8; 149 break; 150 case 16: 151 glyph = fbGlyph16; 152 break; 153 case 32: 154 glyph = fbGlyph32; 155 break; 156 } 157 } 158 159 x += pDrawable->x; 160 y += pDrawable->y; 161 162 if (TERMINALFONT(pGC->font) 163 && !glyph) { 164 opaque = TRUE; 165 } 166 else { 167 int xBack, widthBack; 168 int yBack, heightBack; 169 170 ppci = ppciInit; 171 n = nglyph; 172 widthBack = 0; 173 while (n--) 174 widthBack += (*ppci++)->metrics.characterWidth; 175 176 xBack = x; 177 if (widthBack < 0) { 178 xBack += widthBack; 179 widthBack = -widthBack; 180 } 181 yBack = y - FONTASCENT(pGC->font); 182 heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); 183 fbSolidBoxClipped(pDrawable, 184 fbGetCompositeClip(pGC), 185 xBack, 186 yBack, 187 xBack + widthBack, 188 yBack + heightBack, 189 fbAnd(GXcopy, pPriv->bg, pPriv->pm), 190 fbXor(GXcopy, pPriv->bg, pPriv->pm)); 191 opaque = FALSE; 192 } 193 194 ppci = ppciInit; 195 while (nglyph--) { 196 pci = *ppci++; 197 pglyph = FONTGLYPHBITS(pglyphBase, pci); 198 gWidth = GLYPHWIDTHPIXELS(pci); 199 gHeight = GLYPHHEIGHTPIXELS(pci); 200 if (gWidth && gHeight) { 201 gx = x + pci->metrics.leftSideBearing; 202 gy = y - pci->metrics.ascent; 203 if (glyph && gWidth <= sizeof(FbStip) * 8 && 204 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { 205 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, 206 dstYoff); 207 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, 208 (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); 209 fbFinishAccess(pDrawable); 210 } 211 else { 212 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip); 213 fbPutXYImage(pDrawable, 214 fbGetCompositeClip(pGC), 215 pPriv->fg, 216 pPriv->bg, 217 pPriv->pm, 218 GXcopy, 219 opaque, 220 gx, 221 gy, 222 gWidth, gHeight, (FbStip *) pglyph, gStride, 0); 223 } 224 } 225 x += pci->metrics.characterWidth; 226 } 227} 228