static cairo_status_t _cairo_xml_emit_type42_font (cairo_xml_t *xml, cairo_scaled_font_t *scaled_font) { const cairo_scaled_font_backend_t *backend; cairo_output_stream_t *base64_stream; cairo_output_stream_t *zlib_stream; cairo_status_t status, status2; unsigned long size; uint32_t len; uint8_t *buf; backend = scaled_font->backend; if (backend->load_truetype_table == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; size = 0; status = backend->load_truetype_table (scaled_font, 0, 0, NULL, &size); if (unlikely (status)) return status; buf = malloc (size); if (unlikely (buf == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = backend->load_truetype_table (scaled_font, 0, 0, buf, &size); if (unlikely (status)) { free (buf); return status; } _cairo_xml_printf_start (xml, "<font type='42' flags='%d' index='0'>", _cairo_ft_scaled_font_get_load_flags (scaled_font)); base64_stream = _cairo_base64_stream_create (xml->stream); len = size; _cairo_output_stream_write (base64_stream, &len, sizeof (len)); zlib_stream = _cairo_deflate_stream_create (base64_stream); _cairo_output_stream_write (zlib_stream, buf, size); free (buf); status2 = _cairo_output_stream_destroy (zlib_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; status2 = _cairo_output_stream_destroy (base64_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; _cairo_xml_printf_end (xml, "</font>"); return status; }
static void _device_destroy (void *abstract_device) { cairo_xml_t *xml = abstract_device; cairo_status_t status; status = _cairo_output_stream_destroy (xml->stream); free (xml); }
static cairo_status_t _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators) { cairo_output_stream_t *word_wrap_stream; cairo_status_t status, status2; int i; double x; if (pdf_operators->num_glyphs == 0) return CAIRO_STATUS_SUCCESS; word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72); status = _cairo_output_stream_get_status (word_wrap_stream); if (unlikely (status)) return _cairo_output_stream_destroy (word_wrap_stream); /* Check if glyph advance used to position every glyph */ x = pdf_operators->cur_x; for (i = 0; i < pdf_operators->num_glyphs; i++) { if (fabs(pdf_operators->glyphs[i].x_position - x) > GLYPH_POSITION_TOLERANCE) break; x += pdf_operators->glyphs[i].x_advance; } if (i == pdf_operators->num_glyphs) { status = _cairo_pdf_operators_emit_glyph_string (pdf_operators, word_wrap_stream); } else { status = _cairo_pdf_operators_emit_glyph_string_with_positioning ( pdf_operators, word_wrap_stream); } pdf_operators->num_glyphs = 0; pdf_operators->glyph_buf_x_pos = pdf_operators->cur_x; status2 = _cairo_output_stream_destroy (word_wrap_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; return status; }
/* The line cap value is needed to workaround the fact that PostScript * and PDF semantics for stroking degenerate sub-paths do not match * cairo semantics. (PostScript draws something for any line cap * value, while cairo draws something only for round caps). * * When using this function to emit a path to be filled, rather than * stroked, simply pass %CAIRO_LINE_CAP_ROUND which will guarantee that * the stroke workaround will not modify the path being emitted. */ static cairo_status_t _cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators, const cairo_path_fixed_t*path, cairo_matrix_t *path_transform, cairo_line_cap_t line_cap) { cairo_output_stream_t *word_wrap; cairo_status_t status, status2; pdf_path_info_t info; cairo_box_t box; word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72); status = _cairo_output_stream_get_status (word_wrap); if (unlikely (status)) return _cairo_output_stream_destroy (word_wrap); info.output = word_wrap; info.path_transform = path_transform; info.line_cap = line_cap; if (_cairo_path_fixed_is_rectangle (path, &box) && ((path_transform->xx == 0 && path_transform->yy == 0) || (path_transform->xy == 0 && path_transform->yx == 0))) { status = _cairo_pdf_path_rectangle (&info, &box); } else { status = _cairo_path_fixed_interpret (path, _cairo_pdf_path_move_to, _cairo_pdf_path_line_to, _cairo_pdf_path_curve_to, _cairo_pdf_path_close_path, &info); } status2 = _cairo_output_stream_destroy (word_wrap); if (status == CAIRO_STATUS_SUCCESS) status = status2; return status; }
cairo_status_t _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, unsigned long glyph_index) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status, status2; cairo_output_stream_t *null_stream; if (unlikely (surface->base.status)) return surface->base.status; null_stream = _cairo_null_stream_create (); if (unlikely (null_stream->status)) return null_stream->status; _cairo_type3_glyph_surface_set_stream (surface, null_stream); _cairo_scaled_font_freeze_cache (surface->scaled_font); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE, &scaled_glyph); if (_cairo_status_is_error (status)) goto cleanup; if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = CAIRO_STATUS_SUCCESS; goto cleanup; } status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, &surface->base); if (unlikely (status)) goto cleanup; status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = CAIRO_STATUS_SUCCESS; cleanup: _cairo_scaled_font_thaw_cache (surface->scaled_font); status2 = _cairo_output_stream_destroy (null_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; return status; }
cairo_status_t _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface, unsigned long glyph_index) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status, status2; cairo_output_stream_t *null_stream; null_stream = _cairo_null_stream_create (); _cairo_type3_glyph_surface_set_stream (surface, null_stream); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_META_SURFACE, &scaled_glyph); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) goto cleanup; if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = CAIRO_STATUS_SUCCESS; goto cleanup; } status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, &surface->base); status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status) return status; if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = CAIRO_STATUS_SUCCESS; cleanup: status2 = _cairo_output_stream_destroy (null_stream); if (status) return status; return status2; }
static cairo_status_t _cairo_xml_emit_image (cairo_xml_t *xml, cairo_image_surface_t *image) { cairo_output_stream_t *stream; cairo_status_t status; _cairo_xml_printf_start (xml, "<image width='%d' height='%d' format='%s'>", image->width, image->height, _format_to_string (image->format)); stream = _cairo_base64_stream_create (xml->stream); status = cairo_surface_write_to_png_stream (&image->base, _write_func, stream); assert (status == CAIRO_STATUS_SUCCESS); status = _cairo_output_stream_destroy (stream); if (unlikely (status)) return status; _cairo_xml_printf_end (xml, "</image>"); return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, cairo_output_stream_t *stream, unsigned long glyph_index, cairo_box_t *bbox, double *width) { cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status, status2; double x_advance, y_advance; cairo_output_stream_t *mem_stream; cairo_matrix_t font_matrix_inverse; _cairo_type3_glyph_surface_set_stream (surface, stream); status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_META_SURFACE, &scaled_glyph); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) return status; if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_scaled_glyph_lookup (surface->scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (status) return status; status = CAIRO_INT_STATUS_IMAGE_FALLBACK; } x_advance = scaled_glyph->metrics.x_advance; y_advance = scaled_glyph->metrics.y_advance; font_matrix_inverse = surface->scaled_font->font_matrix; status2 = cairo_matrix_invert (&font_matrix_inverse); /* The invertability of font_matrix is tested in * pdf_operators_show_glyphs before any glyphs are mappped to the * subset. */ assert (status2 == CAIRO_STATUS_SUCCESS); cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance); *width = x_advance; *bbox = scaled_glyph->bbox; _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse, bbox, NULL); _cairo_output_stream_printf (surface->stream, "%f 0 %f %f %f %f d1\n", x_advance, _cairo_fixed_to_double (bbox->p1.x), - _cairo_fixed_to_double (bbox->p2.y), _cairo_fixed_to_double (bbox->p2.x), - _cairo_fixed_to_double (bbox->p1.y)); if (status == CAIRO_STATUS_SUCCESS) { mem_stream = _cairo_memory_stream_create (); _cairo_type3_glyph_surface_set_stream (surface, mem_stream); _cairo_output_stream_printf (surface->stream, "q\n"); status = _cairo_meta_surface_replay (scaled_glyph->meta_surface, &surface->base); status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (status) return status; _cairo_output_stream_printf (surface->stream, "Q\n"); _cairo_type3_glyph_surface_set_stream (surface, stream); if (status == CAIRO_STATUS_SUCCESS) _cairo_memory_stream_copy (mem_stream, stream); status2 = _cairo_output_stream_destroy (mem_stream); if (status2) return status2; } if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index); return status; }