LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-glyph.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 266 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <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)
      38             : 
      39             : /* XXX: These numbers are arbitrary---we've never done any measurements.
      40             :  */
      41             : #define N_GLYPHS_HIGH_WATER  (16384)
      42             : #define N_GLYPHS_LOW_WATER   (8192)
      43             : #define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER)
      44             : #define HASH_MASK (HASH_SIZE - 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];
      63             : };
      64             : 
      65             : static void
      66           0 : free_glyph (glyph_t *glyph)
      67             : {
      68           0 :     pixman_list_unlink (&glyph->mru_link);
      69           0 :     pixman_image_unref (glyph->image);
      70           0 :     free (glyph);
      71           0 : }
      72             : 
      73             : static unsigned int
      74           0 : hash (const void *font_key, const void *glyph_key)
      75             : {
      76           0 :     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           0 :     key = (key << 15) - key - 1;
      85           0 :     key = key ^ (key >> 12);
      86           0 :     key = key + (key << 2);
      87           0 :     key = key ^ (key >> 4);
      88           0 :     key = key + (key << 3) + (key << 11);
      89           0 :     key = key ^ (key >> 16);
      90             : 
      91           0 :     return key;
      92             : }
      93             : 
      94             : static glyph_t *
      95           0 : 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           0 :     idx = hash (font_key, glyph_key);
     103           0 :     while ((g = cache->glyphs[idx++ & HASH_MASK]))
     104             :     {
     105           0 :         if (g != TOMBSTONE                      &&
     106           0 :             g->font_key == font_key          &&
     107           0 :             g->glyph_key == glyph_key)
     108             :         {
     109           0 :             return g;
     110             :         }
     111             :     }
     112             : 
     113           0 :     return NULL;
     114             : }
     115             : 
     116             : static void
     117           0 : insert_glyph (pixman_glyph_cache_t *cache,
     118             :               glyph_t              *glyph)
     119             : {
     120             :     unsigned idx;
     121             :     glyph_t **loc;
     122             : 
     123           0 :     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           0 :         loc = &cache->glyphs[idx++ & HASH_MASK];
     131           0 :     } while (*loc && *loc != TOMBSTONE);
     132             : 
     133           0 :     if (*loc == TOMBSTONE)
     134           0 :         cache->n_tombstones--;
     135           0 :     cache->n_glyphs++;
     136             : 
     137           0 :     *loc = glyph;
     138           0 : }
     139             : 
     140             : static void
     141           0 : remove_glyph (pixman_glyph_cache_t *cache,
     142             :               glyph_t              *glyph)
     143             : {
     144             :     unsigned idx;
     145             : 
     146           0 :     idx = hash (glyph->font_key, glyph->glyph_key);
     147           0 :     while (cache->glyphs[idx & HASH_MASK] != glyph)
     148           0 :         idx++;
     149             : 
     150           0 :     cache->glyphs[idx & HASH_MASK] = TOMBSTONE;
     151           0 :     cache->n_tombstones++;
     152           0 :     cache->n_glyphs--;
     153             : 
     154             :     /* Eliminate tombstones if possible */
     155           0 :     if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL)
     156             :     {
     157           0 :         while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE)
     158             :         {
     159           0 :             cache->glyphs[idx & HASH_MASK] = NULL;
     160           0 :             cache->n_tombstones--;
     161           0 :             idx--;
     162             :         }
     163             :     }
     164           0 : }
     165             : 
     166             : static void
     167           0 : clear_table (pixman_glyph_cache_t *cache)
     168             : {
     169             :     int i;
     170             : 
     171           0 :     for (i = 0; i < HASH_SIZE; ++i)
     172             :     {
     173           0 :         glyph_t *glyph = cache->glyphs[i];
     174             : 
     175           0 :         if (glyph && glyph != TOMBSTONE)
     176           0 :             free_glyph (glyph);
     177             : 
     178           0 :         cache->glyphs[i] = NULL;
     179             :     }
     180             : 
     181           0 :     cache->n_glyphs = 0;
     182           0 :     cache->n_tombstones = 0;
     183           0 : }
     184             : 
     185             : PIXMAN_EXPORT pixman_glyph_cache_t *
     186           0 : pixman_glyph_cache_create (void)
     187             : {
     188             :     pixman_glyph_cache_t *cache;
     189             : 
     190           0 :     if (!(cache = malloc (sizeof *cache)))
     191           0 :         return NULL;
     192             : 
     193           0 :     memset (cache->glyphs, 0, sizeof (cache->glyphs));
     194           0 :     cache->n_glyphs = 0;
     195           0 :     cache->n_tombstones = 0;
     196           0 :     cache->freeze_count = 0;
     197             : 
     198           0 :     pixman_list_init (&cache->mru);
     199             : 
     200           0 :     return cache;
     201             : }
     202             : 
     203             : PIXMAN_EXPORT void
     204           0 : pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache)
     205             : {
     206           0 :     return_if_fail (cache->freeze_count == 0);
     207             : 
     208           0 :     clear_table (cache);
     209             : 
     210           0 :     free (cache);
     211             : }
     212             : 
     213             : PIXMAN_EXPORT void
     214           0 : pixman_glyph_cache_freeze (pixman_glyph_cache_t  *cache)
     215             : {
     216           0 :     cache->freeze_count++;
     217           0 : }
     218             : 
     219             : PIXMAN_EXPORT void
     220           0 : pixman_glyph_cache_thaw (pixman_glyph_cache_t  *cache)
     221             : {
     222           0 :     if (--cache->freeze_count == 0                                   &&
     223           0 :         cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER)
     224             :     {
     225           0 :         if (cache->n_tombstones > N_GLYPHS_HIGH_WATER)
     226             :         {
     227             :             /* More than half the entries are
     228             :              * tombstones. Just dump the whole table.
     229             :              */
     230           0 :             clear_table (cache);
     231             :         }
     232             : 
     233           0 :         while (cache->n_glyphs > N_GLYPHS_LOW_WATER)
     234             :         {
     235           0 :             glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail);
     236             : 
     237           0 :             remove_glyph (cache, glyph);
     238           0 :             free_glyph (glyph);
     239             :         }
     240             :     }
     241           0 : }
     242             : 
     243             : PIXMAN_EXPORT const void *
     244           0 : pixman_glyph_cache_lookup (pixman_glyph_cache_t  *cache,
     245             :                            void                  *font_key,
     246             :                            void                  *glyph_key)
     247             : {
     248           0 :     return lookup_glyph (cache, font_key, glyph_key);
     249             : }
     250             : 
     251             : PIXMAN_EXPORT const void *
     252           0 : 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           0 :     return_val_if_fail (cache->freeze_count > 0, NULL);
     263           0 :     return_val_if_fail (image->type == BITS, NULL);
     264             : 
     265           0 :     width = image->bits.width;
     266           0 :     height = image->bits.height;
     267             : 
     268           0 :     if (cache->n_glyphs >= HASH_SIZE)
     269           0 :         return NULL;
     270             : 
     271           0 :     if (!(glyph = malloc (sizeof *glyph)))
     272           0 :         return NULL;
     273             : 
     274           0 :     glyph->font_key = font_key;
     275           0 :     glyph->glyph_key = glyph_key;
     276           0 :     glyph->origin_x = origin_x;
     277           0 :     glyph->origin_y = origin_y;
     278             : 
     279           0 :     if (!(glyph->image = pixman_image_create_bits (
     280             :               image->bits.format, width, height, NULL, -1)))
     281             :     {
     282           0 :         free (glyph);
     283           0 :         return NULL;
     284             :     }
     285             : 
     286           0 :     pixman_image_composite32 (PIXMAN_OP_SRC,
     287             :                               image, NULL, glyph->image, 0, 0, 0, 0, 0, 0,
     288             :                               width, height);
     289             : 
     290           0 :     if (PIXMAN_FORMAT_A   (glyph->image->bits.format) != 0        &&
     291           0 :         PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0)
     292             :     {
     293           0 :         pixman_image_set_component_alpha (glyph->image, TRUE);
     294             :     }
     295             : 
     296           0 :     pixman_list_prepend (&cache->mru, &glyph->mru_link);
     297             : 
     298           0 :     _pixman_image_validate (glyph->image);
     299           0 :     insert_glyph (cache, glyph);
     300             : 
     301           0 :     return glyph;
     302             : }
     303             : 
     304             : PIXMAN_EXPORT void
     305           0 : pixman_glyph_cache_remove (pixman_glyph_cache_t  *cache,
     306             :                            void                  *font_key,
     307             :                            void                  *glyph_key)
     308             : {
     309             :     glyph_t *glyph;
     310             : 
     311           0 :     if ((glyph = lookup_glyph (cache, font_key, glyph_key)))
     312             :     {
     313           0 :         remove_glyph (cache, glyph);
     314             : 
     315           0 :         free_glyph (glyph);
     316             :     }
     317           0 : }
     318             : 
     319             : PIXMAN_EXPORT void
     320           0 : 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           0 :     extents->x1 = extents->y1 = INT32_MAX;
     328           0 :     extents->x2 = extents->y2 = INT32_MIN;
     329             : 
     330           0 :     for (i = 0; i < n_glyphs; ++i)
     331             :     {
     332           0 :         glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
     333             :         int x1, y1, x2, y2;
     334             : 
     335           0 :         x1 = glyphs[i].x - glyph->origin_x;
     336           0 :         y1 = glyphs[i].y - glyph->origin_y;
     337           0 :         x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width;
     338           0 :         y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height;
     339             : 
     340           0 :         if (x1 < extents->x1)
     341           0 :             extents->x1 = x1;
     342           0 :         if (y1 < extents->y1)
     343           0 :             extents->y1 = y1;
     344           0 :         if (x2 > extents->x2)
     345           0 :             extents->x2 = x2;
     346           0 :         if (y2 > extents->y2)
     347           0 :             extents->y2 = y2;
     348             :     }
     349           0 : }
     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_EXPORT pixman_format_code_t
     355           0 : pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache,
     356             :                               int                   n_glyphs,
     357             :                               const pixman_glyph_t *glyphs)
     358             : {
     359           0 :     pixman_format_code_t format = PIXMAN_a1;
     360             :     int i;
     361             : 
     362           0 :     for (i = 0; i < n_glyphs; ++i)
     363             :     {
     364           0 :         const glyph_t *glyph = glyphs[i].glyph;
     365           0 :         pixman_format_code_t glyph_format = glyph->image->bits.format;
     366             : 
     367           0 :         if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A)
     368             :         {
     369           0 :             if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format))
     370           0 :                 format = glyph_format;
     371             :         }
     372             :         else
     373             :         {
     374           0 :             return PIXMAN_a8r8g8b8;
     375             :         }
     376             :     }
     377             : 
     378           0 :     return format;
     379             : }
     380             : 
     381             : static pixman_bool_t
     382           0 : box32_intersect (pixman_box32_t *dest,
     383             :                  const pixman_box32_t *box1,
     384             :                  const pixman_box32_t *box2)
     385             : {
     386           0 :     dest->x1 = MAX (box1->x1, box2->x1);
     387           0 :     dest->y1 = MAX (box1->y1, box2->y1);
     388           0 :     dest->x2 = MIN (box1->x2, box2->x2);
     389           0 :     dest->y2 = MIN (box1->y2, box2->y2);
     390             : 
     391           0 :     return dest->x2 > dest->x1 && dest->y2 > dest->y1;
     392             : }
     393             : 
     394             : PIXMAN_EXPORT void
     395           0 : pixman_composite_glyphs_no_mask (pixman_op_t            op,
     396             :                                  pixman_image_t        *src,
     397             :                                  pixman_image_t        *dest,
     398             :                                  int32_t                src_x,
     399             :                                  int32_t                src_y,
     400             :                                  int32_t                dest_x,
     401             :                                  int32_t                dest_y,
     402             :                                  pixman_glyph_cache_t  *cache,
     403             :                                  int                    n_glyphs,
     404             :                                  const pixman_glyph_t  *glyphs)
     405             : {
     406             :     pixman_region32_t region;
     407           0 :     pixman_format_code_t glyph_format = PIXMAN_null;
     408           0 :     uint32_t glyph_flags = 0;
     409             :     pixman_format_code_t dest_format;
     410             :     uint32_t dest_flags;
     411           0 :     pixman_composite_func_t func = NULL;
     412           0 :     pixman_implementation_t *implementation = NULL;
     413             :     pixman_composite_info_t info;
     414             :     int i;
     415             : 
     416           0 :     _pixman_image_validate (src);
     417           0 :     _pixman_image_validate (dest);
     418             :     
     419           0 :     dest_format = dest->common.extended_format_code;
     420           0 :     dest_flags = dest->common.flags;
     421             :     
     422           0 :     pixman_region32_init (&region);
     423           0 :     if (!_pixman_compute_composite_region32 (
     424             :             &region,
     425             :             src, NULL, dest,
     426             :             src_x - dest_x, src_y - dest_y, 0, 0, 0, 0,
     427             :             dest->bits.width, dest->bits.height))
     428             :     {
     429           0 :         goto out;
     430             :     }
     431             : 
     432           0 :     info.op = op;
     433           0 :     info.src_image = src;
     434           0 :     info.dest_image = dest;
     435           0 :     info.src_flags = src->common.flags;
     436           0 :     info.dest_flags = dest->common.flags;
     437             : 
     438           0 :     for (i = 0; i < n_glyphs; ++i)
     439             :     {
     440           0 :         glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
     441           0 :         pixman_image_t *glyph_img = glyph->image;
     442             :         pixman_box32_t glyph_box;
     443             :         pixman_box32_t *pbox;
     444           0 :         uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
     445             :         pixman_box32_t composite_box;
     446             :         int n;
     447             : 
     448           0 :         glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x;
     449           0 :         glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y;
     450           0 :         glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
     451           0 :         glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
     452             :         
     453           0 :         pbox = pixman_region32_rectangles (&region, &n);
     454             :         
     455           0 :         info.mask_image = glyph_img;
     456             : 
     457           0 :         while (n--)
     458             :         {
     459           0 :             if (box32_intersect (&composite_box, pbox, &glyph_box))
     460             :             {
     461           0 :                 if (glyph_img->common.extended_format_code != glyph_format   ||
     462           0 :                     glyph_img->common.flags != glyph_flags)
     463             :                 {
     464           0 :                     glyph_format = glyph_img->common.extended_format_code;
     465           0 :                     glyph_flags = glyph_img->common.flags;
     466             : 
     467           0 :                     _pixman_implementation_lookup_composite (
     468             :                         get_implementation(), op,
     469             :                         src->common.extended_format_code, src->common.flags,
     470             :                         glyph_format, glyph_flags | extra,
     471             :                         dest_format, dest_flags,
     472             :                         &implementation, &func);
     473             :                 }
     474             : 
     475           0 :                 info.src_x = src_x + composite_box.x1 - dest_x;
     476           0 :                 info.src_y = src_y + composite_box.y1 - dest_y;
     477           0 :                 info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x);
     478           0 :                 info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y);
     479           0 :                 info.dest_x = composite_box.x1;
     480           0 :                 info.dest_y = composite_box.y1;
     481           0 :                 info.width = composite_box.x2 - composite_box.x1;
     482           0 :                 info.height = composite_box.y2 - composite_box.y1;
     483             : 
     484           0 :                 info.mask_flags = glyph_flags;
     485             : 
     486           0 :                 func (implementation, &info);
     487             :             }
     488             : 
     489           0 :             pbox++;
     490             :         }
     491           0 :         pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
     492             :     }
     493             : 
     494             : out:
     495           0 :     pixman_region32_fini (&region);
     496           0 : }
     497             : 
     498             : static void
     499           0 : add_glyphs (pixman_glyph_cache_t *cache,
     500             :             pixman_image_t *dest,
     501             :             int off_x, int off_y,
     502             :             int n_glyphs, const pixman_glyph_t *glyphs)
     503             : {
     504           0 :     pixman_format_code_t glyph_format = PIXMAN_null;
     505           0 :     uint32_t glyph_flags = 0;
     506           0 :     pixman_composite_func_t func = NULL;
     507           0 :     pixman_implementation_t *implementation = NULL;
     508             :     pixman_format_code_t dest_format;
     509             :     uint32_t dest_flags;
     510             :     pixman_box32_t dest_box;
     511             :     pixman_composite_info_t info;
     512           0 :     pixman_image_t *white_img = NULL;
     513           0 :     pixman_bool_t white_src = FALSE;
     514             :     int i;
     515             : 
     516           0 :     _pixman_image_validate (dest);
     517             : 
     518           0 :     dest_format = dest->common.extended_format_code;
     519           0 :     dest_flags = dest->common.flags;
     520             : 
     521           0 :     info.op = PIXMAN_OP_ADD;
     522           0 :     info.dest_image = dest;
     523           0 :     info.src_x = 0;
     524           0 :     info.src_y = 0;
     525           0 :     info.dest_flags = dest_flags;
     526             : 
     527           0 :     dest_box.x1 = 0;
     528           0 :     dest_box.y1 = 0;
     529           0 :     dest_box.x2 = dest->bits.width;
     530           0 :     dest_box.y2 = dest->bits.height;
     531             : 
     532           0 :     for (i = 0; i < n_glyphs; ++i)
     533             :     {
     534           0 :         glyph_t *glyph = (glyph_t *)glyphs[i].glyph;
     535           0 :         pixman_image_t *glyph_img = glyph->image;
     536             :         pixman_box32_t glyph_box;
     537             :         pixman_box32_t composite_box;
     538             : 
     539           0 :         if (glyph_img->common.extended_format_code != glyph_format   ||
     540           0 :             glyph_img->common.flags != glyph_flags)
     541             :         {
     542             :             pixman_format_code_t src_format, mask_format;
     543             : 
     544           0 :             glyph_format = glyph_img->common.extended_format_code;
     545           0 :             glyph_flags = glyph_img->common.flags;
     546             : 
     547           0 :             if (glyph_format == dest->bits.format)
     548             :             {
     549           0 :                 src_format = glyph_format;
     550           0 :                 mask_format = PIXMAN_null;
     551           0 :                 info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
     552           0 :                 info.mask_flags = FAST_PATH_IS_OPAQUE;
     553           0 :                 info.mask_image = NULL;
     554           0 :                 white_src = FALSE;
     555             :             }
     556             :             else
     557             :             {
     558           0 :                 if (!white_img)
     559             :                 {
     560             :                     static const pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff };
     561             : 
     562           0 :                     if (!(white_img = pixman_image_create_solid_fill (&white)))
     563           0 :                         goto out;
     564             : 
     565           0 :                     _pixman_image_validate (white_img);
     566             :                 }
     567             : 
     568           0 :                 src_format = PIXMAN_solid;
     569           0 :                 mask_format = glyph_format;
     570           0 :                 info.src_flags = white_img->common.flags;
     571           0 :                 info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
     572           0 :                 info.src_image = white_img;
     573           0 :                 white_src = TRUE;
     574             :             }
     575             : 
     576           0 :             _pixman_implementation_lookup_composite (
     577             :                 get_implementation(), PIXMAN_OP_ADD,
     578             :                 src_format, info.src_flags,
     579             :                 mask_format, info.mask_flags,
     580             :                 dest_format, dest_flags,
     581             :                 &implementation, &func);
     582             :         }
     583             : 
     584           0 :         glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x;
     585           0 :         glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y;
     586           0 :         glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width;
     587           0 :         glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height;
     588             :         
     589           0 :         if (box32_intersect (&composite_box, &glyph_box, &dest_box))
     590             :         {
     591           0 :             int src_x = composite_box.x1 - glyph_box.x1;
     592           0 :             int src_y = composite_box.y1 - glyph_box.y1;
     593             : 
     594           0 :             if (white_src)
     595           0 :                 info.mask_image = glyph_img;
     596             :             else
     597           0 :                 info.src_image = glyph_img;
     598             : 
     599           0 :             info.mask_x = info.src_x = src_x;
     600           0 :             info.mask_y = info.src_y = src_y;
     601           0 :             info.dest_x = composite_box.x1;
     602           0 :             info.dest_y = composite_box.y1;
     603           0 :             info.width = composite_box.x2 - composite_box.x1;
     604           0 :             info.height = composite_box.y2 - composite_box.y1;
     605             : 
     606           0 :             func (implementation, &info);
     607             : 
     608           0 :             pixman_list_move_to_front (&cache->mru, &glyph->mru_link);
     609             :         }
     610             :     }
     611             : 
     612             : out:
     613           0 :     if (white_img)
     614           0 :         pixman_image_unref (white_img);
     615           0 : }
     616             : 
     617             : /* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an
     618             :  * infinitely big mask image at the position such that the glyph origin point
     619             :  * is positioned at the (glyphs[i].x, glyphs[i].y) point.
     620             :  *
     621             :  * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source
     622             :  * image are both aligned with (dest_x, dest_y) in the destination image. Then
     623             :  * these three images are composited within the 
     624             :  *
     625             :  *       (dest_x, dest_y, dst_x + width, dst_y + height)
     626             :  *
     627             :  * rectangle.
     628             :  *
     629             :  * TODO:
     630             :  *   - Trim the mask to the destination clip/image?
     631             :  *   - Trim composite region based on sources, when the op ignores 0s.
     632             :  */
     633             : PIXMAN_EXPORT void
     634           0 : pixman_composite_glyphs (pixman_op_t            op,
     635             :                          pixman_image_t        *src,
     636             :                          pixman_image_t        *dest,
     637             :                          pixman_format_code_t   mask_format,
     638             :                          int32_t                src_x,
     639             :                          int32_t                src_y,
     640             :                          int32_t                mask_x,
     641             :                          int32_t                mask_y,
     642             :                          int32_t                dest_x,
     643             :                          int32_t                dest_y,
     644             :                          int32_t                width,
     645             :                          int32_t                height,
     646             :                          pixman_glyph_cache_t  *cache,
     647             :                          int                    n_glyphs,
     648             :                          const pixman_glyph_t  *glyphs)
     649             : {
     650             :     pixman_image_t *mask;
     651             : 
     652           0 :     if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1)))
     653           0 :         return;
     654             : 
     655           0 :     if (PIXMAN_FORMAT_A   (mask_format) != 0 &&
     656           0 :         PIXMAN_FORMAT_RGB (mask_format) != 0)
     657             :     {
     658           0 :         pixman_image_set_component_alpha (mask, TRUE);
     659             :     }
     660             : 
     661           0 :     add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs);
     662             : 
     663           0 :     pixman_image_composite32 (op, src, mask, dest,
     664             :                               src_x, src_y,
     665             :                               0, 0,
     666             :                               dest_x, dest_y,
     667             :                               width, height);
     668             : 
     669           0 :     pixman_image_unref (mask);
     670             : }

Generated by: LCOV version 1.13