Exemplo n.º 1
0
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;
}