1 /* 2 * Copyright 2022 Thomas E. Dickey 3 * Copyright 2000 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 copyright 8 * notice and this permission notice appear in supporting documentation, and 9 * that the name of the above copyright holders not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. The above copyright holders make 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 * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD TO 16 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 * FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE 18 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24 #include "xftint.h" 25 #include FT_OUTLINE_H 26 #include FT_LCD_FILTER_H 27 28 #include FT_SYNTHESIS_H 29 30 #include FT_GLYPH_H 31 32 typedef double m3x3[3][3]; 33 34 static void 35 m3x3_uniform(m3x3 m) 36 { 37 m[0][0] = m[1][1] = m[2][2] = 1.0; 38 m[0][1] = m[1][0] = m[0][2] = m[1][2] = m[2][0] = m[2][1] = 0; 39 } 40 41 static void 42 m3x3_transform(FT_Vector *v, m3x3 m) 43 { 44 double x, y; 45 46 x = (double)v->x; 47 y = (double)v->y; 48 v->x = (FT_Pos)(x * m[0][0] + y * m[0][1] + m[0][2] + 0.5); 49 v->y = (FT_Pos)(x * m[1][0] + y * m[1][1] + m[1][2] + 0.5); 50 } 51 52 static void 53 m3x3_invert(m3x3 m, m3x3 mi) 54 { 55 double det; 56 57 det = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); 58 det -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]); 59 det += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); 60 det = 1.0 / det; 61 mi[0][0] = det * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); 62 mi[1][0] = det * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); 63 mi[2][0] = det * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); 64 mi[0][1] = det * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); 65 mi[1][1] = det * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); 66 mi[2][1] = det * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); 67 mi[0][2] = det * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); 68 mi[1][2] = det * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); 69 mi[2][2] = det * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); 70 } 71 72 /* 73 * Validate the memory info for a font 74 */ 75 76 static void 77 _XftFontValidateMemory (Display *dpy _X_UNUSED, XftFont *public) 78 { 79 XftFontInt *font = (XftFontInt *) public; 80 unsigned long glyph_memory; 81 FT_UInt glyphindex; 82 XftGlyph *xftg; 83 84 glyph_memory = 0; 85 for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++) 86 { 87 xftg = font->glyphs[glyphindex]; 88 if (xftg) 89 { 90 glyph_memory += xftg->glyph_memory; 91 } 92 } 93 if (glyph_memory != font->glyph_memory) 94 printf ("Font glyph cache incorrect has %lu bytes, should have %lu\n", 95 font->glyph_memory, glyph_memory); 96 } 97 98 /* 99 * Validate the glyph usage-links for a font. 100 */ 101 static void 102 _XftValidateGlyphUsage(XftFontInt *font) 103 { 104 if (font->newest != FT_UINT_MAX) { 105 FT_UInt forward; 106 FT_UInt reverse; 107 FT_UInt next; 108 XftGlyphUsage *x1st = (XftGlyphUsage *) font->glyphs[font->newest]; 109 XftGlyphUsage *xuse = x1st; 110 for (forward = 1, 111 next = x1st->newer; 112 xuse != NULL && 113 next != font->newest; 114 next = xuse->newer) { 115 if (next >= font->num_glyphs) { 116 printf("Xft: out of range; %d\n", next); 117 break; 118 } 119 if (++forward > font->total_inuse) { 120 printf("Xft: too many in-use glyphs (%d vs %d)\n", 121 forward, font->total_inuse); 122 if (forward > font->total_inuse + 10) 123 break; 124 } 125 xuse = (XftGlyphUsage *) font->glyphs[next]; 126 } 127 if (forward < font->total_inuse) { 128 printf("Xft: too few in-use glyphs (%u vs %d)\n", 129 forward, font->total_inuse); 130 } 131 for (reverse = 1, 132 next = x1st->older; 133 xuse != NULL && 134 next != font->newest; 135 next = xuse->older) { 136 if (next >= font->num_glyphs) { 137 printf("Xft out of range; %d\n", next); 138 break; 139 } 140 if (++reverse > font->total_inuse) { 141 printf("Xft: too many in-use glyphs (%d vs %d)\n", 142 reverse, font->total_inuse); 143 if (reverse > font->total_inuse + 10) 144 break; 145 } 146 xuse = (XftGlyphUsage *) font->glyphs[next]; 147 } 148 if (reverse < font->total_inuse) { 149 printf("Xft: too few in-use glyphs (%u vs %d)\n", 150 reverse, font->total_inuse); 151 } 152 if (forward != reverse) { 153 printf("Xft: forward %d vs reverse %d\n", 154 forward, reverse); 155 exit(1); 156 } 157 } 158 } 159 160 /* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot 161 * into a different format. For example, we want to convert a 162 * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit 163 * ARGB or ABGR bitmap. 164 * 165 * this function prepares a target descriptor for this operation. 166 * 167 * input :: target bitmap descriptor. The function will set its 168 * 'width', 'rows' and 'pitch' fields, and only these 169 * 170 * slot :: the glyph slot containing the source bitmap. this 171 * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP 172 * 173 * mode :: the requested final rendering mode. supported values are 174 * MONO, NORMAL (i.e. gray), LCD and LCD_V 175 * 176 * the function returns the size in bytes of the corresponding buffer, 177 * it's up to the caller to allocate the corresponding memory block 178 * before calling _fill_xrender_bitmap 179 * 180 * it also returns -1 in case of error (e.g. incompatible arguments, 181 * like trying to convert a gray bitmap into a monochrome one) 182 */ 183 static int 184 _compute_xrender_bitmap_size( FT_Bitmap* target, 185 FT_GlyphSlot slot, 186 FT_Render_Mode mode, 187 FT_Matrix* matrix, 188 m3x3 m ) 189 { 190 FT_Bitmap* ftbit; 191 int width, height, pitch; 192 193 if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) 194 return -1; 195 196 /* compute the size of the final bitmap */ 197 ftbit = &slot->bitmap; 198 199 width = (int)ftbit->width; 200 height = (int)ftbit->rows; 201 202 if ( matrix && mode == FT_RENDER_MODE_NORMAL ) 203 { 204 FT_Matrix mirror, inverse; 205 FT_Vector vector; 206 int xc, yc; 207 int left, right, top, bottom; 208 209 left = right = top = bottom = 0; 210 for (xc = 0; xc <= 1; xc++) { 211 for (yc = 0; yc <= 1; yc++) { 212 vector.x = xc * width; 213 vector.y = yc * height; 214 FT_Vector_Transform(&vector, matrix); 215 if (xc == 0 && yc == 0) { 216 left = right = (int)vector.x; 217 top = bottom = (int)vector.y; 218 } else { 219 if (left > vector.x) left = (int)vector.x; 220 if (right < vector.x) right = (int)vector.x; 221 if (bottom > vector.y) bottom = (int)vector.y; 222 if (top < vector.y) top = (int)vector.y; 223 } 224 } 225 } 226 width = (int)(right - left); 227 height = (int)(top - bottom); 228 229 mirror.xx = + 0x10000; 230 mirror.yy = - 0x10000; 231 mirror.xy = mirror.yx = 0; 232 inverse = *matrix; 233 FT_Matrix_Multiply(&mirror, &inverse); 234 FT_Matrix_Invert(&inverse); 235 FT_Matrix_Multiply(&mirror, &inverse); 236 237 vector.x = vector.y = 0; 238 FT_Vector_Transform(&vector, &inverse); 239 left = (int)vector.x; 240 bottom = (int)vector.y; 241 vector.x = width; 242 vector.y = height; 243 FT_Vector_Transform(&vector, &inverse); 244 right = (int)vector.x; 245 top = (int)vector.y; 246 left = (right - left) - (int)ftbit->width; 247 bottom = (top - bottom) - (int)ftbit->rows; 248 249 m[0][0] = (double)inverse.xx / 0x10000; 250 m[0][1] = (double)inverse.xy / 0x10000; 251 m[1][0] = (double)inverse.yx / 0x10000; 252 m[1][1] = (double)inverse.yy / 0x10000; 253 m[0][2] = (double)-left / 2; 254 m[1][2] = (double)-bottom / 2; 255 m[2][0] = m[2][1] = 0.0; 256 m[2][2] = 1.0; 257 } 258 pitch = (width+3) & ~3; 259 260 switch ( ftbit->pixel_mode ) 261 { 262 case FT_PIXEL_MODE_MONO: 263 if ( mode == FT_RENDER_MODE_MONO ) 264 { 265 pitch = (((width+31) & ~31) >> 3); 266 break; 267 } 268 /* fall-through */ 269 270 case FT_PIXEL_MODE_GRAY: 271 if ( mode == FT_RENDER_MODE_LCD || 272 mode == FT_RENDER_MODE_LCD_V ) 273 { 274 /* each pixel is replicated into a 32-bit ARGB value */ 275 pitch = width*4; 276 } 277 break; 278 279 case FT_PIXEL_MODE_BGRA: 280 pitch = width * 4; 281 break; 282 283 case FT_PIXEL_MODE_LCD: 284 if ( mode != FT_RENDER_MODE_LCD ) 285 return -1; 286 287 /* horz pixel triplets are packed into 32-bit ARGB values */ 288 width /= 3; 289 pitch = width*4; 290 break; 291 292 case FT_PIXEL_MODE_LCD_V: 293 if ( mode != FT_RENDER_MODE_LCD_V ) 294 return -1; 295 296 /* vert pixel triplets are packed into 32-bit ARGB values */ 297 height /= 3; 298 pitch = width*4; 299 break; 300 301 default: /* unsupported source format */ 302 return -1; 303 } 304 305 target->width = (unsigned)width; 306 target->rows = (unsigned)height; 307 target->pitch = pitch; 308 target->buffer = NULL; 309 310 return pitch * height; 311 } 312 313 /* this functions converts the glyph bitmap found in a FT_GlyphSlot 314 * into a different format while scaling by applying the given matrix 315 * (see _compute_xrender_bitmap_size) 316 * 317 * you should call this function after _compute_xrender_bitmap_size 318 * 319 * target :: target bitmap descriptor. Note that its 'buffer' pointer 320 * must point to memory allocated by the caller 321 * 322 * source :: the source bitmap descriptor 323 * 324 * matrix :: the scaling matrix to apply 325 */ 326 static void 327 _scaled_fill_xrender_bitmap( FT_Bitmap* target, 328 FT_Bitmap* source, 329 m3x3 m ) 330 { 331 unsigned char* src_buf = source->buffer; 332 unsigned char* dst_line = target->buffer; 333 int src_pitch = source->pitch; 334 int width = (int) target->width; 335 int height = (int) target->rows; 336 int pitch = target->pitch; 337 int i, x, y; 338 FT_Vector vector, vector0; 339 int sampling_width; 340 int sampling_height; 341 int sample_count; 342 343 if ( src_pitch < 0 ) 344 src_buf -= ((unsigned) src_pitch * (source->rows - 1)); 345 346 /* compute how many source pixels a target pixel spans */ 347 vector.x = 1; 348 vector.y = 1; 349 m3x3_transform(&vector, m); 350 vector0.x = 0; 351 vector0.y = 0; 352 m3x3_transform(&vector0, m); 353 sampling_width = (int) ((vector.x - vector0.x) / 2); 354 sampling_height = (int) ((vector.y - vector0.y) / 2); 355 if (sampling_width < 0) sampling_width = -sampling_width; 356 if (sampling_height < 0) sampling_height = -sampling_height; 357 sample_count = (2 * sampling_width + 1) * (2 * sampling_height + 1); 358 359 for ( y = height; y > 0; y--, dst_line += pitch ) 360 { 361 for ( x = 0; x < width; x++ ) 362 { 363 unsigned char* src; 364 365 /* compute target pixel location in source space */ 366 vector.x = x; 367 vector.y = height - y; 368 m3x3_transform(&vector, m); 369 370 if (source->pixel_mode == FT_PIXEL_MODE_BGRA) 371 { 372 if (vector.x < -sampling_width 373 || vector.x > (source->width + (unsigned) sampling_width)) 374 continue; 375 if (vector.y < -sampling_height 376 || vector.y > (source->rows + (unsigned) sampling_height)) 377 continue; 378 } 379 else 380 { 381 if (vector.x < 0 || vector.x >= source->width) 382 continue; 383 if (vector.y < 0 || vector.y >= source->rows) 384 continue; 385 } 386 387 switch ( source->pixel_mode ) 388 { 389 case FT_PIXEL_MODE_MONO: /* convert mono to 8-bit gray, scale using nearest pixel */ 390 src = src_buf + (vector.y * src_pitch); 391 if ( src[(vector.x >> 3)] & (0x80 >> (vector.x & 7)) ) 392 dst_line[x] = 0xff; 393 break; 394 395 case FT_PIXEL_MODE_GRAY: /* scale using nearest pixel */ 396 src = src_buf + (vector.y * src_pitch); 397 dst_line[x] = src[vector.x]; 398 break; 399 400 case FT_PIXEL_MODE_BGRA: /* scale by averaging all relevant source pixels, keep BGRA format */ 401 { 402 int sample_x, sample_y; 403 int bgra[4] = { 0, 0, 0, 0 }; 404 405 for (sample_y = - sampling_height; sample_y < sampling_height + 1; ++sample_y) 406 { 407 int src_y = (int) (vector.y + sample_y); 408 409 if (src_y < 0 || (FT_Pos) src_y >= source->rows) 410 continue; 411 src = src_buf + (src_y * src_pitch); 412 for (sample_x = - sampling_width; sample_x < sampling_width + 1; ++sample_x) 413 { 414 int src_x = (int) (vector.x + sample_x); 415 416 if (src_x < 0 || (FT_Pos) src_x >= source->width) 417 continue; 418 for (i = 0; i < 4; ++i) 419 bgra[i] += src[src_x * 4 + i]; 420 } 421 } 422 423 for (i = 0; i < 4; ++i) 424 dst_line[4 * x + i] = (unsigned char) (bgra[i] / sample_count); 425 break; 426 } 427 } 428 } 429 } 430 } 431 432 /* this functions converts the glyph bitmap found in a FT_GlyphSlot 433 * into a different format (see _compute_xrender_bitmap_size) 434 * 435 * you should call this function after _compute_xrender_bitmap_size 436 * 437 * target :: target bitmap descriptor. Note that its 'buffer' pointer 438 * must point to memory allocated by the caller 439 * 440 * slot :: the glyph slot containing the source bitmap 441 * 442 * mode :: the requested final rendering mode 443 * 444 * bgr :: boolean, set if BGR or VBGR pixel ordering is needed 445 */ 446 static void 447 _fill_xrender_bitmap( FT_Bitmap* target, 448 FT_GlyphSlot slot, 449 FT_Render_Mode mode, 450 int bgr ) 451 { 452 FT_Bitmap* ftbit = &slot->bitmap; 453 454 { 455 unsigned char* srcLine = ftbit->buffer; 456 unsigned char* dstLine = target->buffer; 457 int src_pitch = ftbit->pitch; 458 int width = (int)target->width; 459 int height = (int)target->rows; 460 int pitch = target->pitch; 461 int subpixel; 462 int h; 463 464 subpixel = ( mode == FT_RENDER_MODE_LCD || 465 mode == FT_RENDER_MODE_LCD_V ); 466 467 if ( src_pitch < 0 ) 468 srcLine -= ((unsigned)src_pitch * (ftbit->rows-1)); 469 470 switch ( ftbit->pixel_mode ) 471 { 472 case FT_PIXEL_MODE_MONO: 473 if ( subpixel ) /* convert mono to ARGB32 values */ 474 { 475 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 476 { 477 int x; 478 479 for ( x = 0; x < width; x++ ) 480 { 481 if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) 482 ((unsigned int*)dstLine)[x] = 0xffffffffU; 483 } 484 } 485 } 486 else if ( mode == FT_RENDER_MODE_NORMAL ) /* convert mono to 8-bit gray */ 487 { 488 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 489 { 490 int x; 491 492 for ( x = 0; x < width; x++ ) 493 { 494 if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) ) 495 dstLine[x] = 0xff; 496 } 497 } 498 } 499 else /* copy mono to mono */ 500 { 501 int bytes = (width+7) >> 3; 502 503 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 504 memcpy( dstLine, srcLine, (size_t)bytes ); 505 } 506 break; 507 508 case FT_PIXEL_MODE_GRAY: 509 if ( subpixel ) /* convert gray to ARGB32 values */ 510 { 511 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 512 { 513 int x; 514 unsigned int* dst = (unsigned int*)dstLine; 515 516 for ( x = 0; x < width; x++ ) 517 { 518 unsigned int pix = srcLine[x]; 519 520 pix |= (pix << 8); 521 pix |= (pix << 16); 522 523 dst[x] = pix; 524 } 525 } 526 } 527 else /* copy gray into gray */ 528 { 529 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 530 memcpy( dstLine, srcLine, (size_t)width ); 531 } 532 break; 533 534 case FT_PIXEL_MODE_BGRA: /* Preserve BGRA format */ 535 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 536 memcpy( dstLine, srcLine, (size_t) width * 4 ); 537 break; 538 539 case FT_PIXEL_MODE_LCD: 540 if ( !bgr ) 541 { 542 /* convert horizontal RGB into ARGB32 */ 543 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 544 { 545 int x; 546 unsigned char* src = srcLine; 547 unsigned int* dst = (unsigned int*)dstLine; 548 549 for ( x = 0; x < width; x++, src += 3 ) 550 { 551 unsigned int pix; 552 553 pix = ((unsigned int)src[0] << 16) | 554 ((unsigned int)src[1] << 8) | 555 ((unsigned int)src[2] ) | 556 ((unsigned int)src[1] << 24) ; 557 558 dst[x] = pix; 559 } 560 } 561 } 562 else 563 { 564 /* convert horizontal BGR into ARGB32 */ 565 for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch ) 566 { 567 int x; 568 unsigned char* src = srcLine; 569 unsigned int* dst = (unsigned int*)dstLine; 570 571 for ( x = 0; x < width; x++, src += 3 ) 572 { 573 unsigned int pix; 574 575 pix = ((unsigned int)src[2] << 16) | 576 ((unsigned int)src[1] << 8) | 577 ((unsigned int)src[0] ) | 578 ((unsigned int)src[1] << 24) ; 579 580 dst[x] = pix; 581 } 582 } 583 } 584 break; 585 586 default: /* FT_PIXEL_MODE_LCD_V */ 587 /* convert vertical RGB into ARGB32 */ 588 if ( !bgr ) 589 { 590 for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) 591 { 592 int x; 593 unsigned char* src = srcLine; 594 unsigned int* dst = (unsigned int*)dstLine; 595 596 for ( x = 0; x < width; x++, src += 1 ) 597 { 598 unsigned int pix; 599 600 pix = ((unsigned int)src[0] << 16) | 601 ((unsigned int)src[src_pitch] << 8) | 602 ((unsigned int)src[src_pitch*2] ) | 603 ((unsigned int)src[src_pitch] << 24) ; 604 605 dst[x] = pix; 606 } 607 } 608 } 609 else 610 { 611 for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch ) 612 { 613 int x; 614 unsigned char* src = srcLine; 615 unsigned int* dst = (unsigned int*)dstLine; 616 617 for ( x = 0; x < width; x++, src += 1 ) 618 { 619 unsigned int pix; 620 621 pix = ((unsigned int)src[src_pitch*2] << 16) | 622 ((unsigned int)src[src_pitch] << 8) | 623 ((unsigned int)src[0] ) | 624 ((unsigned int)src[src_pitch] << 24) ; 625 626 dst[x] = pix; 627 } 628 } 629 } 630 } 631 } 632 } 633 634 _X_EXPORT void 635 XftFontLoadGlyphs (Display *dpy, 636 XftFont *pub, 637 FcBool need_bitmaps, 638 _Xconst FT_UInt *glyphs, 639 int nglyph) 640 { 641 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 642 XftFontInt *font = (XftFontInt *) pub; 643 FT_Error error; 644 FT_UInt glyphindex; 645 FT_GlyphSlot glyphslot; 646 XftGlyph *xftg; 647 Glyph glyph; 648 unsigned char bufLocal[4096]; 649 unsigned char *bufBitmap = bufLocal; 650 int bufSize = sizeof (bufLocal); 651 int size; 652 int width; 653 int height; 654 int left, right, top, bottom; 655 FT_Bitmap* ftbit; 656 FT_Bitmap local; 657 FT_Vector vector; 658 m3x3 m; 659 FT_Face face; 660 FT_Render_Mode mode = FT_RENDER_MODE_MONO; 661 FcBool transform; 662 FcBool glyph_transform; 663 664 if (!info) 665 return; 666 667 face = XftLockFace (&font->public); 668 669 if (!face) 670 return; 671 672 if (font->info.color) 673 mode = FT_RENDER_MODE_NORMAL; 674 if (font->info.antialias) 675 { 676 switch (font->info.rgba) { 677 case FC_RGBA_RGB: 678 case FC_RGBA_BGR: 679 mode = FT_RENDER_MODE_LCD; 680 break; 681 case FC_RGBA_VRGB: 682 case FC_RGBA_VBGR: 683 mode = FT_RENDER_MODE_LCD_V; 684 break; 685 default: 686 mode = FT_RENDER_MODE_NORMAL; 687 } 688 } 689 690 transform = font->info.transform && mode != FT_RENDER_MODE_MONO; 691 692 while (nglyph--) 693 { 694 glyphindex = *glyphs++; 695 xftg = font->glyphs[glyphindex]; 696 if (!xftg) 697 continue; 698 699 if (XftDebug() & XFT_DBG_CACHE) 700 _XftFontValidateMemory (dpy, pub); 701 /* 702 * Check to see if this glyph has just been loaded, 703 * this happens when drawing the same glyph twice 704 * in a single string 705 */ 706 if (xftg->glyph_memory) 707 continue; 708 709 FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter); 710 711 error = FT_Load_Glyph (face, glyphindex, font->info.load_flags); 712 if (error) 713 { 714 /* 715 * If anti-aliasing or transforming glyphs and 716 * no outline version exists, fallback to the 717 * bitmap and let things look bad instead of 718 * missing the glyph 719 */ 720 if (font->info.load_flags & FT_LOAD_NO_BITMAP) 721 error = FT_Load_Glyph (face, glyphindex, 722 font->info.load_flags & ~FT_LOAD_NO_BITMAP); 723 if (error) 724 continue; 725 } 726 727 #define FLOOR(x) ((x) & -64) 728 #define CEIL(x) (((x)+63) & -64) 729 #define TRUNC(x) ((x) >> 6) 730 #define ROUND(x) (((x)+32) & -64) 731 732 glyphslot = face->glyph; 733 734 /* 735 * Embolden if required 736 */ 737 if (font->info.embolden) FT_GlyphSlot_Embolden(glyphslot); 738 739 /* 740 * Compute glyph metrics from FreeType information 741 */ 742 if (transform) 743 { 744 /* 745 * calculate the true width by transforming all four corners. 746 */ 747 int xc, yc; 748 left = right = top = bottom = 0; 749 for (xc = 0; xc <= 1; xc++) { 750 for (yc = 0; yc <= 1; yc++) { 751 vector.x = glyphslot->metrics.horiBearingX + xc * glyphslot->metrics.width; 752 vector.y = glyphslot->metrics.horiBearingY - yc * glyphslot->metrics.height; 753 FT_Vector_Transform(&vector, &font->info.matrix); 754 if (XftDebug() & XFT_DBG_GLYPH) 755 printf("Trans %d %d: %d %d\n", (int) xc, (int) yc, 756 (int) vector.x, (int) vector.y); 757 if (xc == 0 && yc == 0) { 758 left = right = (int)vector.x; 759 top = bottom = (int)vector.y; 760 } else { 761 if (left > vector.x) left = (int)vector.x; 762 if (right < vector.x) right = (int)vector.x; 763 if (bottom > vector.y) bottom = (int)vector.y; 764 if (top < vector.y) top = (int)vector.y; 765 } 766 767 } 768 } 769 left = (int)FLOOR(left); 770 right = (int)CEIL(right); 771 bottom = (int)FLOOR(bottom); 772 top = (int)CEIL(top); 773 774 } else { 775 left = (int)FLOOR( glyphslot->metrics.horiBearingX ); 776 right = (int)CEIL( glyphslot->metrics.horiBearingX + glyphslot->metrics.width ); 777 778 top = (int)CEIL( glyphslot->metrics.horiBearingY ); 779 bottom = (int)FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height ); 780 } 781 782 /* 783 * Clip charcell glyphs to the bounding box 784 * XXX transformed? 785 */ 786 if (font->info.spacing >= FC_CHARCELL && !transform) 787 { 788 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) 789 { 790 if (TRUNC(bottom) > font->public.max_advance_width) 791 { 792 int adjust; 793 794 adjust = bottom - (font->public.max_advance_width << 6); 795 if (adjust > top) 796 adjust = top; 797 top -= adjust; 798 bottom -= adjust; 799 } 800 } 801 else 802 { 803 if (TRUNC(right) > font->public.max_advance_width) 804 { 805 int adjust; 806 807 adjust = right - (font->public.max_advance_width << 6); 808 if (adjust > left) 809 adjust = left; 810 left -= adjust; 811 right -= adjust; 812 } 813 } 814 } 815 816 glyph_transform = transform; 817 if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP ) 818 { 819 error = FT_Render_Glyph( face->glyph, mode ); 820 if (error) 821 continue; 822 glyph_transform = False; 823 } 824 825 FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE ); 826 827 if (font->info.spacing >= FC_MONO) 828 { 829 if (transform) 830 { 831 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) 832 { 833 vector.x = 0; 834 vector.y = -face->size->metrics.max_advance; 835 } 836 else 837 { 838 vector.x = face->size->metrics.max_advance; 839 vector.y = 0; 840 } 841 FT_Vector_Transform(&vector, &font->info.matrix); 842 xftg->metrics.xOff = (short)(TRUNC(ROUND(vector.x))); 843 xftg->metrics.yOff = (short)(-TRUNC(ROUND(vector.y))); 844 } 845 else 846 { 847 short maximum_x = (short)(font->public.max_advance_width); 848 short maximum_y = (short)(-font->public.max_advance_width); 849 short trimmed_x = (short)(TRUNC(ROUND(glyphslot->advance.x))); 850 short trimmed_y = (short)(-TRUNC(ROUND(glyphslot->advance.y))); 851 if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) 852 { 853 xftg->metrics.xOff = 0; 854 xftg->metrics.yOff = min(maximum_y,trimmed_y); 855 } 856 else 857 { 858 xftg->metrics.xOff = min(maximum_x,trimmed_x); 859 xftg->metrics.yOff = 0; 860 } 861 } 862 } 863 else 864 { 865 xftg->metrics.xOff = (short)(TRUNC(ROUND(glyphslot->advance.x))); 866 xftg->metrics.yOff = (short)(-TRUNC(ROUND(glyphslot->advance.y))); 867 } 868 869 /* compute the size of the final bitmap */ 870 ftbit = &glyphslot->bitmap; 871 872 width = (int)ftbit->width; 873 height = (int)ftbit->rows; 874 875 if (XftDebug() & XFT_DBG_GLYPH) 876 { 877 printf ("glyph %d:\n", (int) glyphindex); 878 printf (" xywh (%d %d %d %d), trans (%d %d %d %d) wh (%d %d)\n", 879 (int) glyphslot->metrics.horiBearingX, 880 (int) glyphslot->metrics.horiBearingY, 881 (int) glyphslot->metrics.width, 882 (int) glyphslot->metrics.height, 883 left, right, top, bottom, 884 width, height); 885 if (XftDebug() & XFT_DBG_GLYPHV) 886 { 887 int x, y; 888 unsigned char *line; 889 890 line = ftbit->buffer; 891 if (ftbit->pitch < 0) 892 line -= ftbit->pitch*(height-1); 893 894 for (y = 0; y < height; y++) 895 { 896 if (font->info.antialias) 897 { 898 static const char den[] = { " .:;=+*#" }; 899 for (x = 0; x < width; x++) 900 printf ("%c", den[line[x] >> 5]); 901 } 902 else 903 { 904 for (x = 0; x < width * 8; x++) 905 { 906 printf ("%c", (line[x>>3] & (1 << (x & 7))) ? '#' : ' '); 907 } 908 } 909 printf ("|\n"); 910 line += ftbit->pitch; 911 } 912 printf ("\n"); 913 } 914 } 915 916 m3x3_uniform(m); 917 size = _compute_xrender_bitmap_size( &local, glyphslot, mode, glyph_transform ? &font->info.matrix : NULL, m ); 918 if ( size < 0 ) 919 continue; 920 921 xftg->metrics.width = (unsigned short)local.width; 922 xftg->metrics.height = (unsigned short)local.rows; 923 if (glyph_transform) 924 { 925 m3x3 mi; 926 927 m3x3_invert(m, mi); 928 vector.x = - glyphslot->bitmap_left; 929 vector.y = glyphslot->bitmap_top; 930 m3x3_transform(&vector, mi); 931 xftg->metrics.x = (short)vector.x; 932 xftg->metrics.y = (short)vector.y; 933 } 934 else 935 { 936 xftg->metrics.x = (short)(- glyphslot->bitmap_left); 937 xftg->metrics.y = (short)( glyphslot->bitmap_top); 938 } 939 940 /* 941 * If the glyph is relatively large (> 1% of server memory), 942 * don't send it until necessary. 943 */ 944 if (!need_bitmaps && ((unsigned long) size > (info->max_glyph_memory / 100))) 945 continue; 946 947 /* 948 * Make sure there is enough buffer space for the glyph. 949 */ 950 if (size > bufSize) 951 { 952 if (bufBitmap != bufLocal) 953 free (bufBitmap); 954 bufBitmap = (unsigned char *) malloc ((size_t)size); 955 if (!bufBitmap) 956 continue; 957 bufSize = size; 958 } 959 memset (bufBitmap, 0, (size_t)size); 960 961 local.buffer = bufBitmap; 962 963 if (mode == FT_RENDER_MODE_NORMAL && glyph_transform) 964 _scaled_fill_xrender_bitmap(&local, &glyphslot->bitmap, m); 965 else 966 _fill_xrender_bitmap( &local, glyphslot, mode, 967 (font->info.rgba == FC_RGBA_BGR || 968 font->info.rgba == FC_RGBA_VBGR) ); 969 970 /* 971 * Copy or convert into local buffer. 972 */ 973 974 /* 975 * Use the glyph index as the wire encoding; it 976 * might be more efficient for some locales to map 977 * these by first usage to smaller values, but that 978 * would require persistently storing the map when 979 * glyphs were freed. 980 */ 981 glyph = (Glyph) glyphindex; 982 983 if (xftg->picture) 984 { 985 XRenderFreePicture(dpy, xftg->picture); 986 xftg->picture = 0; 987 } 988 xftg->glyph_memory = (size_t)size + font->sizeof_glyph; 989 if (font->format) 990 { 991 if (!font->glyphset) 992 font->glyphset = XRenderCreateGlyphSet (dpy, font->format); 993 if ( mode == FT_RENDER_MODE_MONO ) 994 { 995 /* swap bits in each byte */ 996 if (BitmapBitOrder (dpy) != MSBFirst) 997 { 998 unsigned char *line = (unsigned char*)bufBitmap; 999 int i = size; 1000 1001 while (i--) 1002 { 1003 int c = *line; 1004 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55); 1005 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33); 1006 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f); 1007 *line++ = (unsigned char)c; 1008 } 1009 } 1010 } 1011 else if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA || mode != FT_RENDER_MODE_NORMAL) 1012 { 1013 /* invert ARGB <=> BGRA */ 1014 if (ImageByteOrder (dpy) != XftNativeByteOrder ()) 1015 XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2); 1016 } 1017 1018 if (glyphslot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) 1019 { 1020 Pixmap pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), local.width, local.rows, 32); 1021 GC gc = XCreateGC(dpy, pixmap, 0, NULL); 1022 XImage image = { 1023 (int) local.width, (int) local.rows, 0, ZPixmap, (char *)bufBitmap, 1024 dpy->byte_order, dpy->bitmap_unit, dpy->bitmap_bit_order, 32, 1025 32, (int) (local.width * 4 - (unsigned) local.pitch), 32, 1026 0, 0, 0, NULL, { NULL } 1027 }; 1028 1029 XInitImage(&image); 1030 XPutImage(dpy, pixmap, gc, &image, 0, 0, 0, 0, local.width, local.rows); 1031 xftg->picture = XRenderCreatePicture(dpy, pixmap, font->format, 0, NULL); 1032 1033 XFreeGC(dpy, gc); 1034 XFreePixmap(dpy, pixmap); 1035 /* 1036 * Record 256 times higher memory pressure for unrotated 1037 * pictures, and maximum for rotated pictures. 1038 */ 1039 if (font->info.matrix.xy || font->info.matrix.yx) 1040 xftg->glyph_memory += font->max_glyph_memory - (unsigned long) size; 1041 else 1042 xftg->glyph_memory += (size_t)size * 255; 1043 } 1044 else 1045 XRenderAddGlyphs (dpy, font->glyphset, &glyph, 1046 &xftg->metrics, 1, 1047 (char *) bufBitmap, size); 1048 } 1049 else 1050 { 1051 if (size) 1052 { 1053 xftg->bitmap = malloc ((size_t)size); 1054 if (xftg->bitmap) 1055 memcpy (xftg->bitmap, bufBitmap, (size_t)size); 1056 } 1057 else 1058 xftg->bitmap = NULL; 1059 } 1060 1061 font->glyph_memory += xftg->glyph_memory; 1062 info->glyph_memory += xftg->glyph_memory; 1063 if (XftDebug() & XFT_DBG_CACHE) 1064 _XftFontValidateMemory (dpy, pub); 1065 if (XftDebug() & XFT_DBG_CACHEV) 1066 printf ("Caching glyph 0x%x size %lu\n", glyphindex, 1067 xftg->glyph_memory); 1068 1069 if (font->track_mem_usage) { 1070 XftGlyphUsage *xuse = (XftGlyphUsage *) xftg; 1071 1072 if (font->newest == FT_UINT_MAX) { 1073 xuse->older = glyphindex; 1074 xuse->newer = glyphindex; 1075 if (XftDebug() & XFT_DBG_USAGE) 1076 printf("alloc %p -> %d: %p USE %d.%d\n", 1077 (void *) font, glyphindex, 1078 (void *) xuse, xuse->older, xuse->newer); 1079 } else { 1080 XftGlyphUsage *xnew; 1081 XftGlyphUsage *xold; 1082 1083 assert(font->glyphs[font->newest] != NULL); 1084 xnew = (XftGlyphUsage *) font->glyphs[font->newest]; 1085 1086 assert(font->glyphs[xnew->newer] != NULL); 1087 xold = (XftGlyphUsage *) font->glyphs[xnew->newer]; 1088 1089 xuse->older = font->newest; 1090 xuse->newer = xnew->newer; 1091 xnew->newer = glyphindex; 1092 xold->older = glyphindex; 1093 if (XftDebug() & XFT_DBG_USAGE) 1094 printf("alloc %p -> %d: %p USE %d.%d, %p NEW %d.%d %p OLD %d.%d\n", 1095 (void *) font, glyphindex, 1096 (void *) xuse, xuse->older, xuse->newer, 1097 (void *) xnew, xnew->older, xnew->newer, 1098 (void *) xold, xold->older, xold->newer); 1099 } 1100 1101 font->newest = glyphindex; 1102 font->total_inuse++; 1103 if (XftDebug() & XFT_DBG_USAGE) 1104 _XftValidateGlyphUsage(font); 1105 } 1106 } 1107 if (bufBitmap != bufLocal) 1108 free (bufBitmap); 1109 XftUnlockFace (&font->public); 1110 } 1111 1112 _X_EXPORT void 1113 XftFontUnloadGlyphs (Display *dpy, 1114 XftFont *pub, 1115 _Xconst FT_UInt *glyphs, 1116 int nglyph) 1117 { 1118 XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); 1119 XftFontInt *font = (XftFontInt *) pub; 1120 XftGlyph *xftg; 1121 FT_UInt glyphindex; 1122 Glyph glyphBuf[1024]; 1123 int nused; 1124 1125 nused = 0; 1126 while (nglyph--) 1127 { 1128 glyphindex = *glyphs++; 1129 xftg = font->glyphs[glyphindex]; 1130 if (!xftg) 1131 continue; 1132 if (xftg->glyph_memory) 1133 { 1134 if (XftDebug() & XFT_DBG_CACHEV) 1135 printf ("Uncaching glyph 0x%x size %lu\n", 1136 glyphindex, xftg->glyph_memory); 1137 if (font->format) 1138 { 1139 if (xftg->picture) 1140 XRenderFreePicture(dpy, xftg->picture); 1141 else if (font->glyphset) 1142 { 1143 glyphBuf[nused++] = (Glyph) glyphindex; 1144 if (nused == sizeof (glyphBuf) / sizeof (glyphBuf[0])) 1145 { 1146 XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused); 1147 nused = 0; 1148 } 1149 } 1150 } 1151 else if (xftg->bitmap) 1152 free (xftg->bitmap); 1153 font->glyph_memory -= xftg->glyph_memory; 1154 if (info) 1155 info->glyph_memory -= xftg->glyph_memory; 1156 } 1157 1158 if (font->track_mem_usage) { 1159 XftGlyphUsage *xuse = (XftGlyphUsage *) xftg; 1160 XftGlyphUsage *xtmp; 1161 1162 if (XftDebug() & XFT_DBG_USAGE) 1163 printf("free %p -> %p USE %d.%d\n", 1164 (void *) font, (void *) xuse, xuse->older, xuse->newer); 1165 1166 if (xuse->older != FT_UINT_MAX) { 1167 xtmp = (XftGlyphUsage *) font->glyphs[xuse->older]; 1168 if (xtmp != NULL) { 1169 /* update link around to oldest glyph */ 1170 xtmp->newer = xuse->newer; 1171 } 1172 if (font->newest == glyphindex) { 1173 if (font->newest == xuse->older) 1174 font->newest = FT_UINT_MAX; 1175 else 1176 font->newest = xuse->older; 1177 } 1178 } 1179 if (xuse->newer != FT_UINT_MAX) { 1180 xtmp = (XftGlyphUsage *) font->glyphs[xuse->newer]; 1181 if (xtmp != NULL) { 1182 /* update link around to newest glyph */ 1183 xtmp->older = xuse->older; 1184 } 1185 } 1186 if (font->total_inuse) { 1187 font->total_inuse--; 1188 } else { 1189 fprintf (stderr, "Xft: glyph count error\n"); 1190 } 1191 if (XftDebug() & XFT_DBG_USAGE) 1192 _XftValidateGlyphUsage(font); 1193 } 1194 1195 free (xftg); 1196 XftMemFree (XFT_MEM_GLYPH, font->sizeof_glyph); 1197 font->glyphs[glyphindex] = NULL; 1198 } 1199 if (font->glyphset && nused) 1200 XRenderFreeGlyphs (dpy, font->glyphset, glyphBuf, nused); 1201 } 1202 1203 _X_EXPORT FcBool 1204 XftFontCheckGlyph (Display *dpy, 1205 XftFont *pub, 1206 FcBool need_bitmaps, 1207 FT_UInt glyph, 1208 FT_UInt *missing, 1209 int *nmissing) 1210 { 1211 XftFontInt *font = (XftFontInt *) pub; 1212 XftGlyph *xftg; 1213 int n; 1214 1215 if (glyph >= font->num_glyphs) 1216 return FcFalse; 1217 xftg = font->glyphs[glyph]; 1218 if (!xftg || (need_bitmaps && !xftg->glyph_memory)) 1219 { 1220 if (!xftg) 1221 { 1222 xftg = malloc (font->sizeof_glyph); 1223 if (!xftg) 1224 return FcFalse; 1225 XftMemAlloc (XFT_MEM_GLYPH, font->sizeof_glyph); 1226 1227 xftg->bitmap = NULL; 1228 xftg->glyph_memory = 0; 1229 xftg->picture = 0; 1230 font->glyphs[glyph] = xftg; 1231 1232 if (font->track_mem_usage) { 1233 XftGlyphUsage *xuse = (XftGlyphUsage *) xftg; 1234 xuse->older = FT_UINT_MAX; 1235 xuse->newer = FT_UINT_MAX; 1236 } 1237 } 1238 n = *nmissing; 1239 missing[n++] = glyph; 1240 if (n == XFT_NMISSING) 1241 { 1242 XftFontLoadGlyphs (dpy, pub, need_bitmaps, missing, n); 1243 n = 0; 1244 } 1245 *nmissing = n; 1246 return FcTrue; 1247 } 1248 1249 /* 1250 * Make unloading faster by moving newly-referenced glyphs to the front 1251 * of the list, leaving the less-used glyphs on the end. 1252 * 1253 * If the glyph is zero, the older/newer data may not have been set. 1254 */ 1255 if (glyph != 0 1256 && font->track_mem_usage 1257 && font->total_inuse > 10 1258 && font->newest != FT_UINT_MAX 1259 && font->newest != glyph) 1260 { 1261 XftGlyphUsage *xuse = (XftGlyphUsage *) xftg; 1262 XftGlyphUsage *xtmp = (XftGlyphUsage *) font->glyphs[font->newest]; 1263 XftGlyphUsage *xold; 1264 XftGlyphUsage *xnew; 1265 1266 /* delink */ 1267 xold = (XftGlyphUsage *) font->glyphs[xuse->older]; 1268 xnew = (XftGlyphUsage *) font->glyphs[xuse->newer]; 1269 assert(xold != NULL); 1270 assert(xnew != NULL); 1271 xold->newer = xuse->newer; 1272 xnew->older = xuse->older; 1273 1274 /* relink */ 1275 xnew = (XftGlyphUsage *) font->glyphs[xtmp->newer]; 1276 assert(xnew != NULL); 1277 xnew->older = glyph; 1278 xuse->older = font->newest; 1279 xuse->newer = xtmp->newer; 1280 xtmp->newer = glyph; 1281 1282 font->newest = glyph; 1283 } 1284 return FcFalse; 1285 } 1286 1287 _X_EXPORT FcBool 1288 XftCharExists (Display *dpy _X_UNUSED, 1289 XftFont *pub, 1290 FcChar32 ucs4) 1291 { 1292 if (pub->charset) 1293 return FcCharSetHasChar (pub->charset, ucs4); 1294 return FcFalse; 1295 } 1296 1297 #define Missing ((FT_UInt) ~0) 1298 1299 _X_EXPORT FT_UInt 1300 XftCharIndex (Display *dpy, 1301 XftFont *pub, 1302 FcChar32 ucs4) 1303 { 1304 XftFontInt *font = (XftFontInt *) pub; 1305 FcChar32 ent, offset; 1306 FT_Face face; 1307 1308 if (!font->hash_value) 1309 return 0; 1310 1311 ent = ucs4 % (FcChar32)font->hash_value; 1312 offset = 0; 1313 while (font->hash_table[ent].ucs4 != ucs4) 1314 { 1315 if (font->hash_table[ent].ucs4 == (FcChar32) ~0) 1316 { 1317 if (!XftCharExists (dpy, pub, ucs4)) 1318 return 0; 1319 face = XftLockFace (pub); 1320 if (!face) 1321 return 0; 1322 font->hash_table[ent].ucs4 = ucs4; 1323 font->hash_table[ent].glyph = FcFreeTypeCharIndex (face, ucs4); 1324 XftUnlockFace (pub); 1325 break; 1326 } 1327 if (!offset) 1328 { 1329 offset = ucs4 % (FcChar32)font->rehash_value; 1330 if (!offset) 1331 offset = 1; 1332 } 1333 ent = ent + offset; 1334 if (ent >= (FcChar32)font->hash_value) 1335 ent -= (FcChar32)font->hash_value; 1336 } 1337 return font->hash_table[ent].glyph; 1338 } 1339 1340 /* 1341 * Remove glyph(s) from the font to reduce memory-usage. 1342 */ 1343 _X_HIDDEN void 1344 _XftFontUncacheGlyph (Display *dpy, XftFont *pub) 1345 { 1346 XftFontInt *font = (XftFontInt *) pub; 1347 unsigned long glyph_memory; 1348 FT_UInt glyphindex; 1349 XftGlyph *xftg; 1350 1351 if (!font->glyph_memory) 1352 return; 1353 1354 if (XftDebug() & XFT_DBG_CACHE) 1355 _XftFontValidateMemory (dpy, pub); 1356 1357 if (font->track_mem_usage) 1358 { 1359 /* 1360 * Remove the oldest glyph from the font. 1361 */ 1362 if (font->newest != FT_UINT_MAX) { 1363 XftGlyphUsage *xuse = (XftGlyphUsage *) font->glyphs[font->newest]; 1364 if ((glyphindex = xuse->newer) != FT_UINT_MAX) 1365 XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1); 1366 } 1367 } 1368 else if (font->use_free_glyphs) 1369 { 1370 /* 1371 * Pick a random glyph from the font and remove it from the cache 1372 */ 1373 glyph_memory = ((unsigned long)rand() % font->glyph_memory); 1374 for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++) 1375 { 1376 xftg = font->glyphs[glyphindex]; 1377 if (xftg) 1378 { 1379 if (xftg->glyph_memory > glyph_memory) 1380 { 1381 XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1); 1382 break; 1383 } 1384 glyph_memory -= xftg->glyph_memory; 1385 } 1386 } 1387 } 1388 else 1389 { 1390 /* 1391 * Free all glyphs, since they are part of a set. 1392 */ 1393 if (font->glyphset) 1394 { 1395 XRenderFreeGlyphSet (dpy, font->glyphset); 1396 font->glyphset = 0; 1397 } 1398 for (glyphindex = 0; glyphindex < font->num_glyphs; glyphindex++) 1399 { 1400 xftg = font->glyphs[glyphindex]; 1401 if (xftg) 1402 { 1403 if (xftg->glyph_memory > 0) 1404 { 1405 XftFontUnloadGlyphs (dpy, pub, &glyphindex, 1); 1406 } 1407 } 1408 } 1409 } 1410 1411 if (XftDebug() & XFT_DBG_CACHE) 1412 _XftFontValidateMemory (dpy, pub); 1413 } 1414 1415 _X_HIDDEN void 1416 _XftFontManageMemory (Display *dpy, XftFont *pub) 1417 { 1418 XftFontInt *font = (XftFontInt *) pub; 1419 1420 if (font->max_glyph_memory) 1421 { 1422 if (XftDebug() & XFT_DBG_CACHE) 1423 { 1424 if (font->glyph_memory > font->max_glyph_memory) 1425 printf ("Reduce memory for font 0x%lx from %lu to %lu\n", 1426 font->glyphset ? font->glyphset : (unsigned long) font, 1427 font->glyph_memory, font->max_glyph_memory); 1428 } 1429 while (font->glyph_memory > font->max_glyph_memory) 1430 _XftFontUncacheGlyph (dpy, pub); 1431 } 1432 _XftDisplayManageMemory (dpy); 1433 } 1434