[cairo-commit] cairo/src Makefile.am, 1.26, 1.27 cairo.c, 1.42,
1.43 cairo_cache.c, NONE, 1.1 cairo_font.c, 1.25,
1.26 cairo_ft_font.c, 1.23, 1.24 cairo_glitz_surface.c, 1.8,
1.9 cairo_gstate.c, 1.60, 1.61 cairo_image_surface.c, 1.16,
1.17 cairo_png_surface.c, 1.8, 1.9 cairo_ps_surface.c, 1.13,
1.14 cairo_xcb_surface.c, 1.11, 1.12 cairo_xlib_surface.c,
1.24, 1.25 cairoint.h, 1.69, 1.70
Graydon Hoare
commit at pdx.freedesktop.org
Fri Oct 8 12:09:54 PDT 2004
Committed by: graydon
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv9655/src
Modified Files:
Makefile.am cairo.c cairo_font.c cairo_ft_font.c
cairo_glitz_surface.c cairo_gstate.c cairo_image_surface.c
cairo_png_surface.c cairo_ps_surface.c cairo_xcb_surface.c
cairo_xlib_surface.c cairoint.h
Added Files:
cairo_cache.c
Log Message:
2004-10-07 Graydon Hoare <graydon at redhat.com>
* src/Makefile.am (libcairo_la_SOURCES): Add cairo_cache.c
* src/cairo.c
(cairo_text_extents)
(cairo_show_text)
(cairo_text_path): Rewrite using temporary glyph arrays
* src/cairo_cache.c: New file.
* src/cairo_font.c (_cairo_glyph_cache_create)
(_cairo_glyph_cache_destroy)
(_cairo_glyph_cache_reference)
(_cairo_glyph_cache_pop_last)
(_cairo_glyph_surface_init)
(_cairo_font_lookup_glyph): Remove old glyph cache code.
(_cairo_font_scale)
(_cairo_font_transform): Remove font-transforming code.
(_cairo_font_text_extents)
(_cairo_font_text_bbox)
(_cairo_font_show_text)
(_cairo_font_text_path): Remove text-API code.
(_cairo_font_cache_key_t): New structure type.
(_font_cache_hash)
(_font_cache_keys_equal)
(_font_cache_create_entry)
(_font_cache_destroy_entry)
(_font_cache_destroy_cache): New font cache code.
(_global_font_cache)
(_lock_global_font_cache)
(_unlock_global_font_cache)
(_get_global_font_cache): New global font cache.
(_cairo_font_text_to_glyphs)
(_cairo_glyph_cache_hash)
(_cairo_glyph_cache_keys_equal)
(_image_glyph_cache_create_entry)
(_image_glyph_cache_destroy_entry)
(_image_glyph_cache_destroy_cache): New glyph cache code.
(_global_image_glyph_cache)
(_cairo_lock_global_image_glyph_cache)
(_cairo_unlock_global_image_glyph_cache)
(_cairo_get_global_image_glyph_cache): New global glyph cache.
(_cairo_font_cache_backend): New structure.
(_cairo_image_cache_backend): Likewise.
(_cairo_font_create): Reimplement in terms of font cache.
(_cairo_font_init): Remove matrix and glyph cache related code.
(_cairo_font_copy): Likewise.
(_cairo_font_show_glyphs): Delegate to surface when possible.
(_cairo_font_glyph_extents)
(_cairo_font_glyph_bbox)
(_cairo_font_glyph_path)
(_cairo_font_font_extents)
(_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX,
and add scale parameter.
* src/cairo_ft_font.c
(ft_cache_t)
(ft_font_val_t)
(cairo_ft_cache_key_t)
(cairo_ft_cache_entry_t): New structure types.
(_create_from_face)
(_reference_font_val)
(_destroy_font_val)
(_create_from_library_and_pattern): New functions.
(_ft_font_cache_hash)
(_ft_font_cache_keys_equal)
(_ft_font_cache_create_entry)
(_ft_font_cache_destroy_entry)
(_ft_font_cache_destroy_cache): New ft font cache code.
(_global_ft_cache)
(_lock_global_ft_cache)
(_unlock_global_ft_cache)
(_get_global_ft_cache): New global ft font cache.
(_ft_font_cache_backend): New structure.
(_cairo_ft_font_create): Rewrite to use cache.
(_cairo_ft_font_destroy): Likewise.
(_cairo_ft_font_copy): Remove.
(_install_font_matrix): Rename as _install_font_scale.
(_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs.
(_cairo_ft_font_text_to_glyphs): Use cache for metrics.
(_cairo_ft_font_extents): Accept size, use scaled metrics.
(_cairo_ft_font_glyph_extents)
(_cairo_ft_font_glyph_bbox)
(_cairo_ft_font_show_glyphs)
(_cairo_ft_font_glyph_path): Modify to use size, cache.
(_cairo_ft_font_text_extents)
(_cairo_ft_font_text_bbox)
(_cairo_ft_font_show_text)
(_cairo_ft_font_text_path): Remove text-API code.
(cairo_ft_font_create)
(cairo_ft_font_create_for_ft_face)
(cairo_ft_font_face)
(cairo_ft_font_pattern): Rewrite using ft_font_val_t.
* src/cairo_gstate.c (cairo_gstate_init_copy): Just reference font.
(_cairo_gstate_fini): Finalize font matrix.
(_cairo_gstate_default_matrix): Initialize font matrix.
(_cairo_gstate_clip): Re-enable clipping rectangle.
(_cairo_gstate_select_font)
(_cairo_gstate_set_font): Set font matrix to identity.
(_cairo_gstate_scale_font): Scale font matrix, not font.
(_cairo_gstate_transform_font): Transform font matrix, not font.
(_cairo_gstate_set_font_transform): Install as font matrix, not in font.
(_build_font_scale): New helper function.
(_cairo_gstate_text_to_glyphs): New function.
(_cairo_gstate_current_font_extents)
(_cairo_gstate_glyph_extents)
(_cairo_gstate_show_glyphs)
(_cairo_gstate_glyph_path): Rewrite using font matrix and size.
(_cairo_gstate_text_path
(_cairo_gstate_text_extents)
(_cairo_gstate_show_text): Remove text-API code.
* src/cairo_xlib_surface.c
(_cairo_xlib_surface_set_clip_region): Minor bug fix.
(_cairo_xlib_surface_show_glyphs): New function.
(_cairo_xlib_surface_backend): Add reference to new function.
(glyphset_cache_t)
(glyphset_cache_entry_t): New structure types.
(_next_xlib_glyph): New helper function.
(_xlib_glyphset_cache_create_value)
(_xlib_glyphset_cache_destroy_cache)
(_xlib_glyphset_cache_destroy_value)
(_xlib_glyphset_cache_backend): New glyphset cache code.
(_xlib_glyphset_caches)
(_lock_xlib_glyphset_caches)
(_unlock_xlib_glyphset_caches)
(_get_glyphset_cache): New global glyphset cache.
* src/cairo_glitz_surface.c (cairo_glitz_surface_backend):
Add NULL entry for show_glyphs.
* src/cairo_image_surface.c (cairo_image_surface_backend):
Add NULL entry for show_glyphs.
* src/cairo_ps_surface.c (cairo_ps_surface_backend):
Add NULL entry for show_glyphs.
* src/cairo_png_surface.c (cairo_png_surface_backend):
Add NULL entry for show_glyphs.
* src/cairo_xcb_surface.c (cairo_xcb_surface_backend):
Add NULL entry for show_glyphs.
* src/cairoint.h (cairo_cache_backend_t): New structure type.
(cairo_cache_entry_base_t)
(cairo_cache_arrangement_t)
(cairo_cache_t): New structure types.
(_cairo_cache_init)
(_cairo_cache_reference)
(_cairo_cache_destroy)
(_cairo_cache_lookup)
(_cairo_hash_string): New cache functions.
(CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT)
(CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT)
(CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT)
(CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants.
(cairo_font_scale_t)
(cairo_glyph_cache_key_t)
(cairo_image_glyph_cache_entry_t): New structure types.
(_cairo_lock_global_image_glyph_cache)
(_cairo_unlock_global_image_glyph_cache)
(_cairo_get_global_image_glyph_cache)
(_cairo_glyph_cache_hash)
(_cairo_glyph_cache_keys_equal): New functions for glyph caches.
(cairo_font_backend_t): Remove text-API calls, add scale params,
remove copy call.
(cairo_surface_backend_t): Add show_glyphs entry.
(cairo_glyph_surface_t)
(cairo_glyph_surface_node_t): Remove old glyph cache structures.
(cairo_unscaled_font_t): New structure type.
(cairo_font): Remove glyph cache member, add pointer to unscaled.
(cairo_gstate): Add font_matrix member, change to hold unscaled.
(_cairo_gstate_set_font_transform)
(_cairo_gstate_current_font_transform)
(_cairo_gstate_text_to_glyphs): New functions.
(_cairo_gstate_text_path
(_cairo_gstate_text_extents)
(_cairo_gstate_show_text)
(_cairo_font_text_extents)
(_cairo_font_text_bbox)
(_cairo_font_show_text)
(_cairo_font_text_path): Remove text-API code.
(_cairo_font_glyph_extents)
(_cairo_font_glyph_bbox)
(_cairo_font_glyph_path)
(_cairo_font_font_extents)
(_cairo_font_show_glyphs): Add scale parameter.
Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.26
retrieving revision 1.27
diff -C2 -d -r1.26 -r1.27
*** Makefile.am 11 Sep 2004 11:23:18 -0000 1.26
--- Makefile.am 8 Oct 2004 19:09:51 -0000 1.27
***************
*** 32,35 ****
--- 32,36 ----
cairo.c \
cairo.h \
+ cairo_cache.c \
cairo_color.c \
cairo_fixed.c \
Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -C2 -d -r1.42 -r1.43
*** cairo.c 4 Sep 2004 13:38:34 -0000 1.42
--- cairo.c 8 Oct 2004 19:09:51 -0000 1.43
***************
*** 901,910 ****
cairo_text_extents_t *extents)
{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
!
! cr->status = _cairo_gstate_text_extents (cr->gstate, utf8, extents);
CAIRO_CHECK_SANITY (cr);
}
--- 901,925 ----
cairo_text_extents_t *extents)
{
+ cairo_glyph_t *glyphs = NULL;
+ int nglyphs;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
!
! cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, &glyphs, &nglyphs);
CAIRO_CHECK_SANITY (cr);
+
+ if (cr->status) {
+ if (glyphs)
+ free (glyphs);
+ return;
+ }
+
+ cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, nglyphs, extents);
+ CAIRO_CHECK_SANITY (cr);
+
+ if (glyphs)
+ free (glyphs);
}
***************
*** 927,930 ****
--- 942,948 ----
cairo_show_text (cairo_t *cr, const unsigned char *utf8)
{
+ cairo_glyph_t *glyphs = NULL;
+ int nglyphs;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
***************
*** 934,939 ****
return;
! cr->status = _cairo_gstate_show_text (cr->gstate, utf8);
CAIRO_CHECK_SANITY (cr);
}
--- 952,969 ----
return;
! cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, &glyphs, &nglyphs);
CAIRO_CHECK_SANITY (cr);
+
+ if (cr->status) {
+ if (glyphs)
+ free (glyphs);
+ return;
+ }
+
+ cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, nglyphs);
+ CAIRO_CHECK_SANITY (cr);
+
+ if (glyphs)
+ free (glyphs);
}
***************
*** 952,961 ****
cairo_text_path (cairo_t *cr, const unsigned char *utf8)
{
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
! cr->status = _cairo_gstate_text_path (cr->gstate, utf8);
CAIRO_CHECK_SANITY (cr);
}
--- 982,1006 ----
cairo_text_path (cairo_t *cr, const unsigned char *utf8)
{
+ cairo_glyph_t *glyphs = NULL;
+ int nglyphs;
+
CAIRO_CHECK_SANITY (cr);
if (cr->status)
return;
! cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, &glyphs, &nglyphs);
CAIRO_CHECK_SANITY (cr);
+
+ if (cr->status) {
+ if (glyphs)
+ free (glyphs);
+ return;
+ }
+
+ cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, nglyphs);
+ CAIRO_CHECK_SANITY (cr);
+
+ if (glyphs)
+ free (glyphs);
}
--- NEW FILE: cairo_cache.c ---
(This appears to be a binary file; contents omitted.)
Index: cairo_font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_font.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** cairo_font.c 4 Sep 2004 13:38:34 -0000 1.25
--- cairo_font.c 8 Oct 2004 19:09:51 -0000 1.26
***************
*** 37,54 ****
#include "cairoint.h"
- static cairo_glyph_cache_t *
- _cairo_glyph_cache_create (void);
! static void
! _cairo_glyph_cache_destroy (cairo_glyph_cache_t *glyph_cache);
! static void
! _cairo_glyph_cache_reference (cairo_glyph_cache_t *glyph_cache);
! cairo_font_t *
! _cairo_font_create (const char *family,
! cairo_font_slant_t slant,
! cairo_font_weight_t weight)
{
const struct cairo_font_backend *backend = CAIRO_FONT_BACKEND_DEFAULT;
--- 37,94 ----
#include "cairoint.h"
! /* First we implement a global font cache for named fonts. */
! typedef struct {
! cairo_cache_entry_base_t base;
! const char *family;
! cairo_font_slant_t slant;
! cairo_font_weight_t weight;
! } cairo_font_cache_key_t;
! typedef struct {
! cairo_font_cache_key_t key;
! cairo_unscaled_font_t *unscaled;
! } cairo_font_cache_entry_t;
!
! static unsigned long
! _font_cache_hash (void *cache, void *key)
! {
! cairo_font_cache_key_t *in;
! in = (cairo_font_cache_key_t *) key;
! unsigned long hash;
!
! /* 1607 and 1451 are just a couple random primes. */
! hash = _cairo_hash_string (in->family);
! hash += ((unsigned long) in->slant) * 1607;
! hash += ((unsigned long) in->weight) * 1451;
! return hash;
! }
!
!
! static int
! _font_cache_keys_equal (void *cache,
! void *k1,
! void *k2)
{
+ cairo_font_cache_key_t *a, *b;
+ a = (cairo_font_cache_key_t *) k1;
+ b = (cairo_font_cache_key_t *) k2;
+
+ return (strcmp (a->family, b->family) == 0)
+ && (a->weight == b->weight)
+ && (a->slant == b->slant);
+ }
+
+
+ static cairo_status_t
+ _font_cache_create_entry (void *cache,
+ void *key,
+ void **return_value)
+ {
+ cairo_font_cache_key_t *k;
+ cairo_font_cache_entry_t *entry;
+ k = (cairo_font_cache_key_t *) key;
+
const struct cairo_font_backend *backend = CAIRO_FONT_BACKEND_DEFAULT;
***************
*** 59,422 ****
* ugly one if necessary). */
! return backend->create (family, slant, weight);
}
! cairo_status_t
! _cairo_font_init (cairo_font_t *font,
! const struct cairo_font_backend *backend)
{
! cairo_matrix_set_identity (&font->matrix);
! font->refcount = 1;
! font->backend = backend;
! font->glyph_cache = _cairo_glyph_cache_create ();
! if (font->glyph_cache == NULL)
! return CAIRO_STATUS_NO_MEMORY;
! return CAIRO_STATUS_SUCCESS;
}
! cairo_font_t *
! _cairo_font_copy (cairo_font_t *font)
{
! cairo_font_t *newfont = NULL;
! char *tmp = NULL;
! if (font == NULL || font->backend->copy == NULL)
! return NULL;
!
! newfont = font->backend->copy (font);
! if (newfont == NULL) {
! free (tmp);
! return NULL;
! }
- newfont->refcount = 1;
- cairo_matrix_copy(&newfont->matrix, &font->matrix);
- newfont->backend = font->backend;
! if (newfont->glyph_cache)
! _cairo_glyph_cache_destroy (newfont->glyph_cache);
!
! newfont->glyph_cache = font->glyph_cache;
! _cairo_glyph_cache_reference (font->glyph_cache);
!
! return newfont;
}
! cairo_status_t
! _cairo_font_scale (cairo_font_t *font, double scale)
{
! return cairo_matrix_scale (&font->matrix, scale, scale);
}
! cairo_status_t
! _cairo_font_transform (cairo_font_t *font, cairo_matrix_t *matrix)
{
! return cairo_matrix_multiply (&font->matrix, matrix, &font->matrix);
}
! cairo_status_t
! _cairo_font_text_extents (cairo_font_t *font,
! const unsigned char *utf8,
! cairo_text_extents_t *extents)
{
! return font->backend->text_extents(font, utf8, extents);
}
! cairo_status_t
! _cairo_font_glyph_extents (cairo_font_t *font,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents)
{
! return font->backend->glyph_extents(font, glyphs, num_glyphs, extents);
}
cairo_status_t
! _cairo_font_text_bbox (cairo_font_t *font,
! cairo_surface_t *surface,
! double x,
! double y,
! const unsigned char *utf8,
! cairo_box_t *bbox)
{
! return font->backend->text_bbox (font, surface, x, y, utf8, bbox);
}
cairo_status_t
! _cairo_font_glyph_bbox (cairo_font_t *font,
! cairo_surface_t *surface,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_box_t *bbox)
{
! return font->backend->glyph_bbox (font, surface, glyphs, num_glyphs, bbox);
}
cairo_status_t
! _cairo_font_show_text (cairo_font_t *font,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! double x,
! double y,
! const unsigned char *utf8)
{
! return font->backend->show_text(font, operator, source,
! surface, source_x, source_y, x, y, utf8);
}
cairo_status_t
! _cairo_font_show_glyphs (cairo_font_t *font,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! cairo_glyph_t *glyphs,
! int num_glyphs)
{
! return font->backend->show_glyphs(font, operator, source,
! surface, source_x, source_y,
! glyphs, num_glyphs);
}
cairo_status_t
! _cairo_font_text_path (cairo_font_t *font,
! double x,
! double y,
! const unsigned char *utf8,
! cairo_path_t *path)
{
! return font->backend->text_path(font, x, y, utf8, path);
}
cairo_status_t
! _cairo_font_glyph_path (cairo_font_t *font,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_path_t *path)
{
! return font->backend->glyph_path(font, glyphs, num_glyphs, path);
}
cairo_status_t
! _cairo_font_font_extents (cairo_font_t *font,
! cairo_font_extents_t *extents)
{
! return font->backend->font_extents(font, extents);
}
! static void
! _cairo_glyph_cache_pop_last (cairo_glyph_cache_t *glyph_cache)
{
! if (glyph_cache->last) {
! cairo_glyph_surface_node_t *remove = glyph_cache->last;
!
! cairo_surface_destroy (remove->s.surface);
! glyph_cache->last = remove->prev;
! if (glyph_cache->last)
! glyph_cache->last->next = NULL;
! free (remove);
! glyph_cache->n_nodes--;
! }
}
- static cairo_glyph_cache_t *
- _cairo_glyph_cache_create (void)
- {
- cairo_glyph_cache_t *glyph_cache;
-
- glyph_cache = malloc (sizeof (cairo_glyph_cache_t));
- if (glyph_cache == NULL)
- return NULL;
-
- glyph_cache->n_nodes = 0;
- glyph_cache->first = NULL;
- glyph_cache->last = NULL;
- glyph_cache->cache_size = CAIRO_FONT_CACHE_SIZE_DEFAULT;
- glyph_cache->ref_count = 1;
! return glyph_cache;
}
! static void
! _cairo_glyph_cache_reference (cairo_glyph_cache_t *glyph_cache)
{
! if (glyph_cache == NULL)
return;
! glyph_cache->ref_count++;
}
! static void
! _cairo_glyph_cache_destroy (cairo_glyph_cache_t *glyph_cache)
{
! if (glyph_cache == NULL)
! return;
! glyph_cache->ref_count--;
! if (glyph_cache->ref_count)
! return;
- while (glyph_cache->last)
- _cairo_glyph_cache_pop_last (glyph_cache);
! free (glyph_cache);
! }
! static void
! _cairo_glyph_surface_init (cairo_font_t *font,
! cairo_surface_t *surface,
! const cairo_glyph_t *glyph,
! cairo_glyph_surface_t *glyph_surface)
{
! cairo_surface_t *image;
!
! glyph_surface->surface = NULL;
! glyph_surface->index = glyph->index;
! glyph_surface->matrix[0][0] = font->matrix.m[0][0];
! glyph_surface->matrix[0][1] = font->matrix.m[0][1];
! glyph_surface->matrix[1][0] = font->matrix.m[1][0];
! glyph_surface->matrix[1][1] = font->matrix.m[1][1];
! image = font->backend->create_glyph (font, glyph, &glyph_surface->size);
! if (image == NULL)
! return;
!
! if (surface->backend != image->backend) {
! cairo_status_t status;
!
! glyph_surface->surface =
! _cairo_surface_create_similar_scratch (surface,
! CAIRO_FORMAT_A8, 0,
! glyph_surface->size.width,
! glyph_surface->size.height);
! if (glyph_surface->surface == NULL) {
! glyph_surface->surface = image;
! return;
! }
!
! status = _cairo_surface_set_image (glyph_surface->surface,
! (cairo_image_surface_t *) image);
! if (status) {
! cairo_surface_destroy (glyph_surface->surface);
! glyph_surface->surface = NULL;
! }
! cairo_surface_destroy (image);
! } else
! glyph_surface->surface = image;
}
! cairo_surface_t *
! _cairo_font_lookup_glyph (cairo_font_t *font,
! cairo_surface_t *surface,
! const cairo_glyph_t *glyph,
! cairo_glyph_size_t *return_size)
{
! cairo_glyph_surface_t glyph_surface;
! cairo_glyph_cache_t *cache = font->glyph_cache;
! cairo_glyph_surface_node_t *node;
!
! for (node = cache->first; node != NULL; node = node->next) {
! cairo_glyph_surface_t *s = &node->s;
! if ((s->surface == NULL || s->surface->backend == surface->backend) &&
! s->index == glyph->index &&
! s->matrix[0][0] == font->matrix.m[0][0] &&
! s->matrix[0][1] == font->matrix.m[0][1] &&
! s->matrix[1][0] == font->matrix.m[1][0] &&
! s->matrix[1][1] == font->matrix.m[1][1]) {
! /* move node first in cache */
! if (node->prev) {
! if (node->next == NULL) {
! cache->last = node->prev;
! node->prev->next = NULL;
! } else {
! node->prev->next = node->next;
! node->next->prev = node->prev;
! }
! node->prev = NULL;
! node->next = cache->first;
! cache->first = node;
! if (node->next)
! node->next->prev = node;
! else
! cache->last = node;
! }
!
! cairo_surface_reference (s->surface);
! *return_size = s->size;
!
! return s->surface;
! }
}
-
- _cairo_glyph_surface_init (font, surface, glyph, &glyph_surface);
! *return_size = glyph_surface.size;
!
! if (cache->cache_size > 0) {
! if (cache->n_nodes == cache->cache_size)
! _cairo_glyph_cache_pop_last (cache);
! node = malloc (sizeof (cairo_glyph_surface_node_t));
! if (node) {
! cairo_surface_reference (glyph_surface.surface);
!
! /* insert node first in cache */
! node->s = glyph_surface;
! node->prev = NULL;
! node->next = cache->first;
! cache->first = node;
! if (node->next)
! node->next->prev = node;
! else
! cache->last = node;
! cache->n_nodes++;
! }
! }
!
! return glyph_surface.surface;
}
- /* public font interface follows */
! void
! cairo_font_reference (cairo_font_t *font)
{
! font->refcount++;
}
! void
! cairo_font_destroy (cairo_font_t *font)
{
! if (--(font->refcount) > 0)
! return;
! _cairo_glyph_cache_destroy (font->glyph_cache);
- if (font->backend->destroy)
- font->backend->destroy (font);
- }
void
! cairo_font_set_transform (cairo_font_t *font,
! cairo_matrix_t *matrix)
{
! cairo_matrix_copy (&(font->matrix), matrix);
}
void
! cairo_font_current_transform (cairo_font_t *font,
! cairo_matrix_t *matrix)
{
! cairo_matrix_copy (matrix, &(font->matrix));
}
--- 99,525 ----
* ugly one if necessary). */
! entry = malloc (sizeof (cairo_font_cache_entry_t));
! if (entry == NULL)
! goto FAIL;
!
! entry->key.slant = k->slant;
! entry->key.weight = k->weight;
! entry->key.family = strdup(k->family);
! if (entry->key.family == NULL)
! goto FREE_ENTRY;
!
! entry->unscaled = backend->create (k->family, k->slant, k->weight);
! if (entry->unscaled == NULL)
! goto FREE_FAMILY;
!
! /* Not sure how to measure backend font mem; use a simple count for now.*/
! entry->key.base.memory = 1;
! *return_value = entry;
! return CAIRO_STATUS_SUCCESS;
!
! FREE_FAMILY:
! free ((void *) entry->key.family);
!
! FREE_ENTRY:
! free (entry);
!
! FAIL:
! return CAIRO_STATUS_NO_MEMORY;
}
! static void
! _font_cache_destroy_entry (void *cache,
! void *entry)
{
! cairo_font_cache_entry_t *e;
! e = (cairo_font_cache_entry_t *) entry;
! _cairo_unscaled_font_destroy (e->unscaled);
! free ((void *) e->key.family);
! free (e);
}
! static void
! _font_cache_destroy_cache (void *cache)
{
! free (cache);
! }
! const struct cairo_cache_backend cairo_font_cache_backend = {
! _font_cache_hash,
! _font_cache_keys_equal,
! _font_cache_create_entry,
! _font_cache_destroy_entry,
! _font_cache_destroy_cache
! };
! static void
! _lock_global_font_cache (void)
! {
! /* FIXME: implement locking. */
}
! static void
! _unlock_global_font_cache (void)
{
! /* FIXME: implement locking. */
}
! static cairo_cache_t *
! _global_font_cache = NULL;
!
! static cairo_cache_t *
! _get_global_font_cache (void)
{
! if (_global_font_cache == NULL) {
! _global_font_cache = malloc (sizeof (cairo_cache_t));
!
! if (_global_font_cache == NULL)
! goto FAIL;
!
! if (_cairo_cache_init (_global_font_cache,
! &cairo_font_cache_backend,
! CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT))
! goto FAIL;
! }
!
! return _global_font_cache;
!
! FAIL:
! if (_global_font_cache)
! free (_global_font_cache);
! _global_font_cache = NULL;
! return NULL;
}
! /* Now the internal "unscaled + scale" font API */
!
! cairo_unscaled_font_t *
! _cairo_unscaled_font_create (const char *family,
! cairo_font_slant_t slant,
! cairo_font_weight_t weight)
{
! cairo_cache_t * cache;
! cairo_font_cache_key_t key;
! cairo_font_cache_entry_t *font;
! cairo_status_t status;
!
! _lock_global_font_cache ();
! cache = _get_global_font_cache ();
! if (cache == NULL) {
! _unlock_global_font_cache ();
! return NULL;
! }
!
! key.family = family;
! key.slant = slant;
! key.weight = weight;
!
! status = _cairo_cache_lookup (cache, &key, (void **) &font);
! if (status) {
! _unlock_global_font_cache ();
! return NULL;
! }
!
! _cairo_unscaled_font_reference (font->unscaled);
! _unlock_global_font_cache ();
! return font->unscaled;
}
! void
! _cairo_font_init (cairo_font_t *scaled,
! cairo_font_scale_t *scale,
! cairo_unscaled_font_t *unscaled)
{
! scaled->scale = *scale;
! scaled->unscaled = unscaled;
! scaled->refcount = 1;
}
cairo_status_t
! _cairo_unscaled_font_init (cairo_unscaled_font_t *font,
! const struct cairo_font_backend *backend)
{
! font->refcount = 1;
! font->backend = backend;
! return CAIRO_STATUS_SUCCESS;
}
+
cairo_status_t
! _cairo_unscaled_font_text_to_glyphs (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! const unsigned char *utf8,
! cairo_glyph_t **glyphs,
! int *num_glyphs)
{
! return font->backend->text_to_glyphs (font, scale, utf8, glyphs, num_glyphs);
}
cairo_status_t
! _cairo_unscaled_font_glyph_extents (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents)
{
! return font->backend->glyph_extents(font, scale, glyphs, num_glyphs, extents);
}
+
cairo_status_t
! _cairo_unscaled_font_glyph_bbox (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_box_t *bbox)
{
! return font->backend->glyph_bbox (font, scale, glyphs, num_glyphs, bbox);
}
cairo_status_t
! _cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! cairo_glyph_t *glyphs,
! int num_glyphs)
{
! cairo_status_t status;
! if (surface->backend->show_glyphs != NULL) {
! status = surface->backend->show_glyphs (font, scale, operator, source,
! surface, source_x, source_y,
! glyphs, num_glyphs);
! if (status == CAIRO_STATUS_SUCCESS)
! return status;
! }
!
! /* Surface display routine either does not exist or failed. */
! return font->backend->show_glyphs (font, scale, operator, source,
! surface, source_x, source_y,
! glyphs, num_glyphs);
}
cairo_status_t
! _cairo_unscaled_font_glyph_path (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_path_t *path)
{
! return font->backend->glyph_path (font, scale, glyphs, num_glyphs, path);
}
cairo_status_t
! _cairo_unscaled_font_font_extents (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_font_extents_t *extents)
{
! return font->backend->font_extents(font, scale, extents);
}
! void
! _cairo_unscaled_font_reference (cairo_unscaled_font_t *font)
{
! font->refcount++;
! }
! void
! _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font)
! {
! if (--(font->refcount) > 0)
! return;
!
! if (font->backend)
! font->backend->destroy (font);
}
!
! /* Public font API follows. */
!
! void
! cairo_font_reference (cairo_font_t *font)
! {
! font->refcount++;
}
! void
! cairo_font_destroy (cairo_font_t *font)
{
! if (--(font->refcount) > 0)
return;
! if (font->unscaled)
! _cairo_unscaled_font_destroy (font->unscaled);
!
! free (font);
}
! void
! cairo_font_set_transform (cairo_font_t *font,
! cairo_matrix_t *matrix)
{
! double dummy;
! cairo_matrix_get_affine (matrix,
! &font->scale.matrix[0][0],
! &font->scale.matrix[0][1],
! &font->scale.matrix[1][0],
! &font->scale.matrix[1][1],
! &dummy, &dummy);
! }
! void
! cairo_font_current_transform (cairo_font_t *font,
! cairo_matrix_t *matrix)
! {
! cairo_matrix_set_affine (matrix,
! font->scale.matrix[0][0],
! font->scale.matrix[0][1],
! font->scale.matrix[1][0],
! font->scale.matrix[1][1],
! 0, 0);
! }
! /* Now we implement functions to access a default global image & metrics
! * cache.
! */
! unsigned long
! _cairo_glyph_cache_hash (void *cache, void *key)
{
! cairo_glyph_cache_key_t *in;
! in = (cairo_glyph_cache_key_t *) key;
! return
! ((unsigned long) in->unscaled)
! ^ ((unsigned long) in->scale.matrix[0][0])
! ^ ((unsigned long) in->scale.matrix[0][1])
! ^ ((unsigned long) in->scale.matrix[1][0])
! ^ ((unsigned long) in->scale.matrix[1][1])
! ^ in->index;
! }
! int
! _cairo_glyph_cache_keys_equal (void *cache,
! void *k1,
! void *k2)
! {
! cairo_glyph_cache_key_t *a, *b;
! a = (cairo_glyph_cache_key_t *) k1;
! b = (cairo_glyph_cache_key_t *) k2;
! return (a->index == b->index)
! && (a->unscaled == b->unscaled)
! && (a->scale.matrix[0][0] == b->scale.matrix[0][0])
! && (a->scale.matrix[0][1] == b->scale.matrix[0][1])
! && (a->scale.matrix[1][0] == b->scale.matrix[1][0])
! && (a->scale.matrix[1][1] == b->scale.matrix[1][1]);
}
!
! static cairo_status_t
! _image_glyph_cache_create_entry (void *cache,
! void *key,
! void **return_value)
{
! cairo_glyph_cache_key_t *k = (cairo_glyph_cache_key_t *) key;
! cairo_image_glyph_cache_entry_t *im;
! cairo_status_t status;
! im = calloc (1, sizeof (cairo_image_glyph_cache_entry_t));
! if (im == NULL)
! return CAIRO_STATUS_NO_MEMORY;
! im->key = *k;
! status = im->key.unscaled->backend->create_glyph (im);
! if (status != CAIRO_STATUS_SUCCESS) {
! free (im);
! return status;
}
! _cairo_unscaled_font_reference (im->key.unscaled);
! im->key.base.memory =
! sizeof (cairo_image_glyph_cache_entry_t)
! + (im->image ?
! sizeof (cairo_image_surface_t)
! + 28 * sizeof (int) /* rough guess at size of pixman image structure */
! + (im->image->height * im->image->stride) : 0);
! *return_value = im;
!
! return CAIRO_STATUS_SUCCESS;
}
! static void
! _image_glyph_cache_destroy_entry (void *cache,
! void *value)
{
! cairo_image_glyph_cache_entry_t *im;
!
! im = (cairo_image_glyph_cache_entry_t *) value;
! _cairo_unscaled_font_destroy (im->key.unscaled);
! cairo_surface_destroy (&(im->image->base));
! free (im);
}
! static void
! _image_glyph_cache_destroy_cache (void *cache)
{
! free (cache);
! }
! const cairo_cache_backend_t cairo_image_cache_backend = {
! _cairo_glyph_cache_hash,
! _cairo_glyph_cache_keys_equal,
! _image_glyph_cache_create_entry,
! _image_glyph_cache_destroy_entry,
! _image_glyph_cache_destroy_cache
! };
void
! _cairo_lock_global_image_glyph_cache()
{
! /* FIXME: implement locking. */
}
void
! _cairo_unlock_global_image_glyph_cache()
{
! /* FIXME: implement locking. */
! }
!
! static cairo_cache_t *
! _global_image_glyph_cache = NULL;
!
! cairo_cache_t *
! _cairo_get_global_image_glyph_cache ()
! {
! if (_global_image_glyph_cache == NULL) {
! _global_image_glyph_cache = malloc (sizeof (cairo_cache_t));
!
! if (_global_image_glyph_cache == NULL)
! goto FAIL;
!
! if (_cairo_cache_init (_global_image_glyph_cache,
! &cairo_image_cache_backend,
! CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT))
! goto FAIL;
! }
!
! return _global_image_glyph_cache;
!
! FAIL:
! if (_global_image_glyph_cache)
! free (_global_image_glyph_cache);
! _global_image_glyph_cache = NULL;
! return NULL;
}
Index: cairo_ft_font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_ft_font.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -d -r1.23 -r1.24
*** cairo_ft_font.c 24 May 2004 09:28:05 -0000 1.23
--- cairo_ft_font.c 8 Oct 2004 19:09:51 -0000 1.24
***************
*** 32,74 ****
#include FT_IMAGE_H
! typedef struct {
! cairo_font_t base;
! FT_Library ft_library;
! int owns_ft_library;
FT_Face face;
int owns_face;
[...1512 lines suppressed...]
+ cairo_ft_font_face (cairo_font_t *abstract_font)
+ {
+ cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font->unscaled;
+
+ if (font == NULL || font->val == NULL)
+ return NULL;
+
+ return font->val->face;
+ }
+
+ FcPattern *
+ cairo_ft_font_pattern (cairo_font_t *abstract_font)
+ {
+ cairo_ft_font_t *font = (cairo_ft_font_t *) abstract_font->unscaled;
+
+ if (font == NULL)
+ return NULL;
+
+ return font->pattern;
+ }
Index: cairo_glitz_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_glitz_surface.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** cairo_glitz_surface.c 4 Oct 2004 11:55:46 -0000 1.8
--- cairo_glitz_surface.c 8 Oct 2004 19:09:51 -0000 1.9
***************
*** 901,905 ****
_cairo_glitz_surface_show_page,
_cairo_glitz_surface_set_clip_region,
! _cairo_glitz_surface_create_pattern
};
--- 901,906 ----
_cairo_glitz_surface_show_page,
_cairo_glitz_surface_set_clip_region,
! _cairo_glitz_surface_create_pattern,
! NULL /* show_glyphs */
};
Index: cairo_gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -C2 -d -r1.60 -r1.61
*** cairo_gstate.c 4 Sep 2004 13:38:34 -0000 1.60
--- cairo_gstate.c 8 Oct 2004 19:09:51 -0000 1.61
***************
*** 78,84 ****
gstate->dash_offset = 0.0;
! gstate->font = _cairo_font_create (CAIRO_FONT_FAMILY_DEFAULT,
! CAIRO_FONT_SLANT_DEFAULT,
! CAIRO_FONT_WEIGHT_DEFAULT);
gstate->surface = NULL;
--- 78,84 ----
gstate->dash_offset = 0.0;
! gstate->font = _cairo_unscaled_font_create (CAIRO_FONT_FAMILY_DEFAULT,
! CAIRO_FONT_SLANT_DEFAULT,
! CAIRO_FONT_WEIGHT_DEFAULT);
gstate->surface = NULL;
***************
*** 120,128 ****
if (other->font) {
! gstate->font = _cairo_font_copy (other->font);
! if (!gstate->font) {
! status = CAIRO_STATUS_NO_MEMORY;
! goto CLEANUP_DASHES;
! }
}
--- 120,125 ----
if (other->font) {
! gstate->font = other->font;
! _cairo_unscaled_font_reference (gstate->font);
}
***************
*** 150,156 ****
CLEANUP_PATH:
_cairo_path_fini (&gstate->path);
CLEANUP_FONT:
! cairo_font_destroy (gstate->font);
! CLEANUP_DASHES:
free (gstate->dash);
gstate->dash = NULL;
--- 147,154 ----
CLEANUP_PATH:
_cairo_path_fini (&gstate->path);
+
CLEANUP_FONT:
! _cairo_unscaled_font_destroy (gstate->font);
!
free (gstate->dash);
gstate->dash = NULL;
***************
*** 162,166 ****
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
! cairo_font_destroy (gstate->font);
if (gstate->surface)
--- 160,164 ----
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
! _cairo_unscaled_font_destroy (gstate->font);
if (gstate->surface)
***************
*** 178,181 ****
--- 176,181 ----
cairo_pattern_destroy (gstate->pattern);
+ _cairo_matrix_fini (&gstate->font_matrix);
+
_cairo_matrix_fini (&gstate->ctm);
_cairo_matrix_fini (&gstate->ctm_inverse);
***************
*** 628,631 ****
--- 628,633 ----
scale = 1;
+ cairo_matrix_set_identity (&gstate->font_matrix);
+
cairo_matrix_set_identity (&gstate->ctm);
cairo_matrix_scale (&gstate->ctm, scale, scale);
***************
*** 1677,1689 ****
cairo_status_t st;
- /* XXX: Something in the rectangle-based clipping support is
- * broken. See cairo_snippets/xxx_clip_rectangle which
- * demonstrates no clipping at all.
- *
- * For now, I'm am disabling this optimization completely until it
- * can be fixed.
- */
- return 0;
-
st = cairo_matrix_get_affine (mat, &a, &b, &c, &d, &tx, &ty);
if (!(st == CAIRO_STATUS_SUCCESS && b == 0. && c == 0.))
--- 1679,1682 ----
***************
*** 1993,1996 ****
--- 1986,1990 ----
}
+
cairo_status_t
_cairo_gstate_select_font (cairo_gstate_t *gstate,
***************
*** 1999,2006 ****
cairo_font_weight_t weight)
{
! if (gstate->font != NULL)
! cairo_font_destroy (gstate->font);
! gstate->font = _cairo_font_create (family, slant, weight);
return CAIRO_STATUS_SUCCESS;
--- 1993,2011 ----
cairo_font_weight_t weight)
{
! cairo_unscaled_font_t *tmp;
! tmp = _cairo_unscaled_font_create (family, slant, weight);
!
! if (tmp == NULL)
! return CAIRO_STATUS_NO_MEMORY;
!
! if (gstate->font != tmp)
! {
! if (gstate->font != NULL)
! _cairo_unscaled_font_destroy (gstate->font);
!
! cairo_matrix_set_identity (&gstate->font_matrix);
! gstate->font = tmp;
! }
return CAIRO_STATUS_SUCCESS;
***************
*** 2011,2015 ****
double scale)
{
! return _cairo_font_scale (gstate->font, scale);
}
--- 2016,2020 ----
double scale)
{
! return cairo_matrix_scale (&gstate->font_matrix, scale, scale);
}
***************
*** 2018,2116 ****
cairo_matrix_t *matrix)
{
! return _cairo_font_transform (gstate->font, matrix);
}
cairo_status_t
_cairo_gstate_current_font (cairo_gstate_t *gstate,
cairo_font_t **font)
{
! *font = gstate->font;
return CAIRO_STATUS_SUCCESS;
}
! cairo_status_t
! _cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
! cairo_font_extents_t *extents)
{
! cairo_int_status_t status;
! cairo_matrix_t saved_font_matrix;
!
! cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
! cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
!
! status = _cairo_font_font_extents (gstate->font, extents);
!
! cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
! return status;
}
! cairo_status_t
! _cairo_gstate_set_font (cairo_gstate_t *gstate,
! cairo_font_t *font)
{
! if (gstate->font != NULL)
! cairo_font_destroy (gstate->font);
! gstate->font = font;
! cairo_font_reference (gstate->font);
! return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
! _cairo_gstate_text_extents (cairo_gstate_t *gstate,
! const unsigned char *utf8,
! cairo_text_extents_t *extents)
{
! cairo_matrix_t saved_font_matrix;
! cairo_status_t status;
! double scale_x, scale_y;
!
! cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
! _cairo_matrix_compute_scale_factors (&gstate->ctm, &scale_x, &scale_y);
! cairo_matrix_scale (&gstate->font->matrix, scale_x, scale_y);
!
! status = _cairo_font_text_extents (gstate->font,
! utf8, extents);
!
! cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
! extents->x_bearing /= scale_x;
! extents->y_bearing /= scale_y;
! extents->width /= scale_x;
! extents->height /= scale_y;
! extents->x_advance /= scale_x;
! extents->y_advance /= scale_y;
! return status;
! }
! cairo_status_t
! _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents)
! {
! cairo_status_t status;
! cairo_matrix_t saved_font_matrix;
! double scale_x, scale_y;
! cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
! _cairo_matrix_compute_scale_factors (&gstate->ctm, &scale_x, &scale_y);
! cairo_matrix_scale (&gstate->font->matrix, scale_x, scale_y);
! status = _cairo_font_glyph_extents (gstate->font,
! glyphs, num_glyphs,
! extents);
! cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
! extents->x_bearing /= scale_x;
! extents->y_bearing /= scale_y;
! extents->width /= scale_x;
! extents->height /= scale_y;
! extents->x_advance /= scale_x;
! extents->y_advance /= scale_y;
return status;
--- 2023,2198 ----
cairo_matrix_t *matrix)
{
! cairo_matrix_t tmp;
! double a, b, c, d, tx, ty;
! cairo_matrix_get_affine (matrix, &a, &b, &c, &d, &tx, &ty);
! cairo_matrix_set_affine (&tmp, a, b, c, d, 0, 0);
! return cairo_matrix_multiply (&gstate->font_matrix, &gstate->font_matrix, &tmp);
}
+
cairo_status_t
_cairo_gstate_current_font (cairo_gstate_t *gstate,
cairo_font_t **font)
{
! cairo_font_scale_t scale;
! cairo_font_t *scaled;
! double dummy;
!
! scaled = malloc (sizeof (cairo_font_t));
! if (scaled == NULL)
! return CAIRO_STATUS_NO_MEMORY;
!
! cairo_matrix_get_affine (&gstate->font_matrix,
! &scale.matrix[0][0],
! &scale.matrix[0][1],
! &scale.matrix[1][0],
! &scale.matrix[1][1],
! &dummy, &dummy);
!
! _cairo_font_init (scaled, &scale, gstate->font);
! _cairo_unscaled_font_reference (gstate->font);
!
! *font = scaled;
return CAIRO_STATUS_SUCCESS;
}
! void
! _cairo_gstate_set_font_transform (cairo_gstate_t *gstate,
! cairo_matrix_t *matrix)
{
! cairo_matrix_copy (&gstate->font_matrix, matrix);
! }
! void
! _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
! cairo_matrix_t *matrix)
! {
! cairo_matrix_copy (matrix, &gstate->font_matrix);
}
+ /*
+ * Like everything else in this file, fonts involve Too Many Coordinate Spaces;
+ * it is easy to get confused about what's going on.
+ *
+ * The user's view
+ * ---------------
+ *
+ * Users ask for things in user space. When cairo starts, a user space unit
+ * is about 1/96 inch, which is similar to (but importantly different from)
+ * the normal "point" units most users think in terms of. When a user
+ * selects a font, its scale is set to "one user unit". The user can then
+ * independently scale the user coordinate system *or* the font matrix, in
+ * order to adjust the rendered size of the font.
+ *
+ * If the user asks for a permanent reference to "a font", they are given a
+ * handle to a structure holding a scale matrix and an unscaled font. This
+ * effectively decouples the font from further changes to user space. Even
+ * if the user then "sets" the current cairo_t font to the handle they were
+ * passed, further changes to the cairo_t CTM will not affect externally
+ * held references to the font.
+ *
+ *
+ * The font's view
+ * ---------------
+ *
+ * Fonts are designed and stored (in say .ttf files) in "font space", which
+ * describes an "EM Square" (a design tile) and has some abstract number
+ * such as 1000, 1024, or 2048 units per "EM". This is basically an
+ * uninteresting space for us, but we need to remember that it exists.
+ *
+ * Font resources (from libraries or operating systems) render themselves
+ * to a particular device. Since they do not want to make most programmers
+ * worry about the font design space, the scaling API is simplified to
+ * involve just telling the font the required pixel size of the EM square
+ * (that is, in device space).
+ *
+ *
+ * Cairo's gstate view
+ * -------------------
+ *
+ * In addition to the CTM and CTM inverse, we keep a matrix in the gstate
+ * called the "font matrix" which describes the user's most recent
+ * font-scaling or font-transforming request. This is kept in terms of an
+ * abstract scale factor, composed with the CTM and used to set the font's
+ * pixel size. So if the user asks to "scale the font by 12", the matrix
+ * is:
+ *
+ * [ 12.0, 0.0, 0.0, 12.0, 0.0, 0.0 ]
+ *
+ * It is an affine matrix, like all cairo matrices, but its tx and ty
+ * components are always set to zero; we don't permit "nudging" fonts
+ * around.
+ *
+ * In order to perform any action on a font, we must build an object
+ * called a cairo_font_scale_t; this contains the central 2x2 matrix
+ * resulting from "font matrix * CTM".
+ *
+ * We pass this to the font when making requests of it, which causes it to
+ * reply for a particular [user request, device] combination, under the CTM
+ * (to accomodate the "zoom in" == "bigger fonts" issue above).
+ *
+ * The other terms in our communication with the font are therefore in
+ * device space. When we ask it to perform text->glyph conversion, it will
+ * produce a glyph string in device space. Glyph vectors we pass to it for
+ * measuring or rendering should be in device space. The metrics which we
+ * get back from the font will be in device space. The contents of the
+ * global glyph image cache will be in device space.
+ *
+ *
+ * Cairo's public view
+ * -------------------
+ *
+ * Since the values entering and leaving via public API calls are in user
+ * space, the gstate functions typically need to multiply argumens by the
+ * CTM (for user-input glyph vectors), and return values by the CTM inverse
+ * (for font responses such as metrics or glyph vectors).
+ *
+ */
! static void
! _build_font_scale (cairo_gstate_t *gstate,
! cairo_font_scale_t *sc)
{
! cairo_matrix_t tmp;
! double dummy;
! cairo_matrix_multiply (&tmp, &gstate->font_matrix, &gstate->ctm);
! cairo_matrix_get_affine (&tmp,
! &sc->matrix[0][0],
! &sc->matrix[0][1],
! &sc->matrix[1][0],
! &sc->matrix[1][1],
! &dummy, &dummy);
}
cairo_status_t
! _cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
! cairo_font_extents_t *extents)
{
! cairo_int_status_t status;
! cairo_font_scale_t sc;
! double dummy = 0.0;
! _build_font_scale (gstate, &sc);
! status = _cairo_unscaled_font_font_extents (gstate->font, &sc, extents);
! /* The font responded in device space; convert to user space. */
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &dummy,
! &extents->ascent);
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &dummy,
! &extents->descent);
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &dummy,
! &extents->height);
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &extents->max_x_advance,
! &extents->max_y_advance);
return status;
***************
*** 2118,2220 ****
cairo_status_t
! _cairo_gstate_show_text (cairo_gstate_t *gstate,
! const unsigned char *utf8)
{
cairo_status_t status;
! cairo_point_t point;
! double x, y;
! cairo_matrix_t saved_font_matrix;
! cairo_pattern_t pattern;
! cairo_box_t bbox;
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
! x = 0;
! y = 0;
! cairo_matrix_transform_point (&gstate->ctm, &x, &y);
} else {
! x = _cairo_fixed_to_double (point.x);
! y = _cairo_fixed_to_double (point.y);
}
-
- cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
- cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
! _cairo_pattern_init_copy (&pattern, gstate->pattern);
!
! status = _cairo_font_text_bbox (gstate->font, gstate->surface,
! x, y, utf8, &bbox);
! if (status)
! return status;
!
! status = _cairo_gstate_create_pattern (gstate, &pattern, &bbox);
! if (status)
return status;
-
- if (gstate->clip.surface)
- {
- cairo_surface_t *intermediate;
- cairo_color_t empty_color;
! _cairo_color_init (&empty_color);
! _cairo_color_set_alpha (&empty_color, .0);
! intermediate = _cairo_surface_create_similar_solid (gstate->clip.surface,
! CAIRO_FORMAT_A8,
! gstate->clip.width,
! gstate->clip.height,
! &empty_color);
! status = _cairo_font_show_text (gstate->font,
! CAIRO_OPERATOR_ADD, pattern.source,
! intermediate,
! gstate->clip.x - pattern.source_offset.x,
! gstate->clip.y - pattern.source_offset.y,
! x - gstate->clip.x,
! y - gstate->clip.y, utf8);
! if (status)
! goto BAIL;
!
! status = _cairo_surface_composite (CAIRO_OPERATOR_IN,
! gstate->clip.surface,
! NULL,
! intermediate,
! 0, 0,
! 0, 0,
! 0, 0,
! gstate->clip.width,
! gstate->clip.height);
! if (status)
! goto BAIL;
! status = _cairo_surface_composite (gstate->operator,
! pattern.source,
! intermediate,
! gstate->surface,
! 0, 0,
! 0, 0,
! gstate->clip.x,
! gstate->clip.y,
! gstate->clip.width,
! gstate->clip.height);
! BAIL:
! cairo_surface_destroy (intermediate);
!
! }
! else
{
! status = _cairo_font_show_text (gstate->font,
! gstate->operator, pattern.source,
! gstate->surface,
! -pattern.source_offset.x,
! -pattern.source_offset.y,
! x, y, utf8);
}
-
- cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
! _cairo_pattern_fini (&pattern);
return status;
--- 2200,2307 ----
cairo_status_t
! _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
! const unsigned char *utf8,
! cairo_glyph_t **glyphs,
! int *nglyphs)
{
cairo_status_t status;
! cairo_font_scale_t sc;
!
! cairo_point_t point;
! double dev_x, dev_y;
! int i;
!
! _build_font_scale (gstate, &sc);
status = _cairo_path_current_point (&gstate->path, &point);
if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
! dev_x = 0.0;
! dev_y = 0.0;
} else {
! dev_x = _cairo_fixed_to_double (point.x);
! dev_y = _cairo_fixed_to_double (point.y);
}
! status = _cairo_unscaled_font_text_to_glyphs (gstate->font,
! &sc, utf8, glyphs, nglyphs);
!
! if (status || !glyphs || !nglyphs || !(*glyphs) || !(nglyphs))
return status;
! /* The font responded in device space, starting from (0,0); add any
! current point offset in device space, and convert to user space. */
! for (i = 0; i < *nglyphs; ++i) {
! (*glyphs)[i].x += dev_x;
! (*glyphs)[i].y += dev_y;
! cairo_matrix_transform_point (&gstate->ctm_inverse,
! &((*glyphs)[i].x),
! &((*glyphs)[i].y));
! }
!
! return CAIRO_STATUS_SUCCESS;
! }
! cairo_status_t
! _cairo_gstate_set_font (cairo_gstate_t *gstate,
! cairo_font_t *font)
! {
! if (gstate->font != NULL)
! _cairo_unscaled_font_destroy (gstate->font);
! gstate->font = font->unscaled;
! _cairo_unscaled_font_reference (gstate->font);
! cairo_matrix_set_affine (&gstate->font_matrix,
! font->scale.matrix[0][0],
! font->scale.matrix[0][1],
! font->scale.matrix[1][0],
! font->scale.matrix[1][1],
! 0, 0);
! return CAIRO_STATUS_SUCCESS;
! }
! cairo_status_t
! _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents)
! {
! cairo_status_t status;
! cairo_glyph_t *transformed_glyphs;
! cairo_font_scale_t sc;
! int i;
! _build_font_scale (gstate, &sc);
! transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
! if (transformed_glyphs == NULL)
! return CAIRO_STATUS_NO_MEMORY;
!
! for (i = 0; i < num_glyphs; ++i)
{
! transformed_glyphs[i] = glyphs[i];
! cairo_matrix_transform_point (&gstate->ctm,
! &transformed_glyphs[i].x,
! &transformed_glyphs[i].y);
}
! status = _cairo_unscaled_font_glyph_extents (gstate->font, &sc,
! transformed_glyphs, num_glyphs,
! extents);
!
! /* The font responded in device space; convert to user space. */
!
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &extents->x_bearing,
! &extents->y_bearing);
!
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &extents->width,
! &extents->height);
!
! cairo_matrix_transform_distance (&gstate->ctm_inverse,
! &extents->x_advance,
! &extents->y_advance);
!
! free (transformed_glyphs);
return status;
***************
*** 2227,2236 ****
{
cairo_status_t status;
- cairo_matrix_t saved_font_matrix;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
cairo_pattern_t pattern;
cairo_box_t bbox;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
--- 2314,2325 ----
{
cairo_status_t status;
int i;
cairo_glyph_t *transformed_glyphs = NULL;
+ cairo_font_scale_t sc;
cairo_pattern_t pattern;
cairo_box_t bbox;
+ _build_font_scale (gstate, &sc);
+
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
***************
*** 2241,2254 ****
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&gstate->ctm,
! &(transformed_glyphs[i].x),
! &(transformed_glyphs[i].y));
}
- cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
- cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
-
_cairo_pattern_init_copy (&pattern, gstate->pattern);
! status = _cairo_font_glyph_bbox (gstate->font, gstate->surface,
! transformed_glyphs, num_glyphs, &bbox);
if (status)
return status;
--- 2330,2341 ----
transformed_glyphs[i] = glyphs[i];
cairo_matrix_transform_point (&gstate->ctm,
! &transformed_glyphs[i].x,
! &transformed_glyphs[i].y);
}
_cairo_pattern_init_copy (&pattern, gstate->pattern);
! status = _cairo_unscaled_font_glyph_bbox (gstate->font, &sc,
! transformed_glyphs, num_glyphs,
! &bbox);
if (status)
return status;
***************
*** 2278,2287 ****
}
! status = _cairo_font_show_glyphs (gstate->font,
! CAIRO_OPERATOR_ADD,
! pattern.source, intermediate,
! gstate->clip.x - pattern.source_offset.x,
! gstate->clip.y - pattern.source_offset.y,
! transformed_glyphs, num_glyphs);
if (status)
--- 2365,2375 ----
}
! status = _cairo_unscaled_font_show_glyphs (gstate->font,
! &sc,
! CAIRO_OPERATOR_ADD,
! pattern.source, intermediate,
! gstate->clip.x - pattern.source_offset.x,
! gstate->clip.y - pattern.source_offset.y,
! transformed_glyphs, num_glyphs);
if (status)
***************
*** 2318,2331 ****
else
{
! status = _cairo_font_show_glyphs (gstate->font,
! gstate->operator, pattern.source,
! gstate->surface,
! -pattern.source_offset.x,
! -pattern.source_offset.y,
! transformed_glyphs, num_glyphs);
}
- cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
-
_cairo_pattern_fini (&pattern);
--- 2406,2418 ----
else
{
! status = _cairo_unscaled_font_show_glyphs (gstate->font,
! &sc,
! gstate->operator, pattern.source,
! gstate->surface,
! -pattern.source_offset.x,
! -pattern.source_offset.y,
! transformed_glyphs, num_glyphs);
}
_cairo_pattern_fini (&pattern);
***************
*** 2335,2372 ****
}
-
- cairo_status_t
- _cairo_gstate_text_path (cairo_gstate_t *gstate,
- const unsigned char *utf8)
- {
- cairo_status_t status;
- cairo_matrix_t saved_font_matrix;
- cairo_point_t point;
- double x, y;
-
- status = _cairo_path_current_point (&gstate->path, &point);
- if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
- x = 0;
- y = 0;
- cairo_matrix_transform_point (&gstate->ctm, &x, &y);
- } else {
- x = _cairo_fixed_to_double (point.x);
- y = _cairo_fixed_to_double (point.y);
- }
-
- cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
- cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
-
- status = _cairo_font_text_path (gstate->font,
- x, y,
- utf8,
- &gstate->path);
-
- cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
-
- return status;
- }
-
-
cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
--- 2422,2425 ----
***************
*** 2377,2381 ****
int i;
cairo_glyph_t *transformed_glyphs = NULL;
! cairo_matrix_t saved_font_matrix;
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
--- 2430,2436 ----
int i;
cairo_glyph_t *transformed_glyphs = NULL;
! cairo_font_scale_t sc;
!
! _build_font_scale (gstate, &sc);
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
***************
*** 2391,2402 ****
}
! cairo_matrix_copy (&saved_font_matrix, &gstate->font->matrix);
! cairo_matrix_multiply (&gstate->font->matrix, &gstate->ctm, &gstate->font->matrix);
!
! status = _cairo_font_glyph_path (gstate->font,
! transformed_glyphs, num_glyphs,
! &gstate->path);
!
! cairo_matrix_copy (&gstate->font->matrix, &saved_font_matrix);
free (transformed_glyphs);
--- 2446,2452 ----
}
! status = _cairo_unscaled_font_glyph_path (gstate->font, &sc,
! transformed_glyphs, num_glyphs,
! &gstate->path);
free (transformed_glyphs);
Index: cairo_image_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_image_surface.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** cairo_image_surface.c 4 Sep 2004 13:38:34 -0000 1.16
--- cairo_image_surface.c 8 Oct 2004 19:09:51 -0000 1.17
***************
*** 526,529 ****
_cairo_image_surface_show_page,
_cairo_image_abstract_surface_set_clip_region,
! _cairo_image_abstract_surface_create_pattern
};
--- 526,530 ----
_cairo_image_surface_show_page,
_cairo_image_abstract_surface_set_clip_region,
! _cairo_image_abstract_surface_create_pattern,
! NULL /* show_glyphs */
};
Index: cairo_png_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_png_surface.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** cairo_png_surface.c 28 May 2004 19:37:15 -0000 1.8
--- cairo_png_surface.c 8 Oct 2004 19:09:51 -0000 1.9
***************
*** 383,386 ****
_cairo_png_surface_show_page,
_cairo_png_surface_set_clip_region,
! _cairo_png_surface_create_pattern
};
--- 383,387 ----
_cairo_png_surface_show_page,
_cairo_png_surface_set_clip_region,
! _cairo_png_surface_create_pattern,
! NULL /* show_glyphs */
};
Index: cairo_ps_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_ps_surface.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** cairo_ps_surface.c 4 Sep 2004 13:38:35 -0000 1.13
--- cairo_ps_surface.c 8 Oct 2004 19:09:51 -0000 1.14
***************
*** 437,440 ****
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region,
! _cairo_ps_surface_create_pattern
};
--- 437,441 ----
_cairo_ps_surface_show_page,
_cairo_ps_surface_set_clip_region,
! _cairo_ps_surface_create_pattern,
! NULL /* show_glyphs */
};
Index: cairo_xcb_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xcb_surface.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** cairo_xcb_surface.c 30 Sep 2004 20:34:19 -0000 1.11
--- cairo_xcb_surface.c 8 Oct 2004 19:09:51 -0000 1.12
***************
*** 746,750 ****
_cairo_xcb_surface_show_page,
_cairo_xcb_surface_set_clip_region,
! _cairo_xcb_surface_create_pattern
};
--- 746,751 ----
_cairo_xcb_surface_show_page,
_cairo_xcb_surface_set_clip_region,
! _cairo_xcb_surface_create_pattern,
! NULL /* show_glyphs */
};
Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** cairo_xlib_surface.c 4 Sep 2004 13:38:35 -0000 1.24
--- cairo_xlib_surface.c 8 Oct 2004 19:09:51 -0000 1.25
***************
*** 632,635 ****
--- 632,637 ----
XUnionRectWithRegion (&xr, xregion, xregion);
rects = malloc(sizeof(XRectangle));
+ if (rects == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
rects[0] = xr;
m = 1;
***************
*** 642,645 ****
--- 644,649 ----
return CAIRO_STATUS_SUCCESS;
rects = malloc(sizeof(XRectangle) * n);
+ if (rects == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
box = pixman_region_rects (region);
xregion = XCreateRegion();
***************
*** 662,666 ****
free(rects);
if (surf->picture)
! XRenderSetPictureClipRegion (surf->dpy, surf->picture, xregion);
XDestroyRegion(xregion);
XSetGraphicsExposures(surf->dpy, surf->gc, gc_values.graphics_exposures);
--- 666,670 ----
free(rects);
if (surf->picture)
! XRenderSetPictureClipRegion (surf->dpy, surf->picture, xregion);
XDestroyRegion(xregion);
XSetGraphicsExposures(surf->dpy, surf->gc, gc_values.graphics_exposures);
***************
*** 676,679 ****
--- 680,694 ----
}
+ static cairo_status_t
+ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ cairo_surface_t *source,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs);
+
static const struct cairo_surface_backend cairo_xlib_surface_backend = {
_cairo_xlib_surface_create_similar,
***************
*** 691,695 ****
_cairo_xlib_surface_show_page,
_cairo_xlib_surface_set_clip_region,
! _cairo_xlib_surface_create_pattern
};
--- 706,711 ----
_cairo_xlib_surface_show_page,
_cairo_xlib_surface_set_clip_region,
! _cairo_xlib_surface_create_pattern,
! _cairo_xlib_surface_show_glyphs
};
***************
*** 762,763 ****
--- 778,1288 ----
}
DEPRECATE (cairo_surface_create_for_drawable, cairo_xlib_surface_create);
+
+
+ /* RENDER glyphset cache code */
+
+ typedef struct glyphset_cache {
+ cairo_cache_t base;
+ struct glyphset_cache *next;
+ Display *display;
+ XRenderPictFormat *a8_pict_format;
+ GlyphSet glyphset;
+ Glyph counter;
+ } glyphset_cache_t;
+
+ typedef struct {
+ cairo_glyph_cache_key_t key;
+ Glyph glyph;
+ XGlyphInfo info;
+ } glyphset_cache_entry_t;
+
+ static Glyph
+ _next_xlib_glyph (glyphset_cache_t *cache)
+ {
+ return ++(cache->counter);
+ }
+
+
+ static cairo_status_t
+ _xlib_glyphset_cache_create_entry (void *cache,
+ void *key,
+ void **return_entry)
+ {
+ glyphset_cache_t *g = (glyphset_cache_t *) cache;
+ cairo_glyph_cache_key_t *k = (cairo_glyph_cache_key_t *)key;
+ glyphset_cache_entry_t *v;
+
+ cairo_status_t status;
+
+ cairo_cache_t *im_cache;
+ cairo_image_glyph_cache_entry_t *im;
+
+ v = malloc (sizeof (glyphset_cache_entry_t));
+ _cairo_lock_global_image_glyph_cache ();
+ im_cache = _cairo_get_global_image_glyph_cache ();
+
+ if (g == NULL || v == NULL ||g == NULL || im_cache == NULL) {
+ _cairo_unlock_global_image_glyph_cache ();
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ status = _cairo_cache_lookup (im_cache, key, (void **) (&im));
+ if (status != CAIRO_STATUS_SUCCESS || im == NULL) {
+ _cairo_unlock_global_image_glyph_cache ();
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ v->key = *k;
+ _cairo_unscaled_font_reference (v->key.unscaled);
+
+ v->glyph = _next_xlib_glyph (g);
+
+ v->info.width = im->image ? im->image->stride : im->size.width;
+ v->info.height = im->size.height;
+ v->info.x = - im->extents.x_bearing;
+ v->info.y = im->extents.y_bearing;
+ v->info.xOff = 0;
+ v->info.yOff = 0;
+
+ XRenderAddGlyphs (g->display, g->glyphset,
+ &(v->glyph), &(v->info), 1,
+ im->image ? im->image->data : NULL,
+ im->image ? v->info.height * v->info.width : 0);
+
+ v->key.base.memory = im->image ? im->image->width * im->image->stride : 0;
+ *return_entry = v;
+ _cairo_unlock_global_image_glyph_cache ();
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ static void
+ _xlib_glyphset_cache_destroy_cache (void *cache)
+ {
+ /* FIXME: will we ever release glyphset caches? */
+ }
+
+ static void
+ _xlib_glyphset_cache_destroy_entry (void *cache, void *entry)
+ {
+ glyphset_cache_t *g;
+ glyphset_cache_entry_t *v;
+
+ g = (glyphset_cache_t *) cache;
+ v = (glyphset_cache_entry_t *) entry;
+
+ _cairo_unscaled_font_destroy (v->key.unscaled);
+ XRenderFreeGlyphs (g->display, g->glyphset, &(v->glyph), 1);
+ free (v);
+ }
+
+ const cairo_cache_backend_t _xlib_glyphset_cache_backend = {
+ _cairo_glyph_cache_hash,
+ _cairo_glyph_cache_keys_equal,
+ _xlib_glyphset_cache_create_entry,
+ _xlib_glyphset_cache_destroy_entry,
+ _xlib_glyphset_cache_destroy_cache
+ };
+
+
+ static glyphset_cache_t *
+ _xlib_glyphset_caches = NULL;
+
+ static void
+ _lock_xlib_glyphset_caches (void)
+ {
+ /* FIXME: implement locking */
+ }
+
+ static void
+ _unlock_xlib_glyphset_caches (void)
+ {
+ /* FIXME: implement locking */
+ }
+
+ static glyphset_cache_t *
+ _get_glyphset_cache (Display *d)
+ {
+ /*
+ * There should usually only be one, or a very small number, of
+ * displays. So we just do a linear scan.
+ */
+
+ glyphset_cache_t *g;
+
+ for (g = _xlib_glyphset_caches; g != NULL; g = g->next) {
+ if (g->display == d)
+ return g;
+ }
+
+ g = malloc (sizeof (glyphset_cache_t));
+ if (g == NULL)
+ goto ERR;
+
+ g->counter = 0;
+ g->display = d;
+ g->a8_pict_format = XRenderFindStandardFormat (d, PictStandardA8);
+ if (g->a8_pict_format == NULL)
+ goto ERR;
+
+ if (_cairo_cache_init (&g->base,
+ &_xlib_glyphset_cache_backend,
+ CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT))
+ goto FREE_GLYPHSET_CACHE;
+
+ g->glyphset = XRenderCreateGlyphSet (d, g->a8_pict_format);
+ g->next = _xlib_glyphset_caches;
+ _xlib_glyphset_caches = g;
+ return g;
+
+ FREE_GLYPHSET_CACHE:
+ free (g);
+
+ ERR:
+ return NULL;
+ }
+
+ #define N_STACK_BUF 1024
+
+ static cairo_status_t
+ _cairo_xlib_surface_show_glyphs32 (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ glyphset_cache_t *g,
+ cairo_glyph_cache_key_t *key,
+ cairo_xlib_surface_t *src,
+ cairo_xlib_surface_t *self,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ glyphset_cache_entry_t **entries,
+ int num_glyphs)
+ {
+ XGlyphElt32 *elts = NULL;
+ XGlyphElt32 stack_elts [N_STACK_BUF];
+
+ unsigned int *chars = NULL;
+ unsigned int stack_chars [N_STACK_BUF];
+
+ int i;
+ int lastX = 0, lastY = 0;
+
+ /* Acquire arrays of suitable sizes. */
+ if (num_glyphs < N_STACK_BUF) {
+ elts = stack_elts;
+ chars = stack_chars;
+
+ } else {
+ elts = malloc (num_glyphs * sizeof (XGlyphElt32));
+ if (elts == NULL)
+ goto FAIL;
+
+ chars = malloc (num_glyphs * sizeof (unsigned int));
+ if (chars == NULL)
+ goto FREE_ELTS;
+
+ }
+
+ for (i = 0; i < num_glyphs; ++i) {
+ chars[i] = entries[i]->glyph;
+ elts[i].chars = &(chars[i]);
+ elts[i].nchars = 1;
+ elts[i].glyphset = g->glyphset;
+ elts[i].xOff = glyphs[i].x - lastX;
+ elts[i].yOff = glyphs[i].y - lastY;
+ lastX = glyphs[i].x;
+ lastY = glyphs[i].y;
+ }
+
+ XRenderCompositeText32 (self->dpy,
+ _render_operator (operator),
+ src->picture,
+ self->picture,
+ g->a8_pict_format,
+ source_x, source_y,
+ 0, 0,
+ elts, num_glyphs);
+
+ if (num_glyphs >= N_STACK_BUF) {
+ free (chars);
+ free (elts);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+ FREE_ELTS:
+ if (num_glyphs >= N_STACK_BUF)
+ free (elts);
+
+ FAIL:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+
+ static cairo_status_t
+ _cairo_xlib_surface_show_glyphs16 (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ glyphset_cache_t *g,
+ cairo_glyph_cache_key_t *key,
+ cairo_xlib_surface_t *src,
+ cairo_xlib_surface_t *self,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ glyphset_cache_entry_t **entries,
+ int num_glyphs)
+ {
+ XGlyphElt16 *elts = NULL;
+ XGlyphElt16 stack_elts [N_STACK_BUF];
+
+ unsigned short *chars = NULL;
+ unsigned short stack_chars [N_STACK_BUF];
+
+ int i;
+ int lastX = 0, lastY = 0;
+
+ /* Acquire arrays of suitable sizes. */
+ if (num_glyphs < N_STACK_BUF) {
+ elts = stack_elts;
+ chars = stack_chars;
+
+ } else {
+ elts = malloc (num_glyphs * sizeof (XGlyphElt16));
+ if (elts == NULL)
+ goto FAIL;
+
+ chars = malloc (num_glyphs * sizeof (unsigned short));
+ if (chars == NULL)
+ goto FREE_ELTS;
+
+ }
+
+ for (i = 0; i < num_glyphs; ++i) {
+ chars[i] = entries[i]->glyph;
+ elts[i].chars = &(chars[i]);
+ elts[i].nchars = 1;
+ elts[i].glyphset = g->glyphset;
+ elts[i].xOff = glyphs[i].x - lastX;
+ elts[i].yOff = glyphs[i].y - lastY;
+ lastX = glyphs[i].x;
+ lastY = glyphs[i].y;
+ }
+
+ XRenderCompositeText16 (self->dpy,
+ _render_operator (operator),
+ src->picture,
+ self->picture,
+ g->a8_pict_format,
+ source_x, source_y,
+ 0, 0,
+ elts, num_glyphs);
+
+ if (num_glyphs >= N_STACK_BUF) {
+ free (chars);
+ free (elts);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+ FREE_ELTS:
+ if (num_glyphs >= N_STACK_BUF)
+ free (elts);
+
+ FAIL:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ static cairo_status_t
+ _cairo_xlib_surface_show_glyphs8 (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ glyphset_cache_t *g,
+ cairo_glyph_cache_key_t *key,
+ cairo_xlib_surface_t *src,
+ cairo_xlib_surface_t *self,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ glyphset_cache_entry_t **entries,
+ int num_glyphs)
+ {
+ XGlyphElt8 *elts = NULL;
+ XGlyphElt8 stack_elts [N_STACK_BUF];
+
+ char *chars = NULL;
+ char stack_chars [N_STACK_BUF];
+
+ int i;
+ int lastX = 0, lastY = 0;
+
+ /* Acquire arrays of suitable sizes. */
+ if (num_glyphs < N_STACK_BUF) {
+ elts = stack_elts;
+ chars = stack_chars;
+
+ } else {
+ elts = malloc (num_glyphs * sizeof (XGlyphElt8));
+ if (elts == NULL)
+ goto FAIL;
+
+ chars = malloc (num_glyphs * sizeof (char));
+ if (chars == NULL)
+ goto FREE_ELTS;
+
+ }
+
+ for (i = 0; i < num_glyphs; ++i) {
+ chars[i] = entries[i]->glyph;
+ elts[i].chars = &(chars[i]);
+ elts[i].nchars = 1;
+ elts[i].glyphset = g->glyphset;
+ elts[i].xOff = glyphs[i].x - lastX;
+ elts[i].yOff = glyphs[i].y - lastY;
+ lastX = glyphs[i].x;
+ lastY = glyphs[i].y;
+ }
+
+ XRenderCompositeText8 (self->dpy,
+ _render_operator (operator),
+ src->picture,
+ self->picture,
+ g->a8_pict_format,
+ source_x, source_y,
+ 0, 0,
+ elts, num_glyphs);
+
+ if (num_glyphs >= N_STACK_BUF) {
+ free (chars);
+ free (elts);
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+
+ FREE_ELTS:
+ if (num_glyphs >= N_STACK_BUF)
+ free (elts);
+
+ FAIL:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+
+ static cairo_status_t
+ _cairo_xlib_surface_show_glyphs (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ cairo_surface_t *source,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs)
+ {
+ unsigned int elt_size;
+ cairo_xlib_surface_t *self = (cairo_xlib_surface_t *) surface;
+ cairo_image_surface_t *tmp = NULL;
+ cairo_xlib_surface_t *src = NULL;
+ glyphset_cache_t *g;
+ cairo_status_t status;
+ cairo_glyph_cache_key_t key;
+ glyphset_cache_entry_t **entries;
+ glyphset_cache_entry_t *stack_entries [N_STACK_BUF];
+ int i;
+
+ /* Acquire an entry array of suitable size. */
+ if (num_glyphs < N_STACK_BUF) {
+ entries = stack_entries;
+
+ } else {
+ entries = malloc (num_glyphs * sizeof (glyphset_cache_entry_t *));
+ if (entries == NULL)
+ goto FAIL;
+ }
+
+ /* prep the source surface. */
+ if (source->backend == surface->backend) {
+ src = (cairo_xlib_surface_t *) source;
+
+ } else {
+ tmp = _cairo_surface_get_image (source);
+ if (tmp == NULL)
+ goto FREE_ENTRIES;
+
+ src = (cairo_xlib_surface_t *)
+ _cairo_surface_create_similar_scratch (surface, self->format, 1,
+ tmp->width, tmp->height);
+
+ if (src == NULL)
+ goto FREE_TMP;
+
+ if (_cairo_surface_set_image (&(src->base), tmp) != CAIRO_STATUS_SUCCESS)
+ goto FREE_SRC;
+ }
+
+ _lock_xlib_glyphset_caches ();
+ g = _get_glyphset_cache (self->dpy);
+ if (g == NULL)
+ goto UNLOCK;
+
+ /* Work out the index size to use. */
+ elt_size = 8;
+ key.scale = *scale;
+ key.unscaled = font;
+
+ for (i = 0; i < num_glyphs; ++i) {
+ key.index = glyphs[i].index;
+ status = _cairo_cache_lookup (&g->base, &key, (void **) (&entries[i]));
+ if (status != CAIRO_STATUS_SUCCESS || entries[i] == NULL)
+ goto UNLOCK;
+
+ if (elt_size == 8 && entries[i]->glyph > 0xff)
+ elt_size = 16;
+ if (elt_size == 16 && entries[i]->glyph > 0xffff) {
+ elt_size = 32;
+ break;
+ }
+ }
+
+ /* Call the appropriate sub-function. */
+
+ if (elt_size == 8)
+ status = _cairo_xlib_surface_show_glyphs8 (font, scale, operator, g, &key, src, self,
+ source_x, source_y,
+ glyphs, entries, num_glyphs);
+ else if (elt_size == 16)
+ status = _cairo_xlib_surface_show_glyphs16 (font, scale, operator, g, &key, src, self,
+ source_x, source_y,
+ glyphs, entries, num_glyphs);
+ else
+ status = _cairo_xlib_surface_show_glyphs32 (font, scale, operator, g, &key, src, self,
+ source_x, source_y,
+ glyphs, entries, num_glyphs);
+
+ _unlock_xlib_glyphset_caches ();
+
+ if (tmp != NULL) {
+ cairo_surface_destroy (&(src->base));
+ cairo_surface_destroy (&(tmp->base));
+ }
+
+ if (num_glyphs >= N_STACK_BUF)
+ free (entries);
+
+ return status;
+
+ UNLOCK:
+ _unlock_xlib_glyphset_caches ();
+
+ FREE_SRC:
+ cairo_surface_destroy (&(src->base));
+
+ FREE_TMP:
+ cairo_surface_destroy (&(tmp->base));
+
+ FREE_ENTRIES:
+ if (num_glyphs >= N_STACK_BUF)
+ free (entries);
+
+ FAIL:
+ return CAIRO_STATUS_NO_MEMORY;
+ }
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.69
retrieving revision 1.70
diff -C2 -d -r1.69 -r1.70
*** cairoint.h 4 Sep 2004 13:38:35 -0000 1.69
--- cairoint.h 8 Oct 2004 19:09:51 -0000 1.70
***************
*** 50,54 ****
#endif
- #include <assert.h>
#include <stdlib.h>
#include <string.h>
--- 50,53 ----
***************
*** 254,303 ****
typedef struct cairo_color cairo_color_t;
typedef struct cairo_font_backend {
! cairo_font_t *(*create) (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
- cairo_font_t *(*copy) (void *font);
-
void (*destroy) (void *font);
cairo_status_t (*font_extents) (void *font,
cairo_font_extents_t *extents);
! cairo_status_t (*text_extents) (void *font,
const unsigned char *utf8,
! cairo_text_extents_t *extents);
!
cairo_status_t (*glyph_extents) (void *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
- cairo_status_t (*text_bbox) (void *font,
- cairo_surface_t *surface,
- double x,
- double y,
- const unsigned char *utf8,
- cairo_box_t *bbox);
-
cairo_status_t (*glyph_bbox) (void *font,
! cairo_surface_t *surface,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox);
- cairo_status_t (*show_text) (void *font,
- cairo_operator_t operator,
- cairo_surface_t *source,
- cairo_surface_t *surface,
- int source_x,
- int source_y,
- double x,
- double y,
- const unsigned char *utf8);
-
cairo_status_t (*show_glyphs) (void *font,
cairo_operator_t operator,
cairo_surface_t *source,
--- 253,454 ----
typedef struct cairo_color cairo_color_t;
+ typedef struct cairo_image_surface cairo_image_surface_t;
+
+ /* cairo_cache.c structures and functions */
+
+ typedef struct cairo_cache_backend {
+
+ unsigned long (*hash) (void *cache,
+ void *key);
+
+ int (*keys_equal) (void *cache,
+ void *k1,
+ void *k2);
+
+ cairo_status_t (*create_entry) (void *cache,
+ void *key,
+ void **entry_return);
+
+ void (*destroy_entry) (void *cache,
+ void *entry);
+
+ void (*destroy_cache) (void *cache);
+
+ } cairo_cache_backend_t;
+
+
+ /*
+ * The cairo_cache system makes the following assumptions about
+ * entries in its cache:
+ *
+ * - a pointer to an entry can be cast to a cairo_cache_entry_base_t.
+ * - a pointer to an entry can also be cast to the "key type".
+ *
+ * The practical effect of this is that your entries must be laid
+ * out this way:
+ *
+ * struct my_entry {
+ * cairo_cache_entry_base_t;
+ * my_key_value_1;
+ * my_key_value_2;
+ * ...
+ * my_value;
+ * };
+ */
+
+ typedef struct {
+ unsigned long memory;
+ unsigned long hashcode;
+ } cairo_cache_entry_base_t;
+
+ typedef struct {
+ unsigned long high_water_mark;
+ unsigned long size;
+ unsigned long rehash;
+ } cairo_cache_arrangement_t;
+
+ #undef CAIRO_MEASURE_CACHE_PERFORMANCE
+
+ typedef struct {
+ unsigned long refcount;
+ const cairo_cache_backend_t *backend;
+ cairo_cache_arrangement_t *arrangement;
+ cairo_cache_entry_base_t **entries;
+
+ unsigned long max_memory;
+ unsigned long used_memory;
+ unsigned long live_entries;
+
+ #ifdef CAIRO_MEASURE_CACHE_PERFORMANCE
+ unsigned long hits;
+ unsigned long misses;
+ unsigned long probes;
+ #endif
+ } cairo_cache_t;
+
+ extern cairo_status_t __internal_linkage
+ _cairo_cache_init (cairo_cache_t *cache,
+ const cairo_cache_backend_t *backend,
+ unsigned long max_memory);
+
+ extern void __internal_linkage
+ _cairo_cache_reference (cairo_cache_t *cache);
+
+ extern void __internal_linkage
+ _cairo_cache_destroy (cairo_cache_t *cache);
+
+ extern cairo_status_t __internal_linkage
+ _cairo_cache_lookup (cairo_cache_t *cache,
+ void *key,
+ void **entry_return);
+
+ extern unsigned long __internal_linkage
+ _cairo_hash_string (const char *c);
+
+ #define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
+ #define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000
+ #define CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT 20
+ #define CAIRO_FT_CACHE_NUM_FONTS_DEFAULT 20
+
+ typedef struct {
+ double matrix[2][2];
+ } cairo_font_scale_t;
+
+ struct cairo_font_backend;
+
+ typedef struct {
+ int refcount;
+ const struct cairo_font_backend *backend;
+ } cairo_unscaled_font_t;
+
+ /*
+ * A cairo_font contains a pointer to a cairo_sizeless_font_t and a scale
+ * matrix. These are the things the user holds references to.
+ */
+
+ struct cairo_font {
+ int refcount;
+ cairo_font_scale_t scale;
+ cairo_unscaled_font_t *unscaled;
+ };
+
+
+ /* cairo_font.c is responsible for two global caches:
+ *
+ * - font entries: [[[base], name, weight, slant], cairo_unscaled_font_t ]
+ * - glyph entries: [[[base], cairo_font_t, index], image, size, extents ]
+ *
+ * Surfaces may build their own glyph caches if they have surface-specific
+ * glyph resources to maintain; those caches can feed off of the global
+ * caches if need be (eg. cairo_xlib_surface.c does this).
+ */
+
+ typedef struct {
+ cairo_cache_entry_base_t base;
+ cairo_unscaled_font_t *unscaled;
+ cairo_font_scale_t scale;
+ unsigned long index;
+ } cairo_glyph_cache_key_t;
+
+ typedef struct {
+ cairo_glyph_cache_key_t key;
+ cairo_image_surface_t *image;
+ cairo_glyph_size_t size;
+ cairo_text_extents_t extents;
+ } cairo_image_glyph_cache_entry_t;
+
+ extern void __internal_linkage
+ _cairo_lock_global_image_glyph_cache (void);
+
+ extern void __internal_linkage
+ _cairo_unlock_global_image_glyph_cache (void);
+
+ extern cairo_cache_t * __internal_linkage
+ _cairo_get_global_image_glyph_cache (void);
+
+ /* Some glyph cache functions you can reuse. */
+
+ extern unsigned long __internal_linkage
+ _cairo_glyph_cache_hash (void *cache, void *key);
+
+ extern int __internal_linkage
+ _cairo_glyph_cache_keys_equal (void *cache,
+ void *k1,
+ void *k2);
+
+
+ /* the font backend interface */
typedef struct cairo_font_backend {
! cairo_unscaled_font_t *(*create) (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight);
void (*destroy) (void *font);
cairo_status_t (*font_extents) (void *font,
+ cairo_font_scale_t *scale,
cairo_font_extents_t *extents);
! cairo_status_t (*text_to_glyphs) (void *font,
! cairo_font_scale_t *scale,
const unsigned char *utf8,
! cairo_glyph_t **glyphs,
! int *num_glyphs);
!
cairo_status_t (*glyph_extents) (void *font,
+ cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_text_extents_t *extents);
cairo_status_t (*glyph_bbox) (void *font,
! cairo_font_scale_t *scale,
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_box_t *bbox);
cairo_status_t (*show_glyphs) (void *font,
+ cairo_font_scale_t *scale,
cairo_operator_t operator,
cairo_surface_t *source,
***************
*** 308,324 ****
int num_glyphs);
- cairo_status_t (*text_path) (void *font,
- double x,
- double y,
- const unsigned char *utf8,
- cairo_path_t *path);
-
cairo_status_t (*glyph_path) (void *font,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
! cairo_surface_t *(*create_glyph) (void *font,
! const cairo_glyph_t *glyph,
! cairo_glyph_size_t *return_size);
} cairo_font_backend_t;
--- 459,470 ----
int num_glyphs);
cairo_status_t (*glyph_path) (void *font,
+ cairo_font_scale_t *scale,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_path_t *path);
!
! cairo_status_t (*create_glyph) (cairo_image_glyph_cache_entry_t *entry);
!
} cairo_font_backend_t;
***************
*** 326,330 ****
extern const struct cairo_font_backend cairo_ft_font_backend;
- typedef struct cairo_image_surface cairo_image_surface_t;
typedef struct cairo_surface_backend {
--- 472,475 ----
***************
*** 411,414 ****
--- 556,576 ----
cairo_pattern_t *pattern,
cairo_box_t *extents);
+
+ /*
+ * This is an optional entry to let the surface manage its own glyph
+ * resources. If null, the font will be asked to render against this
+ * surface, using image surfaces as glyphs.
+ */
+ cairo_status_t
+ (*show_glyphs) (cairo_unscaled_font_t *font,
+ cairo_font_scale_t *scale,
+ cairo_operator_t operator,
+ cairo_surface_t *source,
+ cairo_surface_t *surface,
+ int source_x,
+ int source_y,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs);
+
} cairo_surface_backend_t;
***************
*** 548,585 ****
#define CAIRO_FONT_BACKEND_DEFAULT &cairo_ft_font_backend
- #define CAIRO_FONT_CACHE_SIZE_DEFAULT 256
-
- typedef struct {
- unsigned long index;
- double matrix[2][2];
-
- unsigned int time;
-
- cairo_surface_t *surface;
- cairo_glyph_size_t size;
- } cairo_glyph_surface_t;
-
- typedef struct cairo_glyph_surface_node {
- struct cairo_glyph_surface_node *next;
- struct cairo_glyph_surface_node *prev;
-
- cairo_glyph_surface_t s;
- } cairo_glyph_surface_node_t;
-
- typedef struct {
- cairo_glyph_surface_node_t *first;
- cairo_glyph_surface_node_t *last;
- unsigned int n_nodes;
-
- unsigned int ref_count;
- unsigned int cache_size;
- } cairo_glyph_cache_t;
-
- struct cairo_font {
- int refcount;
- cairo_matrix_t matrix;
- cairo_glyph_cache_t *glyph_cache;
- const struct cairo_font_backend *backend;
- };
#define CAIRO_GSTATE_OPERATOR_DEFAULT CAIRO_OPERATOR_OVER
--- 710,713 ----
***************
*** 619,623 ****
double dash_offset;
! cairo_font_t *font;
cairo_surface_t *surface;
--- 747,751 ----
double dash_offset;
! cairo_unscaled_font_t *font;
cairo_surface_t *surface;
***************
*** 629,632 ****
--- 757,763 ----
double pixels_per_inch;
+
+ cairo_matrix_t font_matrix;
+
cairo_matrix_t ctm;
cairo_matrix_t ctm_inverse;
***************
*** 936,939 ****
--- 1067,1078 ----
cairo_font_t **font);
+ extern void __internal_linkage
+ _cairo_gstate_set_font_transform (cairo_gstate_t *gstate,
+ cairo_matrix_t *matrix);
+
+ extern void __internal_linkage
+ _cairo_gstate_current_font_transform (cairo_gstate_t *gstate,
+ cairo_matrix_t *matrix);
+
extern cairo_status_t __internal_linkage
_cairo_gstate_current_font_extents (cairo_gstate_t *gstate,
***************
*** 944,952 ****
cairo_font_t *font);
-
extern cairo_status_t __internal_linkage
! _cairo_gstate_text_extents (cairo_gstate_t *gstate,
! const unsigned char *utf8,
! cairo_text_extents_t *extents);
extern cairo_status_t __internal_linkage
--- 1083,1091 ----
cairo_font_t *font);
extern cairo_status_t __internal_linkage
! _cairo_gstate_text_to_glyphs (cairo_gstate_t *font,
! const unsigned char *utf8,
! cairo_glyph_t **glyphs,
! int *num_glyphs);
extern cairo_status_t __internal_linkage
***************
*** 957,964 ****
extern cairo_status_t __internal_linkage
- _cairo_gstate_show_text (cairo_gstate_t *gstate,
- const unsigned char *utf8);
-
- extern cairo_status_t __internal_linkage
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
--- 1096,1099 ----
***************
*** 966,973 ****
extern cairo_status_t __internal_linkage
- _cairo_gstate_text_path (cairo_gstate_t *gstate,
- const unsigned char *utf8);
-
- extern cairo_status_t __internal_linkage
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
cairo_glyph_t *glyphs,
--- 1101,1104 ----
***************
*** 993,1085 ****
/* cairo_font.c */
! extern cairo_font_t * __internal_linkage
! _cairo_font_create (const char *family,
! cairo_font_slant_t slant,
! cairo_font_weight_t weight);
!
! extern cairo_status_t __internal_linkage
! _cairo_font_init (cairo_font_t *font,
! const struct cairo_font_backend *backend);
!
! extern cairo_font_t * __internal_linkage
! _cairo_font_copy (cairo_font_t *font);
!
! extern cairo_status_t __internal_linkage
! _cairo_font_scale (cairo_font_t *font, double scale);
! extern cairo_status_t __internal_linkage
! _cairo_font_transform (cairo_font_t *font, cairo_matrix_t *matrix);
extern cairo_status_t __internal_linkage
! _cairo_font_font_extents (cairo_font_t *font,
! cairo_font_extents_t *extents);
! extern cairo_status_t __internal_linkage
! _cairo_font_text_extents (cairo_font_t *font,
! const unsigned char *utf8,
! cairo_text_extents_t *extents);
! extern cairo_status_t __internal_linkage
! _cairo_font_glyph_extents (cairo_font_t *font,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents);
extern cairo_status_t __internal_linkage
! _cairo_font_text_bbox (cairo_font_t *font,
! cairo_surface_t *surface,
! double x,
! double y,
! const unsigned char *utf8,
! cairo_box_t *bbox);
extern cairo_status_t __internal_linkage
! _cairo_font_glyph_bbox (cairo_font_t *font,
! cairo_surface_t *surface,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_box_t *bbox);
extern cairo_status_t __internal_linkage
! _cairo_font_show_text (cairo_font_t *font,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! double x,
! double y,
! const unsigned char *utf8);
!
extern cairo_status_t __internal_linkage
! _cairo_font_show_glyphs (cairo_font_t *font,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! cairo_glyph_t *glyphs,
! int num_glyphs);
!
extern cairo_status_t __internal_linkage
! _cairo_font_text_path (cairo_font_t *font,
! double x,
! double y,
! const unsigned char *utf8,
! cairo_path_t *path);
extern cairo_status_t __internal_linkage
! _cairo_font_glyph_path (cairo_font_t *font,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_path_t *path);
!
! extern cairo_surface_t *__internal_linkage
! _cairo_font_lookup_glyph (cairo_font_t *font,
! cairo_surface_t *surface,
! const cairo_glyph_t *glyph,
! cairo_glyph_size_t *return_size);
/* cairo_hull.c */
--- 1124,1190 ----
/* cairo_font.c */
! extern cairo_unscaled_font_t * __internal_linkage
! _cairo_unscaled_font_create (const char *family,
! cairo_font_slant_t slant,
! cairo_font_weight_t weight);
! extern void __internal_linkage
! _cairo_font_init (cairo_font_t *scaled,
! cairo_font_scale_t *scale,
! cairo_unscaled_font_t *unscaled);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_init (cairo_unscaled_font_t *font,
! const struct cairo_font_backend *backend);
! extern void __internal_linkage
! _cairo_unscaled_font_reference (cairo_unscaled_font_t *font);
! extern void __internal_linkage
! _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_font_extents (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_font_extents_t *extents);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_text_to_glyphs (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! const unsigned char *utf8,
! cairo_glyph_t **glyphs,
! int *num_glyphs);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_glyph_extents (cairo_unscaled_font_t *font,
! cairo_font_scale_t *scale,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_text_extents_t *extents);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_glyph_bbox (cairo_unscaled_font_t *font,
! cairo_font_scale_t *size,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_box_t *bbox);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_show_glyphs (cairo_unscaled_font_t *font,
! cairo_font_scale_t *size,
! cairo_operator_t operator,
! cairo_surface_t *source,
! cairo_surface_t *surface,
! int source_x,
! int source_y,
! cairo_glyph_t *glyphs,
! int num_glyphs);
extern cairo_status_t __internal_linkage
! _cairo_unscaled_font_glyph_path (cairo_unscaled_font_t *font,
! cairo_font_scale_t *size,
! cairo_glyph_t *glyphs,
! int num_glyphs,
! cairo_path_t *path);
/* cairo_hull.c */
More information about the cairo-commit
mailing list