1 /* 2 * Copyright 2000 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Keith Packard not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Keith Packard makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23 #include "xftint.h" 24 #include <stdint.h> 25 26 #define NUM_LOCAL 1024 27 #define NUM_ELT_LOCAL 128 28 29 /* 30 * Dispatch glyph drawing to the correct XRenderCompositeString function 31 */ 32 static void 33 _XftCompositeString (Display *dpy, 34 int op, 35 Picture src, 36 Picture dst, 37 XRenderPictFormat *format, 38 GlyphSet glyphset, 39 int srcx, 40 int srcy, 41 int dstx, 42 int dsty, 43 int charwidth, 44 unsigned int *chars, 45 int nchars) 46 { 47 if (nchars == 0) 48 return; 49 50 switch (charwidth) { 51 case 1: 52 default: 53 XRenderCompositeString8 (dpy, op, 54 src, dst, format, glyphset, 55 srcx, srcy, dstx, dsty, (char*)chars, nchars); 56 break; 57 case 2: 58 XRenderCompositeString16(dpy, op, 59 src, dst, format, glyphset, 60 srcx, srcy, dstx, dsty, (unsigned short*)chars, nchars); 61 break; 62 case 4: 63 XRenderCompositeString32(dpy, op, 64 src, dst, format, glyphset, 65 srcx, srcy, dstx, dsty, (unsigned int*)chars, nchars); 66 break; 67 } 68 } 69 70 /* 71 * Use the Render extension to draw the glyphs 72 */ 73 74 _X_EXPORT void 75 XftGlyphRender (Display *dpy, 76 int op, 77 Picture src, 78 XftFont *pub, 79 Picture dst, 80 int srcx, 81 int srcy, 82 int x, 83 int y, 84 _Xconst FT_UInt *glyphs, 85 int nglyphs) 86 { 87 XftFontInt *font = (XftFontInt *) pub; 88 int i, j; 89 FT_UInt missing[XFT_NMISSING]; 90 int nmissing; 91 FT_UInt g, max; 92 int width; 93 int dstx, dsty; 94 Glyph wire; 95 XftGlyph* glyph; 96 char *char8; 97 unsigned short *char16; 98 unsigned int *char32; 99 unsigned int char_local[NUM_LOCAL]; 100 unsigned int *chars; 101 FcBool glyphs_loaded; 102 size_t size; 103 size_t needed; 104 105 if (!font->format) 106 return; 107 108 /* 109 * Load missing glyphs 110 */ 111 nmissing = 0; 112 max = 0; 113 glyphs_loaded = FcFalse; 114 for (i = 0; i < nglyphs; i++) 115 { 116 g = glyphs[i]; 117 if (g > max) 118 max = g; 119 if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing)) 120 glyphs_loaded = FcTrue; 121 } 122 if (nmissing) 123 XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing); 124 125 if (!font->glyphset) 126 goto bail1; 127 if (max < 0x100) 128 { 129 width = 1; 130 size = sizeof (char); 131 } 132 else if (max < 0x10000) 133 { 134 width = 2; 135 size = sizeof (unsigned short); 136 } 137 else 138 { 139 width = 4; 140 size = sizeof (unsigned int); 141 } 142 chars = char_local; 143 if ((size_t)nglyphs > SIZE_MAX / size) 144 goto bail1; 145 needed = (size_t)nglyphs * size; 146 if (needed > sizeof (char_local)) 147 { 148 chars = malloc (needed); 149 if (!chars) 150 goto bail1; 151 } 152 dstx = x; 153 dsty = y; 154 char8 = (char *) chars; 155 char16 = (unsigned short *) chars; 156 char32 = (unsigned int *) chars; 157 for (i = 0, j = 0; i < nglyphs; i++) 158 { 159 wire = (Glyph) glyphs[i]; 160 if (wire >= (Glyph) font->num_glyphs || !font->glyphs[wire]) 161 wire = 0; 162 glyph = font->glyphs[wire]; 163 if (glyph == NULL) 164 continue; 165 if (glyph->picture) 166 { 167 _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, srcx, srcy, x, y, width, chars, j); 168 XRenderComposite(dpy, PictOpOver, glyph->picture, None, dst, 0, 0, 0, 0, dstx - glyph->metrics.x, dsty - glyph->metrics.y, glyph->metrics.width, glyph->metrics.height); 169 dstx += glyph->metrics.xOff; 170 dsty += glyph->metrics.yOff; 171 x = dstx; 172 y = dsty; 173 j = 0; 174 } 175 else 176 { 177 switch (width) { 178 case 1: char8[j] = (char) wire; break; 179 case 2: char16[j] = (unsigned short) wire; break; 180 case 4: char32[j] = (unsigned int) wire; break; 181 } 182 dstx += glyph->metrics.xOff; 183 dsty += glyph->metrics.yOff; 184 ++j; 185 } 186 } 187 _XftCompositeString(dpy, op, src, dst, font->format, font->glyphset, 188 srcx, srcy, x, y, width, chars, j); 189 if (chars != char_local) 190 free (chars); 191 bail1: 192 if (glyphs_loaded) 193 _XftFontManageMemory (dpy, pub); 194 } 195 196 /* 197 * Dispatch glyph drawing to the correct XRenderCompositeText function 198 */ 199 static void 200 _XftCompositeText (Display *dpy, 201 int op, 202 Picture src, 203 Picture dst, 204 XRenderPictFormat *format, 205 int srcx, 206 int srcy, 207 int dstx, 208 int dsty, 209 int eltwidth, 210 XGlyphElt8 *elts, 211 int nelt) 212 { 213 if (nelt == 0) 214 return; 215 216 switch (eltwidth) { 217 case 1: 218 default: 219 XRenderCompositeText8 (dpy, op, 220 src, dst, format, 221 srcx, srcy, dstx, dsty, 222 (XGlyphElt8*)elts, nelt); 223 break; 224 case 2: 225 XRenderCompositeText16(dpy, op, 226 src, dst, format, 227 srcx, srcy, dstx, dsty, 228 (XGlyphElt16*)elts, nelt); 229 break; 230 case 4: 231 XRenderCompositeText32(dpy, op, 232 src, dst, format, 233 srcx, srcy, dstx, dsty, 234 (XGlyphElt32*)elts, nelt); 235 break; 236 } 237 } 238 239 _X_EXPORT void 240 XftGlyphSpecRender (Display *dpy, 241 int op, 242 Picture src, 243 XftFont *pub, 244 Picture dst, 245 int srcx, 246 int srcy, 247 _Xconst XftGlyphSpec *glyphs, 248 int nglyphs) 249 { 250 XftFontInt *font = (XftFontInt *) pub; 251 int i, j; 252 FT_UInt missing[XFT_NMISSING]; 253 int nmissing; 254 int n; 255 FT_UInt g; 256 XftGlyph *glyph; 257 FT_UInt max; 258 int size, width; 259 char *char8; 260 unsigned short *char16; 261 unsigned int *char32; 262 unsigned int char_local[NUM_LOCAL]; 263 unsigned int *chars; 264 XGlyphElt8 *elts; 265 XGlyphElt8 elts_local[NUM_ELT_LOCAL]; 266 FcBool glyphs_loaded; 267 int nelt; 268 int x, y; 269 270 if (!font->format) 271 return; 272 if (!nglyphs) 273 return; 274 275 /* 276 * Load missing glyphs 277 */ 278 max = 0; 279 nmissing = 0; 280 glyphs_loaded = FcFalse; 281 g = glyphs[0].glyph; 282 for (i = 0; i < nglyphs; i++) 283 { 284 g = glyphs[i].glyph; 285 if (g > max) 286 max = g; 287 if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing)) 288 glyphs_loaded = FcTrue; 289 } 290 if (nmissing) 291 XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing); 292 293 if (!font->glyphset) 294 goto bail1; 295 296 /* 297 * See what encoding size is needed 298 */ 299 if (max < 0x100) 300 { 301 size = sizeof (char); 302 width = 1; 303 } 304 else if (max < 0x10000) 305 { 306 size = sizeof (unsigned short); 307 width = 2; 308 } 309 else 310 { 311 size = sizeof (unsigned int); 312 width = 4; 313 } 314 chars = char_local; 315 if (nglyphs * size > NUM_LOCAL) 316 { 317 chars = malloc ((size_t)(nglyphs * size)); 318 if (!chars) 319 goto bail1; 320 } 321 char8 = (char *) chars; 322 char16 = (unsigned short *) chars; 323 char32 = (unsigned int *) chars; 324 325 /* 326 * Compute the number of glyph elts needed 327 */ 328 nelt = 1; 329 for (i = 0; i < nglyphs; i++) 330 { 331 g = glyphs[i].glyph; 332 /* Substitute default for non-existent glyphs */ 333 if (g >= font->num_glyphs || !font->glyphs[g]) 334 g = 0; 335 if (font->glyphs[g]) 336 break; 337 } 338 if (i == nglyphs) 339 goto bail2; 340 glyph = font->glyphs[g]; 341 x = glyphs[i].x + glyph->metrics.xOff; 342 y = glyphs[i].y + glyph->metrics.yOff; 343 while (++i < nglyphs) 344 { 345 g = glyphs[i].glyph; 346 /* Substitute default for non-existent glyphs */ 347 if (g >= font->num_glyphs || !font->glyphs[g]) 348 g = 0; 349 /* 350 * check to see if the glyph is placed where it would 351 * fall using the normal spacing and if it would render 352 * as a XRender glyph 353 */ 354 if ((glyph = font->glyphs[g]) && !glyph->picture) 355 { 356 if (x != glyphs[i].x || y != glyphs[i].y) 357 { 358 x = glyphs[i].x; 359 y = glyphs[i].y; 360 ++nelt; 361 } 362 x += glyph->metrics.xOff; 363 y += glyph->metrics.yOff; 364 } 365 } 366 367 elts = elts_local; 368 if (nelt > NUM_ELT_LOCAL) 369 { 370 elts = AllocGlyphElt8Array (nelt); 371 if (!elts) 372 goto bail2; 373 } 374 375 /* 376 * Generate the list of glyph elts or render color glyphs 377 */ 378 nelt = 0; 379 x = y = 0; 380 n = 0; 381 j = 0; 382 for (i = 0; i < nglyphs; i++) 383 { 384 g = glyphs[i].glyph; 385 /* Substitute default for non-existent glyphs */ 386 if (g >= font->num_glyphs || !font->glyphs[g]) 387 g = 0; 388 if ((glyph = font->glyphs[g])) 389 { 390 if (glyph->picture) 391 { 392 XRenderComposite(dpy, PictOpOver, glyph->picture, None, 393 dst, 0, 0, 0, 0, 394 glyphs[i].x - glyph->metrics.x, 395 glyphs[i].y - glyph->metrics.y, 396 glyph->metrics.width, 397 glyph->metrics.height); 398 continue; 399 } 400 if (!i || x != glyphs[i].x || y != glyphs[i].y) 401 { 402 if (n) 403 { 404 elts[nelt].nchars = n; 405 nelt++; 406 } 407 elts[nelt].glyphset = font->glyphset; 408 elts[nelt].chars = char8 + size * j; 409 elts[nelt].xOff = glyphs[i].x - x; 410 elts[nelt].yOff = glyphs[i].y - y; 411 x = glyphs[i].x; 412 y = glyphs[i].y; 413 n = 0; 414 } 415 switch (width) { 416 case 1: char8[j] = (char) g; break; 417 case 2: char16[j] = (unsigned short) g; break; 418 case 4: char32[j] = (unsigned int) g; break; 419 } 420 x += glyph->metrics.xOff; 421 y += glyph->metrics.yOff; 422 j++; 423 n++; 424 } 425 } 426 if (n) 427 { 428 elts[nelt].nchars = n; 429 nelt++; 430 } 431 _XftCompositeText(dpy, op, src, dst, font->format, 432 srcx, srcy, glyphs[0].x, glyphs[0].y, 433 width, elts, nelt); 434 435 if (elts != elts_local) 436 free (elts); 437 bail2: 438 if (chars != char_local) 439 free (chars); 440 bail1: 441 if (glyphs_loaded) 442 _XftFontManageMemory (dpy, pub); 443 } 444 445 _X_EXPORT void 446 XftCharSpecRender (Display *dpy, 447 int op, 448 Picture src, 449 XftFont *pub, 450 Picture dst, 451 int srcx, 452 int srcy, 453 _Xconst XftCharSpec *chars, 454 int len) 455 { 456 XftGlyphSpec *glyphs, glyphs_local[NUM_LOCAL]; 457 int i; 458 459 if (len <= 0) 460 return; 461 462 if (len <= NUM_LOCAL) 463 glyphs = glyphs_local; 464 else 465 { 466 glyphs = AllocGlyphSpecArray (len); 467 if (!glyphs) 468 return; 469 } 470 for (i = 0; i < len; i++) 471 { 472 glyphs[i].glyph = XftCharIndex(dpy, pub, chars[i].ucs4); 473 glyphs[i].x = chars[i].x; 474 glyphs[i].y = chars[i].y; 475 } 476 477 XftGlyphSpecRender (dpy, op, src, pub, dst, srcx, srcy, glyphs, len); 478 479 if (glyphs != glyphs_local) 480 free (glyphs); 481 } 482 483 /* 484 * Choose which format to draw text in when drawing with fonts 485 * of different formats. The trick is that ARGB formats aren't 486 * compatible with A formats as PictOpAdd does the wrong thing, so 487 * fall back to an A format when presented with an ARGB and A format 488 */ 489 490 #define XftIsARGBFormat(a) ((a)->depth == 32) 491 492 static XRenderPictFormat * 493 XftPreferFormat (Display *dpy, XRenderPictFormat *a, XRenderPictFormat *b) 494 { 495 XRenderPictFormat *prefer = NULL; 496 497 if (a == b) 498 prefer = a; 499 else if (XftIsARGBFormat(a) != XftIsARGBFormat(b)) 500 prefer = XRenderFindStandardFormat (dpy, PictStandardA8); 501 else if (a->depth > b->depth) 502 prefer = a; 503 else 504 prefer = b; 505 return prefer; 506 } 507 508 _X_EXPORT void 509 XftGlyphFontSpecRender (Display *dpy, 510 int op, 511 Picture src, 512 Picture dst, 513 int srcx, 514 int srcy, 515 _Xconst XftGlyphFontSpec *glyphs, 516 int nglyphs) 517 { 518 int i, j; 519 XftFont *prevPublic; 520 XftFontInt *firstFont; 521 XRenderPictFormat *format; 522 FT_UInt missing[XFT_NMISSING]; 523 int nmissing; 524 int n; 525 FT_UInt g; 526 XftGlyph *glyph; 527 FT_UInt max; 528 int size, width; 529 char *char8; 530 unsigned short *char16; 531 unsigned int *char32; 532 unsigned int char_local[NUM_LOCAL]; 533 unsigned int *chars; 534 XGlyphElt8 *elts; 535 XGlyphElt8 elts_local[NUM_ELT_LOCAL]; 536 FcBool glyphs_loaded; 537 int nelt; 538 int x, y; 539 540 if (!nglyphs) 541 return; 542 543 /* 544 * Load missing glyphs. Have to load them 545 * one at a time in case the font changes 546 */ 547 max = 0; 548 glyphs_loaded = FcFalse; 549 g = glyphs[0].glyph; 550 for (i = 0; i < nglyphs; i++) 551 { 552 XftFont *pub = glyphs[i].font; 553 XftFontInt *font = (XftFontInt *) pub; 554 g = glyphs[i].glyph; 555 if (g > max) 556 max = g; 557 nmissing = 0; 558 if (XftFontCheckGlyph (dpy, pub, FcTrue, g, missing, &nmissing)) 559 glyphs_loaded = FcTrue; 560 if (nmissing) 561 XftFontLoadGlyphs (dpy, pub, FcTrue, missing, nmissing); 562 if (!font->format) 563 goto bail1; 564 if (!font->glyphset) 565 goto bail1; 566 } 567 568 /* 569 * See what encoding size is needed 570 */ 571 if (max < 0x100) 572 { 573 size = sizeof (char); 574 width = 1; 575 } 576 else if (max < 0x10000) 577 { 578 size = sizeof (unsigned short); 579 width = 2; 580 } 581 else 582 { 583 size = sizeof (unsigned int); 584 width = 4; 585 } 586 chars = char_local; 587 if (nglyphs * size > NUM_LOCAL) 588 { 589 chars = malloc ((size_t)(nglyphs * size)); 590 if (!chars) 591 goto bail1; 592 } 593 char8 = (char *) chars; 594 char16 = (unsigned short *) chars; 595 char32 = (unsigned int *) chars; 596 597 /* 598 * Compute the number of glyph elts needed 599 */ 600 nelt = 1; 601 firstFont = NULL; 602 for (i = 0; i < nglyphs; i++) 603 { 604 XftFont *pub = glyphs[i].font; 605 XftFontInt *font = (XftFontInt *) pub; 606 g = glyphs[i].glyph; 607 /* Substitute default for non-existent glyphs */ 608 if (g >= font->num_glyphs || !font->glyphs[g]) 609 g = 0; 610 if (font->glyphs[g]) 611 { 612 firstFont = font; 613 break; 614 } 615 } 616 if (i == nglyphs || !firstFont) 617 goto bail2; 618 glyph = firstFont->glyphs[g]; 619 format = firstFont->format; 620 x = glyphs[i].x + glyph->metrics.xOff; 621 y = glyphs[i].y + glyph->metrics.yOff; 622 prevPublic = NULL; 623 while (++i < nglyphs) 624 { 625 XftFont *pub = glyphs[i].font; 626 XftFontInt *font = (XftFontInt *) pub; 627 g = glyphs[i].glyph; 628 /* Substitute default for non-existent glyphs */ 629 if (g >= font->num_glyphs || !font->glyphs[g]) 630 g = 0; 631 /* 632 * check to see if the glyph is placed where it would 633 * fall using the normal spacing 634 */ 635 if ((glyph = font->glyphs[g]) && !glyph->picture) 636 { 637 if (pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y) 638 { 639 prevPublic = pub; 640 if (font->format != format) 641 format = XftPreferFormat (dpy, font->format, format); 642 x = glyphs[i].x; 643 y = glyphs[i].y; 644 ++nelt; 645 } 646 x += glyph->metrics.xOff; 647 y += glyph->metrics.yOff; 648 } 649 } 650 651 elts = elts_local; 652 if (nelt > NUM_ELT_LOCAL) 653 { 654 elts = AllocGlyphElt8Array (nelt); 655 if (!elts) 656 goto bail2; 657 } 658 659 /* 660 * Generate the list of glyph elts and render color glyphs 661 */ 662 nelt = 0; 663 x = y = 0; 664 n = 0; 665 j = 0; 666 prevPublic = NULL; 667 for (i = 0; i < nglyphs; i++) 668 { 669 XftFont *pub = glyphs[i].font; 670 XftFontInt *font = (XftFontInt *) pub; 671 672 g = glyphs[i].glyph; 673 /* Substitute default for non-existent glyphs */ 674 if (g >= font->num_glyphs || !font->glyphs[g]) 675 g = 0; 676 if ((glyph = font->glyphs[g])) 677 { 678 if (glyph->picture) 679 { 680 XRenderComposite(dpy, PictOpOver, glyph->picture, None, 681 dst, 0, 0, 0, 0, 682 glyphs[i].x - glyph->metrics.x, 683 glyphs[i].y - glyph->metrics.y, 684 glyph->metrics.width, 685 glyph->metrics.height); 686 continue; 687 } 688 if (!i || pub != prevPublic || x != glyphs[i].x || y != glyphs[i].y) 689 { 690 if (n) 691 { 692 elts[nelt].nchars = n; 693 nelt++; 694 } 695 elts[nelt].glyphset = font->glyphset; 696 elts[nelt].chars = char8 + size * j; 697 elts[nelt].xOff = glyphs[i].x - x; 698 elts[nelt].yOff = glyphs[i].y - y; 699 prevPublic = pub; 700 x = glyphs[i].x; 701 y = glyphs[i].y; 702 n = 0; 703 } 704 switch (width) { 705 case 1: char8[j] = (char) g; break; 706 case 2: char16[j] = (unsigned short) g; break; 707 case 4: char32[j] = (unsigned int) g; break; 708 } 709 x += glyph->metrics.xOff; 710 y += glyph->metrics.yOff; 711 j++; 712 n++; 713 } 714 } 715 if (n) 716 { 717 elts[nelt].nchars = n; 718 nelt++; 719 } 720 _XftCompositeText(dpy, op, src, dst, format, 721 srcx, srcy, glyphs[0].x, glyphs[0].y, 722 width, elts, nelt); 723 724 if (elts != elts_local) 725 free (elts); 726 bail2: 727 if (chars != char_local) 728 free (chars); 729 bail1: 730 if (glyphs_loaded) 731 for (i = 0; i < nglyphs; i++) 732 _XftFontManageMemory (dpy, glyphs[i].font); 733 } 734 735 _X_EXPORT void 736 XftCharFontSpecRender (Display *dpy, 737 int op, 738 Picture src, 739 Picture dst, 740 int srcx, 741 int srcy, 742 _Xconst XftCharFontSpec *chars, 743 int len) 744 { 745 XftGlyphFontSpec *glyphs, glyphs_local[NUM_LOCAL]; 746 int i; 747 748 if (len <= 0) 749 return; 750 751 if (len <= NUM_LOCAL) 752 glyphs = glyphs_local; 753 else 754 { 755 glyphs = AllocGlyphFontSpecArray (len); 756 if (!glyphs) 757 return; 758 } 759 for (i = 0; i < len; i++) 760 { 761 glyphs[i].font = chars[i].font; 762 glyphs[i].glyph = XftCharIndex(dpy, glyphs[i].font, chars[i].ucs4); 763 glyphs[i].x = chars[i].x; 764 glyphs[i].y = chars[i].y; 765 } 766 767 XftGlyphFontSpecRender (dpy, op, src, dst, srcx, srcy, glyphs, len); 768 if (glyphs != glyphs_local) 769 free (glyphs); 770 } 771 772 _X_EXPORT void 773 XftTextRender8 (Display *dpy, 774 int op, 775 Picture src, 776 XftFont *pub, 777 Picture dst, 778 int srcx, 779 int srcy, 780 int x, 781 int y, 782 _Xconst FcChar8 *string, 783 int len) 784 { 785 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 786 int i; 787 788 if (len <= 0) 789 return; 790 791 if (len <= NUM_LOCAL) 792 glyphs = glyphs_local; 793 else 794 { 795 glyphs = AllocUIntArray (len); 796 if (!glyphs) 797 return; 798 } 799 for (i = 0; i < len; i++) 800 glyphs[i] = XftCharIndex (dpy, pub, string[i]); 801 XftGlyphRender (dpy, op, src, pub, dst, 802 srcx, srcy, x, y, glyphs, len); 803 if (glyphs != glyphs_local) 804 free (glyphs); 805 } 806 807 _X_EXPORT void 808 XftTextRender16 (Display *dpy, 809 int op, 810 Picture src, 811 XftFont *pub, 812 Picture dst, 813 int srcx, 814 int srcy, 815 int x, 816 int y, 817 _Xconst FcChar16 *string, 818 int len) 819 { 820 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 821 int i; 822 823 if (len <= 0) 824 return; 825 826 if (len <= NUM_LOCAL) 827 glyphs = glyphs_local; 828 else 829 { 830 glyphs = AllocUIntArray (len); 831 if (!glyphs) 832 return; 833 } 834 for (i = 0; i < len; i++) 835 glyphs[i] = XftCharIndex (dpy, pub, string[i]); 836 XftGlyphRender (dpy, op, src, pub, dst, 837 srcx, srcy, x, y, glyphs, len); 838 if (glyphs != glyphs_local) 839 free (glyphs); 840 } 841 842 _X_EXPORT void 843 XftTextRender16BE (Display *dpy, 844 int op, 845 Picture src, 846 XftFont *pub, 847 Picture dst, 848 int srcx, 849 int srcy, 850 int x, 851 int y, 852 _Xconst FcChar8 *string, 853 int len) 854 { 855 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 856 int i; 857 858 if (len <= 0) 859 return; 860 861 if (len <= NUM_LOCAL) 862 glyphs = glyphs_local; 863 else 864 { 865 glyphs = AllocUIntArray (len); 866 if (!glyphs) 867 return; 868 } 869 for (i = 0; i < len; i++) 870 glyphs[i] = XftCharIndex (dpy, pub, 871 (FcChar32)((string[i*2]<<8) | string[i*2+1])); 872 XftGlyphRender (dpy, op, src, pub, dst, 873 srcx, srcy, x, y, glyphs, len); 874 if (glyphs != glyphs_local) 875 free (glyphs); 876 } 877 878 _X_EXPORT void 879 XftTextRender16LE (Display *dpy, 880 int op, 881 Picture src, 882 XftFont *pub, 883 Picture dst, 884 int srcx, 885 int srcy, 886 int x, 887 int y, 888 _Xconst FcChar8 *string, 889 int len) 890 { 891 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 892 int i; 893 894 if (len <= 0) 895 return; 896 897 if (len <= NUM_LOCAL) 898 glyphs = glyphs_local; 899 else 900 { 901 glyphs = AllocUIntArray (len); 902 if (!glyphs) 903 return; 904 } 905 for (i = 0; i < len; i++) 906 glyphs[i] = XftCharIndex (dpy, pub, 907 (FcChar32)(string[i*2] | (string[i*2+1]<<8))); 908 XftGlyphRender (dpy, op, src, pub, dst, 909 srcx, srcy, x, y, glyphs, len); 910 if (glyphs != glyphs_local) 911 free (glyphs); 912 } 913 914 _X_EXPORT void 915 XftTextRender32 (Display *dpy, 916 int op, 917 Picture src, 918 XftFont *pub, 919 Picture dst, 920 int srcx, 921 int srcy, 922 int x, 923 int y, 924 _Xconst FcChar32 *string, 925 int len) 926 { 927 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 928 int i; 929 930 if (len <= 0) 931 return; 932 933 if (len <= NUM_LOCAL) 934 glyphs = glyphs_local; 935 else 936 { 937 glyphs = AllocUIntArray (len); 938 if (!glyphs) 939 return; 940 } 941 for (i = 0; i < len; i++) 942 glyphs[i] = XftCharIndex (dpy, pub, string[i]); 943 XftGlyphRender (dpy, op, src, pub, dst, 944 srcx, srcy, x, y, glyphs, len); 945 if (glyphs != glyphs_local) 946 free (glyphs); 947 } 948 949 _X_EXPORT void 950 XftTextRender32BE (Display *dpy, 951 int op, 952 Picture src, 953 XftFont *pub, 954 Picture dst, 955 int srcx, 956 int srcy, 957 int x, 958 int y, 959 _Xconst FcChar8 *string, 960 int len) 961 { 962 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 963 int i; 964 965 if (len <= 0) 966 return; 967 968 if (len <= NUM_LOCAL) 969 glyphs = glyphs_local; 970 else 971 { 972 glyphs = AllocUIntArray (len); 973 if (!glyphs) 974 return; 975 } 976 for (i = 0; i < len; i++) 977 glyphs[i] = XftCharIndex (dpy, pub, 978 (FcChar32)((string[i*4] << 24) | 979 (string[i*4+1] << 16) | 980 (string[i*4+2] << 8) | 981 (string[i*4+3]))); 982 XftGlyphRender (dpy, op, src, pub, dst, 983 srcx, srcy, x, y, glyphs, len); 984 if (glyphs != glyphs_local) 985 free (glyphs); 986 } 987 988 _X_EXPORT void 989 XftTextRender32LE (Display *dpy, 990 int op, 991 Picture src, 992 XftFont *pub, 993 Picture dst, 994 int srcx, 995 int srcy, 996 int x, 997 int y, 998 _Xconst FcChar8 *string, 999 int len) 1000 { 1001 FT_UInt *glyphs, glyphs_local[NUM_LOCAL]; 1002 int i; 1003 1004 if (len <= 0) 1005 return; 1006 1007 if (len <= NUM_LOCAL) 1008 glyphs = glyphs_local; 1009 else 1010 { 1011 glyphs = AllocUIntArray (len); 1012 if (!glyphs) 1013 return; 1014 } 1015 for (i = 0; i < len; i++) 1016 glyphs[i] = XftCharIndex (dpy, pub, 1017 (FcChar32)((string[i*4]) | 1018 (string[i*4+1] << 8) | 1019 (string[i*4+2] << 16) | 1020 (string[i*4+3] << 24))); 1021 XftGlyphRender (dpy, op, src, pub, dst, 1022 srcx, srcy, x, y, glyphs, len); 1023 if (glyphs != glyphs_local) 1024 free (glyphs); 1025 } 1026 1027 _X_EXPORT void 1028 XftTextRenderUtf8 (Display *dpy, 1029 int op, 1030 Picture src, 1031 XftFont *pub, 1032 Picture dst, 1033 int srcx, 1034 int srcy, 1035 int x, 1036 int y, 1037 _Xconst FcChar8 *string, 1038 int len) 1039 { 1040 FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; 1041 FcChar32 ucs4; 1042 int i; 1043 int l; 1044 int size; 1045 1046 if (len <= 0) 1047 return; 1048 1049 i = 0; 1050 glyphs = glyphs_local; 1051 size = NUM_LOCAL; 1052 while (len && (l = FcUtf8ToUcs4 (string, &ucs4, len)) > 0) 1053 { 1054 if (i == size) 1055 { 1056 glyphs_new = AllocUIntArray (size * 2); 1057 if (!glyphs_new) 1058 { 1059 if (glyphs != glyphs_local) 1060 free (glyphs); 1061 return; 1062 } 1063 memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt)); 1064 size *= 2; 1065 if (glyphs != glyphs_local) 1066 free (glyphs); 1067 glyphs = glyphs_new; 1068 } 1069 glyphs[i++] = XftCharIndex (dpy, pub, ucs4); 1070 string += l; 1071 len -= l; 1072 } 1073 XftGlyphRender (dpy, op, src, pub, dst, 1074 srcx, srcy, x, y, glyphs, i); 1075 if (glyphs != glyphs_local) 1076 free (glyphs); 1077 } 1078 1079 _X_EXPORT void 1080 XftTextRenderUtf16 (Display *dpy, 1081 int op _X_UNUSED, 1082 Picture src, 1083 XftFont *pub, 1084 Picture dst, 1085 int srcx, 1086 int srcy, 1087 int x, 1088 int y, 1089 _Xconst FcChar8 *string, 1090 FcEndian endian, 1091 int len) 1092 { 1093 FT_UInt *glyphs, *glyphs_new, glyphs_local[NUM_LOCAL]; 1094 FcChar32 ucs4; 1095 int i; 1096 int l; 1097 int size; 1098 1099 if (len <= 0) 1100 return; 1101 1102 i = 0; 1103 glyphs = glyphs_local; 1104 size = NUM_LOCAL; 1105 while (len && (l = FcUtf16ToUcs4 (string, endian, &ucs4, len)) > 0) 1106 { 1107 if (i == size) 1108 { 1109 glyphs_new = AllocUIntArray (size * 2); 1110 if (!glyphs_new) 1111 { 1112 if (glyphs != glyphs_local) 1113 free (glyphs); 1114 return; 1115 } 1116 memcpy (glyphs_new, glyphs, (size_t)size * sizeof (FT_UInt)); 1117 size *= 2; 1118 if (glyphs != glyphs_local) 1119 free (glyphs); 1120 glyphs = glyphs_new; 1121 } 1122 glyphs[i++] = XftCharIndex (dpy, pub, ucs4); 1123 string += l; 1124 len -= l; 1125 } 1126 XftGlyphRender (dpy, PictOpOver, src, pub, dst, 1127 srcx, srcy, x, y, glyphs, i); 1128 if (glyphs != glyphs_local) 1129 free (glyphs); 1130 } 1131