static cairo_int_status_t _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, cairo_gl_glyph_cache_t *cache, cairo_scaled_glyph_t *scaled_glyph) { cairo_image_surface_t *glyph_surface = scaled_glyph->surface; cairo_gl_glyph_t *glyph_private; cairo_rtree_node_t *node = NULL; cairo_int_status_t status; int width, height; width = glyph_surface->width; if (width < GLYPH_CACHE_MIN_SIZE) width = GLYPH_CACHE_MIN_SIZE; height = glyph_surface->height; if (height < GLYPH_CACHE_MIN_SIZE) height = GLYPH_CACHE_MIN_SIZE; /* search for an available slot */ status = _cairo_rtree_insert (&cache->rtree, width, height, &node); /* search for an unlocked slot */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_rtree_evict_random (&cache->rtree, width, height, &node); if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_rtree_node_insert (&cache->rtree, node, width, height, &node); } } if (status) return status; /* XXX: Make sure we use the mask texture. This should work automagically somehow */ if(ctx->states_cache.active_texture != GL_TEXTURE1) { glActiveTexture (GL_TEXTURE1); ctx->states_cache.active_texture = GL_TEXTURE1; } status = _cairo_gl_surface_draw_image (cache->surface, glyph_surface, 0, 0, glyph_surface->width, glyph_surface->height, node->x, node->y); if (unlikely (status)) return status; glyph_private = (cairo_gl_glyph_t *) node; glyph_private->cache = cache; glyph_private->glyph = scaled_glyph; _cairo_scaled_glyph_attach_private (scaled_glyph, &glyph_private->base, cache, _cairo_gl_glyph_fini); scaled_glyph->dev_private = glyph_private; scaled_glyph->dev_private_key = cache; /* compute tex coords */ glyph_private->p1.x = node->x; glyph_private->p1.y = node->y; glyph_private->p2.x = node->x + glyph_surface->width; glyph_private->p2.y = node->y + glyph_surface->height; if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) { glyph_private->p1.x /= GLYPH_CACHE_WIDTH; glyph_private->p2.x /= GLYPH_CACHE_WIDTH; glyph_private->p1.y /= GLYPH_CACHE_HEIGHT; glyph_private->p2.y /= GLYPH_CACHE_HEIGHT; } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_gl_glyph_cache_add_glyph (cairo_gl_glyph_cache_t *cache, cairo_scaled_glyph_t *scaled_glyph) { cairo_image_surface_t *glyph_surface = scaled_glyph->surface; cairo_gl_glyph_private_t *glyph_private; cairo_rtree_node_t *node = NULL; cairo_image_surface_t *clone = NULL; cairo_status_t status; int width, height; GLenum internal_format, format, type; cairo_bool_t has_alpha; if (! _cairo_gl_get_image_format_and_type (glyph_surface->pixman_format, &internal_format, &format, &type, &has_alpha)) { cairo_bool_t is_supported; clone = _cairo_image_surface_coerce (glyph_surface, _cairo_format_from_content (glyph_surface->base.content)); if (unlikely (clone->base.status)) return clone->base.status; is_supported = _cairo_gl_get_image_format_and_type (clone->pixman_format, &internal_format, &format, &type, &has_alpha); assert (is_supported); glyph_surface = clone; } width = glyph_surface->width; if (width < GLYPH_CACHE_MIN_SIZE) width = GLYPH_CACHE_MIN_SIZE; height = glyph_surface->height; if (height < GLYPH_CACHE_MIN_SIZE) height = GLYPH_CACHE_MIN_SIZE; /* search for an available slot */ status = _cairo_rtree_insert (&cache->rtree, width, height, &node); /* search for an unlocked slot */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_rtree_evict_random (&cache->rtree, width, height, &node); if (status == CAIRO_STATUS_SUCCESS) { status = _cairo_rtree_node_insert (&cache->rtree, node, width, height, &node); } } if (status) return status; glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_UNPACK_ROW_LENGTH, glyph_surface->stride / (PIXMAN_FORMAT_BPP (glyph_surface->pixman_format) / 8)); glTexSubImage2D (GL_TEXTURE_2D, 0, node->x, node->y, glyph_surface->width, glyph_surface->height, format, type, glyph_surface->data); glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); scaled_glyph->surface_private = node; node->owner = &scaled_glyph->surface_private; glyph_private = (cairo_gl_glyph_private_t *) node; glyph_private->cache = cache; /* compute tex coords */ glyph_private->p1.x = node->x / (double) cache->width; glyph_private->p1.y = node->y / (double) cache->height; glyph_private->p2.x = (node->x + glyph_surface->width) / (double) cache->width; glyph_private->p2.y = (node->y + glyph_surface->height) / (double) cache->height; cairo_surface_destroy (&clone->base); return CAIRO_STATUS_SUCCESS; }