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
32 static Bool
fbGlyphIn(RegionPtr pRegion,int x,int y,int width,int height)33 fbGlyphIn(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 void
fbPolyGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,void * pglyphBase)57 fbPolyGlyphBlt(DrawablePtr pDrawable,
58 GCPtr pGC,
59 int x,
60 int y,
61 unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase)
62 {
63 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
64 CharInfoPtr pci;
65 unsigned char *pglyph; /* pointer bits in glyph */
66 int gx, gy;
67 int gWidth, gHeight; /* width and height of glyph */
68 FbStride gStride; /* stride of glyph */
69 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
70 FbBits *dst = 0;
71 FbStride dstStride = 0;
72 int dstBpp = 0;
73 int dstXoff = 0, dstYoff = 0;
74
75 glyph = 0;
76 if (pGC->fillStyle == FillSolid && pPriv->and == 0) {
77 dstBpp = pDrawable->bitsPerPixel;
78 switch (dstBpp) {
79 case 8:
80 glyph = fbGlyph8;
81 break;
82 case 16:
83 glyph = fbGlyph16;
84 break;
85 case 32:
86 glyph = fbGlyph32;
87 break;
88 }
89 }
90 x += pDrawable->x;
91 y += pDrawable->y;
92
93 while (nglyph--) {
94 pci = *ppci++;
95 pglyph = FONTGLYPHBITS(pglyphBase, pci);
96 gWidth = GLYPHWIDTHPIXELS(pci);
97 gHeight = GLYPHHEIGHTPIXELS(pci);
98 if (gWidth && gHeight) {
99 gx = x + pci->metrics.leftSideBearing;
100 gy = y - pci->metrics.ascent;
101 if (glyph && gWidth <= sizeof(FbStip) * 8 &&
102 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) {
103 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff,
104 dstYoff);
105 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
106 (FbStip *) pglyph, pPriv->xor, gx + dstXoff, gHeight);
107 fbFinishAccess(pDrawable);
108 }
109 else {
110 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
111 fbPushImage(pDrawable,
112 pGC,
113 (FbStip *) pglyph,
114 gStride, 0, gx, gy, gWidth, gHeight);
115 }
116 }
117 x += pci->metrics.characterWidth;
118 }
119 }
120
121 void
fbImageGlyphBlt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppciInit,void * pglyphBase)122 fbImageGlyphBlt(DrawablePtr pDrawable,
123 GCPtr pGC,
124 int x,
125 int y,
126 unsigned int nglyph, CharInfoPtr * ppciInit, void *pglyphBase)
127 {
128 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
129 CharInfoPtr *ppci;
130 CharInfoPtr pci;
131 unsigned char *pglyph; /* pointer bits in glyph */
132 int gWidth, gHeight; /* width and height of glyph */
133 FbStride gStride; /* stride of glyph */
134 Bool opaque;
135 int n;
136 int gx, gy;
137 void (*glyph) (FbBits *, FbStride, int, FbStip *, FbBits, int, int);
138 FbBits *dst = 0;
139 FbStride dstStride = 0;
140 int dstBpp = 0;
141 int dstXoff = 0, dstYoff = 0;
142
143 glyph = 0;
144 if (pPriv->and == 0) {
145 dstBpp = pDrawable->bitsPerPixel;
146 switch (dstBpp) {
147 case 8:
148 glyph = fbGlyph8;
149 break;
150 case 16:
151 glyph = fbGlyph16;
152 break;
153 case 32:
154 glyph = fbGlyph32;
155 break;
156 }
157 }
158
159 x += pDrawable->x;
160 y += pDrawable->y;
161
162 if (TERMINALFONT(pGC->font)
163 && !glyph) {
164 opaque = TRUE;
165 }
166 else {
167 int xBack, widthBack;
168 int yBack, heightBack;
169
170 ppci = ppciInit;
171 n = nglyph;
172 widthBack = 0;
173 while (n--)
174 widthBack += (*ppci++)->metrics.characterWidth;
175
176 xBack = x;
177 if (widthBack < 0) {
178 xBack += widthBack;
179 widthBack = -widthBack;
180 }
181 yBack = y - FONTASCENT(pGC->font);
182 heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
183 fbSolidBoxClipped(pDrawable,
184 fbGetCompositeClip(pGC),
185 xBack,
186 yBack,
187 xBack + widthBack,
188 yBack + heightBack,
189 fbAnd(GXcopy, pPriv->bg, pPriv->pm),
190 fbXor(GXcopy, pPriv->bg, pPriv->pm));
191 opaque = FALSE;
192 }
193
194 ppci = ppciInit;
195 while (nglyph--) {
196 pci = *ppci++;
197 pglyph = FONTGLYPHBITS(pglyphBase, pci);
198 gWidth = GLYPHWIDTHPIXELS(pci);
199 gHeight = GLYPHHEIGHTPIXELS(pci);
200 if (gWidth && gHeight) {
201 gx = x + pci->metrics.leftSideBearing;
202 gy = y - pci->metrics.ascent;
203 if (glyph && gWidth <= sizeof(FbStip) * 8 &&
204 fbGlyphIn(fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) {
205 fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff,
206 dstYoff);
207 (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp,
208 (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight);
209 fbFinishAccess(pDrawable);
210 }
211 else {
212 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof(FbStip);
213 fbPutXYImage(pDrawable,
214 fbGetCompositeClip(pGC),
215 pPriv->fg,
216 pPriv->bg,
217 pPriv->pm,
218 GXcopy,
219 opaque,
220 gx,
221 gy,
222 gWidth, gHeight, (FbStip *) pglyph, gStride, 0);
223 }
224 }
225 x += pci->metrics.characterWidth;
226 }
227 }
228