📄 cairo-ps-surface.c
字号:
/* 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, unsigned long glyph_index){ cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_PATH, &scaled_glyph); if (status) return status; _cairo_output_stream_printf (surface->final_stream, "0 0 %f %f %f %f setcachedevice\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */ status = _cairo_ps_surface_emit_path (surface, surface->final_stream, scaled_glyph->path, CAIRO_LINE_CAP_ROUND); _cairo_output_stream_printf (surface->final_stream, "F\n"); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long glyph_index){ cairo_scaled_glyph_t *scaled_glyph; cairo_status_t status; cairo_image_surface_t *image; unsigned char *row, *byte; int rows, cols, bytes_per_row; status = _cairo_scaled_glyph_lookup (scaled_font, glyph_index, CAIRO_SCALED_GLYPH_INFO_METRICS| CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); image = scaled_glyph->surface; assert (image->format == CAIRO_FORMAT_A1); _cairo_output_stream_printf (surface->final_stream, "0 0 %f %f %f %f setcachedevice\n", _cairo_fixed_to_double (scaled_glyph->bbox.p1.x), - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y), _cairo_fixed_to_double (scaled_glyph->bbox.p2.x), - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y)); _cairo_output_stream_printf (surface->final_stream, "<<\n" " /ImageType 1\n" " /Width %d\n" " /Height %d\n" " /ImageMatrix [%f %f %f %f %f %f]\n" " /Decode [1 0]\n" " /BitsPerComponent 1\n", image->width, image->height, image->base.device_transform.xx, image->base.device_transform.yx, image->base.device_transform.xy, image->base.device_transform.yy, image->base.device_transform.x0, - image->base.device_transform.y0); _cairo_output_stream_printf (surface->final_stream, " /DataSource {<"); bytes_per_row = (image->width + 7) / 8; for (row = image->data, rows = image->height; rows; row += image->stride, rows--) { for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) { unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte); _cairo_output_stream_printf (surface->final_stream, "%02x ", output_byte); } _cairo_output_stream_printf (surface->final_stream, "\n "); } _cairo_output_stream_printf (surface->final_stream, " >}\n"); _cairo_output_stream_printf (surface->final_stream, ">>\n"); _cairo_output_stream_printf (surface->final_stream, "imagemask\n"); return CAIRO_STATUS_SUCCESS;}static void_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface, cairo_scaled_font_t *scaled_font, unsigned long scaled_font_glyph_index, unsigned int subset_glyph_index){ cairo_status_t status; _cairo_output_stream_printf (surface->final_stream, "\t\t{ %% %d\n", subset_glyph_index); status = _cairo_ps_surface_emit_outline_glyph_data (surface, scaled_font, scaled_font_glyph_index); if (status == CAIRO_INT_STATUS_UNSUPPORTED) status = _cairo_ps_surface_emit_bitmap_glyph_data (surface, scaled_font, scaled_font_glyph_index); _cairo_output_stream_printf (surface->final_stream, "\t\t}\n"); if (status) _cairo_surface_set_error (&surface->base, status);}static cairo_status_t_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, cairo_scaled_font_subset_t *font_subset){ cairo_matrix_t matrix; int i; _cairo_output_stream_printf (surface->final_stream, "%% _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[%f %f %f %f 0 0]\n" "\t/Encoding\t[0]\n" "\t/FontBBox\t[0 0 10 10]\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, font_subset->scaled_font, font_subset->glyphs[i], i); } _cairo_output_stream_printf (surface->final_stream, "\t]\n" "\t/BuildChar {\n" "\t\texch /Glyphs get\n" "\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_type1_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; 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_cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface){ cairo_status_t status; _cairo_output_stream_printf (surface->final_stream, "%% _cairo_ps_surface_emit_font_subsets\n"); status = _cairo_scaled_font_subsets_foreach (surface->font_subsets, _cairo_ps_surface_emit_font_subset, surface); _cairo_scaled_font_subsets_destroy (surface->font_subsets); surface->font_subsets = NULL; return status;}static void_cairo_ps_surface_emit_body (cairo_ps_surface_t *surface){ char buf[4096]; int n; rewind (surface->tmpfile); while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0) _cairo_output_stream_write (surface->final_stream, buf, n);}static void_cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface){ _cairo_output_stream_printf (surface->final_stream, "%%%%Trailer\n" "%%%%EOF\n");}static cairo_surface_t *_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, double width, double height){ cairo_status_t status; cairo_ps_surface_t *surface = NULL; surface = malloc (sizeof (cairo_ps_surface_t)); if (surface == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto CLEANUP; } _cairo_surface_init (&surface->base, &cairo_ps_surface_backend, CAIRO_CONTENT_COLOR_ALPHA); surface->final_stream = stream; surface->tmpfile = tmpfile (); if (surface->tmpfile == NULL) goto CLEANUP_SURFACE; surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile); status = _cairo_output_stream_get_status (surface->stream); if (status) goto CLEANUP_TMPFILE; surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT); if (! surface->font_subsets) goto CLEANUP_OUTPUT_STREAM; surface->width = width; surface->height = height; surface->max_width = width; surface->max_height = height; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; surface->num_pages = 0; _cairo_array_init (&surface->dsc_header_comments, sizeof (char *)); _cairo_array_init (&surface->dsc_setup_comments, sizeof (char *)); _cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *)); surface->dsc_comment_target = &surface->dsc_header_comments; return _cairo_paginated_surface_create (&surface->base, CAIRO_CONTENT_COLOR_ALPHA, width, height, &cairo_ps_surface_paginated_backend); CLEANUP_OUTPUT_STREAM: _cairo_output_stream_destroy (surface->stream); CLEANUP_TMPFILE: fclose (surface->tmpfile); CLEANUP_SURFACE: free (surface); CLEANUP: _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil;}/** * cairo_ps_surface_create: * @filename: a filename for the PS output (must be writable) * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) * * Creates a PostScript surface of the specified size in points to be * written to @filename. See cairo_ps_surface_create_for_stream() for * a more flexible mechanism for handling the PostScript output than * simply writing it to a named file. * * Note that the size of individual pages of the PostScript output can * vary. See cairo_ps_surface_set_size(). * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. * * Since: 1.2 **/cairo_surface_t *cairo_ps_surface_create (const char *filename, double width_in_points, double height_in_points){ cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create_for_filename (filename); status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } return _cairo_ps_surface_create_for_stream_internal (stream, width_in_points, height_in_points);}/** * cairo_ps_surface_create_for_stream: * @write_func: a #cairo_write_func_t to accept the output data * @closure: the closure argument for @write_func * @width_in_points: width of the surface, in points (1 point == 1/72.0 inch) * @height_in_points: height of the surface, in points (1 point == 1/72.0 inch) * * Creates a PostScript surface of the specified size in points to be * written incrementally to the stream represented by @write_func and * @closure. See cairo_ps_surface_create() for a more convenient way * to simply direct the PostScript output to a named file. * * Note that the size of individual pages of the PostScript * output can vary. See cairo_ps_surface_set_size(). * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. * * Since: 1.2 */cairo_surface_t *cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points){ cairo_status_t status; cairo_output_stream_t *stream; stream = _cairo_output_stream_create (write_func, NULL, closure); status = _cairo_output_stream_get_status (stream); if (status) { _cairo_error (status); return (cairo_surface_t*) &_cairo_surface_nil; } return _cairo_ps_surface_create_for_stream_internal (stream,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -