Add patch that contain Mali fixes.
[deb_xorg-server.git] / fb / fbglyph.c
CommitLineData
a09e091a
JB
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
32Bool
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
56#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg)
57#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg)
58#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg)
59#if FB_UNIT == 6 && IMAGE_BYTE_ORDER == LSBFirst
60#define WRITE8(d) WRITE((FbBits *) &(d[0]), fg)
61#else
62#define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB)
63#endif
64
65/*
66 * This is a bit tricky, but it's brief. Write 12 bytes worth
67 * of dest, which is four pixels, at a time. This gives constant
68 * code for each pattern as they're always aligned the same
69 *
70 * a b c d a b c d a b c d bytes
71 * A B C A B C A B C A B C pixels
72 *
73 * f0 f1 f2
74 * A B C A B C A B C A B C pixels LSB
75 * C A B C A B C A B C A B pixels MSB
76 *
77 * LSB MSB
78 * A f0 f1
79 * B f1 f2
80 * C f2 f0
81 * A B f0 f2
82 * B C f1 f0
83 * C A f2 f1
84 * A B C A f0 f1
85 * B C A B f1 f2
86 * C A B C f2 f0
87 */
88
89#undef _A
90#undef _B
91#undef _C
92#undef _AB
93#undef _BC
94#undef _CA
95#undef _ABCA
96#undef _BCAB
97#undef _CABC
98
99#if IMAGE_BYTE_ORDER == MSBFirst
100#define _A f1
101#define _B f2
102#define _C f0
103#define _AB f2
104#define _BC f0
105#define _CA f1
106#define _ABCA f1
107#define _BCAB f2
108#define _CABC f0
109#define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d)
110#else
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#endif
122
123void
124fbGlyph24(FbBits * dstBits,
125 FbStride dstStride,
126 int dstBpp, FbStip * stipple, FbBits fg, int x, int height)
127{
128 int lshift;
129 FbStip bits;
130 CARD8 *dstLine;
131 CARD8 *dst;
132 FbStip f0, f1, f2;
133 int n;
134 int shift;
135
136 f0 = fg;
137 f1 = FbRot24(f0, 16);
138 f2 = FbRot24(f0, 8);
139
140 dstLine = (CARD8 *) dstBits;
141 dstLine += (x & ~3) * 3;
142 dstStride *= (sizeof(FbBits) / sizeof(CARD8));
143 shift = x & 3;
144 lshift = 4 - shift;
145 while (height--) {
146 bits = READ(stipple++);
147 n = lshift;
148 dst = dstLine;
149 while (bits) {
150 switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) {
151 case CASE(0, 0, 0, 0):
152 break;
153 case CASE(1, 0, 0, 0):
154 WRITE2(dst, 0, _AB);
155 WRITE1(dst, 2, _C);
156 break;
157 case CASE(0, 1, 0, 0):
158 WRITE1(dst, 3, _A);
159 WRITE2(dst, 4, _BC);
160 break;
161 case CASE(1, 1, 0, 0):
162 WRITE4(dst, 0, _ABCA);
163 WRITE2(dst, 4, _BC);
164 break;
165 case CASE(0, 0, 1, 0):
166 WRITE2(dst, 6, _AB);
167 WRITE1(dst, 8, _C);
168 break;
169 case CASE(1, 0, 1, 0):
170 WRITE2(dst, 0, _AB);
171 WRITE1(dst, 2, _C);
172
173 WRITE2(dst, 6, _AB);
174 WRITE1(dst, 8, _C);
175 break;
176 case CASE(0, 1, 1, 0):
177 WRITE1(dst, 3, _A);
178 WRITE4(dst, 4, _BCAB);
179 WRITE1(dst, 8, _C);
180 break;
181 case CASE(1, 1, 1, 0):
182 WRITE8(dst);
183 WRITE1(dst, 8, _C);
184 break;
185 case CASE(0, 0, 0, 1):
186 WRITE1(dst, 9, _A);
187 WRITE2(dst, 10, _BC);
188 break;
189 case CASE(1, 0, 0, 1):
190 WRITE2(dst, 0, _AB);
191 WRITE1(dst, 2, _C);
192
193 WRITE1(dst, 9, _A);
194 WRITE2(dst, 10, _BC);
195 break;
196 case CASE(0, 1, 0, 1):
197 WRITE1(dst, 3, _A);
198 WRITE2(dst, 4, _BC);
199
200 WRITE1(dst, 9, _A);
201 WRITE2(dst, 10, _BC);
202 break;
203 case CASE(1, 1, 0, 1):
204 WRITE4(dst, 0, _ABCA);
205 WRITE2(dst, 4, _BC);
206
207 WRITE1(dst, 9, _A);
208 WRITE2(dst, 10, _BC);
209 break;
210 case CASE(0, 0, 1, 1):
211 WRITE2(dst, 6, _AB);
212 WRITE4(dst, 8, _CABC);
213 break;
214 case CASE(1, 0, 1, 1):
215 WRITE2(dst, 0, _AB);
216 WRITE1(dst, 2, _C);
217
218 WRITE2(dst, 6, _AB);
219 WRITE4(dst, 8, _CABC);
220 break;
221 case CASE(0, 1, 1, 1):
222 WRITE1(dst, 3, _A);
223 WRITE4(dst, 4, _BCAB);
224 WRITE4(dst, 8, _CABC);
225 break;
226 case CASE(1, 1, 1, 1):
227 WRITE8(dst);
228 WRITE4(dst, 8, _CABC);
229 break;
230 }
231 bits = FbStipLeft(bits, n);
232 n = 4;
233 dst += 12;
234 }
235 dstLine += dstStride;
236 }
237}
238
239void
240fbPolyGlyphBlt(DrawablePtr pDrawable,
241 GCPtr pGC,
242 int x,
243 int y,
244 unsigned int nglyph, CharInfoPtr * ppci, pointer pglyphBase)
245{
246 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
247 CharInfoPtr pci;
248 unsigned char *pglyph; /* pointer bits in glyph */
249 int gx, gy;
250 int gWidth, gHeight; /* width and height of glyph */
251 FbStride gStride; /* stride of glyph */
252 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
253 FbBits *dst = 0;
254 FbStride dstStride = 0;
255 int dstBpp = 0;
256 int dstXoff = 0, dstYoff = 0;
257
258 glyph = 0;
259 if (pGC->fillStyle == FillSolid && pPriv->and == 0) {
260 dstBpp = pDrawable->bitsPerPixel;
261 switch (dstBpp) {
262 case 8:
263 glyph = fbGlyph8;
264 break;
265 case 16:
266 glyph = fbGlyph16;
267 break;
268 case 24:
269 glyph = fbGlyph24;
270 break;
271 case 32:
272 glyph = fbGlyph32;
273 break;
274 }
275 }
276 x += pDrawable->x;
277 y += pDrawable->y;
278
279 while (nglyph--) {
280 pci = *ppci++;
281 pglyph = FONTGLYPHBITS(pglyphBase, pci);
282 gWidth = GLYPHWIDTHPIXELS(pci);
283 gHeight = GLYPHHEIGHTPIXELS(pci);
284 if (gWidth && gHeight) {
285 gx = x + pci->metrics.leftSideBearing;
286 gy = y - pci->metrics.ascent;
287 if (glyph && gWidth <= sizeof(FbStip) * 8 &&
288 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) {
289 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff,
290 dstYoff);
291 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
292 (FbStip *) pglyph, pPriv->xor, gx + dstXoff, gHeight);
293 fbFinishAccess(pDrawable);
294 }
295 else {
296 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
297 fbPushImage(pDrawable,
298 pGC,
299 (FbStip *) pglyph,
300 gStride, 0, gx, gy, gWidth, gHeight);
301 }
302 }
303 x += pci->metrics.characterWidth;
304 }
305}
306
307void
308fbImageGlyphBlt(DrawablePtr pDrawable,
309 GCPtr pGC,
310 int x,
311 int y,
312 unsigned int nglyph, CharInfoPtr * ppciInit, pointer pglyphBase)
313{
314 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
315 CharInfoPtr *ppci;
316 CharInfoPtr pci;
317 unsigned char *pglyph; /* pointer bits in glyph */
318 int gWidth, gHeight; /* width and height of glyph */
319 FbStride gStride; /* stride of glyph */
320 Bool opaque;
321 int n;
322 int gx, gy;
323 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
324 FbBits *dst = 0;
325 FbStride dstStride = 0;
326 int dstBpp = 0;
327 int dstXoff = 0, dstYoff = 0;
328
329 glyph = 0;
330 if (pPriv->and == 0) {
331 dstBpp = pDrawable->bitsPerPixel;
332 switch (dstBpp) {
333 case 8:
334 glyph = fbGlyph8;
335 break;
336 case 16:
337 glyph = fbGlyph16;
338 break;
339 case 24:
340 glyph = fbGlyph24;
341 break;
342 case 32:
343 glyph = fbGlyph32;
344 break;
345 }
346 }
347
348 x += pDrawable->x;
349 y += pDrawable->y;
350
351 if (TERMINALFONT(pGC->font)
352 && !glyph) {
353 opaque = TRUE;
354 }
355 else {
356 int xBack, widthBack;
357 int yBack, heightBack;
358
359 ppci = ppciInit;
360 n = nglyph;
361 widthBack = 0;
362 while (n--)
363 widthBack += (*ppci++)->metrics.characterWidth;
364
365 xBack = x;
366 if (widthBack < 0) {
367 xBack += widthBack;
368 widthBack = -widthBack;
369 }
370 yBack = y - FONTASCENT(pGC->font);
371 heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
372 fbSolidBoxClipped(pDrawable,
373 fbGetCompositeClip(pGC),
374 xBack,
375 yBack,
376 xBack + widthBack,
377 yBack + heightBack,
378 fbAnd(GXcopy, pPriv->bg, pPriv->pm),
379 fbXor(GXcopy, pPriv->bg, pPriv->pm));
380 opaque = FALSE;
381 }
382
383 ppci = ppciInit;
384 while (nglyph--) {
385 pci = *ppci++;
386 pglyph = FONTGLYPHBITS(pglyphBase, pci);
387 gWidth = GLYPHWIDTHPIXELS(pci);
388 gHeight = GLYPHHEIGHTPIXELS(pci);
389 if (gWidth && gHeight) {
390 gx = x + pci->metrics.leftSideBearing;
391 gy = y - pci->metrics.ascent;
392 if (glyph && gWidth <= sizeof(FbStip) * 8 &&
393 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) {
394 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff,
395 dstYoff);
396 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
397 (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight);
398 fbFinishAccess(pDrawable);
399 }
400 else {
401 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
402 fbPutXYImage(pDrawable,
403 fbGetCompositeClip(pGC),
404 pPriv->fg,
405 pPriv->bg,
406 pPriv->pm,
407 GXcopy,
408 opaque,
409 gx,
410 gy,
411 gWidth, gHeight, (FbStip *) pglyph, gStride, 0);
412 }
413 }
414 x += pci->metrics.characterWidth;
415 }
416}