File: | root/firefox-clang/gfx/cairo/libpixman/src/pixman-glyph.c |
Warning: | line 490, column 3 Called function pointer is null (null dereference) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk> | |||
3 | * Copyright 2010, 2011, 2012, Red Hat, Inc | |||
4 | * | |||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
6 | * copy of this software and associated documentation files (the "Software"), | |||
7 | * to deal in the Software without restriction, including without limitation | |||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
9 | * and/or sell copies of the Software, and to permit persons to whom the | |||
10 | * Software is furnished to do so, subject to the following conditions: | |||
11 | * | |||
12 | * The above copyright notice and this permission notice (including the next | |||
13 | * paragraph) shall be included in all copies or substantial portions of the | |||
14 | * Software. | |||
15 | * | |||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
22 | * DEALINGS IN THE SOFTWARE. | |||
23 | * | |||
24 | * Author: Soren Sandmann <sandmann@cs.au.dk> | |||
25 | */ | |||
26 | ||||
27 | #ifdef HAVE_CONFIG_H | |||
28 | #include <pixman-config.h> | |||
29 | #endif | |||
30 | #include "pixman-private.h" | |||
31 | ||||
32 | #include <stdlib.h> | |||
33 | ||||
34 | typedef struct glyph_metrics_t glyph_metrics_t; | |||
35 | typedef struct glyph_t glyph_t; | |||
36 | ||||
37 | #define TOMBSTONE((glyph_t *)0x1) ((glyph_t *)0x1) | |||
38 | ||||
39 | /* XXX: These numbers are arbitrary---we've never done any measurements. | |||
40 | */ | |||
41 | #define N_GLYPHS_HIGH_WATER(16384) (16384) | |||
42 | #define N_GLYPHS_LOW_WATER(8192) (8192) | |||
43 | #define HASH_SIZE(2 * (16384)) (2 * N_GLYPHS_HIGH_WATER(16384)) | |||
44 | #define HASH_MASK((2 * (16384)) - 1) (HASH_SIZE(2 * (16384)) - 1) | |||
45 | ||||
46 | struct glyph_t | |||
47 | { | |||
48 | void * font_key; | |||
49 | void * glyph_key; | |||
50 | int origin_x; | |||
51 | int origin_y; | |||
52 | pixman_image_t * image; | |||
53 | pixman_link_t mru_link; | |||
54 | }; | |||
55 | ||||
56 | struct pixman_glyph_cache_t | |||
57 | { | |||
58 | int n_glyphs; | |||
59 | int n_tombstones; | |||
60 | int freeze_count; | |||
61 | pixman_list_t mru; | |||
62 | glyph_t * glyphs[HASH_SIZE(2 * (16384))]; | |||
63 | }; | |||
64 | ||||
65 | static void | |||
66 | free_glyph (glyph_t *glyph) | |||
67 | { | |||
68 | pixman_list_unlink (&glyph->mru_link); | |||
69 | pixman_image_unref_moz_pixman_image_unref (glyph->image); | |||
70 | free (glyph); | |||
71 | } | |||
72 | ||||
73 | static unsigned int | |||
74 | hash (const void *font_key, const void *glyph_key) | |||
75 | { | |||
76 | size_t key = (size_t)font_key + (size_t)glyph_key; | |||
77 | ||||
78 | /* This hash function is based on one found on Thomas Wang's | |||
79 | * web page at | |||
80 | * | |||
81 | * http://www.concentric.net/~Ttwang/tech/inthash.htm | |||
82 | * | |||
83 | */ | |||
84 | key = (key << 15) - key - 1; | |||
85 | key = key ^ (key >> 12); | |||
86 | key = key + (key << 2); | |||
87 | key = key ^ (key >> 4); | |||
88 | key = key + (key << 3) + (key << 11); | |||
89 | key = key ^ (key >> 16); | |||
90 | ||||
91 | return key; | |||
92 | } | |||
93 | ||||
94 | static glyph_t * | |||
95 | lookup_glyph (pixman_glyph_cache_t *cache, | |||
96 | void *font_key, | |||
97 | void *glyph_key) | |||
98 | { | |||
99 | unsigned idx; | |||
100 | glyph_t *g; | |||
101 | ||||
102 | idx = hash (font_key, glyph_key); | |||
103 | while ((g = cache->glyphs[idx++ & HASH_MASK((2 * (16384)) - 1)])) | |||
104 | { | |||
105 | if (g != TOMBSTONE((glyph_t *)0x1) && | |||
106 | g->font_key == font_key && | |||
107 | g->glyph_key == glyph_key) | |||
108 | { | |||
109 | return g; | |||
110 | } | |||
111 | } | |||
112 | ||||
113 | return NULL((void*)0); | |||
114 | } | |||
115 | ||||
116 | static void | |||
117 | insert_glyph (pixman_glyph_cache_t *cache, | |||
118 | glyph_t *glyph) | |||
119 | { | |||
120 | unsigned idx; | |||
121 | glyph_t **loc; | |||
122 | ||||
123 | idx = hash (glyph->font_key, glyph->glyph_key); | |||
124 | ||||
125 | /* Note: we assume that there is room in the table. If there isn't, | |||
126 | * this will be an infinite loop. | |||
127 | */ | |||
128 | do | |||
129 | { | |||
130 | loc = &cache->glyphs[idx++ & HASH_MASK((2 * (16384)) - 1)]; | |||
131 | } while (*loc && *loc != TOMBSTONE((glyph_t *)0x1)); | |||
132 | ||||
133 | if (*loc == TOMBSTONE((glyph_t *)0x1)) | |||
134 | cache->n_tombstones--; | |||
135 | cache->n_glyphs++; | |||
136 | ||||
137 | *loc = glyph; | |||
138 | } | |||
139 | ||||
140 | static void | |||
141 | remove_glyph (pixman_glyph_cache_t *cache, | |||
142 | glyph_t *glyph) | |||
143 | { | |||
144 | unsigned idx; | |||
145 | ||||
146 | idx = hash (glyph->font_key, glyph->glyph_key); | |||
147 | while (cache->glyphs[idx & HASH_MASK((2 * (16384)) - 1)] != glyph) | |||
148 | idx++; | |||
149 | ||||
150 | cache->glyphs[idx & HASH_MASK((2 * (16384)) - 1)] = TOMBSTONE((glyph_t *)0x1); | |||
151 | cache->n_tombstones++; | |||
152 | cache->n_glyphs--; | |||
153 | ||||
154 | /* Eliminate tombstones if possible */ | |||
155 | if (cache->glyphs[(idx + 1) & HASH_MASK((2 * (16384)) - 1)] == NULL((void*)0)) | |||
156 | { | |||
157 | while (cache->glyphs[idx & HASH_MASK((2 * (16384)) - 1)] == TOMBSTONE((glyph_t *)0x1)) | |||
158 | { | |||
159 | cache->glyphs[idx & HASH_MASK((2 * (16384)) - 1)] = NULL((void*)0); | |||
160 | cache->n_tombstones--; | |||
161 | idx--; | |||
162 | } | |||
163 | } | |||
164 | } | |||
165 | ||||
166 | static void | |||
167 | clear_table (pixman_glyph_cache_t *cache) | |||
168 | { | |||
169 | int i; | |||
170 | ||||
171 | for (i = 0; i < HASH_SIZE(2 * (16384)); ++i) | |||
172 | { | |||
173 | glyph_t *glyph = cache->glyphs[i]; | |||
174 | ||||
175 | if (glyph && glyph != TOMBSTONE((glyph_t *)0x1)) | |||
176 | free_glyph (glyph); | |||
177 | ||||
178 | cache->glyphs[i] = NULL((void*)0); | |||
179 | } | |||
180 | ||||
181 | cache->n_glyphs = 0; | |||
182 | cache->n_tombstones = 0; | |||
183 | } | |||
184 | ||||
185 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) pixman_glyph_cache_t * | |||
186 | pixman_glyph_cache_create_moz_pixman_glyph_cache_create (void) | |||
187 | { | |||
188 | pixman_glyph_cache_t *cache; | |||
189 | ||||
190 | if (!(cache = malloc (sizeof *cache))) | |||
191 | return NULL((void*)0); | |||
192 | ||||
193 | memset (cache->glyphs, 0, sizeof (cache->glyphs)); | |||
194 | cache->n_glyphs = 0; | |||
195 | cache->n_tombstones = 0; | |||
196 | cache->freeze_count = 0; | |||
197 | ||||
198 | pixman_list_init (&cache->mru); | |||
199 | ||||
200 | return cache; | |||
201 | } | |||
202 | ||||
203 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
204 | pixman_glyph_cache_destroy_moz_pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) | |||
205 | { | |||
206 | return_if_fail (cache->freeze_count == 0)do { if (__builtin_expect ((!(cache->freeze_count == 0)), 0 )) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__)) , "The expression " "cache->freeze_count == 0" " was false" ); return; } } while (0); | |||
207 | ||||
208 | clear_table (cache); | |||
209 | ||||
210 | free (cache); | |||
211 | } | |||
212 | ||||
213 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
214 | pixman_glyph_cache_freeze_moz_pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) | |||
215 | { | |||
216 | cache->freeze_count++; | |||
217 | } | |||
218 | ||||
219 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
220 | pixman_glyph_cache_thaw_moz_pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) | |||
221 | { | |||
222 | if (--cache->freeze_count == 0 && | |||
223 | cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER(16384)) | |||
224 | { | |||
225 | if (cache->n_tombstones > N_GLYPHS_HIGH_WATER(16384)) | |||
226 | { | |||
227 | /* More than half the entries are | |||
228 | * tombstones. Just dump the whole table. | |||
229 | */ | |||
230 | clear_table (cache); | |||
231 | } | |||
232 | ||||
233 | while (cache->n_glyphs > N_GLYPHS_LOW_WATER(8192)) | |||
234 | { | |||
235 | glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail)((glyph_t *)(((uint8_t *)cache->mru.tail) - __builtin_offsetof (glyph_t, mru_link))); | |||
236 | ||||
237 | remove_glyph (cache, glyph); | |||
238 | free_glyph (glyph); | |||
239 | } | |||
240 | } | |||
241 | } | |||
242 | ||||
243 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) const void * | |||
244 | pixman_glyph_cache_lookup_moz_pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, | |||
245 | void *font_key, | |||
246 | void *glyph_key) | |||
247 | { | |||
248 | return lookup_glyph (cache, font_key, glyph_key); | |||
249 | } | |||
250 | ||||
251 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) const void * | |||
252 | pixman_glyph_cache_insert_moz_pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, | |||
253 | void *font_key, | |||
254 | void *glyph_key, | |||
255 | int origin_x, | |||
256 | int origin_y, | |||
257 | pixman_image_t *image) | |||
258 | { | |||
259 | glyph_t *glyph; | |||
260 | int32_t width, height; | |||
261 | ||||
262 | return_val_if_fail (cache->freeze_count > 0, NULL)do { if (__builtin_expect ((!(cache->freeze_count > 0)) , 0)) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__ )), "The expression " "cache->freeze_count > 0" " was false" ); return (((void*)0)); } } while (0); | |||
263 | return_val_if_fail (image->type == BITS, NULL)do { if (__builtin_expect ((!(image->type == BITS)), 0)) { _pixman_log_error (((const char*) (__PRETTY_FUNCTION__)), "The expression " "image->type == BITS" " was false"); return (((void*)0)); } } while (0); | |||
264 | ||||
265 | width = image->bits.width; | |||
266 | height = image->bits.height; | |||
267 | ||||
268 | if (cache->n_glyphs >= HASH_SIZE(2 * (16384))) | |||
269 | return NULL((void*)0); | |||
270 | ||||
271 | if (!(glyph = malloc (sizeof *glyph))) | |||
272 | return NULL((void*)0); | |||
273 | ||||
274 | glyph->font_key = font_key; | |||
275 | glyph->glyph_key = glyph_key; | |||
276 | glyph->origin_x = origin_x; | |||
277 | glyph->origin_y = origin_y; | |||
278 | ||||
279 | if (!(glyph->image = pixman_image_create_bits_moz_pixman_image_create_bits ( | |||
280 | image->bits.format, width, height, NULL((void*)0), -1))) | |||
281 | { | |||
282 | free (glyph); | |||
283 | return NULL((void*)0); | |||
284 | } | |||
285 | ||||
286 | pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC, | |||
287 | image, NULL((void*)0), glyph->image, 0, 0, 0, 0, 0, 0, | |||
288 | width, height); | |||
289 | ||||
290 | if (PIXMAN_FORMAT_A (glyph->image->bits.format)(((glyph->image->bits.format >> (12)) & ((1 << (4)) - 1)) << ((glyph->image->bits.format >> 22) & 3)) != 0 && | |||
291 | PIXMAN_FORMAT_RGB (glyph->image->bits.format)(((glyph->image->bits.format) ) & 0xfff) != 0) | |||
292 | { | |||
293 | pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (glyph->image, TRUE1); | |||
294 | } | |||
295 | ||||
296 | pixman_list_prepend (&cache->mru, &glyph->mru_link); | |||
297 | ||||
298 | _pixman_image_validate (glyph->image); | |||
299 | insert_glyph (cache, glyph); | |||
300 | ||||
301 | return glyph; | |||
302 | } | |||
303 | ||||
304 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
305 | pixman_glyph_cache_remove_moz_pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, | |||
306 | void *font_key, | |||
307 | void *glyph_key) | |||
308 | { | |||
309 | glyph_t *glyph; | |||
310 | ||||
311 | if ((glyph = lookup_glyph (cache, font_key, glyph_key))) | |||
312 | { | |||
313 | remove_glyph (cache, glyph); | |||
314 | ||||
315 | free_glyph (glyph); | |||
316 | } | |||
317 | } | |||
318 | ||||
319 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
320 | pixman_glyph_get_extents_moz_pixman_glyph_get_extents (pixman_glyph_cache_t *cache, | |||
321 | int n_glyphs, | |||
322 | pixman_glyph_t *glyphs, | |||
323 | pixman_box32_t *extents) | |||
324 | { | |||
325 | int i; | |||
326 | ||||
327 | extents->x1 = extents->y1 = INT32_MAX(2147483647); | |||
328 | extents->x2 = extents->y2 = INT32_MIN(-2147483647-1); | |||
329 | ||||
330 | for (i = 0; i < n_glyphs; ++i) | |||
331 | { | |||
332 | glyph_t *glyph = (glyph_t *)glyphs[i].glyph; | |||
333 | int x1, y1, x2, y2; | |||
334 | ||||
335 | x1 = glyphs[i].x - glyph->origin_x; | |||
336 | y1 = glyphs[i].y - glyph->origin_y; | |||
337 | x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; | |||
338 | y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; | |||
339 | ||||
340 | if (x1 < extents->x1) | |||
341 | extents->x1 = x1; | |||
342 | if (y1 < extents->y1) | |||
343 | extents->y1 = y1; | |||
344 | if (x2 > extents->x2) | |||
345 | extents->x2 = x2; | |||
346 | if (y2 > extents->y2) | |||
347 | extents->y2 = y2; | |||
348 | } | |||
349 | } | |||
350 | ||||
351 | /* This function returns a format that is suitable for use as a mask for the | |||
352 | * set of glyphs in question. | |||
353 | */ | |||
354 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) pixman_format_code_t | |||
355 | pixman_glyph_get_mask_format_moz_pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, | |||
356 | int n_glyphs, | |||
357 | const pixman_glyph_t *glyphs) | |||
358 | { | |||
359 | pixman_format_code_t format = PIXMAN_a1; | |||
360 | int i; | |||
361 | ||||
362 | for (i = 0; i < n_glyphs; ++i) | |||
363 | { | |||
364 | const glyph_t *glyph = glyphs[i].glyph; | |||
365 | pixman_format_code_t glyph_format = glyph->image->bits.format; | |||
366 | ||||
367 | if (PIXMAN_FORMAT_TYPE (glyph_format)(((glyph_format) >> 16) & 0x3f) == PIXMAN_TYPE_A1) | |||
368 | { | |||
369 | if (PIXMAN_FORMAT_A (glyph_format)(((glyph_format >> (12)) & ((1 << (4)) - 1)) << ((glyph_format >> 22) & 3)) > PIXMAN_FORMAT_A (format)(((format >> (12)) & ((1 << (4)) - 1)) << ((format >> 22) & 3))) | |||
370 | format = glyph_format; | |||
371 | } | |||
372 | else | |||
373 | { | |||
374 | return PIXMAN_a8r8g8b8; | |||
375 | } | |||
376 | } | |||
377 | ||||
378 | return format; | |||
379 | } | |||
380 | ||||
381 | static pixman_bool_t | |||
382 | box32_intersect (pixman_box32_t *dest, | |||
383 | const pixman_box32_t *box1, | |||
384 | const pixman_box32_t *box2) | |||
385 | { | |||
386 | dest->x1 = MAX (box1->x1, box2->x1)((box1->x1 > box2->x1) ? box1->x1 : box2->x1); | |||
387 | dest->y1 = MAX (box1->y1, box2->y1)((box1->y1 > box2->y1) ? box1->y1 : box2->y1); | |||
388 | dest->x2 = MIN (box1->x2, box2->x2)((box1->x2 < box2->x2) ? box1->x2 : box2->x2); | |||
389 | dest->y2 = MIN (box1->y2, box2->y2)((box1->y2 < box2->y2) ? box1->y2 : box2->y2); | |||
390 | ||||
391 | return dest->x2 > dest->x1 && dest->y2 > dest->y1; | |||
392 | } | |||
393 | ||||
394 | #if defined(__GNUC__4) && defined(__i386__) && !defined(__x86_64__1) && \ | |||
395 | !defined(__amd64__1) | |||
396 | __attribute__((__force_align_arg_pointer__)) | |||
397 | #endif | |||
398 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
399 | pixman_composite_glyphs_no_mask_moz_pixman_composite_glyphs_no_mask (pixman_op_t op, | |||
400 | pixman_image_t *src, | |||
401 | pixman_image_t *dest, | |||
402 | int32_t src_x, | |||
403 | int32_t src_y, | |||
404 | int32_t dest_x, | |||
405 | int32_t dest_y, | |||
406 | pixman_glyph_cache_t *cache, | |||
407 | int n_glyphs, | |||
408 | const pixman_glyph_t *glyphs) | |||
409 | { | |||
410 | pixman_region32_t region; | |||
411 | pixman_format_code_t glyph_format = PIXMAN_null(((0) << 24) | ((0) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))); | |||
412 | uint32_t glyph_flags = 0; | |||
413 | pixman_format_code_t dest_format; | |||
414 | uint32_t dest_flags; | |||
415 | pixman_composite_func_t func = NULL((void*)0); | |||
| ||||
416 | pixman_implementation_t *implementation = NULL((void*)0); | |||
417 | pixman_composite_info_t info; | |||
418 | int i; | |||
419 | ||||
420 | _pixman_image_validate (src); | |||
421 | _pixman_image_validate (dest); | |||
422 | ||||
423 | dest_format = dest->common.extended_format_code; | |||
424 | dest_flags = dest->common.flags; | |||
425 | ||||
426 | pixman_region32_init_moz_pixman_region32_init (®ion); | |||
427 | if (!_pixman_compute_composite_region32 ( | |||
428 | ®ion, | |||
429 | src, NULL((void*)0), dest, | |||
430 | src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, | |||
431 | dest->bits.width, dest->bits.height)) | |||
432 | { | |||
433 | goto out; | |||
434 | } | |||
435 | ||||
436 | info.op = op; | |||
437 | info.src_image = src; | |||
438 | info.dest_image = dest; | |||
439 | info.src_flags = src->common.flags; | |||
440 | info.dest_flags = dest->common.flags; | |||
441 | ||||
442 | for (i = 0; i < n_glyphs; ++i) | |||
443 | { | |||
444 | glyph_t *glyph = (glyph_t *)glyphs[i].glyph; | |||
445 | pixman_image_t *glyph_img = glyph->image; | |||
446 | pixman_box32_t glyph_box; | |||
447 | pixman_box32_t *pbox; | |||
448 | uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST(1 << 23); | |||
449 | pixman_box32_t composite_box; | |||
450 | int n; | |||
451 | ||||
452 | glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; | |||
453 | glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; | |||
454 | glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; | |||
455 | glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; | |||
456 | ||||
457 | pbox = pixman_region32_rectangles_moz_pixman_region32_rectangles (®ion, &n); | |||
458 | ||||
459 | info.mask_image = glyph_img; | |||
460 | ||||
461 | while (n--) | |||
462 | { | |||
463 | if (box32_intersect (&composite_box, pbox, &glyph_box)) | |||
464 | { | |||
465 | if (glyph_img->common.extended_format_code != glyph_format || | |||
466 | glyph_img->common.flags != glyph_flags) | |||
467 | { | |||
468 | glyph_format = glyph_img->common.extended_format_code; | |||
469 | glyph_flags = glyph_img->common.flags; | |||
470 | ||||
471 | _pixman_implementation_lookup_composite ( | |||
472 | get_implementation(), op, | |||
473 | src->common.extended_format_code, src->common.flags, | |||
474 | glyph_format, glyph_flags | extra, | |||
475 | dest_format, dest_flags, | |||
476 | &implementation, &func); | |||
477 | } | |||
478 | ||||
479 | info.src_x = src_x + composite_box.x1 - dest_x; | |||
480 | info.src_y = src_y + composite_box.y1 - dest_y; | |||
481 | info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); | |||
482 | info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); | |||
483 | info.dest_x = composite_box.x1; | |||
484 | info.dest_y = composite_box.y1; | |||
485 | info.width = composite_box.x2 - composite_box.x1; | |||
486 | info.height = composite_box.y2 - composite_box.y1; | |||
487 | ||||
488 | info.mask_flags = glyph_flags; | |||
489 | ||||
490 | func (implementation, &info); | |||
| ||||
491 | } | |||
492 | ||||
493 | pbox++; | |||
494 | } | |||
495 | pixman_list_move_to_front (&cache->mru, &glyph->mru_link); | |||
496 | } | |||
497 | ||||
498 | out: | |||
499 | pixman_region32_fini_moz_pixman_region32_fini (®ion); | |||
500 | } | |||
501 | ||||
502 | static void | |||
503 | add_glyphs (pixman_glyph_cache_t *cache, | |||
504 | pixman_image_t *dest, | |||
505 | int off_x, int off_y, | |||
506 | int n_glyphs, const pixman_glyph_t *glyphs) | |||
507 | { | |||
508 | pixman_format_code_t glyph_format = PIXMAN_null(((0) << 24) | ((0) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))); | |||
509 | uint32_t glyph_flags = 0; | |||
510 | pixman_composite_func_t func = NULL((void*)0); | |||
511 | pixman_implementation_t *implementation = NULL((void*)0); | |||
512 | pixman_format_code_t dest_format; | |||
513 | uint32_t dest_flags; | |||
514 | pixman_box32_t dest_box; | |||
515 | pixman_composite_info_t info; | |||
516 | pixman_image_t *white_img = NULL((void*)0); | |||
517 | pixman_bool_t white_src = FALSE0; | |||
518 | int i; | |||
519 | ||||
520 | _pixman_image_validate (dest); | |||
521 | ||||
522 | dest_format = dest->common.extended_format_code; | |||
523 | dest_flags = dest->common.flags; | |||
524 | ||||
525 | info.op = PIXMAN_OP_ADD; | |||
526 | info.dest_image = dest; | |||
527 | info.src_x = 0; | |||
528 | info.src_y = 0; | |||
529 | info.dest_flags = dest_flags; | |||
530 | ||||
531 | dest_box.x1 = 0; | |||
532 | dest_box.y1 = 0; | |||
533 | dest_box.x2 = dest->bits.width; | |||
534 | dest_box.y2 = dest->bits.height; | |||
535 | ||||
536 | for (i = 0; i < n_glyphs; ++i) | |||
537 | { | |||
538 | glyph_t *glyph = (glyph_t *)glyphs[i].glyph; | |||
539 | pixman_image_t *glyph_img = glyph->image; | |||
540 | pixman_box32_t glyph_box; | |||
541 | pixman_box32_t composite_box; | |||
542 | ||||
543 | if (glyph_img->common.extended_format_code != glyph_format || | |||
544 | glyph_img->common.flags != glyph_flags) | |||
545 | { | |||
546 | pixman_format_code_t src_format, mask_format; | |||
547 | ||||
548 | glyph_format = glyph_img->common.extended_format_code; | |||
549 | glyph_flags = glyph_img->common.flags; | |||
550 | ||||
551 | if (glyph_format == dest->bits.format) | |||
552 | { | |||
553 | src_format = glyph_format; | |||
554 | mask_format = PIXMAN_null(((0) << 24) | ((0) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))); | |||
555 | info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST(1 << 23); | |||
556 | info.mask_flags = FAST_PATH_IS_OPAQUE(1 << 13); | |||
557 | info.mask_image = NULL((void*)0); | |||
558 | white_src = FALSE0; | |||
559 | } | |||
560 | else | |||
561 | { | |||
562 | if (!white_img) | |||
563 | { | |||
564 | static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; | |||
565 | ||||
566 | if (!(white_img = pixman_image_create_solid_fill_moz_pixman_image_create_solid_fill (&white))) | |||
567 | goto out; | |||
568 | ||||
569 | _pixman_image_validate (white_img); | |||
570 | } | |||
571 | ||||
572 | src_format = PIXMAN_solid(((0) << 24) | ((1) << 16) | ((0) << 12) | ( (0) << 8) | ((0) << 4) | ((0))); | |||
573 | mask_format = glyph_format; | |||
574 | info.src_flags = white_img->common.flags; | |||
575 | info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST(1 << 23); | |||
576 | info.src_image = white_img; | |||
577 | white_src = TRUE1; | |||
578 | } | |||
579 | ||||
580 | _pixman_implementation_lookup_composite ( | |||
581 | get_implementation(), PIXMAN_OP_ADD, | |||
582 | src_format, info.src_flags, | |||
583 | mask_format, info.mask_flags, | |||
584 | dest_format, dest_flags, | |||
585 | &implementation, &func); | |||
586 | } | |||
587 | ||||
588 | glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; | |||
589 | glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; | |||
590 | glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; | |||
591 | glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; | |||
592 | ||||
593 | if (box32_intersect (&composite_box, &glyph_box, &dest_box)) | |||
594 | { | |||
595 | int src_x = composite_box.x1 - glyph_box.x1; | |||
596 | int src_y = composite_box.y1 - glyph_box.y1; | |||
597 | ||||
598 | if (white_src) | |||
599 | info.mask_image = glyph_img; | |||
600 | else | |||
601 | info.src_image = glyph_img; | |||
602 | ||||
603 | info.mask_x = info.src_x = src_x; | |||
604 | info.mask_y = info.src_y = src_y; | |||
605 | info.dest_x = composite_box.x1; | |||
606 | info.dest_y = composite_box.y1; | |||
607 | info.width = composite_box.x2 - composite_box.x1; | |||
608 | info.height = composite_box.y2 - composite_box.y1; | |||
609 | ||||
610 | func (implementation, &info); | |||
611 | ||||
612 | pixman_list_move_to_front (&cache->mru, &glyph->mru_link); | |||
613 | } | |||
614 | } | |||
615 | ||||
616 | out: | |||
617 | if (white_img) | |||
618 | pixman_image_unref_moz_pixman_image_unref (white_img); | |||
619 | } | |||
620 | ||||
621 | /* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an | |||
622 | * infinitely big mask image at the position such that the glyph origin point | |||
623 | * is positioned at the (glyphs[i].x, glyphs[i].y) point. | |||
624 | * | |||
625 | * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source | |||
626 | * image are both aligned with (dest_x, dest_y) in the destination image. Then | |||
627 | * these three images are composited within the | |||
628 | * | |||
629 | * (dest_x, dest_y, dst_x + width, dst_y + height) | |||
630 | * | |||
631 | * rectangle. | |||
632 | * | |||
633 | * TODO: | |||
634 | * - Trim the mask to the destination clip/image? | |||
635 | * - Trim composite region based on sources, when the op ignores 0s. | |||
636 | */ | |||
637 | #if defined(__GNUC__4) && !defined(__x86_64__1) && !defined(__amd64__1) | |||
638 | __attribute__((__force_align_arg_pointer__)) | |||
639 | #endif | |||
640 | PIXMAN_EXPORTextern __attribute__((visibility("hidden"))) void | |||
641 | pixman_composite_glyphs_moz_pixman_composite_glyphs (pixman_op_t op, | |||
642 | pixman_image_t *src, | |||
643 | pixman_image_t *dest, | |||
644 | pixman_format_code_t mask_format, | |||
645 | int32_t src_x, | |||
646 | int32_t src_y, | |||
647 | int32_t mask_x, | |||
648 | int32_t mask_y, | |||
649 | int32_t dest_x, | |||
650 | int32_t dest_y, | |||
651 | int32_t width, | |||
652 | int32_t height, | |||
653 | pixman_glyph_cache_t *cache, | |||
654 | int n_glyphs, | |||
655 | const pixman_glyph_t *glyphs) | |||
656 | { | |||
657 | pixman_image_t *mask; | |||
658 | ||||
659 | if (!(mask = pixman_image_create_bits_moz_pixman_image_create_bits (mask_format, width, height, NULL((void*)0), -1))) | |||
660 | return; | |||
661 | ||||
662 | if (PIXMAN_FORMAT_A (mask_format)(((mask_format >> (12)) & ((1 << (4)) - 1)) << ((mask_format >> 22) & 3)) != 0 && | |||
663 | PIXMAN_FORMAT_RGB (mask_format)(((mask_format) ) & 0xfff) != 0) | |||
664 | { | |||
665 | pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (mask, TRUE1); | |||
666 | } | |||
667 | ||||
668 | add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); | |||
669 | ||||
670 | pixman_image_composite32_moz_pixman_image_composite32 (op, src, mask, dest, | |||
671 | src_x, src_y, | |||
672 | 0, 0, | |||
673 | dest_x, dest_y, | |||
674 | width, height); | |||
675 | ||||
676 | pixman_image_unref_moz_pixman_image_unref (mask); | |||
677 | } |