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
52 static bool
fbGlyphIn(GCPtr gc,int x,int y,int width,int height)53 fbGlyphIn(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
122 void
fbPolyGlyphBlt(DrawablePtr drawable,GCPtr gc,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,pointer glyphs)123 fbPolyGlyphBlt(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
184 void
fbImageGlyphBlt(DrawablePtr drawable,GCPtr gc,int x,int y,unsigned int nglyph,CharInfoPtr * ppciInit,pointer glyphs)185 fbImageGlyphBlt(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