mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-03 21:00:18 +01:00
CFF subset: add support for latin subsets
This commit is contained in:
parent
f20814e07e
commit
b950212a2a
6 changed files with 489 additions and 119 deletions
|
|
@ -739,9 +739,9 @@ cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* Use maximum sized encoding to reserve space for later modification. */
|
||||
end_buf = encode_integer_max (buf, 0);
|
||||
status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
|
||||
/* Use maximum sized encoding to reserve space for later modification. */
|
||||
end_buf = encode_integer_max (buf, 0);
|
||||
status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
|
@ -935,23 +935,37 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
|
|||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDSELECT_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDARRAY_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
CHARSET_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
cff_dict_remove (font->top_dict, ENCODING_OP);
|
||||
cff_dict_remove (font->top_dict, PRIVATE_OP);
|
||||
if (font->scaled_font_subset->is_latin) {
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
ENCODING_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
/* Private has two operands - size and offset */
|
||||
end_buf = encode_integer_max (end_buf, 0);
|
||||
cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
} else {
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDSELECT_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDARRAY_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
cff_dict_remove (font->top_dict, ENCODING_OP);
|
||||
cff_dict_remove (font->top_dict, PRIVATE_OP);
|
||||
}
|
||||
|
||||
/* Remove the unique identifier operators as the subsetted font is
|
||||
* not the same is the original font. */
|
||||
|
|
@ -1238,20 +1252,28 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font)
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_cff_font_set_ros_strings (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (!font->scaled_font_subset->is_latin) {
|
||||
status = cairo_cff_font_set_ros_strings (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
status = cairo_cff_font_subset_charstrings (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (font->is_cid)
|
||||
status = cairo_cff_font_subset_fontdict (font);
|
||||
else
|
||||
status = cairo_cff_font_create_cid_fontdict (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (!font->scaled_font_subset->is_latin) {
|
||||
if (font->is_cid)
|
||||
status = cairo_cff_font_subset_fontdict (font);
|
||||
else
|
||||
status = cairo_cff_font_create_cid_fontdict (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
} else {
|
||||
font->private_dict_offset = malloc (sizeof (int));
|
||||
if (unlikely (font->private_dict_offset == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = cairo_cff_font_subset_strings (font);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1373,6 +1395,30 @@ cairo_cff_font_write_global_subrs (cairo_cff_font_t *font)
|
|||
return cff_index_write (&font->global_sub_index, &font->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_encoding (cairo_cff_font_t *font)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
cairo_status_t status;
|
||||
unsigned int i;
|
||||
|
||||
cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP);
|
||||
buf[0] = 0; /* Format 0 */
|
||||
buf[1] = font->scaled_font_subset->num_glyphs - 1;
|
||||
status = _cairo_array_append_multiple (&font->output, buf, 2);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
unsigned char ch = font->scaled_font_subset->to_latin_char[i];
|
||||
status = _cairo_array_append (&font->output, &ch);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
|
||||
{
|
||||
|
|
@ -1426,8 +1472,100 @@ cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Winansi to CFF standard strings mapping for characters 128 to 255 */
|
||||
const int winansi_to_cff_std_string[] = {
|
||||
/* 128 */
|
||||
0, 0, 117, 101, 118, 121, 112, 113,
|
||||
126, 122, 192, 107, 142, 0, 199, 0,
|
||||
/* 144 */
|
||||
0, 65, 8, 105, 119, 116, 111, 137,
|
||||
127, 153, 221, 108, 148, 0, 228, 198,
|
||||
/* 160 */
|
||||
0, 96, 97, 98, 103, 100, 160, 102,
|
||||
131, 170, 139, 106, 151, 0, 165, 128,
|
||||
/* 176 */
|
||||
161, 156, 164, 169, 125, 152, 115, 114,
|
||||
133, 150, 143, 187, 158, 155, 163, 123,
|
||||
/* 192 */
|
||||
174, 171, 172, 176, 173, 175, 138, 177,
|
||||
181, 178, 179, 180, 185, 182, 183, 184,
|
||||
/* 208 */
|
||||
154, 186, 190, 187, 188, 191, 189, 168,
|
||||
141, 196, 193, 194, 195, 197, 157, 149,
|
||||
/* 224 */
|
||||
203, 200, 201, 205, 202, 204, 144, 206,
|
||||
210, 207, 208, 209, 214, 211, 212, 213,
|
||||
/* 240 */
|
||||
167, 215, 219, 216, 217, 220, 218, 159,
|
||||
147, 225, 222, 223, 224, 226, 162, 227,
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_charset (cairo_cff_font_t *font)
|
||||
cairo_cff_font_get_sid_for_winansi_char (cairo_cff_font_t *font, int ch, int *sid_out)
|
||||
{
|
||||
int sid;
|
||||
cairo_status_t status;
|
||||
const char *euro = "Euro";
|
||||
|
||||
if (ch == 39) {
|
||||
sid = 104;
|
||||
|
||||
} else if (ch == 96) {
|
||||
sid = 124;
|
||||
|
||||
} else if (ch >= 32 && ch <= 126) {
|
||||
sid = ch - 31;
|
||||
|
||||
} else if (ch == 128) {
|
||||
sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
|
||||
status = cff_index_append_copy (&font->strings_subset_index,
|
||||
(unsigned char *)euro, strlen(euro));
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
} else if (ch >= 128 && ch <= 255) {
|
||||
sid = winansi_to_cff_std_string[ch - 128];
|
||||
|
||||
} else {
|
||||
sid = 0;
|
||||
}
|
||||
|
||||
*sid_out = sid;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_type1_charset (cairo_cff_font_t *font)
|
||||
{
|
||||
unsigned char format = 0;
|
||||
unsigned int i;
|
||||
int ch, sid;
|
||||
cairo_status_t status;
|
||||
uint16_t sid_be16;
|
||||
|
||||
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
|
||||
status = _cairo_array_append (&font->output, &format);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
ch = font->scaled_font_subset->to_latin_char[i];
|
||||
status = cairo_cff_font_get_sid_for_winansi_char (font, ch, &sid);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
sid_be16 = cpu_to_be16(sid);
|
||||
status = _cairo_array_append_multiple (&font->output, &sid_be16, sizeof(sid_be16));
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_cid_charset (cairo_cff_font_t *font)
|
||||
{
|
||||
unsigned char byte;
|
||||
uint16_t word;
|
||||
|
|
@ -1499,9 +1637,9 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
|
|||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
|
||||
int dict_num,
|
||||
cairo_hash_table_t *parent_dict,
|
||||
cairo_hash_table_t *private_dict)
|
||||
int dict_num,
|
||||
cairo_hash_table_t *parent_dict,
|
||||
cairo_hash_table_t *private_dict)
|
||||
{
|
||||
int offset;
|
||||
int size;
|
||||
|
|
@ -1605,32 +1743,75 @@ cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_type1_private_dict_and_local_sub (cairo_cff_font_t *font)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = cairo_cff_font_write_private_dict (font,
|
||||
0,
|
||||
font->top_dict,
|
||||
font->private_dict);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cairo_cff_font_write_local_sub (font,
|
||||
0,
|
||||
font->private_dict,
|
||||
&font->local_sub_index);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
typedef cairo_status_t
|
||||
(*font_write_t) (cairo_cff_font_t *font);
|
||||
|
||||
static const font_write_t font_write_funcs[] = {
|
||||
static const font_write_t font_write_cid_funcs[] = {
|
||||
cairo_cff_font_write_header,
|
||||
cairo_cff_font_write_name,
|
||||
cairo_cff_font_write_top_dict,
|
||||
cairo_cff_font_write_strings,
|
||||
cairo_cff_font_write_global_subrs,
|
||||
cairo_cff_font_write_charset,
|
||||
cairo_cff_font_write_cid_charset,
|
||||
cairo_cff_font_write_fdselect,
|
||||
cairo_cff_font_write_charstrings,
|
||||
cairo_cff_font_write_cid_fontdict,
|
||||
cairo_cff_font_write_cid_private_dict_and_local_sub,
|
||||
};
|
||||
|
||||
static const font_write_t font_write_type1_funcs[] = {
|
||||
cairo_cff_font_write_header,
|
||||
cairo_cff_font_write_name,
|
||||
cairo_cff_font_write_top_dict,
|
||||
cairo_cff_font_write_strings,
|
||||
cairo_cff_font_write_global_subrs,
|
||||
cairo_cff_font_write_encoding,
|
||||
cairo_cff_font_write_type1_charset,
|
||||
cairo_cff_font_write_charstrings,
|
||||
cairo_cff_font_write_type1_private_dict_and_local_sub,
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
cairo_cff_font_write_subset (cairo_cff_font_t *font)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
|
||||
status = font_write_funcs[i] (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (font->scaled_font_subset->is_latin) {
|
||||
for (i = 0; i < ARRAY_LENGTH (font_write_type1_funcs); i++) {
|
||||
status = font_write_type1_funcs[i] (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_LENGTH (font_write_cid_funcs); i++) {
|
||||
status = font_write_cid_funcs[i] (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1984,6 +2165,12 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
|
|||
memcpy (cff_subset->data, data, length);
|
||||
cff_subset->data_length = length;
|
||||
|
||||
{
|
||||
FILE *f;
|
||||
f=fopen("font.cff", "wb");
|
||||
fwrite(data, length, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
cairo_cff_font_destroy (font);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -2012,23 +2199,90 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
|
|||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font)
|
||||
_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
cairo_status_t status;
|
||||
unsigned char *data;
|
||||
unsigned long data_length;
|
||||
unsigned char *current_ptr;
|
||||
unsigned char *data_end;
|
||||
cff_header_t *header;
|
||||
cff_index_element_t *element;
|
||||
cairo_hash_table_t *top_dict;
|
||||
cairo_array_t index;
|
||||
int size;
|
||||
cairo_bool_t is_cid = FALSE;
|
||||
|
||||
backend = scaled_font->backend;
|
||||
if (!backend->load_truetype_table)
|
||||
return FALSE;
|
||||
|
||||
/* check for CFF font */
|
||||
data_length = 0;
|
||||
status = backend->load_truetype_table(scaled_font,
|
||||
TT_TAG_CFF, 0, NULL, &data_length);
|
||||
if (status)
|
||||
return FALSE;;
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
/* load CFF data */
|
||||
data = malloc (data_length);
|
||||
if (unlikely (data == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = backend->load_truetype_table (scaled_font, TT_TAG_CFF,
|
||||
0, data, &data_length);
|
||||
if (unlikely (status))
|
||||
goto fail1;
|
||||
|
||||
data_end = data + data_length;
|
||||
|
||||
/* skip header */
|
||||
if (data_length < sizeof (cff_header_t))
|
||||
goto fail1;
|
||||
|
||||
header = (cff_header_t *) data;
|
||||
current_ptr = data + header->header_size;
|
||||
|
||||
/* skip name */
|
||||
cff_index_init (&index);
|
||||
status = cff_index_read (&index, ¤t_ptr, data_end);
|
||||
cff_index_fini (&index);
|
||||
|
||||
if (status)
|
||||
goto fail1;
|
||||
|
||||
/* read top dict */
|
||||
cff_index_init (&index);
|
||||
status = cff_index_read (&index, ¤t_ptr, data_end);
|
||||
if (unlikely (status))
|
||||
goto fail2;
|
||||
|
||||
status = cff_dict_init (&top_dict);
|
||||
if (unlikely (status))
|
||||
goto fail2;
|
||||
|
||||
element = _cairo_array_index (&index, 0);
|
||||
status = cff_dict_read (top_dict, element->data, element->length);
|
||||
if (unlikely (status))
|
||||
goto fail3;
|
||||
|
||||
/* check for ROS operator indicating a CID font */
|
||||
if (cff_dict_get_operands (top_dict, ROS_OP, &size) != NULL)
|
||||
is_cid = TRUE;
|
||||
|
||||
fail3:
|
||||
cff_dict_fini (top_dict);
|
||||
|
||||
fail2:
|
||||
cff_index_fini (&index);
|
||||
|
||||
fail1:
|
||||
free (data);
|
||||
|
||||
return is_cid;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -2133,8 +2387,9 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
|
|||
cff_header_t header;
|
||||
cairo_array_t *charstring;
|
||||
unsigned char buf[40];
|
||||
unsigned char *end_buf;
|
||||
unsigned char *end_buf, *end_buf2;
|
||||
unsigned int i;
|
||||
int sid;
|
||||
|
||||
/* Create header */
|
||||
header.major = 1;
|
||||
|
|
@ -2145,6 +2400,28 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
|
|||
|
||||
/* Create Top Dict */
|
||||
font->is_cid = FALSE;
|
||||
|
||||
snprintf((char*)buf, sizeof(buf), "CairoFont-%u-%u",
|
||||
font->scaled_font_subset->font_id,
|
||||
font->scaled_font_subset->subset_id);
|
||||
sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
|
||||
status = cff_index_append_copy (&font->strings_subset_index,
|
||||
(unsigned char *)buf,
|
||||
strlen((char*)buf));
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
end_buf = encode_integer (buf, sid);
|
||||
status = cff_dict_set_operands (font->top_dict, FULLNAME_OP,
|
||||
buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict, FAMILYNAME_OP,
|
||||
buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
end_buf = encode_integer (buf, type2_subset->x_min);
|
||||
end_buf = encode_integer (end_buf, type2_subset->y_min);
|
||||
end_buf = encode_integer (end_buf, type2_subset->x_max);
|
||||
|
|
@ -2160,29 +2437,50 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDSELECT_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDARRAY_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (font->scaled_font_subset->is_latin) {
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
ENCODING_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* Private has two operands - size and offset */
|
||||
end_buf2 = encode_integer_max (end_buf, 0);
|
||||
cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf2 - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
} else {
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDSELECT_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
FDARRAY_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
status = cff_dict_set_operands (font->top_dict,
|
||||
CHARSET_OP, buf, end_buf - buf);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cairo_cff_font_set_ros_strings (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (!font->scaled_font_subset->is_latin) {
|
||||
status = cairo_cff_font_set_ros_strings (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* Create CID FD dictionary */
|
||||
status = cairo_cff_font_create_cid_fontdict (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
/* Create CID FD dictionary */
|
||||
status = cairo_cff_font_create_cid_fontdict (font);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
} else {
|
||||
font->private_dict_offset = malloc (sizeof (int));
|
||||
if (unlikely (font->private_dict_offset == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Create charstrings */
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
|
|
@ -2261,7 +2559,13 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
|
|||
|
||||
memcpy (cff_subset->data, data, length);
|
||||
cff_subset->data_length = length;
|
||||
cff_subset->data_length = length;
|
||||
|
||||
{
|
||||
FILE *f;
|
||||
f=fopen("font.cff", "wb");
|
||||
fwrite(data, length, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
_cairo_type2_charstrings_fini (&type2_subset);
|
||||
cairo_cff_font_destroy (font);
|
||||
|
|
|
|||
|
|
@ -3888,7 +3888,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
|
|||
cairo_pdf_resource_t stream, descriptor, cidfont_dict;
|
||||
cairo_pdf_resource_t subset_resource, to_unicode_stream;
|
||||
cairo_pdf_font_t font;
|
||||
unsigned int i;
|
||||
unsigned int i, last_glyph;
|
||||
cairo_status_t status;
|
||||
char tag[10];
|
||||
|
||||
|
|
@ -3903,6 +3903,8 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
|
|||
status = _cairo_pdf_surface_open_stream (surface,
|
||||
NULL,
|
||||
TRUE,
|
||||
font_subset->is_latin ?
|
||||
" /Subtype /Type1C\n" :
|
||||
" /Subtype /CIDFontType0C\n");
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
@ -3959,58 +3961,106 @@ _cairo_pdf_surface_emit_cff_font (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)
|
||||
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 /CIDFontType0\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++)
|
||||
last_glyph = i;
|
||||
_cairo_pdf_surface_update_object (surface, subset_resource);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" %ld",
|
||||
(long)(subset->widths[i]*PDF_UNITS_PER_EM));
|
||||
"%d 0 obj\r\n"
|
||||
"<< /Type /Font\n"
|
||||
" /Subtype /Type1\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);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" ]]\n"
|
||||
">>\n"
|
||||
"endobj\n");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
_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");
|
||||
|
||||
if (to_unicode_stream.id != 0)
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
" /ToUnicode %d 0 R\n",
|
||||
to_unicode_stream.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");
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
">>\n"
|
||||
"endobj\n");
|
||||
} else {
|
||||
cidfont_dict = _cairo_pdf_surface_new_object (surface);
|
||||
if (cidfont_dict.id == 0)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\n"
|
||||
"<< /Type /Font\n"
|
||||
" /Subtype /CIDFontType0\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"
|
||||
">>\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;
|
||||
|
|
|
|||
|
|
@ -387,13 +387,13 @@ cairo_private void
|
|||
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
|
||||
|
||||
/**
|
||||
* _cairo_cff_scaled_font_is_cff:
|
||||
* _cairo_cff_scaled_font_is_cid_cff:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Return %TRUE if @scaled_font is a CFF font, otherwise return %FALSE.
|
||||
* Return %TRUE if @scaled_font is a CID CFF font, otherwise return %FALSE.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_cff_scaled_font_is_cff (cairo_scaled_font_t *scaled_font);
|
||||
_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
/**
|
||||
* _cairo_cff_fallback_init:
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ typedef struct _cairo_sub_font_collection {
|
|||
unsigned long *glyphs; /* scaled_font_glyph_index */
|
||||
char **utf8;
|
||||
unsigned int glyphs_size;
|
||||
int *to_latin_char;
|
||||
unsigned long *latin_to_subset_glyph_index;
|
||||
unsigned int max_glyph;
|
||||
unsigned int num_glyphs;
|
||||
|
|
@ -232,6 +233,7 @@ _cairo_sub_font_glyph_collect (void *entry, void *closure)
|
|||
|
||||
collection->glyphs[subset_glyph_index] = scaled_font_glyph_index;
|
||||
collection->utf8[subset_glyph_index] = sub_font_glyph->utf8;
|
||||
collection->to_latin_char[subset_glyph_index] = sub_font_glyph->latin_character;
|
||||
if (sub_font_glyph->is_latin)
|
||||
collection->latin_to_subset_glyph_index[sub_font_glyph->latin_character] = subset_glyph_index;
|
||||
|
||||
|
|
@ -296,8 +298,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
sub_font->font_id = font_id;
|
||||
|
||||
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 (_cairo_cff_scaled_font_is_cid_cff (scaled_font))
|
||||
sub_font->use_latin_subset = FALSE; /* latin subsets of CID CFF fonts are not supported */
|
||||
|
||||
if (sub_font->use_latin_subset)
|
||||
sub_font->current_subset = 1; /* reserve subset 0 for latin glyphs */
|
||||
|
|
@ -349,16 +351,20 @@ static unsigned int _winansi_0x80_to_0x9f[] = {
|
|||
};
|
||||
|
||||
int
|
||||
_cairo_unicode_to_winansi (unsigned long unicode)
|
||||
_cairo_unicode_to_winansi (unsigned long uni)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (unicode < 0x80 || (unicode >= 0xa0 && unicode <= 0xff))
|
||||
return unicode;
|
||||
/* exclude the extra "hyphen" at 0xad to avoid duplicate glyphnames */
|
||||
if ((uni >= 0x20 && uni <= 0x7e) ||
|
||||
(uni >= 0xa1 && uni <= 0xff && uni != 0xad))
|
||||
return uni;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (_winansi_0x80_to_0x9f[i] == unicode)
|
||||
return i + 0x80;
|
||||
if (uni >= 0x80 && uni <= 0x9f) {
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (_winansi_0x80_to_0x9f[i] == uni)
|
||||
return i + 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
@ -709,8 +715,10 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
subset.is_latin = FALSE;
|
||||
if (sub_font->use_latin_subset && i == 0) {
|
||||
subset.is_latin = TRUE;
|
||||
subset.to_latin_char = collection->to_latin_char;
|
||||
subset.latin_to_subset_glyph_index = collection->latin_to_subset_glyph_index;
|
||||
} else {
|
||||
subset.to_latin_char = NULL;
|
||||
subset.latin_to_subset_glyph_index = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1025,14 +1033,18 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
|||
|
||||
collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
|
||||
collection.utf8 = _cairo_malloc_ab (collection.glyphs_size, sizeof(char *));
|
||||
collection.to_latin_char = _cairo_malloc_ab (collection.glyphs_size, sizeof(int));
|
||||
collection.latin_to_subset_glyph_index = _cairo_malloc_ab (256, sizeof(unsigned long));
|
||||
if (unlikely (collection.glyphs == NULL ||
|
||||
collection.utf8 == NULL ||
|
||||
collection.to_latin_char == NULL ||
|
||||
collection.latin_to_subset_glyph_index == NULL)) {
|
||||
if (collection.glyphs != NULL)
|
||||
free (collection.glyphs);
|
||||
if (collection.utf8 != NULL)
|
||||
free (collection.utf8);
|
||||
if (collection.to_latin_char != NULL)
|
||||
free (collection.to_latin_char);
|
||||
if (collection.latin_to_subset_glyph_index != NULL)
|
||||
free (collection.latin_to_subset_glyph_index);
|
||||
|
||||
|
|
@ -1056,6 +1068,7 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
|||
}
|
||||
free (collection.utf8);
|
||||
free (collection.glyphs);
|
||||
free (collection.to_latin_char);
|
||||
free (collection.latin_to_subset_glyph_index);
|
||||
|
||||
return collection.status;
|
||||
|
|
@ -1191,7 +1204,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
|||
|
||||
if (utf16_len == 1) {
|
||||
int ch = _cairo_unicode_to_winansi (utf16[0]);
|
||||
if (ch > 0)
|
||||
if (ch > 0 && _cairo_winansi_to_glyphname (ch))
|
||||
strncpy (buf, _cairo_winansi_to_glyphname (ch), sizeof (buf));
|
||||
else
|
||||
snprintf (buf, sizeof (buf), "uni%04X", (int) utf16[0]);
|
||||
|
|
|
|||
|
|
@ -836,7 +836,7 @@ static const char *winansi_encoding[256] = {
|
|||
NULL, NULL, NULL, NULL,
|
||||
/* 32 */
|
||||
"space", "exclam", "quotedbl", "numbersign",
|
||||
"dollar", "percent", "ampersand", "quoteright",
|
||||
"dollar", "percent", "ampersand", "quotesingle",
|
||||
"parenleft", "parenright", "asterisk", "plus",
|
||||
"comma", "hyphen", "period", "slash",
|
||||
/* 48 */
|
||||
|
|
@ -855,7 +855,7 @@ static const char *winansi_encoding[256] = {
|
|||
"X", "Y", "Z", "bracketleft",
|
||||
"backslash", "bracketright", "asciicircum", "underscore",
|
||||
/* 96 */
|
||||
"quoteleft", "a", "b", "c",
|
||||
"grave", "a", "b", "c",
|
||||
"d", "e", "f", "g",
|
||||
"h", "i", "j", "k",
|
||||
"l", "m", "n", "o",
|
||||
|
|
@ -868,17 +868,18 @@ static const char *winansi_encoding[256] = {
|
|||
"Euro", NULL, "quotesinglbase","florin",
|
||||
"quotedblbase", "ellipsis", "dagger", "daggerdbl",
|
||||
"circumflex", "perthousand", "Scaron", "guilsinglleft",
|
||||
"OE", "bullet", "Zcaron", NULL,
|
||||
"OE", NULL, "Zcaron", NULL,
|
||||
/* 144 */
|
||||
NULL, "quoteleft", "quoteright", "quotedblleft",
|
||||
"quotedblright","bullet", "endash", "emdash",
|
||||
"tilde", "trademark", "scaron", "guilsinglright",
|
||||
"oe", "bullet", "zcaron", "Ydieresis",
|
||||
"oe", NULL, "zcaron", "Ydieresis",
|
||||
/* 160 */
|
||||
"space", "exclamdown", "cent", "sterling",
|
||||
NULL, "exclamdown", "cent", "sterling",
|
||||
"currency", "yen", "brokenbar", "section",
|
||||
"dieresis", "copyright", "ordfeminine", "guillemotleft",
|
||||
"logicalnot", "hyphen", "registered", "macron",
|
||||
/* 173 is also "hyphen" but we leave this NULL to avoid duplicate names */
|
||||
"logicalnot", NULL, "registered", "macron",
|
||||
/* 176 */
|
||||
"degree", "plusminus", "twosuperior", "threesuperior",
|
||||
"acute", "mu", "paragraph", "periodcentered",
|
||||
|
|
|
|||
|
|
@ -433,9 +433,11 @@ typedef struct _cairo_scaled_font_subset {
|
|||
* Value of glyphs array is scaled_font_glyph_index.
|
||||
*/
|
||||
unsigned long *glyphs;
|
||||
|
||||
unsigned long *to_unicode;
|
||||
char **utf8;
|
||||
char **glyph_names;
|
||||
int *to_latin_char;
|
||||
unsigned long *latin_to_subset_glyph_index;
|
||||
unsigned int num_glyphs;
|
||||
cairo_bool_t is_composite;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue