mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-20 03:40:45 +02:00
SVG: Discard custom font subsetting in favor of sharing cairo-scaled-font-subsets
This commit is contained in:
parent
f459c1f0de
commit
7c137b7e2c
2 changed files with 45 additions and 229 deletions
2
ROADMAP
2
ROADMAP
|
|
@ -71,7 +71,7 @@ We don't expect to release without these being complete.
|
|||
cairo_set_line_width should immediately use CTM
|
||||
_transform_glyph_bitmap http://lists.freedesktop.org/archives/cairo/2005-October/005564.html
|
||||
6759 fontconfig option AntiAlias doesn't work in cairo 1.1.2
|
||||
PS/PDF subsetting code needs bitmapped-glyph support
|
||||
SVG/PS/PDF emit_glyph functions need to support bitmapped glyphs
|
||||
|
||||
Fix memory leaks
|
||||
1. Ensure 'make check-valgrind' passes with no leaks
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2005-2006 Emmanuel Pacaud <emmanuel.pacaud@free.fr>
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
* Contributor(s):
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
|
@ -42,6 +44,7 @@
|
|||
#include "cairo-ft-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
||||
#include <libxml/tree.h>
|
||||
|
||||
|
|
@ -73,19 +76,6 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
|
|||
"1.2"
|
||||
};
|
||||
|
||||
typedef struct cairo_svg_glyph {
|
||||
cairo_hash_entry_t base; /* font glyph index */
|
||||
unsigned int output_glyph; /* font glyph index */
|
||||
} cairo_svg_glyph_t;
|
||||
|
||||
typedef struct cairo_svg_font {
|
||||
cairo_hash_entry_t base;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned int output_font;
|
||||
cairo_hash_table_t *glyphs;
|
||||
unsigned int max_glyph;
|
||||
} cairo_svg_font_t;
|
||||
|
||||
struct cairo_svg_document {
|
||||
cairo_output_stream_t *output_stream;
|
||||
unsigned long refcount;
|
||||
|
|
@ -116,8 +106,7 @@ struct cairo_svg_document {
|
|||
|
||||
cairo_svg_version_t svg_version;
|
||||
|
||||
cairo_hash_table_t *fonts;
|
||||
unsigned int max_font;
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
};
|
||||
|
||||
struct cairo_svg_surface {
|
||||
|
|
@ -556,167 +545,12 @@ _cairo_svg_path_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_glyph_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
const cairo_svg_glyph_t *svg_glyph_a = key_a;
|
||||
const cairo_svg_glyph_t *svg_glyph_b = key_b;
|
||||
|
||||
return svg_glyph_a->base.hash == svg_glyph_b->base.hash;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_glyph_key_init (cairo_svg_glyph_t *svg_glyph,
|
||||
unsigned long index)
|
||||
{
|
||||
svg_glyph->base.hash = index;
|
||||
}
|
||||
|
||||
static cairo_svg_glyph_t *
|
||||
_cairo_svg_glyph_create (cairo_svg_font_t *svg_font,
|
||||
unsigned long index)
|
||||
{
|
||||
cairo_svg_glyph_t *svg_glyph = malloc (sizeof (cairo_svg_glyph_t));
|
||||
|
||||
if (!svg_glyph)
|
||||
return NULL;
|
||||
|
||||
_cairo_svg_glyph_key_init (svg_glyph, index);
|
||||
svg_glyph->output_glyph = svg_font->max_glyph++;
|
||||
|
||||
return svg_glyph;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_glyph_destroy (cairo_svg_glyph_t *svg_glyph)
|
||||
{
|
||||
free (svg_glyph);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_glyph_find (cairo_svg_font_t *font,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long index,
|
||||
cairo_svg_glyph_t **result)
|
||||
{
|
||||
cairo_svg_glyph_t key;
|
||||
cairo_svg_glyph_t *svg_glyph;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_svg_glyph_key_init (&key, index);
|
||||
if (!_cairo_hash_table_lookup (font->glyphs,
|
||||
&key.base,
|
||||
(cairo_hash_entry_t **) &svg_glyph)) {
|
||||
svg_glyph = _cairo_svg_glyph_create (font, index);
|
||||
if (!svg_glyph)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
status = _cairo_hash_table_insert (font->glyphs, &svg_glyph->base);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
*result = svg_glyph;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_font_equal (const void *key_a, const void *key_b)
|
||||
{
|
||||
const cairo_svg_font_t *svg_font_a = key_a;
|
||||
const cairo_svg_font_t *svg_font_b = key_b;
|
||||
|
||||
return svg_font_a->scaled_font == svg_font_b->scaled_font;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_font_key_init (cairo_svg_font_t *svg_font,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
/* FIXME cast a pointer to unsigned long, really ? */
|
||||
svg_font->base.hash = (unsigned long) scaled_font;
|
||||
svg_font->scaled_font = scaled_font;
|
||||
}
|
||||
|
||||
static cairo_svg_font_t *
|
||||
_cairo_svg_document_font_create (cairo_svg_document_t *document,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_svg_font_t *svg_font = malloc (sizeof (cairo_svg_font_t));
|
||||
|
||||
if (!svg_font)
|
||||
return NULL;
|
||||
|
||||
_cairo_svg_font_key_init (svg_font, scaled_font);
|
||||
svg_font->glyphs = _cairo_hash_table_create (_cairo_svg_glyph_equal);
|
||||
if (!svg_font->glyphs) {
|
||||
free (svg_font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
svg_font->max_glyph = 0;
|
||||
svg_font->output_font = document->max_font++;
|
||||
cairo_scaled_font_reference (svg_font->scaled_font);
|
||||
return svg_font;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_font_destroy_glyph (void *entry, void *closure)
|
||||
{
|
||||
cairo_svg_glyph_t *svg_glyph = entry;
|
||||
cairo_svg_font_t *svg_font = closure;
|
||||
|
||||
_cairo_hash_table_remove (svg_font->glyphs, &svg_glyph->base);
|
||||
_cairo_svg_glyph_destroy (svg_glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_font_destroy (cairo_svg_font_t *svg_font)
|
||||
{
|
||||
_cairo_hash_table_foreach (svg_font->glyphs,
|
||||
_cairo_svg_font_destroy_glyph,
|
||||
svg_font);
|
||||
_cairo_hash_table_destroy (svg_font->glyphs);
|
||||
cairo_scaled_font_destroy (svg_font->scaled_font);
|
||||
free (svg_font);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_document_destroy_font (cairo_svg_document_t *document,
|
||||
cairo_svg_font_t *svg_font)
|
||||
{
|
||||
_cairo_hash_table_remove (document->fonts, &svg_font->base);
|
||||
_cairo_svg_font_destroy (svg_font);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_font_find (cairo_svg_document_t *document,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_svg_font_t **result)
|
||||
{
|
||||
cairo_svg_font_t key;
|
||||
cairo_svg_font_t *svg_font;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_svg_font_key_init (&key, scaled_font);
|
||||
if (!_cairo_hash_table_lookup (document->fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &svg_font))
|
||||
{
|
||||
svg_font = _cairo_svg_document_font_create (document, scaled_font);
|
||||
if (!svg_font)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_hash_table_insert (document->fonts,
|
||||
&svg_font->base);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
*result = svg_font;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
||||
cairo_svg_font_t *svg_font,
|
||||
cairo_svg_glyph_t *svg_glyph)
|
||||
_cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int font_id,
|
||||
unsigned int subset_glyph_index)
|
||||
{
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
|
|
@ -724,8 +558,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
|||
xmlNodePtr symbol, child;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (svg_font->scaled_font,
|
||||
svg_glyph->base.hash,
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS|
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
&scaled_glyph);
|
||||
|
|
@ -733,8 +567,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
|||
* If that fails, try again but ask for an image instead
|
||||
*/
|
||||
if (status)
|
||||
status = _cairo_scaled_glyph_lookup (svg_font->scaled_font,
|
||||
svg_glyph->base.hash,
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS|
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
|
|
@ -755,8 +589,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
|||
symbol = xmlNewChild (document->xml_node_glyphs, NULL,
|
||||
CC2XML ("symbol"), NULL);
|
||||
snprintf (buffer, sizeof buffer, "glyph%d-%d",
|
||||
svg_font->output_font,
|
||||
svg_glyph->output_glyph);
|
||||
font_id,
|
||||
subset_glyph_index);
|
||||
xmlSetProp (symbol, CC2XML ("id"), C2XML (buffer));
|
||||
child = xmlNewChild (symbol, NULL, CC2XML ("path"), NULL);
|
||||
xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
|
||||
|
|
@ -767,47 +601,34 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
cairo_svg_document_t *document;
|
||||
cairo_svg_font_t *svg_font;
|
||||
} emit_glyph_info_t;
|
||||
|
||||
static void
|
||||
_emit_glyph (void *entry, void *closure)
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_svg_glyph_t *svg_glyph = entry;
|
||||
emit_glyph_info_t *info = closure;
|
||||
|
||||
_cairo_svg_document_emit_glyph (info->document,
|
||||
info->svg_font,
|
||||
svg_glyph);
|
||||
_cairo_svg_font_destroy_glyph (svg_glyph, info->svg_font);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_document_emit_font (void *entry, void *closure)
|
||||
{
|
||||
cairo_svg_font_t *svg_font = entry;
|
||||
cairo_svg_document_t *document = closure;
|
||||
emit_glyph_info_t info;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
info.document = document;
|
||||
info.svg_font = svg_font;
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
status = _cairo_svg_document_emit_glyph (document,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i],
|
||||
font_subset->font_id, i);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_hash_table_foreach (svg_font->glyphs,
|
||||
_emit_glyph,
|
||||
&info);
|
||||
_cairo_svg_document_destroy_font (document, svg_font);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_document_emit_fonts (cairo_svg_document_t *document)
|
||||
_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
|
||||
{
|
||||
_cairo_hash_table_foreach (document->fonts,
|
||||
_cairo_svg_document_emit_font,
|
||||
document);
|
||||
_cairo_hash_table_destroy (document->fonts);
|
||||
document->fonts = NULL;
|
||||
_cairo_scaled_font_subsets_foreach (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
||||
document->font_subsets = NULL;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -1813,12 +1634,11 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_status_t status;
|
||||
cairo_svg_font_t *svg_font;
|
||||
cairo_svg_glyph_t *svg_glyph;
|
||||
xmlNodePtr glyph_node;
|
||||
xmlNodePtr child;
|
||||
xmlBufferPtr style;
|
||||
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
|
||||
unsigned int font_id, subset_id, subset_glyph_index;
|
||||
int i;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
|
|
@ -1835,10 +1655,6 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
goto FALLBACK;
|
||||
|
||||
status = _cairo_svg_document_font_find (document, scaled_font, &svg_font);
|
||||
if (status)
|
||||
goto FALLBACK;
|
||||
|
||||
child = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
|
||||
style = xmlBufferCreate ();
|
||||
emit_pattern (surface, pattern, style, 0);
|
||||
|
|
@ -1846,8 +1662,9 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
xmlBufferFree (style);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_svg_glyph_find (svg_font, scaled_font,
|
||||
glyphs[i].index, &svg_glyph);
|
||||
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&font_id, &subset_id, &subset_glyph_index);
|
||||
if (status) {
|
||||
glyphs += i;
|
||||
num_glyphs -= i;
|
||||
|
|
@ -1856,8 +1673,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
glyph_node = xmlNewChild (child, NULL, CC2XML ("use"), NULL);
|
||||
snprintf (buffer, sizeof buffer, "#glyph%d-%d",
|
||||
svg_font->output_font,
|
||||
svg_glyph->output_glyph);
|
||||
font_id, subset_glyph_index);
|
||||
xmlSetProp (glyph_node, CC2XML ("xlink:href"), C2XML (buffer));
|
||||
_cairo_dtostr (buffer, sizeof buffer, glyphs[i].x);
|
||||
xmlSetProp (glyph_node, CC2XML ("x"), C2XML (buffer));
|
||||
|
|
@ -1997,13 +1813,13 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
document->fonts = _cairo_hash_table_create (_cairo_svg_font_equal);
|
||||
if (!document->fonts) {
|
||||
/* The use of defs for font glyphs imposes no per-subset limit. */
|
||||
document->font_subsets = _cairo_scaled_font_subsets_create (0);
|
||||
if (document->font_subsets == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
free (document);
|
||||
return NULL;
|
||||
}
|
||||
document->max_font = 0;
|
||||
|
||||
document->output_stream = output_stream;
|
||||
document->refcount = 1;
|
||||
|
|
@ -2119,7 +1935,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
if (document->finished)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_svg_document_emit_fonts (document);
|
||||
_cairo_svg_document_emit_font_subsets (document);
|
||||
|
||||
xmlSetProp (document->xml_node_main, CC2XML ("version"),
|
||||
CC2XML (_cairo_svg_internal_version_strings [document->svg_version]));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue