| File: | xftfreetype.c |
| Location: | line 863, column 2 |
| Description: | Value stored to 'num_unicode' is never read |
| 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 | |
| 25 | _X_HIDDEN__attribute__((visibility("hidden"))) FT_Library _XftFTlibrary; |
| 26 | |
| 27 | #define FT_Matrix_Equal(a,b)((a)->xx == (b)->xx && (a)->yy == (b)->yy && (a)->xy == (b)->xy && (a)->yx == (b)->yx) ((a)->xx == (b)->xx && \ |
| 28 | (a)->yy == (b)->yy && \ |
| 29 | (a)->xy == (b)->xy && \ |
| 30 | (a)->yx == (b)->yx) |
| 31 | /* |
| 32 | * List of all open files (each face in a file is managed separately) |
| 33 | */ |
| 34 | |
| 35 | static XftFtFile *_XftFtFiles; |
| 36 | static int XftMaxFreeTypeFiles = 5; |
| 37 | |
| 38 | static XftFtFile * |
| 39 | _XftGetFile (const FcChar8 *file, int id) |
| 40 | { |
| 41 | XftFtFile *f; |
| 42 | |
| 43 | if (!XftInitFtLibrary ()) |
| 44 | return NULL((void*)0); |
| 45 | |
| 46 | for (f = _XftFtFiles; f; f = f->next) |
| 47 | { |
| 48 | if (!strcmp (f->file, (char *) file) && f->id == id) |
| 49 | { |
| 50 | ++f->ref; |
| 51 | if (XftDebug () & XFT_DBG_REF16) |
| 52 | printf ("FontFile %s/%d matches existing (%d)\n", |
| 53 | file, id, f->ref); |
| 54 | return f; |
| 55 | } |
| 56 | } |
| 57 | f = malloc (sizeof (XftFtFile) + strlen ((char *) file) + 1); |
| 58 | if (!f) |
| 59 | return NULL((void*)0); |
| 60 | |
| 61 | XftMemAlloc (XFT_MEM_FILE2, sizeof (XftFtFile) + strlen ((char *) file) + 1); |
| 62 | if (XftDebug () & XFT_DBG_REF16) |
| 63 | printf ("FontFile %s/%d matches new\n", |
| 64 | file, id); |
| 65 | f->next = _XftFtFiles; |
| 66 | _XftFtFiles = f; |
| 67 | |
| 68 | f->ref = 1; |
| 69 | |
| 70 | f->file = (char *) (f+1); |
| 71 | strcpy (f->file, (char *) file)__builtin___strcpy_chk (f->file, (char *) file, __builtin_object_size (f->file, 2 > 1 ? 1 : 0)); |
| 72 | f->id = id; |
| 73 | |
| 74 | f->lock = 0; |
| 75 | f->face = NULL((void*)0); |
| 76 | f->xsize = 0; |
| 77 | f->ysize = 0; |
| 78 | f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0; |
| 79 | return f; |
| 80 | } |
| 81 | |
| 82 | static XftFtFile * |
| 83 | _XftGetFaceFile (FT_Face face) |
| 84 | { |
| 85 | XftFtFile *f; |
| 86 | |
| 87 | f = malloc (sizeof (XftFtFile)); |
| 88 | if (!f) |
| 89 | return NULL((void*)0); |
| 90 | XftMemAlloc (XFT_MEM_FILE2, sizeof(XftFtFile)); |
| 91 | f->next = NULL((void*)0); |
| 92 | |
| 93 | f->ref = 1; |
| 94 | |
| 95 | f->file = NULL((void*)0); |
| 96 | f->id = 0; |
| 97 | f->lock = 0; |
| 98 | f->face = face; |
| 99 | f->xsize = 0; |
| 100 | f->ysize = 0; |
| 101 | f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0; |
| 102 | return f; |
| 103 | } |
| 104 | |
| 105 | static int |
| 106 | _XftNumFiles (void) |
| 107 | { |
| 108 | XftFtFile *f; |
| 109 | int count = 0; |
| 110 | for (f = _XftFtFiles; f; f = f->next) |
| 111 | if (f->face && !f->lock) |
| 112 | ++count; |
| 113 | return count; |
| 114 | } |
| 115 | |
| 116 | static XftFtFile * |
| 117 | _XftNthFile (int n) |
| 118 | { |
| 119 | XftFtFile *f; |
| 120 | int count = 0; |
| 121 | for (f = _XftFtFiles; f; f = f->next) |
| 122 | if (f->face && !f->lock) |
| 123 | if (count++ == n) |
| 124 | break; |
| 125 | return f; |
| 126 | } |
| 127 | |
| 128 | static void |
| 129 | _XftUncacheFiles (void) |
| 130 | { |
| 131 | int n; |
| 132 | XftFtFile *f; |
| 133 | while ((n = _XftNumFiles ()) > XftMaxFreeTypeFiles) |
| 134 | { |
| 135 | f = _XftNthFile (rand () % n); |
| 136 | if (f) |
| 137 | { |
| 138 | if (XftDebug() & XFT_DBG_REF16) |
| 139 | printf ("Discard file %s/%d from cache\n", |
| 140 | f->file, f->id); |
| 141 | FT_Done_Face (f->face); |
| 142 | f->face = NULL((void*)0); |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | static FT_Face |
| 148 | _XftLockFile (XftFtFile *f) |
| 149 | { |
| 150 | ++f->lock; |
| 151 | if (!f->face) |
| 152 | { |
| 153 | if (XftDebug() & XFT_DBG_REF16) |
| 154 | printf ("Loading file %s/%d\n", f->file, f->id); |
| 155 | if (FT_New_Face (_XftFTlibrary, f->file, f->id, &f->face)) |
| 156 | --f->lock; |
| 157 | |
| 158 | f->xsize = 0; |
| 159 | f->ysize = 0; |
| 160 | f->matrix.xx = f->matrix.xy = f->matrix.yx = f->matrix.yy = 0; |
| 161 | _XftUncacheFiles (); |
| 162 | } |
| 163 | return f->face; |
| 164 | } |
| 165 | |
| 166 | static void |
| 167 | _XftLockError (const char *reason) |
| 168 | { |
| 169 | fprintf (stderr__stderrp, "Xft: locking error %s\n", reason); |
| 170 | } |
| 171 | |
| 172 | static void |
| 173 | _XftUnlockFile (XftFtFile *f) |
| 174 | { |
| 175 | if (--f->lock < 0) |
| 176 | _XftLockError ("too many file unlocks"); |
| 177 | } |
| 178 | |
| 179 | #define X_SIZE(face,i)((face)->available_sizes[i].x_ppem) ((face)->available_sizes[i].x_ppem) |
| 180 | #define Y_SIZE(face,i)((face)->available_sizes[i].y_ppem) ((face)->available_sizes[i].y_ppem) |
| 181 | |
| 182 | _X_HIDDEN__attribute__((visibility("hidden"))) FcBool |
| 183 | _XftSetFace (XftFtFile *f, FT_F26Dot6 xsize, FT_F26Dot6 ysize, FT_Matrix *matrix) |
| 184 | { |
| 185 | FT_Face face = f->face; |
| 186 | |
| 187 | if (f->xsize != xsize || f->ysize != ysize) |
| 188 | { |
| 189 | if (XftDebug() & XFT_DBG_GLYPH32) |
| 190 | printf ("Set face size to %dx%d (%dx%d)\n", |
| 191 | (int) (xsize >> 6), (int) (ysize >> 6), (int) xsize, (int) ysize); |
| 192 | /* |
| 193 | * Bitmap only faces must match exactly, so find the closest |
| 194 | * one (height dominant search) |
| 195 | */ |
| 196 | if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 ))) |
| 197 | { |
| 198 | int i, best = 0; |
| 199 | |
| 200 | #define xft_abs(a)((a) < 0 ? -(a) : (a)) ((a) < 0 ? -(a) : (a)) |
| 201 | #define dist(a,b)((((a)-(b)) < 0 ? -((a)-(b)) : ((a)-(b)))) (xft_abs((a)-(b))(((a)-(b)) < 0 ? -((a)-(b)) : ((a)-(b)))) |
| 202 | |
| 203 | for (i = 1; i < face->num_fixed_sizes; i++) |
| 204 | { |
| 205 | if (dist (ysize, Y_SIZE(face,i))((((ysize)-(((face)->available_sizes[i].y_ppem))) < 0 ? -((ysize)-(((face)->available_sizes[i].y_ppem))) : ((ysize )-(((face)->available_sizes[i].y_ppem))))) < |
| 206 | dist (ysize, Y_SIZE(face, best))((((ysize)-(((face)->available_sizes[best].y_ppem))) < 0 ? -((ysize)-(((face)->available_sizes[best].y_ppem))) : ( (ysize)-(((face)->available_sizes[best].y_ppem))))) || |
| 207 | (dist (ysize, Y_SIZE(face, i))((((ysize)-(((face)->available_sizes[i].y_ppem))) < 0 ? -((ysize)-(((face)->available_sizes[i].y_ppem))) : ((ysize )-(((face)->available_sizes[i].y_ppem))))) == |
| 208 | dist (ysize, Y_SIZE(face, best))((((ysize)-(((face)->available_sizes[best].y_ppem))) < 0 ? -((ysize)-(((face)->available_sizes[best].y_ppem))) : ( (ysize)-(((face)->available_sizes[best].y_ppem))))) && |
| 209 | dist (xsize, X_SIZE(face, i))((((xsize)-(((face)->available_sizes[i].x_ppem))) < 0 ? -((xsize)-(((face)->available_sizes[i].x_ppem))) : ((xsize )-(((face)->available_sizes[i].x_ppem))))) < |
| 210 | dist (xsize, X_SIZE(face, best))((((xsize)-(((face)->available_sizes[best].x_ppem))) < 0 ? -((xsize)-(((face)->available_sizes[best].x_ppem))) : ( (xsize)-(((face)->available_sizes[best].x_ppem))))))) |
| 211 | { |
| 212 | best = i; |
| 213 | } |
| 214 | } |
| 215 | /* |
| 216 | * Freetype 2.1.7 and earlier used width/height |
| 217 | * for matching sizes in the BDF and PCF loaders. |
| 218 | * This has been fixed for 2.1.8. Because BDF and PCF |
| 219 | * files have but a single strike per file, we can |
| 220 | * simply try both sizes. |
| 221 | */ |
| 222 | if (FT_Set_Char_Size (face, face->available_sizes[best].x_ppem, |
| 223 | face->available_sizes[best].y_ppem, 0, 0) != 0 |
| 224 | && |
| 225 | FT_Set_Char_Size (face, face->available_sizes[best].width << 6, |
| 226 | face->available_sizes[best].height << 6, |
| 227 | 0, 0) != 0) |
| 228 | { |
| 229 | return False0; |
| 230 | } |
| 231 | } |
| 232 | else |
| 233 | { |
| 234 | if (FT_Set_Char_Size (face, xsize, ysize, 0, 0)) |
| 235 | { |
| 236 | return False0; |
| 237 | } |
| 238 | } |
| 239 | f->xsize = xsize; |
| 240 | f->ysize = ysize; |
| 241 | } |
| 242 | if (!FT_Matrix_Equal (&f->matrix, matrix)((&f->matrix)->xx == (matrix)->xx && (& f->matrix)->yy == (matrix)->yy && (&f-> matrix)->xy == (matrix)->xy && (&f->matrix )->yx == (matrix)->yx)) |
| 243 | { |
| 244 | if (XftDebug() & XFT_DBG_GLYPH32) |
| 245 | printf ("Set face matrix to (%g,%g,%g,%g)\n", |
| 246 | (double) matrix->xx / 0x10000, |
| 247 | (double) matrix->xy / 0x10000, |
| 248 | (double) matrix->yx / 0x10000, |
| 249 | (double) matrix->yy / 0x10000); |
| 250 | FT_Set_Transform (face, matrix, NULL((void*)0)); |
| 251 | f->matrix = *matrix; |
| 252 | } |
| 253 | return True1; |
| 254 | } |
| 255 | |
| 256 | static void |
| 257 | _XftReleaseFile (XftFtFile *f) |
| 258 | { |
| 259 | XftFtFile **prev; |
| 260 | |
| 261 | if (--f->ref != 0) |
| 262 | return; |
| 263 | if (f->lock) |
| 264 | _XftLockError ("Attempt to close locked file"); |
| 265 | if (f->file) |
| 266 | { |
| 267 | for (prev = &_XftFtFiles; *prev; prev = &(*prev)->next) |
| 268 | { |
| 269 | if (*prev == f) |
| 270 | { |
| 271 | *prev = f->next; |
| 272 | break; |
| 273 | } |
| 274 | } |
| 275 | if (f->face) |
| 276 | FT_Done_Face (f->face); |
| 277 | } |
| 278 | XftMemFree (XFT_MEM_FILE2, |
| 279 | sizeof (XftFtFile) + (f->file ? strlen (f->file) + 1 : 0)); |
| 280 | free (f); |
| 281 | } |
| 282 | |
| 283 | /* |
| 284 | * Find a prime larger than the minimum reasonable hash size |
| 285 | */ |
| 286 | |
| 287 | static FcChar32 |
| 288 | _XftSqrt (FcChar32 a) |
| 289 | { |
| 290 | FcChar32 l, h, m; |
| 291 | |
| 292 | l = 2; |
| 293 | h = a/2; |
| 294 | while ((h-l) > 1) |
| 295 | { |
| 296 | m = (h+l) >> 1; |
| 297 | if (m * m < a) |
| 298 | l = m; |
| 299 | else |
| 300 | h = m; |
| 301 | } |
| 302 | return h; |
| 303 | } |
| 304 | |
| 305 | static FcBool |
| 306 | _XftIsPrime (FcChar32 i) |
| 307 | { |
| 308 | FcChar32 l, t; |
| 309 | |
| 310 | if (i < 2) |
| 311 | return FcFalse0; |
| 312 | if ((i & 1) == 0) |
| 313 | { |
| 314 | if (i == 2) |
| 315 | return FcTrue1; |
| 316 | return FcFalse0; |
| 317 | } |
| 318 | l = _XftSqrt (i) + 1; |
| 319 | for (t = 3; t <= l; t += 2) |
| 320 | if (i % t == 0) |
| 321 | return FcFalse0; |
| 322 | return FcTrue1; |
| 323 | } |
| 324 | |
| 325 | static FcChar32 |
| 326 | _XftHashSize (FcChar32 num_unicode) |
| 327 | { |
| 328 | /* at least 31.25 % extra space */ |
| 329 | FcChar32 hash = num_unicode + (num_unicode >> 2) + (num_unicode >> 4); |
| 330 | |
| 331 | if ((hash & 1) == 0) |
| 332 | hash++; |
| 333 | while (!_XftIsPrime (hash)) |
| 334 | hash += 2; |
| 335 | return hash; |
| 336 | } |
| 337 | |
| 338 | _X_EXPORT__attribute__((visibility("default"))) FT_Face |
| 339 | XftLockFace (XftFont *public) |
| 340 | { |
| 341 | XftFontInt *font = (XftFontInt *) public; |
| 342 | XftFontInfo *fi = &font->info; |
| 343 | FT_Face face; |
| 344 | |
| 345 | face = _XftLockFile (fi->file); |
| 346 | /* |
| 347 | * Make sure the face is usable at the requested size |
| 348 | */ |
| 349 | if (face && !_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix)) |
| 350 | { |
| 351 | _XftUnlockFile (fi->file); |
| 352 | face = NULL((void*)0); |
| 353 | } |
| 354 | return face; |
| 355 | } |
| 356 | |
| 357 | _X_EXPORT__attribute__((visibility("default"))) void |
| 358 | XftUnlockFace (XftFont *public) |
| 359 | { |
| 360 | XftFontInt *font = (XftFontInt *) public; |
| 361 | _XftUnlockFile (font->info.file); |
| 362 | } |
| 363 | |
| 364 | static FcBool |
| 365 | XftFontInfoFill (Display *dpy, _Xconstconst FcPattern *pattern, XftFontInfo *fi) |
| 366 | { |
| 367 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1); |
| 368 | FcChar8 *filename; |
| 369 | int id; |
| 370 | double dsize; |
| 371 | double aspect; |
| 372 | FcMatrix *font_matrix; |
| 373 | FcBool hinting, vertical_layout, autohint, global_advance; |
| 374 | int hint_style; |
| 375 | FcChar32 hash, *hashp; |
| 376 | FT_Face face; |
| 377 | int nhash; |
| 378 | FcBool bitmap; |
| 379 | |
| 380 | if (!info) |
| 381 | return FcFalse0; |
| 382 | |
| 383 | /* |
| 384 | * Initialize the whole XftFontInfo so that padding doesn't interfere with |
| 385 | * hash or XftFontInfoEqual(). |
| 386 | */ |
| 387 | |
| 388 | memset (fi, '\0', sizeof(*fi))__builtin___memset_chk (fi, '\0', sizeof(*fi), __builtin_object_size (fi, 0)); |
| 389 | |
| 390 | /* |
| 391 | * Find the associated file |
| 392 | */ |
| 393 | switch (FcPatternGetString (pattern, FC_FILE"file", 0, &filename)) { |
| 394 | case FcResultNoMatch: |
| 395 | filename = NULL((void*)0); |
| 396 | break; |
| 397 | case FcResultMatch: |
| 398 | break; |
| 399 | default: |
| 400 | goto bail0; |
| 401 | } |
| 402 | |
| 403 | switch (FcPatternGetInteger (pattern, FC_INDEX"index", 0, &id)) { |
| 404 | case FcResultNoMatch: |
| 405 | id = 0; |
| 406 | break; |
| 407 | case FcResultMatch: |
| 408 | break; |
| 409 | default: |
| 410 | goto bail0; |
| 411 | } |
| 412 | |
| 413 | if (filename) |
| 414 | fi->file = _XftGetFile (filename, id); |
| 415 | else if (FcPatternGetFTFace (pattern, FC_FT_FACE"ftface", 0, &face) == FcResultMatch |
| 416 | && face) |
| 417 | fi->file = _XftGetFaceFile (face); |
| 418 | if (!fi->file) |
| 419 | goto bail0; |
| 420 | |
| 421 | /* |
| 422 | * Compute pixel size |
| 423 | */ |
| 424 | if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE"pixelsize", 0, &dsize) != FcResultMatch) |
| 425 | goto bail1; |
| 426 | |
| 427 | if (FcPatternGetDouble (pattern, FC_ASPECT"aspect", 0, &aspect) != FcResultMatch) |
| 428 | aspect = 1.0; |
| 429 | |
| 430 | fi->ysize = (FT_F26Dot6) (dsize * 64.0); |
| 431 | fi->xsize = (FT_F26Dot6) (dsize * aspect * 64.0); |
| 432 | |
| 433 | if (XftDebug() & XFT_DBG_OPEN1) |
| 434 | printf ("XftFontInfoFill: %s: %d (%g pixels)\n", |
| 435 | (filename ? filename : (FcChar8 *) "<none>"), id, dsize); |
| 436 | /* |
| 437 | * Get antialias value |
| 438 | */ |
| 439 | switch (FcPatternGetBool (pattern, FC_ANTIALIAS"antialias", 0, &fi->antialias)) { |
| 440 | case FcResultNoMatch: |
| 441 | fi->antialias = True1; |
| 442 | break; |
| 443 | case FcResultMatch: |
| 444 | break; |
| 445 | default: |
| 446 | goto bail1; |
| 447 | } |
| 448 | |
| 449 | /* |
| 450 | * Get rgba value |
| 451 | */ |
| 452 | switch (FcPatternGetInteger (pattern, FC_RGBA"rgba", 0, &fi->rgba)) { |
| 453 | case FcResultNoMatch: |
| 454 | fi->rgba = FC_RGBA_UNKNOWN0; |
| 455 | break; |
| 456 | case FcResultMatch: |
| 457 | break; |
| 458 | default: |
| 459 | goto bail1; |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | * Get lcd_filter value |
| 464 | */ |
| 465 | switch (FcPatternGetInteger (pattern, FC_LCD_FILTER"lcdfilter", 0, &fi->lcd_filter)) { |
| 466 | case FcResultNoMatch: |
| 467 | fi->lcd_filter = FC_LCD_DEFAULT1; |
| 468 | break; |
| 469 | case FcResultMatch: |
| 470 | break; |
| 471 | default: |
| 472 | goto bail1; |
| 473 | } |
| 474 | |
| 475 | /* |
| 476 | * Get matrix and transform values |
| 477 | */ |
| 478 | switch (FcPatternGetMatrix (pattern, FC_MATRIX"matrix", 0, &font_matrix)) { |
| 479 | case FcResultNoMatch: |
| 480 | fi->matrix.xx = fi->matrix.yy = 0x10000; |
| 481 | fi->matrix.xy = fi->matrix.yx = 0; |
| 482 | break; |
| 483 | case FcResultMatch: |
| 484 | fi->matrix.xx = 0x10000L * font_matrix->xx; |
| 485 | fi->matrix.yy = 0x10000L * font_matrix->yy; |
| 486 | fi->matrix.xy = 0x10000L * font_matrix->xy; |
| 487 | fi->matrix.yx = 0x10000L * font_matrix->yx; |
| 488 | break; |
| 489 | default: |
| 490 | goto bail1; |
| 491 | } |
| 492 | |
| 493 | fi->transform = (fi->matrix.xx != 0x10000 || fi->matrix.xy != 0 || |
| 494 | fi->matrix.yx != 0 || fi->matrix.yy != 0x10000); |
| 495 | |
| 496 | /* |
| 497 | * Get render value, set to false if no Render extension present |
| 498 | */ |
| 499 | if (info->hasRender) |
| 500 | { |
| 501 | switch (FcPatternGetBool (pattern, XFT_RENDER"render", 0, &fi->render)) { |
| 502 | case FcResultNoMatch: |
| 503 | fi->render = info->hasRender; |
| 504 | break; |
| 505 | case FcResultMatch: |
| 506 | break; |
| 507 | default: |
| 508 | goto bail1; |
| 509 | } |
| 510 | } |
| 511 | else |
| 512 | fi->render = FcFalse0; |
| 513 | |
| 514 | /* |
| 515 | * Compute glyph load flags |
| 516 | */ |
| 517 | fi->load_flags = FT_LOAD_DEFAULT0x0; |
| 518 | |
| 519 | #ifndef XFT_EMBEDDED_BITMAP"embeddedbitmap" |
| 520 | #define XFT_EMBEDDED_BITMAP"embeddedbitmap" "embeddedbitmap" |
| 521 | #endif |
| 522 | |
| 523 | switch (FcPatternGetBool (pattern, XFT_EMBEDDED_BITMAP"embeddedbitmap", 0, &bitmap)) { |
| 524 | case FcResultNoMatch: |
| 525 | bitmap = FcFalse0; |
| 526 | break; |
| 527 | case FcResultMatch: |
| 528 | break; |
| 529 | default: |
| 530 | goto bail1; |
| 531 | } |
| 532 | |
| 533 | /* disable bitmaps when anti-aliasing or transforming glyphs */ |
| 534 | if ((!bitmap && fi->antialias) || fi->transform) |
| 535 | fi->load_flags |= FT_LOAD_NO_BITMAP0x8; |
| 536 | |
| 537 | /* disable hinting if requested */ |
| 538 | switch (FcPatternGetBool (pattern, FC_HINTING"hinting", 0, &hinting)) { |
| 539 | case FcResultNoMatch: |
| 540 | hinting = FcTrue1; |
| 541 | break; |
| 542 | case FcResultMatch: |
| 543 | break; |
| 544 | default: |
| 545 | goto bail1; |
| 546 | } |
| 547 | |
| 548 | switch (FcPatternGetBool (pattern, FC_EMBOLDEN"embolden", 0, &fi->embolden)) { |
| 549 | case FcResultNoMatch: |
| 550 | fi->embolden = FcFalse0; |
| 551 | break; |
| 552 | case FcResultMatch: |
| 553 | break; |
| 554 | default: |
| 555 | goto bail1; |
| 556 | } |
| 557 | |
| 558 | switch (FcPatternGetInteger (pattern, FC_HINT_STYLE"hintstyle", 0, &hint_style)) { |
| 559 | case FcResultNoMatch: |
| 560 | hint_style = FC_HINT_FULL3; |
| 561 | break; |
| 562 | case FcResultMatch: |
| 563 | break; |
| 564 | default: |
| 565 | goto bail1; |
| 566 | } |
| 567 | |
| 568 | if (!hinting |
| 569 | || hint_style == FC_HINT_NONE0 |
| 570 | ) |
| 571 | { |
| 572 | fi->load_flags |= FT_LOAD_NO_HINTING0x2; |
| 573 | } |
| 574 | |
| 575 | /* Figure out the load target, which modifies the hinting |
| 576 | * behavior of FreeType based on the intended use of the glyphs. |
| 577 | */ |
| 578 | if (fi->antialias) |
| 579 | { |
| 580 | if (FC_HINT_NONE0 < hint_style && hint_style < FC_HINT_FULL3) |
| 581 | { |
| 582 | fi->load_flags |= FT_LOAD_TARGET_LIGHT( (FT_Int32)( (FT_RENDER_MODE_LIGHT) & 15 ) << 16 ); |
| 583 | } |
| 584 | else |
| 585 | { |
| 586 | /* autohinter will snap stems to integer widths, when |
| 587 | * the LCD targets are used. |
| 588 | */ |
| 589 | switch (fi->rgba) { |
| 590 | case FC_RGBA_RGB1: |
| 591 | case FC_RGBA_BGR2: |
| 592 | fi->load_flags |= FT_LOAD_TARGET_LCD( (FT_Int32)( (FT_RENDER_MODE_LCD) & 15 ) << 16 ); |
| 593 | break; |
| 594 | case FC_RGBA_VRGB3: |
| 595 | case FC_RGBA_VBGR4: |
| 596 | fi->load_flags |= FT_LOAD_TARGET_LCD_V( (FT_Int32)( (FT_RENDER_MODE_LCD_V) & 15 ) << 16 ); |
| 597 | break; |
| 598 | } |
| 599 | } |
| 600 | } |
| 601 | else |
| 602 | fi->load_flags |= FT_LOAD_TARGET_MONO( (FT_Int32)( (FT_RENDER_MODE_MONO) & 15 ) << 16 ); |
| 603 | |
| 604 | /* set vertical layout if requested */ |
| 605 | switch (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT"verticallayout", 0, &vertical_layout)) { |
| 606 | case FcResultNoMatch: |
| 607 | vertical_layout = FcFalse0; |
| 608 | break; |
| 609 | case FcResultMatch: |
| 610 | break; |
| 611 | default: |
| 612 | goto bail1; |
| 613 | } |
| 614 | |
| 615 | if (vertical_layout) |
| 616 | fi->load_flags |= FT_LOAD_VERTICAL_LAYOUT0x10; |
| 617 | |
| 618 | /* force autohinting if requested */ |
| 619 | switch (FcPatternGetBool (pattern, FC_AUTOHINT"autohint", 0, &autohint)) { |
| 620 | case FcResultNoMatch: |
| 621 | autohint = FcFalse0; |
| 622 | break; |
| 623 | case FcResultMatch: |
| 624 | break; |
| 625 | default: |
| 626 | goto bail1; |
| 627 | } |
| 628 | |
| 629 | if (autohint) |
| 630 | fi->load_flags |= FT_LOAD_FORCE_AUTOHINT0x20; |
| 631 | |
| 632 | /* disable global advance width (for broken DynaLab TT CJK fonts) */ |
| 633 | switch (FcPatternGetBool (pattern, FC_GLOBAL_ADVANCE"globaladvance", 0, &global_advance)) { |
| 634 | case FcResultNoMatch: |
| 635 | global_advance = FcTrue1; |
| 636 | break; |
| 637 | case FcResultMatch: |
| 638 | break; |
| 639 | default: |
| 640 | goto bail1; |
| 641 | } |
| 642 | |
| 643 | if (!global_advance) |
| 644 | fi->load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH0x200; |
| 645 | |
| 646 | /* |
| 647 | * Get requested spacing value |
| 648 | */ |
| 649 | switch (FcPatternGetInteger (pattern, FC_SPACING"spacing", 0, &fi->spacing)) { |
| 650 | case FcResultNoMatch: |
| 651 | fi->spacing = FC_PROPORTIONAL0; |
| 652 | break; |
| 653 | case FcResultMatch: |
| 654 | break; |
| 655 | default: |
| 656 | goto bail1; |
| 657 | } |
| 658 | |
| 659 | /* |
| 660 | * Check for minspace |
| 661 | */ |
| 662 | |
| 663 | switch (FcPatternGetBool (pattern, FC_MINSPACE"minspace", 0, &fi->minspace)) { |
| 664 | case FcResultNoMatch: |
| 665 | fi->minspace = FcFalse0; |
| 666 | break; |
| 667 | case FcResultMatch: |
| 668 | break; |
| 669 | default: |
| 670 | goto bail1; |
| 671 | } |
| 672 | /* |
| 673 | * Check for fixed pixel spacing |
| 674 | */ |
| 675 | switch (FcPatternGetInteger (pattern, FC_CHAR_WIDTH"charwidth", 0, &fi->char_width)) { |
| 676 | case FcResultNoMatch: |
| 677 | fi->char_width = 0; |
| 678 | break; |
| 679 | case FcResultMatch: |
| 680 | if (fi->char_width) |
| 681 | fi->spacing = FC_MONO100; |
| 682 | break; |
| 683 | default: |
| 684 | goto bail1; |
| 685 | } |
| 686 | |
| 687 | /* |
| 688 | * Step over hash value in the structure |
| 689 | */ |
| 690 | hash = 0; |
| 691 | hashp = (FcChar32 *) fi + 1; |
| 692 | nhash = (sizeof (XftFontInfo) / sizeof (FcChar32)) - 1; |
| 693 | |
| 694 | while (nhash--) |
| 695 | hash += *hashp++; |
| 696 | fi->hash = hash; |
| 697 | |
| 698 | /* |
| 699 | * All done |
| 700 | */ |
| 701 | return FcTrue1; |
| 702 | |
| 703 | bail1: |
| 704 | _XftReleaseFile (fi->file); |
| 705 | fi->file = NULL((void*)0); |
| 706 | bail0: |
| 707 | return FcFalse0; |
| 708 | } |
| 709 | |
| 710 | static void |
| 711 | XftFontInfoEmpty (Display *dpy, XftFontInfo *fi) |
| 712 | { |
| 713 | if (fi->file) |
| 714 | _XftReleaseFile (fi->file); |
| 715 | } |
| 716 | |
| 717 | XftFontInfo * |
| 718 | XftFontInfoCreate (Display *dpy, _Xconstconst FcPattern *pattern) |
| 719 | { |
| 720 | XftFontInfo *fi = malloc (sizeof (XftFontInfo)); |
| 721 | |
| 722 | if (!fi) |
| 723 | return NULL((void*)0); |
| 724 | |
| 725 | if (!XftFontInfoFill (dpy, pattern, fi)) |
| 726 | { |
| 727 | free (fi); |
| 728 | fi = NULL((void*)0); |
| 729 | } |
| 730 | XftMemAlloc (XFT_MEM_FONT1, sizeof (XftFontInfo)); |
| 731 | return fi; |
| 732 | } |
| 733 | |
| 734 | _X_EXPORT__attribute__((visibility("default"))) void |
| 735 | XftFontInfoDestroy (Display *dpy, XftFontInfo *fi) |
| 736 | { |
| 737 | XftFontInfoEmpty (dpy, fi); |
| 738 | XftMemFree (XFT_MEM_FONT1, sizeof (XftFontInfo)); |
| 739 | free (fi); |
| 740 | } |
| 741 | |
| 742 | _X_EXPORT__attribute__((visibility("default"))) FcChar32 |
| 743 | XftFontInfoHash (_Xconstconst XftFontInfo *fi) |
| 744 | { |
| 745 | return fi->hash; |
| 746 | } |
| 747 | |
| 748 | _X_EXPORT__attribute__((visibility("default"))) FcBool |
| 749 | XftFontInfoEqual (_Xconstconst XftFontInfo *a, _Xconstconst XftFontInfo *b) |
| 750 | { |
| 751 | return memcmp ((void *) a, (void *) b, sizeof (XftFontInfo)) == 0; |
| 752 | } |
| 753 | |
| 754 | _X_EXPORT__attribute__((visibility("default"))) XftFont * |
| 755 | XftFontOpenInfo (Display *dpy, |
| 756 | FcPattern *pattern, |
| 757 | XftFontInfo *fi) |
| 758 | { |
| 759 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1); |
| 760 | FT_Face face; |
| 761 | XftFont **bucket; |
| 762 | XftFontInt *font; |
| 763 | XRenderPictFormat *format; |
| 764 | FcCharSet *charset; |
| 765 | FcChar32 num_unicode; |
| 766 | FcChar32 hash_value; |
| 767 | FcChar32 rehash_value; |
| 768 | FcBool antialias; |
| 769 | int max_glyph_memory; |
| 770 | int alloc_size; |
| 771 | int ascent, descent, height; |
| 772 | int i; |
| 773 | int num_glyphs; |
| 774 | |
| 775 | if (!info) |
| 776 | return NULL((void*)0); |
| 777 | /* |
| 778 | * Find a matching previously opened font |
| 779 | */ |
| 780 | bucket = &info->fontHash[fi->hash % XFT_NUM_FONT_HASH127]; |
| 781 | for (font = (XftFontInt *) *bucket; font; font = (XftFontInt *) font->hash_next) |
| 782 | if (XftFontInfoEqual (&font->info, fi)) |
| 783 | { |
| 784 | if (!font->ref++) |
| 785 | --info->num_unref_fonts; |
| 786 | FcPatternDestroy (pattern); |
| 787 | return &font->public; |
| 788 | } |
| 789 | |
| 790 | /* |
| 791 | * No existing font, create another. |
| 792 | */ |
| 793 | |
| 794 | if (XftDebug () & XFT_DBG_CACHE128) |
| 795 | printf ("New font %s/%d size %dx%d\n", |
| 796 | fi->file->file, fi->file->id, |
| 797 | (int) fi->xsize >> 6, (int) fi->ysize >> 6); |
| 798 | |
| 799 | if (FcPatternGetInteger (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0, |
| 800 | &max_glyph_memory) != FcResultMatch) |
| 801 | max_glyph_memory = XFT_FONT_MAX_GLYPH_MEMORY(1024 * 1024); |
| 802 | |
| 803 | face = _XftLockFile (fi->file); |
| 804 | if (!face) |
| 805 | goto bail0; |
| 806 | |
| 807 | if (!_XftSetFace (fi->file, fi->xsize, fi->ysize, &fi->matrix)) |
| 808 | goto bail1; |
| 809 | |
| 810 | /* |
| 811 | * Get the set of Unicode codepoints covered by the font. |
| 812 | * If the incoming pattern doesn't provide this data, go |
| 813 | * off and compute it. Yes, this is expensive, but it's |
| 814 | * required to map Unicode to glyph indices. |
| 815 | */ |
| 816 | if (FcPatternGetCharSet (pattern, FC_CHARSET"charset", 0, &charset) == FcResultMatch) |
| 817 | charset = FcCharSetCopy (charset); |
| 818 | else |
| 819 | charset = FcFreeTypeCharSet (face, FcConfigGetBlanks (NULL((void*)0))); |
| 820 | |
| 821 | antialias = fi->antialias; |
| 822 | if (!(face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 ))) |
| 823 | antialias = FcFalse0; |
| 824 | |
| 825 | /* |
| 826 | * Find the appropriate picture format |
| 827 | */ |
| 828 | if (fi->render) |
| 829 | { |
| 830 | if (antialias) |
| 831 | { |
| 832 | switch (fi->rgba) { |
| 833 | case FC_RGBA_RGB1: |
| 834 | case FC_RGBA_BGR2: |
| 835 | case FC_RGBA_VRGB3: |
| 836 | case FC_RGBA_VBGR4: |
| 837 | format = XRenderFindStandardFormat (dpy, PictStandardARGB320); |
| 838 | break; |
| 839 | default: |
| 840 | format = XRenderFindStandardFormat (dpy, PictStandardA82); |
| 841 | break; |
| 842 | } |
| 843 | } |
| 844 | else |
| 845 | { |
| 846 | format = XRenderFindStandardFormat (dpy, PictStandardA14); |
| 847 | } |
| 848 | |
| 849 | if (!format) |
| 850 | goto bail2; |
| 851 | } |
| 852 | else |
| 853 | format = NULL((void*)0); |
| 854 | |
| 855 | if (charset) |
| 856 | { |
| 857 | num_unicode = FcCharSetCount (charset); |
| 858 | hash_value = _XftHashSize (num_unicode); |
| 859 | rehash_value = hash_value - 2; |
| 860 | } |
| 861 | else |
| 862 | { |
| 863 | num_unicode = 0; |
Value stored to 'num_unicode' is never read | |
| 864 | hash_value = 0; |
| 865 | rehash_value = 0; |
| 866 | } |
| 867 | |
| 868 | /* |
| 869 | * Sometimes the glyphs are numbered 1..n, other times 0..n-1, |
| 870 | * accept either numbering scheme by making room in the table |
| 871 | */ |
| 872 | num_glyphs = face->num_glyphs + 1; |
| 873 | alloc_size = (sizeof (XftFontInt) + |
| 874 | num_glyphs * sizeof (XftGlyph *) + |
| 875 | hash_value * sizeof (XftUcsHash)); |
| 876 | font = malloc (alloc_size); |
| 877 | |
| 878 | if (!font) |
| 879 | goto bail2; |
| 880 | |
| 881 | XftMemAlloc (XFT_MEM_FONT1, alloc_size); |
| 882 | |
| 883 | /* |
| 884 | * Public fields |
| 885 | */ |
| 886 | if (fi->transform) |
| 887 | { |
| 888 | FT_Vector vector; |
| 889 | |
| 890 | vector.x = 0; |
| 891 | vector.y = face->size->metrics.descender; |
| 892 | FT_Vector_Transform (&vector, &fi->matrix); |
| 893 | descent = -(vector.y >> 6); |
| 894 | |
| 895 | vector.x = 0; |
| 896 | vector.y = face->size->metrics.ascender; |
| 897 | FT_Vector_Transform (&vector, &fi->matrix); |
| 898 | ascent = vector.y >> 6; |
| 899 | |
| 900 | if (fi->minspace) |
| 901 | height = ascent + descent; |
| 902 | else |
| 903 | { |
| 904 | vector.x = 0; |
| 905 | vector.y = face->size->metrics.height; |
| 906 | FT_Vector_Transform (&vector, &fi->matrix); |
| 907 | height = vector.y >> 6; |
| 908 | } |
| 909 | } |
| 910 | else |
| 911 | { |
| 912 | descent = -(face->size->metrics.descender >> 6); |
| 913 | ascent = face->size->metrics.ascender >> 6; |
| 914 | if (fi->minspace) |
| 915 | height = ascent + descent; |
| 916 | else |
| 917 | height = face->size->metrics.height >> 6; |
| 918 | } |
| 919 | font->public.ascent = ascent; |
| 920 | font->public.descent = descent; |
| 921 | font->public.height = height; |
| 922 | |
| 923 | if (fi->char_width) |
| 924 | font->public.max_advance_width = fi->char_width; |
| 925 | else |
| 926 | { |
| 927 | if (fi->transform) |
| 928 | { |
| 929 | FT_Vector vector; |
| 930 | vector.x = face->size->metrics.max_advance; |
| 931 | vector.y = 0; |
| 932 | FT_Vector_Transform (&vector, &fi->matrix); |
| 933 | font->public.max_advance_width = vector.x >> 6; |
| 934 | } |
| 935 | else |
| 936 | font->public.max_advance_width = face->size->metrics.max_advance >> 6; |
| 937 | } |
| 938 | font->public.charset = charset; |
| 939 | font->public.pattern = pattern; |
| 940 | |
| 941 | /* |
| 942 | * Management fields |
| 943 | */ |
| 944 | font->ref = 1; |
| 945 | |
| 946 | font->next = info->fonts; |
| 947 | info->fonts = &font->public; |
| 948 | |
| 949 | font->hash_next = *bucket; |
| 950 | *bucket = &font->public; |
| 951 | |
| 952 | /* |
| 953 | * Copy the info over |
| 954 | */ |
| 955 | font->info = *fi; |
| 956 | /* |
| 957 | * reset the antialias field. It can't |
| 958 | * be set correctly until the font is opened, |
| 959 | * which doesn't happen in XftFontInfoFill |
| 960 | */ |
| 961 | font->info.antialias = antialias; |
| 962 | /* |
| 963 | * bump XftFile reference count |
| 964 | */ |
| 965 | font->info.file->ref++; |
| 966 | |
| 967 | /* |
| 968 | * Per glyph information |
| 969 | */ |
| 970 | font->glyphs = (XftGlyph **) (font + 1); |
| 971 | memset (font->glyphs, '\0', num_glyphs * sizeof (XftGlyph *))__builtin___memset_chk (font->glyphs, '\0', num_glyphs * sizeof (XftGlyph *), __builtin_object_size (font->glyphs, 0)); |
| 972 | font->num_glyphs = num_glyphs; |
| 973 | /* |
| 974 | * Unicode hash table information |
| 975 | */ |
| 976 | font->hash_table = (XftUcsHash *) (font->glyphs + font->num_glyphs); |
| 977 | for (i = 0; i < hash_value; i++) |
| 978 | { |
| 979 | font->hash_table[i].ucs4 = ((FcChar32) ~0); |
| 980 | font->hash_table[i].glyph = 0; |
| 981 | } |
| 982 | font->hash_value = hash_value; |
| 983 | font->rehash_value = rehash_value; |
| 984 | /* |
| 985 | * X specific fields |
| 986 | */ |
| 987 | font->glyphset = 0; |
| 988 | font->format = format; |
| 989 | |
| 990 | /* |
| 991 | * Glyph memory management fields |
| 992 | */ |
| 993 | font->glyph_memory = 0; |
| 994 | font->max_glyph_memory = max_glyph_memory; |
| 995 | font->use_free_glyphs = info->use_free_glyphs; |
| 996 | |
| 997 | _XftUnlockFile (fi->file); |
| 998 | |
| 999 | return &font->public; |
| 1000 | |
| 1001 | bail2: |
| 1002 | FcCharSetDestroy (charset); |
| 1003 | bail1: |
| 1004 | _XftUnlockFile (fi->file); |
| 1005 | bail0: |
| 1006 | return NULL((void*)0); |
| 1007 | } |
| 1008 | |
| 1009 | _X_EXPORT__attribute__((visibility("default"))) XftFont * |
| 1010 | XftFontOpenPattern (Display *dpy, FcPattern *pattern) |
| 1011 | { |
| 1012 | XftFontInfo info; |
| 1013 | XftFont *font; |
| 1014 | |
| 1015 | if (!XftFontInfoFill (dpy, pattern, &info)) |
| 1016 | return NULL((void*)0); |
| 1017 | |
| 1018 | font = XftFontOpenInfo (dpy, pattern, &info); |
| 1019 | XftFontInfoEmpty (dpy, &info); |
| 1020 | return font; |
| 1021 | } |
| 1022 | |
| 1023 | _X_EXPORT__attribute__((visibility("default"))) XftFont * |
| 1024 | XftFontCopy (Display *dpy, XftFont *public) |
| 1025 | { |
| 1026 | XftFontInt *font = (XftFontInt *) public; |
| 1027 | |
| 1028 | font->ref++; |
| 1029 | return public; |
| 1030 | } |
| 1031 | |
| 1032 | static void |
| 1033 | XftFontDestroy (Display *dpy, XftFont *public) |
| 1034 | { |
| 1035 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0); |
| 1036 | XftFontInt *font = (XftFontInt *) public; |
| 1037 | int i; |
| 1038 | |
| 1039 | /* note reduction in memory use */ |
| 1040 | if (info) |
| 1041 | info->glyph_memory -= font->glyph_memory; |
| 1042 | /* Clean up the info */ |
| 1043 | XftFontInfoEmpty (dpy, &font->info); |
| 1044 | /* Free the glyphset */ |
| 1045 | if (font->glyphset) |
| 1046 | XRenderFreeGlyphSet (dpy, font->glyphset); |
| 1047 | /* Free the glyphs */ |
| 1048 | for (i = 0; i < font->num_glyphs; i++) |
| 1049 | { |
| 1050 | XftGlyph *xftg = font->glyphs[i]; |
| 1051 | if (xftg) |
| 1052 | { |
| 1053 | if (xftg->bitmap) |
| 1054 | free (xftg->bitmap); |
| 1055 | free (xftg); |
| 1056 | } |
| 1057 | } |
| 1058 | |
| 1059 | /* Free the pattern and the charset */ |
| 1060 | FcPatternDestroy (font->public.pattern); |
| 1061 | FcCharSetDestroy (font->public.charset); |
| 1062 | |
| 1063 | /* Finally, free the font structure */ |
| 1064 | XftMemFree (XFT_MEM_FONT1, sizeof (XftFontInt) + |
| 1065 | font->num_glyphs * sizeof (XftGlyph *) + |
| 1066 | font->hash_value * sizeof (XftUcsHash)); |
| 1067 | free (font); |
| 1068 | } |
| 1069 | |
| 1070 | static XftFont * |
| 1071 | XftFontFindNthUnref (XftDisplayInfo *info, int n) |
| 1072 | { |
| 1073 | XftFont *public; |
| 1074 | XftFontInt *font; |
| 1075 | |
| 1076 | for (public = info->fonts; public; public = font->next) |
| 1077 | { |
| 1078 | font = (XftFontInt*) public; |
| 1079 | if (!font->ref && !n--) |
| 1080 | break; |
| 1081 | } |
| 1082 | return public; |
| 1083 | } |
| 1084 | |
| 1085 | _X_HIDDEN__attribute__((visibility("hidden"))) void |
| 1086 | XftFontManageMemory (Display *dpy) |
| 1087 | { |
| 1088 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0); |
| 1089 | XftFont **prev; |
| 1090 | XftFont *public; |
| 1091 | XftFontInt *font; |
| 1092 | |
| 1093 | if (!info) |
| 1094 | return; |
| 1095 | while (info->num_unref_fonts > info->max_unref_fonts) |
| 1096 | { |
| 1097 | public = XftFontFindNthUnref (info, rand() % info->num_unref_fonts); |
| 1098 | font = (XftFontInt *) public; |
| 1099 | |
| 1100 | if (XftDebug () & XFT_DBG_CACHE128) |
| 1101 | printf ("freeing unreferenced font %s/%d size %dx%d\n", |
| 1102 | font->info.file->file, font->info.file->id, |
| 1103 | (int) font->info.xsize >> 6, (int) font->info.ysize >> 6); |
| 1104 | |
| 1105 | /* Unhook from display list */ |
| 1106 | for (prev = &info->fonts; *prev; prev = &(*(XftFontInt **) prev)->next) |
| 1107 | { |
| 1108 | if (*prev == public) |
| 1109 | { |
| 1110 | *prev = font->next; |
| 1111 | break; |
| 1112 | } |
| 1113 | } |
| 1114 | /* Unhook from hash list */ |
| 1115 | for (prev = &info->fontHash[font->info.hash % XFT_NUM_FONT_HASH127]; |
| 1116 | *prev; |
| 1117 | prev = &(*(XftFontInt **) prev)->hash_next) |
| 1118 | { |
| 1119 | if (*prev == public) |
| 1120 | { |
| 1121 | *prev = font->hash_next; |
| 1122 | break; |
| 1123 | } |
| 1124 | } |
| 1125 | /* Destroy the font */ |
| 1126 | XftFontDestroy (dpy, public); |
| 1127 | --info->num_unref_fonts; |
| 1128 | } |
| 1129 | } |
| 1130 | |
| 1131 | _X_EXPORT__attribute__((visibility("default"))) void |
| 1132 | XftFontClose (Display *dpy, XftFont *public) |
| 1133 | { |
| 1134 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0); |
| 1135 | XftFontInt *font = (XftFontInt *) public; |
| 1136 | |
| 1137 | if (--font->ref != 0) |
| 1138 | return; |
| 1139 | |
| 1140 | if (info) |
| 1141 | { |
| 1142 | ++info->num_unref_fonts; |
| 1143 | XftFontManageMemory (dpy); |
| 1144 | } |
| 1145 | else |
| 1146 | { |
| 1147 | XftFontDestroy (dpy, public); |
| 1148 | } |
| 1149 | } |
| 1150 | |
| 1151 | _X_EXPORT__attribute__((visibility("default"))) FcBool |
| 1152 | XftInitFtLibrary (void) |
| 1153 | { |
| 1154 | if (_XftFTlibrary) |
| 1155 | return FcTrue1; |
| 1156 | if (FT_Init_FreeType (&_XftFTlibrary)) |
| 1157 | return FcFalse0; |
| 1158 | return FcTrue1; |
| 1159 | } |