mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-09 04:58:04 +02:00
Merge branch 'truetype-subsetting' into cairo
Conflicts: src/Makefile.am src/cairo-font-subset.c src/cairo-pdf-surface.c src/cairo-ps-surface.c
This commit is contained in:
commit
c7b194c595
5 changed files with 418 additions and 76 deletions
|
|
@ -1,14 +1,19 @@
|
|||
font_subset_sources = \
|
||||
cairo-font-subset.c \
|
||||
cairo-font-subset-private.h \
|
||||
cairo-scaled-font-subsets.c \
|
||||
cairo-scaled-font-subsets-private.h
|
||||
|
||||
if CAIRO_HAS_PS_SURFACE
|
||||
libcairo_ps_headers = cairo-ps.h
|
||||
libcairo_ps_sources = cairo-ps-surface.c cairo-ps-test.h cairo-scaled-font-subsets.c cairo-scaled-font-subsets-private.h
|
||||
libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
|
||||
libcairo_ps_sources = cairo-ps-surface.c cairo-ps-test.h
|
||||
libcairo_font_subset_sources = $(font_subset_sources)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_PDF_SURFACE
|
||||
libcairo_pdf_headers = cairo-pdf.h
|
||||
libcairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-test.h
|
||||
libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
|
||||
libcairo_font_subset_sources = $(font_subset_sources)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_PNG_FUNCTIONS
|
||||
|
|
@ -18,6 +23,7 @@ endif
|
|||
if CAIRO_HAS_SVG_SURFACE
|
||||
libcairo_svg_headers = cairo-svg.h
|
||||
libcairo_svg_sources = cairo-svg-surface.c cairo-svg-test.h
|
||||
libcairo_font_subset_sources = $(font_subset_sources)
|
||||
endif
|
||||
|
||||
if CAIRO_HAS_TEST_SURFACES
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-font-subset-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
||||
/* XXX: Eventually, we need to handle other font backends */
|
||||
#include "cairo-ft-private.h"
|
||||
|
|
@ -51,28 +52,31 @@ struct ft_subset_glyph {
|
|||
unsigned long location;
|
||||
};
|
||||
|
||||
struct cairo_font_subset_backend {
|
||||
int (*use_glyph) (void *abstract_font,
|
||||
int glyph);
|
||||
cairo_status_t (*generate) (void *abstract_font,
|
||||
const char **data,
|
||||
unsigned long *length);
|
||||
void (*destroy) (void *abstract_font);
|
||||
};
|
||||
typedef struct _cairo_ft_font {
|
||||
|
||||
cairo_scaled_font_subset_t *scaled_font_subset;
|
||||
|
||||
struct {
|
||||
cairo_unscaled_font_t *unscaled_font;
|
||||
unsigned int font_id;
|
||||
char *base_font;
|
||||
int num_glyphs;
|
||||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
} base;
|
||||
|
||||
typedef struct cairo_pdf_ft_font cairo_pdf_ft_font_t;
|
||||
struct cairo_pdf_ft_font {
|
||||
cairo_font_subset_t base;
|
||||
ft_subset_glyph_t *glyphs;
|
||||
FT_Face face;
|
||||
int checksum_index;
|
||||
cairo_array_t output;
|
||||
int *parent_to_subset;
|
||||
cairo_status_t status;
|
||||
};
|
||||
|
||||
} cairo_pdf_ft_font_t;
|
||||
|
||||
static int
|
||||
cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph);
|
||||
cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph);
|
||||
|
||||
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
|
||||
|
||||
|
|
@ -113,56 +117,44 @@ be32_to_cpu(unsigned long v)
|
|||
|
||||
#endif
|
||||
|
||||
static cairo_font_subset_backend_t cairo_pdf_ft_font_backend;
|
||||
|
||||
int
|
||||
_cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph)
|
||||
{
|
||||
return font->backend->use_glyph (font, glyph);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_font_subset_generate (cairo_font_subset_t *font,
|
||||
const char **data, unsigned long *length)
|
||||
{
|
||||
return font->backend->generate (font, data, length);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_font_subset_destroy (cairo_font_subset_t *font)
|
||||
{
|
||||
font->backend->destroy (font);
|
||||
}
|
||||
|
||||
cairo_font_subset_t *
|
||||
_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
|
||||
static cairo_status_t
|
||||
_cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
||||
cairo_pdf_ft_font_t **font_return)
|
||||
{
|
||||
cairo_unscaled_font_t *unscaled_font;
|
||||
cairo_ft_unscaled_font_t *ft_unscaled_font;
|
||||
FT_Face face;
|
||||
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
|
||||
cairo_pdf_ft_font_t *font;
|
||||
FT_Face face;
|
||||
unsigned long size;
|
||||
int i, j;
|
||||
|
||||
/* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
|
||||
if (! _cairo_unscaled_font_is_ft (unscaled_font))
|
||||
return NULL;
|
||||
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);
|
||||
|
||||
ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;
|
||||
|
||||
face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);
|
||||
if (face == NULL)
|
||||
/* Assume out of memory */
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* We currently only support freetype truetype fonts. */
|
||||
size = 0;
|
||||
if (!FT_IS_SFNT (face) ||
|
||||
FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0)
|
||||
return NULL;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
font = malloc (sizeof (cairo_pdf_ft_font_t));
|
||||
if (font == NULL)
|
||||
return NULL;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
font->scaled_font_subset = scaled_font_subset;
|
||||
|
||||
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
|
||||
font->base.backend = &cairo_pdf_ft_font_backend;
|
||||
|
||||
_cairo_array_init (&font->output, sizeof (char));
|
||||
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
|
||||
|
|
@ -176,7 +168,7 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
|
|||
if (font->parent_to_subset == NULL)
|
||||
goto fail3;
|
||||
|
||||
font->base.num_glyphs = 1;
|
||||
font->base.num_glyphs = 0;
|
||||
font->base.x_min = face->bbox.xMin;
|
||||
font->base.y_min = face->bbox.yMin;
|
||||
font->base.x_max = face->bbox.xMax;
|
||||
|
|
@ -202,7 +194,9 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
|
|||
|
||||
font->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return &font->base;
|
||||
*font_return = font;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail5:
|
||||
free (font->base.base_font);
|
||||
|
|
@ -214,14 +208,13 @@ _cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
|
|||
_cairo_array_fini (&font->output);
|
||||
fail1:
|
||||
free (font);
|
||||
return NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_pdf_ft_font_destroy (void *abstract_font)
|
||||
cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font)
|
||||
{
|
||||
cairo_pdf_ft_font_t *font = abstract_font;
|
||||
|
||||
_cairo_unscaled_font_destroy (font->base.unscaled_font);
|
||||
free (font->base.base_font);
|
||||
free (font->parent_to_subset);
|
||||
|
|
@ -735,10 +728,8 @@ cairo_pdf_ft_font_generate (void *abstract_font,
|
|||
}
|
||||
|
||||
static int
|
||||
cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph)
|
||||
cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph)
|
||||
{
|
||||
cairo_pdf_ft_font_t *font = abstract_font;
|
||||
|
||||
if (font->parent_to_subset[glyph] == 0) {
|
||||
font->parent_to_subset[glyph] = font->base.num_glyphs;
|
||||
font->glyphs[font->base.num_glyphs].parent_index = glyph;
|
||||
|
|
@ -748,8 +739,72 @@ cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph)
|
|||
return font->parent_to_subset[glyph];
|
||||
}
|
||||
|
||||
static cairo_font_subset_backend_t cairo_pdf_ft_font_backend = {
|
||||
cairo_pdf_ft_font_use_glyph,
|
||||
cairo_pdf_ft_font_generate,
|
||||
cairo_pdf_ft_font_destroy
|
||||
};
|
||||
cairo_status_t
|
||||
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_ft_font_t *font;
|
||||
cairo_status_t status;
|
||||
const char *data;
|
||||
unsigned long length, parent_glyph;
|
||||
int i;
|
||||
|
||||
status = _cairo_pdf_ft_font_create (font_subset, &font);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
parent_glyph = font->scaled_font_subset->glyphs[i];
|
||||
cairo_pdf_ft_font_use_glyph (font, parent_glyph);
|
||||
}
|
||||
|
||||
status = cairo_pdf_ft_font_generate (font, &data, &length);
|
||||
if (status)
|
||||
goto fail1;
|
||||
|
||||
truetype_subset->base_font = strdup (font->base.base_font);
|
||||
if (truetype_subset->base_font == NULL)
|
||||
goto fail1;
|
||||
|
||||
truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs);
|
||||
if (truetype_subset->widths == NULL)
|
||||
goto fail2;
|
||||
for (i = 0; i < font->base.num_glyphs; i++)
|
||||
truetype_subset->widths[i] = font->base.widths[i];
|
||||
|
||||
truetype_subset->x_min = font->base.x_min;
|
||||
truetype_subset->y_min = font->base.y_min;
|
||||
truetype_subset->x_max = font->base.x_max;
|
||||
truetype_subset->y_max = font->base.y_max;
|
||||
truetype_subset->ascent = font->base.ascent;
|
||||
truetype_subset->descent = font->base.descent;
|
||||
|
||||
truetype_subset->data = malloc (length);
|
||||
if (truetype_subset->data == NULL)
|
||||
goto fail3;
|
||||
|
||||
memcpy (truetype_subset->data, data, length);
|
||||
truetype_subset->data_length = length;
|
||||
|
||||
cairo_pdf_ft_font_destroy (font);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail3:
|
||||
free (truetype_subset->widths);
|
||||
fail2:
|
||||
free (truetype_subset->base_font);
|
||||
fail1:
|
||||
cairo_pdf_ft_font_destroy (font);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
|
||||
{
|
||||
free (subset->base_font);
|
||||
free (subset->widths);
|
||||
free (subset->data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1579,6 +1579,108 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
|
|||
"endobj\r\n");
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_resource_t stream, descriptor, subset_resource;
|
||||
cairo_status_t status;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_truetype_subset_t subset;
|
||||
unsigned long compressed_length;
|
||||
char *compressed;
|
||||
int i;
|
||||
|
||||
status = _cairo_truetype_subset_init (&subset, font_subset);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
compressed = compress_dup (subset.data, subset.data_length,
|
||||
&compressed_length);
|
||||
if (compressed == NULL) {
|
||||
_cairo_truetype_subset_fini (&subset);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
stream = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Filter /FlateDecode\r\n"
|
||||
" /Length %lu\r\n"
|
||||
" /Length1 %lu\r\n"
|
||||
">>\r\n"
|
||||
"stream\r\n",
|
||||
stream.id,
|
||||
compressed_length,
|
||||
subset.data_length);
|
||||
_cairo_output_stream_write (surface->output, compressed, compressed_length);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\r\n"
|
||||
"endstream\r\n"
|
||||
"endobj\r\n");
|
||||
free (compressed);
|
||||
|
||||
descriptor = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /FontDescriptor\r\n"
|
||||
" /FontName /7%s\r\n"
|
||||
" /Flags 4\r\n"
|
||||
" /FontBBox [ %ld %ld %ld %ld ]\r\n"
|
||||
" /ItalicAngle 0\r\n"
|
||||
" /Ascent %ld\r\n"
|
||||
" /Descent %ld\r\n"
|
||||
" /CapHeight 500\r\n"
|
||||
" /StemV 80\r\n"
|
||||
" /StemH 80\r\n"
|
||||
" /FontFile2 %u 0 R\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n",
|
||||
descriptor.id,
|
||||
subset.base_font,
|
||||
subset.x_min,
|
||||
subset.y_min,
|
||||
subset.x_max,
|
||||
subset.y_max,
|
||||
subset.ascent,
|
||||
subset.descent,
|
||||
stream.id);
|
||||
|
||||
subset_resource = _cairo_pdf_surface_new_object (surface);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\r\n"
|
||||
" /Subtype /TrueType\r\n"
|
||||
" /BaseFont /%s\r\n"
|
||||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n"
|
||||
" /FontDescriptor %d 0 R\r\n"
|
||||
" /Widths [",
|
||||
subset_resource.id,
|
||||
subset.base_font,
|
||||
font_subset->num_glyphs,
|
||||
descriptor.id);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" %d",
|
||||
subset.widths[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]\r\n"
|
||||
">>\r\n"
|
||||
"endobj\r\n");
|
||||
|
||||
font.font_id = font_subset->font_id;
|
||||
font.subset_id = font_subset->subset_id;
|
||||
font.subset_resource = subset_resource;
|
||||
_cairo_array_append (&surface->fonts, &font);
|
||||
|
||||
_cairo_truetype_subset_fini (&subset);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_emit_outline_glyph_data (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
@ -1678,19 +1780,19 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t *surface,
|
|||
_cairo_surface_set_error (&surface->base, status);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = closure;
|
||||
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
|
||||
cairo_pdf_font_t font;
|
||||
cairo_matrix_t matrix;
|
||||
int i;
|
||||
|
||||
glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
|
||||
if (glyphs == NULL) {
|
||||
_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
|
|
@ -1726,17 +1828,23 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
"endobj\r\n");
|
||||
|
||||
subset_resource = _cairo_pdf_surface_new_object (surface);
|
||||
matrix = font_subset->scaled_font->scale;
|
||||
cairo_matrix_invert (&matrix);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\r\n"
|
||||
" /Subtype /Type3\r\n"
|
||||
" /FontBBox [0 0 0 0]\r\n"
|
||||
" /FontMatrix\t[1 0 0 1 0 0]\r\n"
|
||||
" /FontMatrix [ %f %f %f %f 0 0 ]\r\n"
|
||||
" /Encoding %d 0 R\r\n"
|
||||
" /CharProcs %d 0 R\r\n"
|
||||
" /FirstChar 0\r\n"
|
||||
" /LastChar %d\r\n",
|
||||
subset_resource.id,
|
||||
matrix.xx,
|
||||
matrix.yx,
|
||||
-matrix.xy,
|
||||
-matrix.yy,
|
||||
encoding.id,
|
||||
char_procs.id,
|
||||
font_subset->num_glyphs - 1);
|
||||
|
|
@ -1756,6 +1864,24 @@ _cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
font.subset_id = font_subset->subset_id;
|
||||
font.subset_resource = subset_resource;
|
||||
_cairo_array_append (&surface->fonts, &font);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = closure;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -2330,6 +2456,9 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"BT\r\n");
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
|
|
@ -2343,13 +2472,22 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
|
|||
font_id, subset_id);
|
||||
current_subset_id = subset_id;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"BT %f %f Td <%c%c> Tj ET\r\n",
|
||||
glyphs[i].x, glyphs[i].y,
|
||||
"%f %f %f %f %f %f Tm <%c%c> Tj\r\n",
|
||||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
-scaled_font->scale.xy,
|
||||
-scaled_font->scale.yy,
|
||||
glyphs[i].x,
|
||||
glyphs[i].y,
|
||||
hex_digit (subset_glyph_index >> 4),
|
||||
hex_digit (subset_glyph_index));
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"ET\r\n");
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,73 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
|
||||
|
||||
{
|
||||
cairo_truetype_subset_t subset;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
status = _cairo_truetype_subset_init (&subset, font_subset);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* FIXME: Figure out document structure convention for fonts */
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%% _cairo_ps_surface_emit_truetype_font_subset\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"11 dict begin\n"
|
||||
"/FontType 42 def\n"
|
||||
"/FontName /CairoFont-%d-%d def\n"
|
||||
"/PaintType 0 def\n"
|
||||
"/FontMatrix [ 1 0 0 1 0 0 ] def\n"
|
||||
"/FontBBox [ 0 0 0 0 ] def\n"
|
||||
"/Encoding 256 array def\n"
|
||||
"0 1 255 { Encoding exch /.notdef put } for\n",
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id);
|
||||
|
||||
/* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
|
||||
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"Encoding %d /g%d put\n", i, i);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/CharStrings %d dict dup begin\n"
|
||||
"/.notdef 0 def\n",
|
||||
font_subset->num_glyphs);
|
||||
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/g%d %d def\n", i, i);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"end readonly def\n");
|
||||
|
||||
/* FIXME: We need to break up fonts bigger than 64k so we don't
|
||||
* exceed string size limitation. At glyph boundaries. Stupid
|
||||
* postscript. */
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/sfnts [<");
|
||||
|
||||
_cairo_output_stream_write_hex_string (surface->final_stream,
|
||||
subset.data, subset.data_length);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
">] def\n"
|
||||
"FontName currentdict end definefont pop\n");
|
||||
|
||||
_cairo_truetype_subset_fini (&subset);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
@ -304,27 +371,35 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
|
|||
_cairo_surface_set_error (&surface->base, status);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
|
||||
|
||||
{
|
||||
cairo_ps_surface_t *surface = closure;
|
||||
cairo_matrix_t matrix;
|
||||
int i;
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%% _cairo_ps_surface_emit_font_subset\n");
|
||||
"%% _cairo_ps_surface_emit_type3_font_subset\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/CairoFont-%d-%d <<\n",
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id);
|
||||
|
||||
matrix = font_subset->scaled_font->scale;
|
||||
cairo_matrix_invert (&matrix);
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"\t/FontType\t3\n"
|
||||
"\t/FontMatrix\t[1 0 0 1 0 0]\n"
|
||||
"\t/FontMatrix\t[%f %f %f %f 0 0]\n"
|
||||
"\t/Encoding\t[0]\n"
|
||||
"\t/FontBBox\t[0 0 10 10]\n"
|
||||
"\t/Glyphs [\n");
|
||||
"\t/Glyphs [\n",
|
||||
matrix.xx,
|
||||
matrix.yx,
|
||||
-matrix.xy,
|
||||
-matrix.yy);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
_cairo_ps_surface_emit_glyph (surface,
|
||||
|
|
@ -339,6 +414,25 @@ _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
"\t\texch get exec\n"
|
||||
"\t}\n"
|
||||
">> definefont pop\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
||||
void *closure)
|
||||
{
|
||||
cairo_ps_surface_t *surface = closure;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -1785,10 +1879,18 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
if (subset_id != current_subset_id) {
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"/CairoFont-%d-%d 1 selectfont\n",
|
||||
font_id, subset_id);
|
||||
"/CairoFont-%d-%d findfont\n"
|
||||
"[ %f %f %f %f 0 0 ] makefont\n"
|
||||
"setfont\n",
|
||||
font_id,
|
||||
subset_id,
|
||||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
-scaled_font->scale.xy,
|
||||
-scaled_font->scale.yy);
|
||||
current_subset_id = subset_id;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%f %f M <%c%c> S\n",
|
||||
glyphs[i].x, glyphs[i].y,
|
||||
|
|
|
|||
|
|
@ -179,4 +179,45 @@ _cairo_scaled_font_subsets_foreach (cairo_scaled_font_subsets_t *font_subsets,
|
|||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure);
|
||||
|
||||
|
||||
typedef struct _cairo_truetype_subset {
|
||||
char *base_font;
|
||||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
char *data;
|
||||
unsigned long data_length;
|
||||
} cairo_truetype_subset_t;
|
||||
|
||||
/**
|
||||
* _cairo_truetype_subset_init:
|
||||
* @truetype_subset: a #cairo_truetype_subset_t to initialize
|
||||
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
|
||||
*
|
||||
* If possible (depending on the format of the underlying
|
||||
* cairo_scaled_font_t and the font backend in use) generate a
|
||||
* truetype file corresponding to @font_subset and initialize
|
||||
* @truetype_subset with information about the subset and the truetype
|
||||
* data.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
|
||||
* truetype file, or an non-zero value indicating an error. Possible
|
||||
* errors include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_truetype_subset_fini:
|
||||
* @truetype_subset: a #cairo_truetype_subset_t
|
||||
*
|
||||
* Free all resources associated with @truetype_subset. After this
|
||||
* call, @truetype_subset should not be used again without a
|
||||
* subsequent call to _cairo_truetype_subset_init() again first.
|
||||
**/
|
||||
cairo_private void
|
||||
_cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
|
||||
|
||||
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue