3 * Copyright © 1998 Keith Packard
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.
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.
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
29 #include <X11/fonts/fontstruct.h>
30 #include "dixfontstr.h"
33 fbGlyphIn(RegionPtr pRegion
, int x
, int y
, int width
, int height
)
36 BoxPtr pExtents
= RegionExtents(pRegion
);
39 * Check extents by hand to avoid 16 bit overflows
41 if (x
< (int) pExtents
->x1
)
43 if ((int) pExtents
->x2
< x
+ width
)
45 if (y
< (int) pExtents
->y1
)
47 if ((int) pExtents
->y2
< y
+ height
)
53 return RegionContainsRect(pRegion
, &box
) == rgnIN
;
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)
62 #define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB)
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
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
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
99 #if IMAGE_BYTE_ORDER == MSBFirst
109 #define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d)
120 #define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3))
124 fbGlyph24(FbBits
* dstBits
,
126 int dstBpp
, FbStip
* stipple
, FbBits fg
, int x
, int height
)
137 f1
= FbRot24(f0
, 16);
140 dstLine
= (CARD8
*) dstBits
;
141 dstLine
+= (x
& ~3) * 3;
142 dstStride
*= (sizeof(FbBits
) / sizeof(CARD8
));
146 bits
= READ(stipple
++);
150 switch (FbStipMoveLsb(FbLeftStipBits(bits
, n
), 4, n
)) {
151 case CASE(0, 0, 0, 0):
153 case CASE(1, 0, 0, 0):
157 case CASE(0, 1, 0, 0):
161 case CASE(1, 1, 0, 0):
162 WRITE4(dst
, 0, _ABCA
);
165 case CASE(0, 0, 1, 0):
169 case CASE(1, 0, 1, 0):
176 case CASE(0, 1, 1, 0):
178 WRITE4(dst
, 4, _BCAB
);
181 case CASE(1, 1, 1, 0):
185 case CASE(0, 0, 0, 1):
187 WRITE2(dst
, 10, _BC
);
189 case CASE(1, 0, 0, 1):
194 WRITE2(dst
, 10, _BC
);
196 case CASE(0, 1, 0, 1):
201 WRITE2(dst
, 10, _BC
);
203 case CASE(1, 1, 0, 1):
204 WRITE4(dst
, 0, _ABCA
);
208 WRITE2(dst
, 10, _BC
);
210 case CASE(0, 0, 1, 1):
212 WRITE4(dst
, 8, _CABC
);
214 case CASE(1, 0, 1, 1):
219 WRITE4(dst
, 8, _CABC
);
221 case CASE(0, 1, 1, 1):
223 WRITE4(dst
, 4, _BCAB
);
224 WRITE4(dst
, 8, _CABC
);
226 case CASE(1, 1, 1, 1):
228 WRITE4(dst
, 8, _CABC
);
231 bits
= FbStipLeft(bits
, n
);
235 dstLine
+= dstStride
;
240 fbPolyGlyphBlt(DrawablePtr pDrawable
,
244 unsigned int nglyph
, CharInfoPtr
* ppci
, pointer pglyphBase
)
246 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
248 unsigned char *pglyph
; /* pointer bits in glyph */
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);
254 FbStride dstStride
= 0;
256 int dstXoff
= 0, dstYoff
= 0;
259 if (pGC
->fillStyle
== FillSolid
&& pPriv
->and == 0) {
260 dstBpp
= pDrawable
->bitsPerPixel
;
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
,
291 (*glyph
) (dst
+ (gy
+ dstYoff
) * dstStride
, dstStride
, dstBpp
,
292 (FbStip
*) pglyph
, pPriv
->xor, gx
+ dstXoff
, gHeight
);
293 fbFinishAccess(pDrawable
);
296 gStride
= GLYPHWIDTHBYTESPADDED(pci
) / sizeof(FbStip
);
297 fbPushImage(pDrawable
,
300 gStride
, 0, gx
, gy
, gWidth
, gHeight
);
303 x
+= pci
->metrics
.characterWidth
;
308 fbImageGlyphBlt(DrawablePtr pDrawable
,
312 unsigned int nglyph
, CharInfoPtr
* ppciInit
, pointer pglyphBase
)
314 FbGCPrivPtr pPriv
= fbGetGCPrivate(pGC
);
317 unsigned char *pglyph
; /* pointer bits in glyph */
318 int gWidth
, gHeight
; /* width and height of glyph */
319 FbStride gStride
; /* stride of glyph */
323 void (*glyph
) (FbBits
*, FbStride
, int, FbStip
*, FbBits
, int, int);
325 FbStride dstStride
= 0;
327 int dstXoff
= 0, dstYoff
= 0;
330 if (pPriv
->and == 0) {
331 dstBpp
= pDrawable
->bitsPerPixel
;
351 if (TERMINALFONT(pGC
->font
)
356 int xBack
, widthBack
;
357 int yBack
, heightBack
;
363 widthBack
+= (*ppci
++)->metrics
.characterWidth
;
368 widthBack
= -widthBack
;
370 yBack
= y
- FONTASCENT(pGC
->font
);
371 heightBack
= FONTASCENT(pGC
->font
) + FONTDESCENT(pGC
->font
);
372 fbSolidBoxClipped(pDrawable
,
373 fbGetCompositeClip(pGC
),
378 fbAnd(GXcopy
, pPriv
->bg
, pPriv
->pm
),
379 fbXor(GXcopy
, pPriv
->bg
, pPriv
->pm
));
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
,
396 (*glyph
) (dst
+ (gy
+ dstYoff
) * dstStride
, dstStride
, dstBpp
,
397 (FbStip
*) pglyph
, pPriv
->fg
, gx
+ dstXoff
, gHeight
);
398 fbFinishAccess(pDrawable
);
401 gStride
= GLYPHWIDTHBYTESPADDED(pci
) / sizeof(FbStip
);
402 fbPutXYImage(pDrawable
,
403 fbGetCompositeClip(pGC
),
411 gWidth
, gHeight
, (FbStip
*) pglyph
, gStride
, 0);
414 x
+= pci
->metrics
.characterWidth
;