📄 cairo-ps-surface.c
字号:
{ cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; cairo_status_t status; const char *ps_operator; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return CAIRO_STATUS_SUCCESS; _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_intersect_clip_path\n"); if (path == NULL) { _cairo_output_stream_printf (stream, "initclip\n"); return CAIRO_STATUS_SUCCESS; } /* We're "filling" not stroking, so we pass CAIRO_LINE_CAP_ROUND. */ status = _cairo_ps_surface_emit_path (surface, stream, path, CAIRO_LINE_CAP_ROUND); switch (fill_rule) { case CAIRO_FILL_RULE_WINDING: ps_operator = "clip"; break; case CAIRO_FILL_RULE_EVEN_ODD: ps_operator = "eoclip"; break; default: ASSERT_NOT_REACHED; } _cairo_output_stream_printf (stream, "%s newpath\n", ps_operator); return status;}static cairo_int_status_t_cairo_ps_surface_get_extents (void *abstract_surface, cairo_rectangle_int16_t *rectangle){ cairo_ps_surface_t *surface = abstract_surface; rectangle->x = 0; rectangle->y = 0; /* XXX: The conversion to integers here is pretty bogus, (not to * mention the aribitray limitation of width to a short(!). We * may need to come up with a better interface for get_extents. */ rectangle->width = (int) ceil (surface->width); rectangle->height = (int) ceil (surface->height); return CAIRO_STATUS_SUCCESS;}static void_cairo_ps_surface_get_font_options (void *abstract_surface, cairo_font_options_t *options){ _cairo_font_options_init_default (options); cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);}static cairo_int_status_t_cairo_ps_surface_paint (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source){ cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; cairo_rectangle_int16_t extents; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); /* XXX: It would be nice to be able to assert this condition * here. But, we actually allow one 'cheat' that is used when * painting the final image-based fallbacks. The final fallbacks * do have alpha which we support by blending with white. This is * possible only because there is nothing between the fallback * images and the paper, nor is anything painted above. */ /* assert (_operation_supported (op, source)); */ _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_paint\n"); _cairo_pattern_get_extents (source, &extents); emit_pattern (surface, source, extents.x, extents.y); _cairo_output_stream_printf (stream, "%d %d M\n", extents.x, extents.y); _cairo_output_stream_printf (stream, "%d %d L\n", extents.x + extents.width, extents.y); _cairo_output_stream_printf (stream, "%d %d L\n", extents.x + extents.width, extents.y + extents.height); _cairo_output_stream_printf (stream, "%d %d L\n", extents.x, extents.y + extents.height); _cairo_output_stream_printf (stream, "P F\n"); return CAIRO_STATUS_SUCCESS;}static int_cairo_ps_line_cap (cairo_line_cap_t cap){ switch (cap) { case CAIRO_LINE_CAP_BUTT: return 0; case CAIRO_LINE_CAP_ROUND: return 1; case CAIRO_LINE_CAP_SQUARE: return 2; default: ASSERT_NOT_REACHED; return 0; }}static int_cairo_ps_line_join (cairo_line_join_t join){ switch (join) { case CAIRO_LINE_JOIN_MITER: return 0; case CAIRO_LINE_JOIN_ROUND: return 1; case CAIRO_LINE_JOIN_BEVEL: return 2; default: ASSERT_NOT_REACHED; return 0; }}static cairo_int_status_t_cairo_ps_surface_stroke (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias){ cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; cairo_int_status_t status; double *dash = style->dash; int num_dashes = style->num_dashes; double dash_offset = style->dash_offset; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_stroke\n"); /* PostScript has "special needs" when it comes to zero-length * dash segments with butt caps. It apparently (at least * according to ghostscript) draws hairlines for this * case. That's not what the cairo semantics want, so we first * touch up the array to eliminate any 0.0 values that will * result in "on" segments. */ if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) { int i; /* If there's an odd number of dash values they will each get * interpreted as both on and off. So we first explicitly * expand the array to remove the duplicate usage so that we * can modify some of the values. */ if (num_dashes % 2) { dash = malloc (2 * num_dashes * sizeof (double)); if (dash == NULL) return CAIRO_STATUS_NO_MEMORY; memcpy (dash, style->dash, num_dashes * sizeof (double)); memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double)); num_dashes *= 2; } for (i = 0; i < num_dashes; i += 2) { if (dash[i] == 0.0) { /* If we're at the front of the list, we first rotate * two elements from the end of the list to the front * of the list before folding away the 0.0. Or, if * there are only two dash elements, then there is * nothing at all to draw. */ if (i == 0) { double last_two[2]; if (num_dashes == 2) { if (dash != style->dash) free (dash); return CAIRO_STATUS_SUCCESS; } /* The cases of num_dashes == 0, 1, or 3 elements * cannot exist, so the rotation of 2 elements * will always be safe */ memcpy (last_two, dash + num_dashes - 2, sizeof (last_two)); memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double)); memcpy (dash, last_two, sizeof (last_two)); dash_offset += dash[0] + dash[1]; i = 2; } dash[i-1] += dash[i+1]; num_dashes -= 2; memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double)); /* If we might have just rotated, it's possible that * we rotated a 0.0 value to the front of the list. * Set i to -2 so it will get incremented to 0. */ if (i == 2) i = -2; } } } emit_pattern (surface, source, 0, 0); _cairo_output_stream_printf (stream, "gsave\n"); status = _cairo_ps_surface_emit_path (surface, stream, path, style->line_cap); /* * Switch to user space to set line parameters */ _cairo_output_stream_printf (stream, "[%f %f %f %f 0 0] concat\n", ctm->xx, ctm->yx, ctm->xy, ctm->yy); /* line width */ _cairo_output_stream_printf (stream, "%f setlinewidth\n", style->line_width); /* line cap */ _cairo_output_stream_printf (stream, "%d setlinecap\n", _cairo_ps_line_cap (style->line_cap)); /* line join */ _cairo_output_stream_printf (stream, "%d setlinejoin\n", _cairo_ps_line_join (style->line_join)); /* dashes */ if (num_dashes) { int d; _cairo_output_stream_printf (stream, "["); for (d = 0; d < num_dashes; d++) _cairo_output_stream_printf (stream, " %f", dash[d]); _cairo_output_stream_printf (stream, "] %f setdash\n", dash_offset); } if (dash != style->dash) free (dash); /* miter limit */ _cairo_output_stream_printf (stream, "%f setmiterlimit\n", style->miter_limit); _cairo_output_stream_printf (stream, "stroke\n"); _cairo_output_stream_printf (stream, "grestore\n"); return status;}static cairo_int_status_t_cairo_ps_surface_fill (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias){ cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; cairo_int_status_t status; const char *ps_operator; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_fill\n"); emit_pattern (surface, source, 0, 0); /* We're filling not stroking, so we pass CAIRO_LINE_CAP_ROUND. */ status = _cairo_ps_surface_emit_path (surface, stream, path, CAIRO_LINE_CAP_ROUND); switch (fill_rule) { case CAIRO_FILL_RULE_WINDING: ps_operator = "F"; break; case CAIRO_FILL_RULE_EVEN_ODD: ps_operator = "eofill"; break; default: ASSERT_NOT_REACHED; } _cairo_output_stream_printf (stream, "%s\n", ps_operator); return status;}static cairo_int_status_t_cairo_ps_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, const cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font){ cairo_ps_surface_t *surface = abstract_surface; cairo_output_stream_t *stream = surface->stream; int current_subset_id = -1; unsigned int font_id, subset_id, subset_glyph_index; cairo_status_t status; int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (operation_supported (surface, op, source)); _cairo_output_stream_printf (stream, "%% _cairo_ps_surface_show_glyphs\n"); if (num_glyphs) emit_pattern (surface, source, 0, 0); for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, scaled_font, glyphs[i].index, &font_id, &subset_id, &subset_glyph_index); if (status) return status; if (subset_id != current_subset_id) { _cairo_output_stream_printf (surface->stream, "/CairoFont-%d-%d findfont\n" "[ %f %f %f %f 0 0 ] makefont\n" "setfont\n", font_id, subset_id, scaled_font->scale.xx, scaled_font->scale.yx, -scaled_font->scale.xy, -scaled_font->scale.yy); current_subset_id = subset_id; } _cairo_output_stream_printf (surface->stream, "%f %f M <%02x> S\n", glyphs[i].x, glyphs[i].y, subset_glyph_index); } return _cairo_output_stream_get_status (surface->stream);}static void_cairo_ps_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode){ cairo_ps_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode;}static const cairo_surface_backend_t cairo_ps_surface_backend = { CAIRO_SURFACE_TYPE_PS, _cairo_ps_surface_create_similar, _cairo_ps_surface_finish, NULL, /* acquire_source_image */ NULL, /* release_source_image */ NULL, /* acquire_dest_image */ NULL, /* release_dest_image */ NULL, /* clone_similar */ NULL, /* composite */ NULL, /* fill_rectangles */ NULL, /* composite_trapezoids */ _cairo_ps_surface_copy_page, _cairo_ps_surface_show_page, NULL, /* set_clip_region */ _cairo_ps_surface_intersect_clip_path, _cairo_ps_surface_get_extents, NULL, /* old_show_glyphs */ _cairo_ps_surface_get_font_options, NULL, /* flush */ NULL, /* mark_dirty_rectangle */ NULL, /* scaled_font_fini */ NULL, /* scaled_glyph_fini */ /* Here are the drawing functions */ _cairo_ps_surface_paint, /* paint */ NULL, /* mask */ _cairo_ps_surface_stroke, _cairo_ps_surface_fill, _cairo_ps_surface_show_glyphs, NULL, /* snapshot */};static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend = { _cairo_ps_surface_start_page, _cairo_ps_surface_set_paginated_mode};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -