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