void fbGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs) { #define N_STACK_GLYPHS 512 ScreenPtr pScreen = pDst->pDrawable->pScreen; pixman_glyph_t stack_glyphs[N_STACK_GLYPHS]; pixman_glyph_t *pglyphs = stack_glyphs; pixman_image_t *srcImage, *dstImage; int srcXoff, srcYoff, dstXoff, dstYoff; GlyphPtr glyph; int n_glyphs; int x, y; int i, n; int xDst = list->xOff, yDst = list->yOff; miCompositeSourceValidate(pSrc); n_glyphs = 0; for (i = 0; i < nlist; ++i) n_glyphs += list[i].len; if (!glyphCache) glyphCache = pixman_glyph_cache_create(); pixman_glyph_cache_freeze (glyphCache); if (n_glyphs > N_STACK_GLYPHS) { if (!(pglyphs = malloc (n_glyphs * sizeof (pixman_glyph_t)))) goto out; } i = 0; x = y = 0; while (nlist--) { x += list->xOff; y += list->yOff; n = list->len; while (n--) { const void *g; glyph = *glyphs++; if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) { pixman_image_t *glyphImage; PicturePtr pPicture; int xoff, yoff; pPicture = GetGlyphPicture(glyph, pScreen); if (!pPicture) { n_glyphs--; goto next; } if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff))) goto out; g = pixman_glyph_cache_insert(glyphCache, glyph, NULL, glyph->info.x, glyph->info.y, glyphImage); free_pixman_pict(pPicture, glyphImage); if (!g) goto out; } pglyphs[i].x = x; pglyphs[i].y = y; pglyphs[i].glyph = g; i++; next: x += glyph->info.xOff; y += glyph->info.yOff; } list++; } if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff))) goto out; if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff))) goto out_free_src; if (maskFormat) { pixman_format_code_t format; pixman_box32_t extents; format = maskFormat->format | (maskFormat->depth << 24); pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents); pixman_composite_glyphs(op, srcImage, dstImage, format, xSrc + srcXoff + extents.x1 - xDst, ySrc + srcYoff + extents.y1 - yDst, extents.x1, extents.y1, extents.x1 + dstXoff, extents.y1 + dstYoff, extents.x2 - extents.x1, extents.y2 - extents.y1, glyphCache, n_glyphs, pglyphs); } else { pixman_composite_glyphs_no_mask(op, srcImage, dstImage, xSrc + srcXoff - xDst, ySrc + srcYoff - yDst, dstXoff, dstYoff, glyphCache, n_glyphs, pglyphs); } free_pixman_pict(pDst, dstImage); out_free_src: free_pixman_pict(pSrc, srcImage); out: pixman_glyph_cache_thaw(glyphCache); if (pglyphs != stack_glyphs) free(pglyphs); }
uint32_t test_glyphs (int testnum, int verbose) { pixman_image_t *glyph_images[MAX_GLYPHS]; pixman_glyph_t glyphs[4 * MAX_GLYPHS]; uint32_t crc32 = 0; pixman_image_t *source, *dest; int n_glyphs, i; pixman_glyph_cache_t *cache; lcg_srand (testnum); cache = pixman_glyph_cache_create (); source = create_image (300, formats, ALLOW_CLIPPED | ALLOW_ALPHA_MAP | ALLOW_SOURCE_CLIPPING | ALLOW_REPEAT | ALLOW_SOLID); dest = create_image (128, formats, ALLOW_CLIPPED | ALLOW_ALPHA_MAP | ALLOW_SOURCE_CLIPPING); pixman_glyph_cache_freeze (cache); n_glyphs = lcg_rand_n (MAX_GLYPHS); for (i = 0; i < n_glyphs; ++i) glyph_images[i] = create_image (32, glyph_formats, 0); for (i = 0; i < 4 * n_glyphs; ++i) { int g = lcg_rand_n (n_glyphs); pixman_image_t *glyph_img = glyph_images[g]; void *key1 = KEY1 (glyph_img); void *key2 = KEY2 (glyph_img); const void *glyph; if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2))) { glyph = pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img); } glyphs[i].glyph = glyph; glyphs[i].x = lcg_rand_n (128); glyphs[i].y = lcg_rand_n (128); } if (lcg_rand_n (2) == 0) { int src_x = lcg_rand_n (300) - 150; int src_y = lcg_rand_n (300) - 150; int mask_x = lcg_rand_n (64) - 32; int mask_y = lcg_rand_n (64) - 32; int dest_x = lcg_rand_n (64) - 32; int dest_y = lcg_rand_n (64) - 32; int width = lcg_rand_n (64); int height = lcg_rand_n (64); pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; pixman_format_code_t format = random_format (glyph_formats); pixman_composite_glyphs ( op, source, dest, format, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height, cache, 4 * n_glyphs, glyphs); } else { pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; int src_x = lcg_rand_n (300) - 150; int src_y = lcg_rand_n (300) - 150; int dest_x = lcg_rand_n (64) - 32; int dest_y = lcg_rand_n (64) - 32; pixman_composite_glyphs_no_mask ( op, source, dest, src_x, src_y, dest_x, dest_y, cache, 4 * n_glyphs, glyphs); } pixman_glyph_cache_thaw (cache); for (i = 0; i < n_glyphs; ++i) { pixman_image_t *img = glyph_images[i]; void *key1, *key2; key1 = KEY1 (img); key2 = KEY2 (img); pixman_glyph_cache_remove (cache, key1, key2); pixman_image_unref (glyph_images[i]); } crc32 = compute_crc32_for_image (0, dest); pixman_image_unref (source); pixman_image_unref (dest); pixman_glyph_cache_destroy (cache); return crc32; }