11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright 2010, 2012, Soren Sandmann <sandmann@cs.au.dk> 31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright 2010, 2011, 2012, Red Hat, Inc 41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission is hereby granted, free of charge, to any person obtaining a 61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copy of this software and associated documentation files (the "Software"), 71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to deal in the Software without restriction, including without limitation 81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the rights to use, copy, modify, merge, publish, distribute, sublicense, 91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * and/or sell copies of the Software, and to permit persons to whom the 101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software is furnished to do so, subject to the following conditions: 111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The above copyright notice and this permission notice (including the next 131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * paragraph) shall be included in all copies or substantial portions of the 141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software. 151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * DEALINGS IN THE SOFTWARE. 231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Author: Soren Sandmann <sandmann@cs.au.dk> 251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef HAVE_CONFIG_H 281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <config.h> 291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "pixman-private.h" 311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <stdlib.h> 331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 341176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef struct glyph_metrics_t glyph_metrics_t; 351176bdada62cabc6ec4b0308a930e83b679d5d36John Recktypedef struct glyph_t glyph_t; 361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define TOMBSTONE ((glyph_t *)0x1) 381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* XXX: These numbers are arbitrary---we've never done any measurements. 401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define N_GLYPHS_HIGH_WATER (16384) 421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define N_GLYPHS_LOW_WATER (8192) 431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER) 441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#define HASH_MASK (HASH_SIZE - 1) 451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 461176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstruct glyph_t 471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void * font_key; 491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void * glyph_key; 501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int origin_x; 511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int origin_y; 521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t * image; 531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_link_t mru_link; 541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}; 551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 561176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstruct pixman_glyph_cache_t 571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs; 591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_tombstones; 601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int freeze_count; 611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_t mru; 621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t * glyphs[HASH_SIZE]; 631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck}; 641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 651176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void 661176bdada62cabc6ec4b0308a930e83b679d5d36John Reckfree_glyph (glyph_t *glyph) 671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_unlink (&glyph->mru_link); 691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_unref (glyph->image); 701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free (glyph); 711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 731176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic unsigned int 741176bdada62cabc6ec4b0308a930e83b679d5d36John Reckhash (const void *font_key, const void *glyph_key) 751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck size_t key = (size_t)font_key + (size_t)glyph_key; 771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* This hash function is based on one found on Thomas Wang's 791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * web page at 801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * http://www.concentric.net/~Ttwang/tech/inthash.htm 821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = (key << 15) - key - 1; 851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = key ^ (key >> 12); 861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = key + (key << 2); 871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = key ^ (key >> 4); 881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = key + (key << 3) + (key << 11); 891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck key = key ^ (key >> 16); 901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return key; 921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 941176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic glyph_t * 951176bdada62cabc6ec4b0308a930e83b679d5d36John Recklookup_glyph (pixman_glyph_cache_t *cache, 961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *font_key, 971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *glyph_key) 981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unsigned idx; 1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *g; 1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck idx = hash (font_key, glyph_key); 1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while ((g = cache->glyphs[idx++ & HASH_MASK])) 1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (g != TOMBSTONE && 1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck g->font_key == font_key && 1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck g->glyph_key == glyph_key) 1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return g; 1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void 1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reckinsert_glyph (pixman_glyph_cache_t *cache, 1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph) 1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unsigned idx; 1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t **loc; 1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck idx = hash (glyph->font_key, glyph->glyph_key); 1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* Note: we assume that there is room in the table. If there isn't, 1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * this will be an infinite loop. 1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck do 1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck loc = &cache->glyphs[idx++ & HASH_MASK]; 1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } while (*loc && *loc != TOMBSTONE); 1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (*loc == TOMBSTONE) 1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_tombstones--; 1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_glyphs++; 1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *loc = glyph; 1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void 1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reckremove_glyph (pixman_glyph_cache_t *cache, 1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph) 1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck unsigned idx; 1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck idx = hash (glyph->font_key, glyph->glyph_key); 1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (cache->glyphs[idx & HASH_MASK] != glyph) 1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck idx++; 1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->glyphs[idx & HASH_MASK] = TOMBSTONE; 1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_tombstones++; 1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_glyphs--; 1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* Eliminate tombstones if possible */ 1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL) 1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE) 1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->glyphs[idx & HASH_MASK] = NULL; 1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_tombstones--; 1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck idx--; 1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void 1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reckclear_table (pixman_glyph_cache_t *cache) 1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < HASH_SIZE; ++i) 1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph = cache->glyphs[i]; 1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (glyph && glyph != TOMBSTONE) 1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free_glyph (glyph); 1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->glyphs[i] = NULL; 1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_glyphs = 0; 1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_tombstones = 0; 1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1851176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_glyph_cache_t * 1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_create (void) 1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_glyph_cache_t *cache; 1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!(cache = malloc (sizeof *cache))) 1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck memset (cache->glyphs, 0, sizeof (cache->glyphs)); 1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_glyphs = 0; 1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_tombstones = 0; 1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->freeze_count = 0; 1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_init (&cache->mru); 1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return cache; 2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2031176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) 2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return_if_fail (cache->freeze_count == 0); 2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck clear_table (cache); 2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free (cache); 2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2131176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) 2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->freeze_count++; 2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2191176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) 2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (--cache->freeze_count == 0 && 2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER) 2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (cache->n_tombstones > N_GLYPHS_HIGH_WATER) 2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* More than half the entries are 2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * tombstones. Just dump the whole table. 2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck clear_table (cache); 2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (cache->n_glyphs > N_GLYPHS_LOW_WATER) 2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail); 2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck remove_glyph (cache, glyph); 2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free_glyph (glyph); 2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2431176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT const void * 2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, 2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *font_key, 2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *glyph_key) 2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return lookup_glyph (cache, font_key, glyph_key); 2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2511176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT const void * 2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_insert (pixman_glyph_cache_t *cache, 2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *font_key, 2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *glyph_key, 2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int origin_x, 2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int origin_y, 2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *image) 2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph; 2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t width, height; 2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return_val_if_fail (cache->freeze_count > 0, NULL); 2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return_val_if_fail (image->type == BITS, NULL); 2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck width = image->bits.width; 2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck height = image->bits.height; 2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (cache->n_glyphs >= HASH_SIZE) 2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!(glyph = malloc (sizeof *glyph))) 2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph->font_key = font_key; 2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph->glyph_key = glyph_key; 2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph->origin_x = origin_x; 2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph->origin_y = origin_y; 2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!(glyph->image = pixman_image_create_bits ( 2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image->bits.format, width, height, NULL, -1))) 2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free (glyph); 2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return NULL; 2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_composite32 (PIXMAN_OP_SRC, 2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck image, NULL, glyph->image, 0, 0, 0, 0, 0, 0, 2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck width, height); 2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 && 2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0) 2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_set_component_alpha (glyph->image, TRUE); 2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_prepend (&cache->mru, &glyph->mru_link); 2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_image_validate (glyph->image); 2991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck insert_glyph (cache, glyph); 3001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return glyph; 3021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 3031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3041176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 3051176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_cache_remove (pixman_glyph_cache_t *cache, 3061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *font_key, 3071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *glyph_key) 3081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 3091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph; 3101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((glyph = lookup_glyph (cache, font_key, glyph_key))) 3121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck remove_glyph (cache, glyph); 3141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck free_glyph (glyph); 3161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 3181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3191176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 3201176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_get_extents (pixman_glyph_cache_t *cache, 3211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs, 3221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_glyph_t *glyphs, 3231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t *extents) 3241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 3251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 3261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->x1 = extents->y1 = INT32_MAX; 3281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->x2 = extents->y2 = INT32_MIN; 3291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < n_glyphs; ++i) 3311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 3331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int x1, y1, x2, y2; 3341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x1 = glyphs[i].x - glyph->origin_x; 3361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck y1 = glyphs[i].y - glyph->origin_y; 3371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; 3381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; 3391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (x1 < extents->x1) 3411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->x1 = x1; 3421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (y1 < extents->y1) 3431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->y1 = y1; 3441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (x2 > extents->x2) 3451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->x2 = x2; 3461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (y2 > extents->y2) 3471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck extents->y2 = y2; 3481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 3501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* This function returns a format that is suitable for use as a mask for the 3521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * set of glyphs in question. 3531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 3541176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT pixman_format_code_t 3551176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, 3561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs, 3571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_glyph_t *glyphs) 3581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 3591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t format = PIXMAN_a1; 3601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 3611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < n_glyphs; ++i) 3631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const glyph_t *glyph = glyphs[i].glyph; 3651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t glyph_format = glyph->image->bits.format; 3661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A) 3681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format)) 3701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck format = glyph_format; 3711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 3731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 3741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return PIXMAN_a8r8g8b8; 3751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 3771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return format; 3791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 3801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3811176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic pixman_bool_t 3821176bdada62cabc6ec4b0308a930e83b679d5d36John Reckbox32_intersect (pixman_box32_t *dest, 3831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_box32_t *box1, 3841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_box32_t *box2) 3851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 3861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest->x1 = MAX (box1->x1, box2->x1); 3871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest->y1 = MAX (box1->y1, box2->y1); 3881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest->x2 = MIN (box1->x2, box2->x2); 3891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest->y2 = MIN (box1->y2, box2->y2); 3901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return dest->x2 > dest->x1 && dest->y2 > dest->y1; 3921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 3931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3941176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 3951176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_composite_glyphs_no_mask (pixman_op_t op, 3961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *src, 3971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *dest, 3981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t src_x, 3991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t src_y, 4001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t dest_x, 4011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t dest_y, 4021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_glyph_cache_t *cache, 4031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs, 4041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_glyph_t *glyphs) 4051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 4061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_region32_t region; 4071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t glyph_format = PIXMAN_null; 4081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t glyph_flags = 0; 4091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t dest_format; 4101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t dest_flags; 4111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_composite_func_t func = NULL; 4121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_implementation_t *implementation = NULL; 4131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_composite_info_t info; 4141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 4151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_image_validate (src); 4171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_image_validate (dest); 4181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_format = dest->common.extended_format_code; 4201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_flags = dest->common.flags; 4211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_region32_init (®ion); 4231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!_pixman_compute_composite_region32 ( 4241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck ®ion, 4251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src, NULL, dest, 4261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, 4271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest->bits.width, dest->bits.height)) 4281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck goto out; 4301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.op = op; 4331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_image = src; 4341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_image = dest; 4351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_flags = src->common.flags; 4361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_flags = dest->common.flags; 4371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < n_glyphs; ++i) 4391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 4411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *glyph_img = glyph->image; 4421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t glyph_box; 4431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t *pbox; 4441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 4451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t composite_box; 4461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n; 4471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; 4491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; 4501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; 4511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; 4521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pbox = pixman_region32_rectangles (®ion, &n); 4541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_image = glyph_img; 4561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (n--) 4581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (box32_intersect (&composite_box, pbox, &glyph_box)) 4601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (glyph_img->common.extended_format_code != glyph_format || 4621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_img->common.flags != glyph_flags) 4631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 4641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_format = glyph_img->common.extended_format_code; 4651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_flags = glyph_img->common.flags; 4661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_implementation_lookup_composite ( 4681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck get_implementation(), op, 4691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src->common.extended_format_code, src->common.flags, 4701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_format, glyph_flags | extra, 4711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_format, dest_flags, 4721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &implementation, &func); 4731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_x = src_x + composite_box.x1 - dest_x; 4761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_y = src_y + composite_box.y1 - dest_y; 4771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); 4781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); 4791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_x = composite_box.x1; 4801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_y = composite_box.y1; 4811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.width = composite_box.x2 - composite_box.x1; 4821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.height = composite_box.y2 - composite_box.y1; 4831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_flags = glyph_flags; 4851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck func (implementation, &info); 4871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pbox++; 4901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_move_to_front (&cache->mru, &glyph->mru_link); 4921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 4931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4941176bdada62cabc6ec4b0308a930e83b679d5d36John Reckout: 4951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_region32_fini (®ion); 4961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 4971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 4981176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic void 4991176bdada62cabc6ec4b0308a930e83b679d5d36John Reckadd_glyphs (pixman_glyph_cache_t *cache, 5001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *dest, 5011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int off_x, int off_y, 5021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs, const pixman_glyph_t *glyphs) 5031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 5041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t glyph_format = PIXMAN_null; 5051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t glyph_flags = 0; 5061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_composite_func_t func = NULL; 5071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_implementation_t *implementation = NULL; 5081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t dest_format; 5091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t dest_flags; 5101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t dest_box; 5111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_composite_info_t info; 5121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *white_img = NULL; 5131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_bool_t white_src = FALSE; 5141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 5151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_image_validate (dest); 5171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_format = dest->common.extended_format_code; 5191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_flags = dest->common.flags; 5201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.op = PIXMAN_OP_ADD; 5221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_image = dest; 5231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_x = 0; 5241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_y = 0; 5251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_flags = dest_flags; 5261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_box.x1 = 0; 5281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_box.y1 = 0; 5291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_box.x2 = dest->bits.width; 5301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_box.y2 = dest->bits.height; 5311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < n_glyphs; ++i) 5331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_t *glyph = (glyph_t *)glyphs[i].glyph; 5351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *glyph_img = glyph->image; 5361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t glyph_box; 5371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_box32_t composite_box; 5381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (glyph_img->common.extended_format_code != glyph_format || 5401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_img->common.flags != glyph_flags) 5411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t src_format, mask_format; 5431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_format = glyph_img->common.extended_format_code; 5451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_flags = glyph_img->common.flags; 5461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (glyph_format == dest->bits.format) 5481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src_format = glyph_format; 5501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_format = PIXMAN_null; 5511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 5521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_flags = FAST_PATH_IS_OPAQUE; 5531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_image = NULL; 5541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck white_src = FALSE; 5551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 5561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 5571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!white_img) 5591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; 5611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!(white_img = pixman_image_create_solid_fill (&white))) 5631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck goto out; 5641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_image_validate (white_img); 5661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 5671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src_format = PIXMAN_solid; 5691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_format = glyph_format; 5701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_flags = white_img->common.flags; 5711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; 5721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_image = white_img; 5731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck white_src = TRUE; 5741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 5751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _pixman_implementation_lookup_composite ( 5771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck get_implementation(), PIXMAN_OP_ADD, 5781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src_format, info.src_flags, 5791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_format, info.mask_flags, 5801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_format, dest_flags, 5811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck &implementation, &func); 5821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 5831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; 5851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; 5861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; 5871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; 5881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (box32_intersect (&composite_box, &glyph_box, &dest_box)) 5901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 5911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int src_x = composite_box.x1 - glyph_box.x1; 5921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int src_y = composite_box.y1 - glyph_box.y1; 5931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (white_src) 5951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_image = glyph_img; 5961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 5971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.src_image = glyph_img; 5981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 5991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_x = info.src_x = src_x; 6001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.mask_y = info.src_y = src_y; 6011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_x = composite_box.x1; 6021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.dest_y = composite_box.y1; 6031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.width = composite_box.x2 - composite_box.x1; 6041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck info.height = composite_box.y2 - composite_box.y1; 6051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck func (implementation, &info); 6071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_list_move_to_front (&cache->mru, &glyph->mru_link); 6091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 6101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 6111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6121176bdada62cabc6ec4b0308a930e83b679d5d36John Reckout: 6131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (white_img) 6141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_unref (white_img); 6151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 6161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an 6181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * infinitely big mask image at the position such that the glyph origin point 6191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * is positioned at the (glyphs[i].x, glyphs[i].y) point. 6201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 6211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source 6221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * image are both aligned with (dest_x, dest_y) in the destination image. Then 6231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * these three images are composited within the 6241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 6251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * (dest_x, dest_y, dst_x + width, dst_y + height) 6261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 6271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * rectangle. 6281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 6291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * TODO: 6301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * - Trim the mask to the destination clip/image? 6311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * - Trim composite region based on sources, when the op ignores 0s. 6321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 6331176bdada62cabc6ec4b0308a930e83b679d5d36John ReckPIXMAN_EXPORT void 6341176bdada62cabc6ec4b0308a930e83b679d5d36John Reckpixman_composite_glyphs (pixman_op_t op, 6351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *src, 6361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *dest, 6371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_format_code_t mask_format, 6381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t src_x, 6391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t src_y, 6401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t mask_x, 6411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t mask_y, 6421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t dest_x, 6431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t dest_y, 6441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t width, 6451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t height, 6461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_glyph_cache_t *cache, 6471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int n_glyphs, 6481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const pixman_glyph_t *glyphs) 6491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 6501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_t *mask; 6511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1))) 6531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return; 6541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (PIXMAN_FORMAT_A (mask_format) != 0 && 6561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PIXMAN_FORMAT_RGB (mask_format) != 0) 6571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 6581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_set_component_alpha (mask, TRUE); 6591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 6601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); 6621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_composite32 (op, src, mask, dest, 6641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck src_x, src_y, 6651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0, 0, 6661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck dest_x, dest_y, 6671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck width, height); 6681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 6691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck pixman_image_unref (mask); 6701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 671