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