Skip to content

Commit

Permalink
PDF: Add support for latin subsets
Browse files Browse the repository at this point in the history
Add support for Type 1 and TrueType latin subsets.

CFF latin subsets are not yet implemented.
  • Loading branch information
Adrian Johnson committed Oct 1, 2010
1 parent 85c25d7 commit af3b550
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 61 deletions.
20 changes: 20 additions & 0 deletions src/cairo-cff-subset.c
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,26 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
free (subset->data);
}

cairo_bool_t
_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font)
{
const cairo_scaled_font_backend_t *backend;
cairo_status_t status;
unsigned long data_length;

backend = scaled_font->backend;
if (!backend->load_truetype_table)
return FALSE;

data_length = 0;
status = backend->load_truetype_table(scaled_font,
TT_TAG_CFF, 0, NULL, &data_length);
if (status)
return FALSE;;

return TRUE;
}

static cairo_int_status_t
_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_cff_font_t **font_return,
Expand Down
191 changes: 133 additions & 58 deletions src/cairo-pdf-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
goto BAIL1;
}

_cairo_scaled_font_subsets_enable_latin_subset (surface->font_subsets, TRUE);

surface->next_available_resource.id = 1;
surface->pages_resource = _cairo_pdf_surface_new_object (surface);
if (surface->pages_resource.id == 0) {
Expand Down Expand Up @@ -4069,7 +4071,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_pdf_font_t font;
cairo_status_t status;
unsigned long length;
unsigned int i;
unsigned int i, last_glyph;
char tag[10];

_create_font_subset_tag (font_subset, subset->base_font, tag);
Expand Down Expand Up @@ -4105,6 +4107,15 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
if (_cairo_status_is_error (status))
return status;

if (font_subset->is_latin) {
/* find last glyph used */
for (i = 255; i >= 32; i--)
if (font_subset->latin_to_subset_glyph_index[i] > 0)
break;

last_glyph = i;
}

descriptor = _cairo_pdf_surface_new_object (surface);
if (descriptor.id == 0)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
Expand All @@ -4113,7 +4124,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
"%d 0 obj\n"
"<< /Type /FontDescriptor\n"
" /FontName /%s+%s\n"
" /Flags 4\n"
" /Flags %d\n"
" /FontBBox [ %ld %ld %ld %ld ]\n"
" /ItalicAngle 0\n"
" /Ascent %ld\n"
Expand All @@ -4127,6 +4138,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
descriptor.id,
tag,
subset->base_font,
font_subset->is_latin ? 32 : 4,
(long)(subset->x_min*PDF_UNITS_PER_EM),
(long)(subset->y_min*PDF_UNITS_PER_EM),
(long)(subset->x_max*PDF_UNITS_PER_EM),
Expand All @@ -4142,20 +4154,34 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
"<< /Type /Font\n"
" /Subtype /Type1\n"
" /BaseFont /%s+%s\n"
" /FirstChar 0\n"
" /FirstChar %d\n"
" /LastChar %d\n"
" /FontDescriptor %d 0 R\n"
" /Widths [",
subset_resource.id,
tag,
subset->base_font,
font_subset->num_glyphs - 1,
font_subset->is_latin ? 32 : 0,
font_subset->is_latin ? last_glyph : font_subset->num_glyphs - 1,
descriptor.id);

for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset->widths[i]*PDF_UNITS_PER_EM));
if (font_subset->is_latin) {
for (i = 32; i < last_glyph + 1; i++) {
int glyph = font_subset->latin_to_subset_glyph_index[i];
if (glyph > 0) {
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset->widths[glyph]*PDF_UNITS_PER_EM));
} else {
_cairo_output_stream_printf (surface->output, " 0");
}
}
} else {
for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset->widths[i]*PDF_UNITS_PER_EM));
}

_cairo_output_stream_printf (surface->output,
" ]\n");
Expand Down Expand Up @@ -4226,7 +4252,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_status_t status;
cairo_pdf_font_t font;
cairo_truetype_subset_t subset;
unsigned int i;
unsigned int i, last_glyph;
char tag[10];

subset_resource = _cairo_pdf_surface_get_font_resource (surface,
Expand Down Expand Up @@ -4289,7 +4315,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
}

_cairo_output_stream_printf (surface->output,
" /Flags 4\n"
" /Flags %d\n"
" /FontBBox [ %ld %ld %ld %ld ]\n"
" /ItalicAngle 0\n"
" /Ascent %ld\n"
Expand All @@ -4300,6 +4326,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
" /FontFile2 %u 0 R\n"
">>\n"
"endobj\n",
font_subset->is_latin ? 32 : 4,
(long)(subset.x_min*PDF_UNITS_PER_EM),
(long)(subset.y_min*PDF_UNITS_PER_EM),
(long)(subset.x_max*PDF_UNITS_PER_EM),
Expand All @@ -4309,60 +4336,108 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
(long)(subset.y_max*PDF_UNITS_PER_EM),
stream.id);

cidfont_dict = _cairo_pdf_surface_new_object (surface);
if (cidfont_dict.id == 0) {
_cairo_truetype_subset_fini (&subset);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
if (font_subset->is_latin) {
/* find last glyph used */
for (i = 255; i >= 32; i--)
if (font_subset->latin_to_subset_glyph_index[i] > 0)
break;

_cairo_output_stream_printf (surface->output,
"%d 0 obj\n"
"<< /Type /Font\n"
" /Subtype /CIDFontType2\n"
" /BaseFont /%s+%s\n"
" /CIDSystemInfo\n"
" << /Registry (Adobe)\n"
" /Ordering (Identity)\n"
" /Supplement 0\n"
" >>\n"
" /FontDescriptor %d 0 R\n"
" /W [0 [",
cidfont_dict.id,
tag,
subset.ps_name,
descriptor.id);
last_glyph = i;
_cairo_pdf_surface_update_object (surface, subset_resource);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Type /Font\n"
" /Subtype /TrueType\n"
" /BaseFont /%s+%s\n"
" /FirstChar 32\n"
" /LastChar %d\n"
" /FontDescriptor %d 0 R\n"
" /Encoding /WinAnsiEncoding\n"
" /Widths [",
subset_resource.id,
tag,
subset.ps_name,
last_glyph,
descriptor.id);

for (i = 32; i < last_glyph + 1; i++) {
int glyph = font_subset->latin_to_subset_glyph_index[i];
if (glyph > 0) {
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset.widths[glyph]*PDF_UNITS_PER_EM));
} else {
_cairo_output_stream_printf (surface->output, " 0");
}
}

for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset.widths[i]*PDF_UNITS_PER_EM));
_cairo_output_stream_printf (surface->output,
" ]\n");

_cairo_output_stream_printf (surface->output,
" ]]\n"
">>\n"
"endobj\n");
if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
" /ToUnicode %d 0 R\n",
to_unicode_stream.id);

_cairo_pdf_surface_update_object (surface, subset_resource);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\n"
"<< /Type /Font\n"
" /Subtype /Type0\n"
" /BaseFont /%s+%s\n"
" /Encoding /Identity-H\n"
" /DescendantFonts [ %d 0 R]\n",
subset_resource.id,
tag,
subset.ps_name,
cidfont_dict.id);
_cairo_output_stream_printf (surface->output,
">>\n"
"endobj\n");
} else {
cidfont_dict = _cairo_pdf_surface_new_object (surface);
if (cidfont_dict.id == 0) {
_cairo_truetype_subset_fini (&subset);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}

if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
" /ToUnicode %d 0 R\n",
to_unicode_stream.id);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\n"
"<< /Type /Font\n"
" /Subtype /CIDFontType2\n"
" /BaseFont /%s+%s\n"
" /CIDSystemInfo\n"
" << /Registry (Adobe)\n"
" /Ordering (Identity)\n"
" /Supplement 0\n"
" >>\n"
" /FontDescriptor %d 0 R\n"
" /W [0 [",
cidfont_dict.id,
tag,
subset.ps_name,
descriptor.id);

for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->output,
" %ld",
(long)(subset.widths[i]*PDF_UNITS_PER_EM));

_cairo_output_stream_printf (surface->output,
">>\n"
"endobj\n");
_cairo_output_stream_printf (surface->output,
" ]]\n"
">>\n"
"endobj\n");

_cairo_pdf_surface_update_object (surface, subset_resource);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\n"
"<< /Type /Font\n"
" /Subtype /Type0\n"
" /BaseFont /%s+%s\n"
" /Encoding /Identity-H\n"
" /DescendantFonts [ %d 0 R]\n",
subset_resource.id,
tag,
subset.ps_name,
cidfont_dict.id);

if (to_unicode_stream.id != 0)
_cairo_output_stream_printf (surface->output,
" /ToUnicode %d 0 R\n",
to_unicode_stream.id);

_cairo_output_stream_printf (surface->output,
">>\n"
"endobj\n");
}

font.font_id = font_subset->font_id;
font.subset_id = font_subset->subset_id;
Expand Down
9 changes: 9 additions & 0 deletions src/cairo-scaled-font-subsets-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,15 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cairo_private void
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);

/**
* _cairo_cff_scaled_font_is_cff:
* @scaled_font: a #cairo_scaled_font_t
*
* Return %TRUE if @scaled_font is a CFF font, otherwise return %FALSE.
**/
cairo_bool_t
_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font);

/**
* _cairo_cff_fallback_init:
* @cff_subset: a #cairo_cff_subset_t to initialize
Expand Down
11 changes: 8 additions & 3 deletions src/cairo-scaled-font-subsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ typedef struct _cairo_sub_font {
cairo_bool_t is_scaled;
cairo_bool_t is_composite;
cairo_bool_t is_user;
cairo_bool_t use_latin_subset;
cairo_scaled_font_subsets_t *parent;
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
Expand Down Expand Up @@ -294,7 +295,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
sub_font->scaled_font = scaled_font;
sub_font->font_id = font_id;

if (parent->use_latin_subset)
sub_font->use_latin_subset = parent->use_latin_subset;
if (_cairo_cff_scaled_font_is_cff (scaled_font))
sub_font->use_latin_subset = FALSE; /* CFF latin subsets are NYI */

if (sub_font->use_latin_subset)
sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
else
sub_font->current_subset = 0;
Expand Down Expand Up @@ -616,7 +621,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
* create a separate subset just for the .notdef glyph.
*/
is_latin = FALSE;
if (sub_font->parent->use_latin_subset &&
if (sub_font->use_latin_subset &&
(! _cairo_font_face_is_user (sub_font->scaled_font->font_face)))
{
latin_character = _cairo_unicode_to_winansi (font_unicode);
Expand Down Expand Up @@ -702,7 +707,7 @@ _cairo_sub_font_collect (void *entry, void *closure)
subset.glyph_names = NULL;

subset.is_latin = FALSE;
if (sub_font->parent->use_latin_subset && i == 0) {
if (sub_font->use_latin_subset && i == 0) {
subset.is_latin = TRUE;
subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
} else {
Expand Down

0 comments on commit af3b550

Please sign in to comment.