fbglyph.c revision 05b261ec
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#define dummyScreen screenInfo.screens[0] 33 34Bool 35fbGlyphIn (RegionPtr pRegion, 36 int x, 37 int y, 38 int width, 39 int height) 40{ 41 BoxRec box; 42 BoxPtr pExtents = REGION_EXTENTS (dummyScreen, pRegion); 43 44 /* 45 * Check extents by hand to avoid 16 bit overflows 46 */ 47 if (x < (int) pExtents->x1) 48 return FALSE; 49 if ((int) pExtents->x2 < x + width) 50 return FALSE; 51 if (y < (int) pExtents->y1) 52 return FALSE; 53 if ((int) pExtents->y2 < y + height) 54 return FALSE; 55 box.x1 = x; 56 box.x2 = x + width; 57 box.y1 = y; 58 box.y2 = y + height; 59 return RECT_IN_REGION (dummyScreen, pRegion, &box) == rgnIN; 60} 61 62#ifdef FB_24BIT 63#ifndef FBNOPIXADDR 64 65#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg) 66#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg) 67#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg) 68#if FB_UNIT == 6 && IMAGE_BYTE_ORDER == LSBFirst 69#define WRITE8(d) WRITE((FbBits *) &(d[0]), fg) 70#else 71#define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB) 72#endif 73 74/* 75 * This is a bit tricky, but it's brief. Write 12 bytes worth 76 * of dest, which is four pixels, at a time. This gives constant 77 * code for each pattern as they're always aligned the same 78 * 79 * a b c d a b c d a b c d bytes 80 * A B C A B C A B C A B C pixels 81 * 82 * f0 f1 f2 83 * A B C A B C A B C A B C pixels LSB 84 * C A B C A B C A B C A B pixels MSB 85 * 86 * LSB MSB 87 * A f0 f1 88 * B f1 f2 89 * C f2 f0 90 * A B f0 f2 91 * B C f1 f0 92 * C A f2 f1 93 * A B C A f0 f1 94 * B C A B f1 f2 95 * C A B C f2 f0 96 */ 97 98#undef _A 99#undef _B 100#undef _C 101#undef _AB 102#undef _BC 103#undef _CA 104#undef _ABCA 105#undef _BCAB 106#undef _CABC 107 108#if IMAGE_BYTE_ORDER == MSBFirst 109#define _A f1 110#define _B f2 111#define _C f0 112#define _AB f2 113#define _BC f0 114#define _CA f1 115#define _ABCA f1 116#define _BCAB f2 117#define _CABC f0 118#define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d) 119#else 120#define _A f0 121#define _B f1 122#define _C f2 123#define _AB f0 124#define _BC f1 125#define _CA f2 126#define _ABCA f0 127#define _BCAB f1 128#define _CABC f2 129#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) 130#endif 131 132void 133fbGlyph24 (FbBits *dstBits, 134 FbStride dstStride, 135 int dstBpp, 136 FbStip *stipple, 137 FbBits fg, 138 int x, 139 int height) 140{ 141 int lshift; 142 FbStip bits; 143 CARD8 *dstLine; 144 CARD8 *dst; 145 FbStip f0, f1, f2; 146 int n; 147 int shift; 148 149 f0 = fg; 150 f1 = FbRot24(f0,16); 151 f2 = FbRot24(f0,8); 152 153 dstLine = (CARD8 *) dstBits; 154 dstLine += (x & ~3) * 3; 155 dstStride *= (sizeof (FbBits) / sizeof (CARD8)); 156 shift = x & 3; 157 lshift = 4 - shift; 158 while (height--) 159 { 160 bits = READ(stipple++); 161 n = lshift; 162 dst = dstLine; 163 while (bits) 164 { 165 switch (FbStipMoveLsb (FbLeftStipBits (bits, n), 4, n)) { 166 case CASE(0,0,0,0): 167 break; 168 case CASE(1,0,0,0): 169 WRITE2(dst,0,_AB); 170 WRITE1(dst,2,_C); 171 break; 172 case CASE(0,1,0,0): 173 WRITE1(dst,3,_A); 174 WRITE2(dst,4,_BC); 175 break; 176 case CASE(1,1,0,0): 177 WRITE4(dst,0,_ABCA); 178 WRITE2(dst,4,_BC); 179 break; 180 case CASE(0,0,1,0): 181 WRITE2(dst,6,_AB); 182 WRITE1(dst,8,_C); 183 break; 184 case CASE(1,0,1,0): 185 WRITE2(dst,0,_AB); 186 WRITE1(dst,2,_C); 187 188 WRITE2(dst,6,_AB); 189 WRITE1(dst,8,_C); 190 break; 191 case CASE(0,1,1,0): 192 WRITE1(dst,3,_A); 193 WRITE4(dst,4,_BCAB); 194 WRITE1(dst,8,_C); 195 break; 196 case CASE(1,1,1,0): 197 WRITE8(dst); 198 WRITE1(dst,8,_C); 199 break; 200 case CASE(0,0,0,1): 201 WRITE1(dst,9,_A); 202 WRITE2(dst,10,_BC); 203 break; 204 case CASE(1,0,0,1): 205 WRITE2(dst,0,_AB); 206 WRITE1(dst,2,_C); 207 208 WRITE1(dst,9,_A); 209 WRITE2(dst,10,_BC); 210 break; 211 case CASE(0,1,0,1): 212 WRITE1(dst,3,_A); 213 WRITE2(dst,4,_BC); 214 215 WRITE1(dst,9,_A); 216 WRITE2(dst,10,_BC); 217 break; 218 case CASE(1,1,0,1): 219 WRITE4(dst,0,_ABCA); 220 WRITE2(dst,4,_BC); 221 222 WRITE1(dst,9,_A); 223 WRITE2(dst,10,_BC); 224 break; 225 case CASE(0,0,1,1): 226 WRITE2(dst,6,_AB); 227 WRITE4(dst,8,_CABC); 228 break; 229 case CASE(1,0,1,1): 230 WRITE2(dst,0,_AB); 231 WRITE1(dst,2,_C); 232 233 WRITE2(dst,6,_AB); 234 WRITE4(dst,8,_CABC); 235 break; 236 case CASE(0,1,1,1): 237 WRITE1(dst,3,_A); 238 WRITE4(dst,4,_BCAB); 239 WRITE4(dst,8,_CABC); 240 break; 241 case CASE(1,1,1,1): 242 WRITE8(dst); 243 WRITE4(dst,8,_CABC); 244 break; 245 } 246 bits = FbStipLeft (bits, n); 247 n = 4; 248 dst += 12; 249 } 250 dstLine += dstStride; 251 } 252} 253#endif 254#endif 255 256void 257fbPolyGlyphBlt (DrawablePtr pDrawable, 258 GCPtr pGC, 259 int x, 260 int y, 261 unsigned int nglyph, 262 CharInfoPtr *ppci, 263 pointer pglyphBase) 264{ 265 FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); 266 CharInfoPtr pci; 267 unsigned char *pglyph; /* pointer bits in glyph */ 268 int gx, gy; 269 int gWidth, gHeight; /* width and height of glyph */ 270 FbStride gStride; /* stride of glyph */ 271#ifndef FBNOPIXADDR 272 void (*glyph) (FbBits *, 273 FbStride, 274 int, 275 FbStip *, 276 FbBits, 277 int, 278 int); 279 FbBits *dst = 0; 280 FbStride dstStride = 0; 281 int dstBpp = 0; 282 int dstXoff = 0, dstYoff = 0; 283 284 glyph = 0; 285 if (pGC->fillStyle == FillSolid && pPriv->and == 0) 286 { 287 dstBpp = pDrawable->bitsPerPixel; 288 switch (dstBpp) { 289 case 8: glyph = fbGlyph8; break; 290 case 16: glyph = fbGlyph16; break; 291#ifdef FB_24BIT 292 case 24: glyph = fbGlyph24; break; 293#endif 294 case 32: glyph = fbGlyph32; break; 295 } 296 } 297#endif 298 x += pDrawable->x; 299 y += pDrawable->y; 300 301 while (nglyph--) 302 { 303 pci = *ppci++; 304 pglyph = FONTGLYPHBITS(pglyphBase, pci); 305 gWidth = GLYPHWIDTHPIXELS(pci); 306 gHeight = GLYPHHEIGHTPIXELS(pci); 307 if (gWidth && gHeight) 308 { 309 gx = x + pci->metrics.leftSideBearing; 310 gy = y - pci->metrics.ascent; 311#ifndef FBNOPIXADDR 312 if (glyph && gWidth <= sizeof (FbStip) * 8 && 313 fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) 314 { 315 fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 316 (*glyph) (dst + (gy + dstYoff) * dstStride, 317 dstStride, 318 dstBpp, 319 (FbStip *) pglyph, 320 pPriv->xor, 321 gx + dstXoff, 322 gHeight); 323 fbFinishAccess (pDrawable); 324 } 325 else 326#endif 327 { 328 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); 329 fbPushImage (pDrawable, 330 pGC, 331 332 (FbStip *) pglyph, 333 gStride, 334 0, 335 336 gx, 337 gy, 338 gWidth, gHeight); 339 } 340 } 341 x += pci->metrics.characterWidth; 342 } 343} 344 345 346void 347fbImageGlyphBlt (DrawablePtr pDrawable, 348 GCPtr pGC, 349 int x, 350 int y, 351 unsigned int nglyph, 352 CharInfoPtr *ppciInit, 353 pointer pglyphBase) 354{ 355 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 356 CharInfoPtr *ppci; 357 CharInfoPtr pci; 358 unsigned char *pglyph; /* pointer bits in glyph */ 359 int gWidth, gHeight; /* width and height of glyph */ 360 FbStride gStride; /* stride of glyph */ 361 Bool opaque; 362 int n; 363 int gx, gy; 364#ifndef FBNOPIXADDR 365 void (*glyph) (FbBits *, 366 FbStride, 367 int, 368 FbStip *, 369 FbBits, 370 int, 371 int); 372 FbBits *dst = 0; 373 FbStride dstStride = 0; 374 int dstBpp = 0; 375 int dstXoff = 0, dstYoff = 0; 376 377 glyph = 0; 378 if (pPriv->and == 0) 379 { 380 dstBpp = pDrawable->bitsPerPixel; 381 switch (dstBpp) { 382 case 8: glyph = fbGlyph8; break; 383 case 16: glyph = fbGlyph16; break; 384#ifdef FB_24BIT 385 case 24: glyph = fbGlyph24; break; 386#endif 387 case 32: glyph = fbGlyph32; break; 388 } 389 } 390#endif 391 392 x += pDrawable->x; 393 y += pDrawable->y; 394 395 if (TERMINALFONT (pGC->font) 396#ifndef FBNOPIXADDR 397 && !glyph 398#endif 399 ) 400 { 401 opaque = TRUE; 402 } 403 else 404 { 405 int xBack, widthBack; 406 int yBack, heightBack; 407 408 ppci = ppciInit; 409 n = nglyph; 410 widthBack = 0; 411 while (n--) 412 widthBack += (*ppci++)->metrics.characterWidth; 413 414 xBack = x; 415 if (widthBack < 0) 416 { 417 xBack += widthBack; 418 widthBack = -widthBack; 419 } 420 yBack = y - FONTASCENT(pGC->font); 421 heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); 422 fbSolidBoxClipped (pDrawable, 423 fbGetCompositeClip(pGC), 424 xBack, 425 yBack, 426 xBack + widthBack, 427 yBack + heightBack, 428 fbAnd(GXcopy,pPriv->bg,pPriv->pm), 429 fbXor(GXcopy,pPriv->bg,pPriv->pm)); 430 opaque = FALSE; 431 } 432 433 ppci = ppciInit; 434 while (nglyph--) 435 { 436 pci = *ppci++; 437 pglyph = FONTGLYPHBITS(pglyphBase, pci); 438 gWidth = GLYPHWIDTHPIXELS(pci); 439 gHeight = GLYPHHEIGHTPIXELS(pci); 440 if (gWidth && gHeight) 441 { 442 gx = x + pci->metrics.leftSideBearing; 443 gy = y - pci->metrics.ascent; 444#ifndef FBNOPIXADDR 445 if (glyph && gWidth <= sizeof (FbStip) * 8 && 446 fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) 447 { 448 fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 449 (*glyph) (dst + (gy + dstYoff) * dstStride, 450 dstStride, 451 dstBpp, 452 (FbStip *) pglyph, 453 pPriv->fg, 454 gx + dstXoff, 455 gHeight); 456 fbFinishAccess (pDrawable); 457 } 458 else 459#endif 460 { 461 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); 462 fbPutXYImage (pDrawable, 463 fbGetCompositeClip(pGC), 464 pPriv->fg, 465 pPriv->bg, 466 pPriv->pm, 467 GXcopy, 468 opaque, 469 470 gx, 471 gy, 472 gWidth, gHeight, 473 474 (FbStip *) pglyph, 475 gStride, 476 0); 477 } 478 } 479 x += pci->metrics.characterWidth; 480 } 481} 482