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