mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 22:48:07 +02:00
This patch fixes the problem where the postscript output
does not print when the size of the embedded truetype font exceeds 64k.
This commit is contained in:
parent
226178539a
commit
067d97eb17
4 changed files with 77 additions and 15 deletions
|
|
@ -56,7 +56,8 @@ _cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph);
|
|||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_font_subset_generate (cairo_font_subset_t *font,
|
||||
const char **data, unsigned long *length);
|
||||
const char **data, unsigned long *length,
|
||||
const unsigned long **string_offsets, unsigned long *num_strings);
|
||||
|
||||
cairo_private void
|
||||
_cairo_font_subset_destroy (cairo_font_subset_t *font);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
|
@ -69,6 +70,9 @@ typedef struct _cairo_ft_font {
|
|||
FT_Face face;
|
||||
int checksum_index;
|
||||
cairo_array_t output;
|
||||
cairo_array_t string_offsets;
|
||||
unsigned long last_offset;
|
||||
unsigned long last_boundary;
|
||||
int *parent_to_subset;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -80,6 +84,7 @@ cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph);
|
|||
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
|
||||
|
||||
#define SFNT_VERSION 0x00010000
|
||||
#define SFNT_STRING_MAX_LENGTH 65535
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
|
|
@ -158,6 +163,8 @@ _cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
|
||||
font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
|
||||
|
||||
font->last_offset = 0;
|
||||
font->last_boundary = 0;
|
||||
_cairo_array_init (&font->output, sizeof (char));
|
||||
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
|
||||
goto fail1;
|
||||
|
|
@ -192,6 +199,10 @@ _cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
if (font->base.widths == NULL)
|
||||
goto fail5;
|
||||
|
||||
_cairo_array_init (&font->string_offsets, sizeof (unsigned long));
|
||||
if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS)
|
||||
goto fail6;
|
||||
|
||||
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
||||
|
||||
font->status = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -200,6 +211,8 @@ _cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail6:
|
||||
free (font->base.widths);
|
||||
fail5:
|
||||
free (font->base.base_font);
|
||||
fail4:
|
||||
|
|
@ -222,6 +235,7 @@ cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font)
|
|||
free (font->parent_to_subset);
|
||||
free (font->glyphs);
|
||||
_cairo_array_fini (&font->output);
|
||||
_cairo_array_fini (&font->string_offsets);
|
||||
free (font);
|
||||
}
|
||||
|
||||
|
|
@ -287,6 +301,16 @@ cairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font)
|
|||
return aligned;
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_pdf_ft_font_check_boundary (cairo_pdf_ft_font_t *font, unsigned long boundary)
|
||||
{
|
||||
if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH) {
|
||||
_cairo_array_append(&font->string_offsets, &font->last_boundary);
|
||||
font->last_offset = font->last_boundary;
|
||||
}
|
||||
font->last_boundary = boundary;
|
||||
}
|
||||
|
||||
static int
|
||||
cairo_pdf_ft_font_write_cmap_table (cairo_pdf_ft_font_t *font, unsigned long tag)
|
||||
{
|
||||
|
|
@ -389,7 +413,7 @@ cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
|
|||
unsigned long tag)
|
||||
{
|
||||
cairo_status_t status;
|
||||
unsigned long start_offset, index, size;
|
||||
unsigned long start_offset, index, size, next;
|
||||
TT_Header *header;
|
||||
unsigned long begin, end;
|
||||
unsigned char *buffer;
|
||||
|
|
@ -427,8 +451,10 @@ cairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font,
|
|||
|
||||
size = end - begin;
|
||||
|
||||
font->glyphs[i].location =
|
||||
cairo_pdf_ft_font_align_output (font) - start_offset;
|
||||
next = cairo_pdf_ft_font_align_output (font);
|
||||
cairo_pdf_ft_font_check_boundary (font, next);
|
||||
font->glyphs[i].location = next - start_offset;
|
||||
|
||||
status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer);
|
||||
if (status)
|
||||
break;
|
||||
|
|
@ -681,7 +707,8 @@ cairo_pdf_ft_font_update_entry (cairo_pdf_ft_font_t *font, int index, unsigned l
|
|||
|
||||
static cairo_status_t
|
||||
cairo_pdf_ft_font_generate (void *abstract_font,
|
||||
const char **data, unsigned long *length)
|
||||
const char **data, unsigned long *length,
|
||||
const unsigned long **string_offsets, unsigned long *num_strings)
|
||||
{
|
||||
cairo_ft_unscaled_font_t *ft_unscaled_font;
|
||||
cairo_pdf_ft_font_t *font = abstract_font;
|
||||
|
|
@ -711,6 +738,7 @@ cairo_pdf_ft_font_generate (void *abstract_font,
|
|||
next = cairo_pdf_ft_font_align_output (font);
|
||||
cairo_pdf_ft_font_update_entry (font, i, truetype_tables[i].tag,
|
||||
start, end);
|
||||
cairo_pdf_ft_font_check_boundary (font, next);
|
||||
start = next;
|
||||
}
|
||||
|
||||
|
|
@ -721,6 +749,11 @@ cairo_pdf_ft_font_generate (void *abstract_font,
|
|||
|
||||
*data = _cairo_array_index (&font->output, 0);
|
||||
*length = _cairo_array_num_elements (&font->output);
|
||||
*num_strings = _cairo_array_num_elements (&font->string_offsets);
|
||||
if (*num_strings != 0)
|
||||
*string_offsets = _cairo_array_index (&font->string_offsets, 0);
|
||||
else
|
||||
*string_offsets = NULL;
|
||||
|
||||
fail:
|
||||
_cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);
|
||||
|
|
@ -748,8 +781,11 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
cairo_pdf_ft_font_t *font;
|
||||
cairo_status_t status;
|
||||
const char *data = NULL; /* squelch bogus compiler warning */
|
||||
unsigned long parent_glyph, length = 0; /* squelch bogus compiler warning */
|
||||
unsigned long length = 0; /* squelch bogus compiler warning */
|
||||
unsigned long parent_glyph, offsets_length;
|
||||
int i;
|
||||
const unsigned long *string_offsets = NULL;
|
||||
unsigned long num_strings = 0;
|
||||
|
||||
status = _cairo_pdf_ft_font_create (font_subset, &font);
|
||||
if (status)
|
||||
|
|
@ -760,7 +796,8 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
cairo_pdf_ft_font_use_glyph (font, parent_glyph);
|
||||
}
|
||||
|
||||
status = cairo_pdf_ft_font_generate (font, &data, &length);
|
||||
status = cairo_pdf_ft_font_generate (font, &data, &length,
|
||||
&string_offsets, &num_strings);
|
||||
if (status)
|
||||
goto fail1;
|
||||
|
||||
|
|
@ -788,10 +825,20 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
memcpy (truetype_subset->data, data, length);
|
||||
truetype_subset->data_length = length;
|
||||
|
||||
offsets_length = num_strings * sizeof (unsigned long);
|
||||
truetype_subset->string_offsets = malloc (offsets_length);
|
||||
if (truetype_subset->string_offsets == NULL)
|
||||
goto fail4;
|
||||
|
||||
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
|
||||
truetype_subset->num_string_offsets = num_strings;
|
||||
|
||||
cairo_pdf_ft_font_destroy (font);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail4:
|
||||
free (truetype_subset->data);
|
||||
fail3:
|
||||
free (truetype_subset->widths);
|
||||
fail2:
|
||||
|
|
@ -808,5 +855,6 @@ _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
|
|||
free (subset->base_font);
|
||||
free (subset->widths);
|
||||
free (subset->data);
|
||||
free (subset->string_offsets);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -424,6 +424,7 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
|||
cairo_truetype_subset_t subset;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
unsigned int begin, end;
|
||||
|
||||
status = _cairo_truetype_subset_init (&subset, font_subset);
|
||||
if (status)
|
||||
|
|
@ -464,17 +465,27 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
|||
_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);
|
||||
"/sfnts [\n");
|
||||
begin = 0;
|
||||
end = 0;
|
||||
for (i = 0; i < subset.num_string_offsets; i++) {
|
||||
end = subset.string_offsets[i];
|
||||
_cairo_output_stream_printf (surface->final_stream,"<");
|
||||
_cairo_output_stream_write_hex_string (surface->final_stream,
|
||||
subset.data + begin, end - begin);
|
||||
_cairo_output_stream_printf (surface->final_stream,"00>\n");
|
||||
begin = end;
|
||||
}
|
||||
if (subset.data_length > end) {
|
||||
_cairo_output_stream_printf (surface->final_stream,"<");
|
||||
_cairo_output_stream_write_hex_string (surface->final_stream,
|
||||
subset.data + end, subset.data_length - end);
|
||||
_cairo_output_stream_printf (surface->final_stream,"00>\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
">] def\n"
|
||||
"] def\n"
|
||||
"FontName currentdict end definefont pop\n");
|
||||
|
||||
_cairo_truetype_subset_fini (&subset);
|
||||
|
|
|
|||
|
|
@ -187,6 +187,8 @@ typedef struct _cairo_truetype_subset {
|
|||
long ascent, descent;
|
||||
char *data;
|
||||
unsigned long data_length;
|
||||
unsigned long *string_offsets;
|
||||
unsigned long num_string_offsets;
|
||||
} cairo_truetype_subset_t;
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue