1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-glyph.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,670 @@ 1.4 +/* 1.5 + * Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk> 1.6 + * Copyright 2010, 2011, 2012, Red Hat, Inc 1.7 + * 1.8 + * Permission is hereby granted, free of charge, to any person obtaining a 1.9 + * copy of this software and associated documentation files (the "Software"), 1.10 + * to deal in the Software without restriction, including without limitation 1.11 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1.12 + * and/or sell copies of the Software, and to permit persons to whom the 1.13 + * Software is furnished to do so, subject to the following conditions: 1.14 + * 1.15 + * The above copyright notice and this permission notice (including the next 1.16 + * paragraph) shall be included in all copies or substantial portions of the 1.17 + * Software. 1.18 + * 1.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1.24 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 1.25 + * DEALINGS IN THE SOFTWARE. 1.26 + * 1.27 + * Author: Soren Sandmann <sandmann@cs.au.dk> 1.28 + */ 1.29 + 1.30 +#ifdef HAVE_CONFIG_H 1.31 +#include <config.h> 1.32 +#endif 1.33 +#include "pixman-private.h" 1.34 + 1.35 +#include <stdlib.h> 1.36 + 1.37 +typedef struct glyph_metrics_t glyph_metrics_t; 1.38 +typedef struct glyph_t glyph_t; 1.39 + 1.40 +#define TOMBSTONE ((glyph_t *)0x1) 1.41 + 1.42 +/* XXX: These numbers are arbitrary---we've never done any measurements. 1.43 + */ 1.44 +#define N_GLYPHS_HIGH_WATER (16384) 1.45 +#define N_GLYPHS_LOW_WATER (8192) 1.46 +#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER) 1.47 +#define HASH_MASK (HASH_SIZE - 1) 1.48 + 1.49 +struct glyph_t 1.50 +{ 1.51 + void * font_key; 1.52 + void * glyph_key; 1.53 + int origin_x; 1.54 + int origin_y; 1.55 + pixman_image_t * image; 1.56 + pixman_link_t mru_link; 1.57 +}; 1.58 + 1.59 +struct pixman_glyph_cache_t 1.60 +{ 1.61 + int n_glyphs; 1.62 + int n_tombstones; 1.63 + int freeze_count; 1.64 + pixman_list_t mru; 1.65 + glyph_t * glyphs[HASH_SIZE]; 1.66 +}; 1.67 + 1.68 +static void 1.69 +free_glyph (glyph_t *glyph) 1.70 +{ 1.71 + pixman_list_unlink (&glyph->mru_link); 1.72 + pixman_image_unref (glyph->image); 1.73 + free (glyph); 1.74 +} 1.75 + 1.76 +static unsigned int 1.77 +hash (const void *font_key, const void *glyph_key) 1.78 +{ 1.79 + size_t key = (size_t)font_key + (size_t)glyph_key; 1.80 + 1.81 + /* This hash function is based on one found on Thomas Wang's 1.82 + * web page at 1.83 + * 1.84 + * http://www.concentric.net/~Ttwang/tech/inthash.htm 1.85 + * 1.86 + */ 1.87 + key = (key << 15) - key - 1; 1.88 + key = key ^ (key >> 12); 1.89 + key = key + (key << 2); 1.90 + key = key ^ (key >> 4); 1.91 + key = key + (key << 3) + (key << 11); 1.92 + key = key ^ (key >> 16); 1.93 + 1.94 + return key; 1.95 +} 1.96 + 1.97 +static glyph_t * 1.98 +lookup_glyph (pixman_glyph_cache_t *cache, 1.99 + void *font_key, 1.100 + void *glyph_key) 1.101 +{ 1.102 + unsigned idx; 1.103 + glyph_t *g; 1.104 + 1.105 + idx = hash (font_key, glyph_key); 1.106 + while ((g = cache->glyphs[idx++ & HASH_MASK])) 1.107 + { 1.108 + if (g != TOMBSTONE && 1.109 + g->font_key == font_key && 1.110 + g->glyph_key == glyph_key) 1.111 + { 1.112 + return g; 1.113 + } 1.114 + } 1.115 + 1.116 + return NULL; 1.117 +} 1.118 + 1.119 +static void 1.120 +insert_glyph (pixman_glyph_cache_t *cache, 1.121 + glyph_t *glyph) 1.122 +{ 1.123 + unsigned idx; 1.124 + glyph_t **loc; 1.125 + 1.126 + idx = hash (glyph->font_key, glyph->glyph_key); 1.127 + 1.128 + /* Note: we assume that there is room in the table. If there isn't, 1.129 + * this will be an infinite loop. 1.130 + */ 1.131 + do 1.132 + { 1.133 + loc = &cache->glyphs[idx++ & HASH_MASK]; 1.134 + } while (*loc && *loc != TOMBSTONE); 1.135 + 1.136 + if (*loc == TOMBSTONE) 1.137 + cache->n_tombstones--; 1.138 + cache->n_glyphs++; 1.139 + 1.140 + *loc = glyph; 1.141 +} 1.142 + 1.143 +static void 1.144 +remove_glyph (pixman_glyph_cache_t *cache, 1.145 + glyph_t *glyph) 1.146 +{ 1.147 + unsigned idx; 1.148 + 1.149 + idx = hash (glyph->font_key, glyph->glyph_key); 1.150 + while (cache->glyphs[idx & HASH_MASK] != glyph) 1.151 + idx++; 1.152 + 1.153 + cache->glyphs[idx & HASH_MASK] = TOMBSTONE; 1.154 + cache->n_tombstones++; 1.155 + cache->n_glyphs--; 1.156 + 1.157 + /* Eliminate tombstones if possible */ 1.158 + if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL) 1.159 + { 1.160 + while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE) 1.161 + { 1.162 + cache->glyphs[idx & HASH_MASK] = NULL; 1.163 + cache->n_tombstones--; 1.164 + idx--; 1.165 + } 1.166 + } 1.167 +} 1.168 + 1.169 +static void 1.170 +clear_table (pixman_glyph_cache_t *cache) 1.171 +{ 1.172 + int i; 1.173 + 1.174 + for (i = 0; i < HASH_SIZE; ++i) 1.175 + { 1.176 + glyph_t *glyph = cache->glyphs[i]; 1.177 + 1.178 + if (glyph && glyph != TOMBSTONE) 1.179 + free_glyph (glyph); 1.180 + 1.181 + cache->glyphs[i] = NULL; 1.182 + } 1.183 + 1.184 + cache->n_glyphs = 0; 1.185 + cache->n_tombstones = 0; 1.186 +} 1.187 + 1.188 +PIXMAN_EXPORT pixman_glyph_cache_t * 1.189 +pixman_glyph_cache_create (void) 1.190 +{ 1.191 + pixman_glyph_cache_t *cache; 1.192 + 1.193 + if (!(cache = malloc (sizeof *cache))) 1.194 + return NULL; 1.195 + 1.196 + memset (cache->glyphs, 0, sizeof (cache->glyphs)); 1.197 + cache->n_glyphs = 0; 1.198 + cache->n_tombstones = 0; 1.199 + cache->freeze_count = 0; 1.200 + 1.201 + pixman_list_init (&cache->mru); 1.202 + 1.203 + return cache; 1.204 +} 1.205 + 1.206 +PIXMAN_EXPORT void 1.207 +pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) 1.208 +{ 1.209 + return_if_fail (cache->freeze_count == 0); 1.210 + 1.211 + clear_table (cache); 1.212 + 1.213 + free (cache); 1.214 +} 1.215 + 1.216 +PIXMAN_EXPORT void 1.217 +pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) 1.218 +{ 1.219 + cache->freeze_count++; 1.220 +} 1.221 + 1.222 +PIXMAN_EXPORT void 1.223 +pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) 1.224 +{ 1.225 + if (--cache->freeze_count == 0 && 1.226 + cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER) 1.227 + { 1.228 + if (cache->n_tombstones > N_GLYPHS_HIGH_WATER) 1.229 + { 1.230 + /* More than half the entries are 1.231 + * tombstones. Just dump the whole table. 1.232 + */ 1.233 + clear_table (cache); 1.234 + } 1.235 + 1.236 + while (cache->n_glyphs > N_GLYPHS_LOW_WATER) 1.237 + { 1.238 + glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail); 1.239 + 1.240 + remove_glyph (cache, glyph); 1.241 + free_glyph (glyph); 1.242 + } 1.243 + } 1.244 +} 1.245 + 1.246 +PIXMAN_EXPORT const void * 1.247 +pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, 1.248 + void *font_key, 1.249 + void *glyph_key) 1.250 +{ 1.251 + return lookup_glyph (cache, font_key, glyph_key); 1.252 +} 1.253 + 1.254 +PIXMAN_EXPORT const void * 1.255 +pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, 1.256 + void *font_key, 1.257 + void *glyph_key, 1.258 + int origin_x, 1.259 + int origin_y, 1.260 + pixman_image_t *image) 1.261 +{ 1.262 + glyph_t *glyph; 1.263 + int32_t width, height; 1.264 + 1.265 + return_val_if_fail (cache->freeze_count > 0, NULL); 1.266 + return_val_if_fail (image->type == BITS, NULL); 1.267 + 1.268 + width = image->bits.width; 1.269 + height = image->bits.height; 1.270 + 1.271 + if (cache->n_glyphs >= HASH_SIZE) 1.272 + return NULL; 1.273 + 1.274 + if (!(glyph = malloc (sizeof *glyph))) 1.275 + return NULL; 1.276 + 1.277 + glyph->font_key = font_key; 1.278 + glyph->glyph_key = glyph_key; 1.279 + glyph->origin_x = origin_x; 1.280 + glyph->origin_y = origin_y; 1.281 + 1.282 + if (!(glyph->image = pixman_image_create_bits ( 1.283 + image->bits.format, width, height, NULL, -1))) 1.284 + { 1.285 + free (glyph); 1.286 + return NULL; 1.287 + } 1.288 + 1.289 + pixman_image_composite32 (PIXMAN_OP_SRC, 1.290 + image, NULL, glyph->image, 0, 0, 0, 0, 0, 0, 1.291 + width, height); 1.292 + 1.293 + if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 && 1.294 + PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0) 1.295 + { 1.296 + pixman_image_set_component_alpha (glyph->image, TRUE); 1.297 + } 1.298 + 1.299 + pixman_list_prepend (&cache->mru, &glyph->mru_link); 1.300 + 1.301 + _pixman_image_validate (glyph->image); 1.302 + insert_glyph (cache, glyph); 1.303 + 1.304 + return glyph; 1.305 +} 1.306 + 1.307 +PIXMAN_EXPORT void 1.308 +pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, 1.309 + void *font_key, 1.310 + void *glyph_key) 1.311 +{ 1.312 + glyph_t *glyph; 1.313 + 1.314 + if ((glyph = lookup_glyph (cache, font_key, glyph_key))) 1.315 + { 1.316 + remove_glyph (cache, glyph); 1.317 + 1.318 + free_glyph (glyph); 1.319 + } 1.320 +} 1.321 + 1.322 +PIXMAN_EXPORT void 1.323 +pixman_glyph_get_extents (pixman_glyph_cache_t *cache, 1.324 + int n_glyphs, 1.325 + pixman_glyph_t *glyphs, 1.326 + pixman_box32_t *extents) 1.327 +{ 1.328 + int i; 1.329 + 1.330 + extents->x1 = extents->y1 = INT32_MAX; 1.331 + extents->x2 = extents->y2 = INT32_MIN; 1.332 + 1.333 + for (i = 0; i < n_glyphs; ++i) 1.334 + { 1.335 + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 1.336 + int x1, y1, x2, y2; 1.337 + 1.338 + x1 = glyphs[i].x - glyph->origin_x; 1.339 + y1 = glyphs[i].y - glyph->origin_y; 1.340 + x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; 1.341 + y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; 1.342 + 1.343 + if (x1 < extents->x1) 1.344 + extents->x1 = x1; 1.345 + if (y1 < extents->y1) 1.346 + extents->y1 = y1; 1.347 + if (x2 > extents->x2) 1.348 + extents->x2 = x2; 1.349 + if (y2 > extents->y2) 1.350 + extents->y2 = y2; 1.351 + } 1.352 +} 1.353 + 1.354 +/* This function returns a format that is suitable for use as a mask for the 1.355 + * set of glyphs in question. 1.356 + */ 1.357 +PIXMAN_EXPORT pixman_format_code_t 1.358 +pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, 1.359 + int n_glyphs, 1.360 + const pixman_glyph_t *glyphs) 1.361 +{ 1.362 + pixman_format_code_t format = PIXMAN_a1; 1.363 + int i; 1.364 + 1.365 + for (i = 0; i < n_glyphs; ++i) 1.366 + { 1.367 + const glyph_t *glyph = glyphs[i].glyph; 1.368 + pixman_format_code_t glyph_format = glyph->image->bits.format; 1.369 + 1.370 + if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A) 1.371 + { 1.372 + if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format)) 1.373 + format = glyph_format; 1.374 + } 1.375 + else 1.376 + { 1.377 + return PIXMAN_a8r8g8b8; 1.378 + } 1.379 + } 1.380 + 1.381 + return format; 1.382 +} 1.383 + 1.384 +static pixman_bool_t 1.385 +box32_intersect (pixman_box32_t *dest, 1.386 + const pixman_box32_t *box1, 1.387 + const pixman_box32_t *box2) 1.388 +{ 1.389 + dest->x1 = MAX (box1->x1, box2->x1); 1.390 + dest->y1 = MAX (box1->y1, box2->y1); 1.391 + dest->x2 = MIN (box1->x2, box2->x2); 1.392 + dest->y2 = MIN (box1->y2, box2->y2); 1.393 + 1.394 + return dest->x2 > dest->x1 && dest->y2 > dest->y1; 1.395 +} 1.396 + 1.397 +PIXMAN_EXPORT void 1.398 +pixman_composite_glyphs_no_mask (pixman_op_t op, 1.399 + pixman_image_t *src, 1.400 + pixman_image_t *dest, 1.401 + int32_t src_x, 1.402 + int32_t src_y, 1.403 + int32_t dest_x, 1.404 + int32_t dest_y, 1.405 + pixman_glyph_cache_t *cache, 1.406 + int n_glyphs, 1.407 + const pixman_glyph_t *glyphs) 1.408 +{ 1.409 + pixman_region32_t region; 1.410 + pixman_format_code_t glyph_format = PIXMAN_null; 1.411 + uint32_t glyph_flags = 0; 1.412 + pixman_format_code_t dest_format; 1.413 + uint32_t dest_flags; 1.414 + pixman_composite_func_t func = NULL; 1.415 + pixman_implementation_t *implementation = NULL; 1.416 + pixman_composite_info_t info; 1.417 + int i; 1.418 + 1.419 + _pixman_image_validate (src); 1.420 + _pixman_image_validate (dest); 1.421 + 1.422 + dest_format = dest->common.extended_format_code; 1.423 + dest_flags = dest->common.flags; 1.424 + 1.425 + pixman_region32_init (®ion); 1.426 + if (!_pixman_compute_composite_region32 ( 1.427 + ®ion, 1.428 + src, NULL, dest, 1.429 + src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, 1.430 + dest->bits.width, dest->bits.height)) 1.431 + { 1.432 + goto out; 1.433 + } 1.434 + 1.435 + info.op = op; 1.436 + info.src_image = src; 1.437 + info.dest_image = dest; 1.438 + info.src_flags = src->common.flags; 1.439 + info.dest_flags = dest->common.flags; 1.440 + 1.441 + for (i = 0; i < n_glyphs; ++i) 1.442 + { 1.443 + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 1.444 + pixman_image_t *glyph_img = glyph->image; 1.445 + pixman_box32_t glyph_box; 1.446 + pixman_box32_t *pbox; 1.447 + uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 1.448 + pixman_box32_t composite_box; 1.449 + int n; 1.450 + 1.451 + glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; 1.452 + glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; 1.453 + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; 1.454 + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; 1.455 + 1.456 + pbox = pixman_region32_rectangles (®ion, &n); 1.457 + 1.458 + info.mask_image = glyph_img; 1.459 + 1.460 + while (n--) 1.461 + { 1.462 + if (box32_intersect (&composite_box, pbox, &glyph_box)) 1.463 + { 1.464 + if (glyph_img->common.extended_format_code != glyph_format || 1.465 + glyph_img->common.flags != glyph_flags) 1.466 + { 1.467 + glyph_format = glyph_img->common.extended_format_code; 1.468 + glyph_flags = glyph_img->common.flags; 1.469 + 1.470 + _pixman_implementation_lookup_composite ( 1.471 + get_implementation(), op, 1.472 + src->common.extended_format_code, src->common.flags, 1.473 + glyph_format, glyph_flags | extra, 1.474 + dest_format, dest_flags, 1.475 + &implementation, &func); 1.476 + } 1.477 + 1.478 + info.src_x = src_x + composite_box.x1 - dest_x; 1.479 + info.src_y = src_y + composite_box.y1 - dest_y; 1.480 + info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); 1.481 + info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); 1.482 + info.dest_x = composite_box.x1; 1.483 + info.dest_y = composite_box.y1; 1.484 + info.width = composite_box.x2 - composite_box.x1; 1.485 + info.height = composite_box.y2 - composite_box.y1; 1.486 + 1.487 + info.mask_flags = glyph_flags; 1.488 + 1.489 + func (implementation, &info); 1.490 + } 1.491 + 1.492 + pbox++; 1.493 + } 1.494 + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); 1.495 + } 1.496 + 1.497 +out: 1.498 + pixman_region32_fini (®ion); 1.499 +} 1.500 + 1.501 +static void 1.502 +add_glyphs (pixman_glyph_cache_t *cache, 1.503 + pixman_image_t *dest, 1.504 + int off_x, int off_y, 1.505 + int n_glyphs, const pixman_glyph_t *glyphs) 1.506 +{ 1.507 + pixman_format_code_t glyph_format = PIXMAN_null; 1.508 + uint32_t glyph_flags = 0; 1.509 + pixman_composite_func_t func = NULL; 1.510 + pixman_implementation_t *implementation = NULL; 1.511 + pixman_format_code_t dest_format; 1.512 + uint32_t dest_flags; 1.513 + pixman_box32_t dest_box; 1.514 + pixman_composite_info_t info; 1.515 + pixman_image_t *white_img = NULL; 1.516 + pixman_bool_t white_src = FALSE; 1.517 + int i; 1.518 + 1.519 + _pixman_image_validate (dest); 1.520 + 1.521 + dest_format = dest->common.extended_format_code; 1.522 + dest_flags = dest->common.flags; 1.523 + 1.524 + info.op = PIXMAN_OP_ADD; 1.525 + info.dest_image = dest; 1.526 + info.src_x = 0; 1.527 + info.src_y = 0; 1.528 + info.dest_flags = dest_flags; 1.529 + 1.530 + dest_box.x1 = 0; 1.531 + dest_box.y1 = 0; 1.532 + dest_box.x2 = dest->bits.width; 1.533 + dest_box.y2 = dest->bits.height; 1.534 + 1.535 + for (i = 0; i < n_glyphs; ++i) 1.536 + { 1.537 + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 1.538 + pixman_image_t *glyph_img = glyph->image; 1.539 + pixman_box32_t glyph_box; 1.540 + pixman_box32_t composite_box; 1.541 + 1.542 + if (glyph_img->common.extended_format_code != glyph_format || 1.543 + glyph_img->common.flags != glyph_flags) 1.544 + { 1.545 + pixman_format_code_t src_format, mask_format; 1.546 + 1.547 + glyph_format = glyph_img->common.extended_format_code; 1.548 + glyph_flags = glyph_img->common.flags; 1.549 + 1.550 + if (glyph_format == dest->bits.format) 1.551 + { 1.552 + src_format = glyph_format; 1.553 + mask_format = PIXMAN_null; 1.554 + info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 1.555 + info.mask_flags = FAST_PATH_IS_OPAQUE; 1.556 + info.mask_image = NULL; 1.557 + white_src = FALSE; 1.558 + } 1.559 + else 1.560 + { 1.561 + if (!white_img) 1.562 + { 1.563 + static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; 1.564 + 1.565 + if (!(white_img = pixman_image_create_solid_fill (&white))) 1.566 + goto out; 1.567 + 1.568 + _pixman_image_validate (white_img); 1.569 + } 1.570 + 1.571 + src_format = PIXMAN_solid; 1.572 + mask_format = glyph_format; 1.573 + info.src_flags = white_img->common.flags; 1.574 + info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 1.575 + info.src_image = white_img; 1.576 + white_src = TRUE; 1.577 + } 1.578 + 1.579 + _pixman_implementation_lookup_composite ( 1.580 + get_implementation(), PIXMAN_OP_ADD, 1.581 + src_format, info.src_flags, 1.582 + mask_format, info.mask_flags, 1.583 + dest_format, dest_flags, 1.584 + &implementation, &func); 1.585 + } 1.586 + 1.587 + glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; 1.588 + glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; 1.589 + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; 1.590 + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; 1.591 + 1.592 + if (box32_intersect (&composite_box, &glyph_box, &dest_box)) 1.593 + { 1.594 + int src_x = composite_box.x1 - glyph_box.x1; 1.595 + int src_y = composite_box.y1 - glyph_box.y1; 1.596 + 1.597 + if (white_src) 1.598 + info.mask_image = glyph_img; 1.599 + else 1.600 + info.src_image = glyph_img; 1.601 + 1.602 + info.mask_x = info.src_x = src_x; 1.603 + info.mask_y = info.src_y = src_y; 1.604 + info.dest_x = composite_box.x1; 1.605 + info.dest_y = composite_box.y1; 1.606 + info.width = composite_box.x2 - composite_box.x1; 1.607 + info.height = composite_box.y2 - composite_box.y1; 1.608 + 1.609 + func (implementation, &info); 1.610 + 1.611 + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); 1.612 + } 1.613 + } 1.614 + 1.615 +out: 1.616 + if (white_img) 1.617 + pixman_image_unref (white_img); 1.618 +} 1.619 + 1.620 +/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an 1.621 + * infinitely big mask image at the position such that the glyph origin point 1.622 + * is positioned at the (glyphs[i].x, glyphs[i].y) point. 1.623 + * 1.624 + * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source 1.625 + * image are both aligned with (dest_x, dest_y) in the destination image. Then 1.626 + * these three images are composited within the 1.627 + * 1.628 + * (dest_x, dest_y, dst_x + width, dst_y + height) 1.629 + * 1.630 + * rectangle. 1.631 + * 1.632 + * TODO: 1.633 + * - Trim the mask to the destination clip/image? 1.634 + * - Trim composite region based on sources, when the op ignores 0s. 1.635 + */ 1.636 +PIXMAN_EXPORT void 1.637 +pixman_composite_glyphs (pixman_op_t op, 1.638 + pixman_image_t *src, 1.639 + pixman_image_t *dest, 1.640 + pixman_format_code_t mask_format, 1.641 + int32_t src_x, 1.642 + int32_t src_y, 1.643 + int32_t mask_x, 1.644 + int32_t mask_y, 1.645 + int32_t dest_x, 1.646 + int32_t dest_y, 1.647 + int32_t width, 1.648 + int32_t height, 1.649 + pixman_glyph_cache_t *cache, 1.650 + int n_glyphs, 1.651 + const pixman_glyph_t *glyphs) 1.652 +{ 1.653 + pixman_image_t *mask; 1.654 + 1.655 + if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1))) 1.656 + return; 1.657 + 1.658 + if (PIXMAN_FORMAT_A (mask_format) != 0 && 1.659 + PIXMAN_FORMAT_RGB (mask_format) != 0) 1.660 + { 1.661 + pixman_image_set_component_alpha (mask, TRUE); 1.662 + } 1.663 + 1.664 + add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); 1.665 + 1.666 + pixman_image_composite32 (op, src, mask, dest, 1.667 + src_x, src_y, 1.668 + 0, 0, 1.669 + dest_x, dest_y, 1.670 + width, height); 1.671 + 1.672 + pixman_image_unref (mask); 1.673 +}