📄 cairo-svg-surface.c
字号:
surface->xml_node = _cairo_memory_stream_create (); if (op == CAIRO_OPERATOR_CLEAR) { if (surface->content == CAIRO_CONTENT_COLOR) { _cairo_output_stream_printf (surface->xml_node, "<rect " "width=\"%f\" height=\"%f\" " "style=\"opacity: 1; " "stroke: none; " "fill: rgb(0,0,0);\"/>\n", surface->width, surface->height); } return CAIRO_STATUS_SUCCESS; } } emit_paint (surface->xml_node, surface, op, source, NULL); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_svg_surface_mask (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_pattern_t *mask){ cairo_svg_surface_t *surface = abstract_surface; cairo_svg_document_t *document = surface->document; cairo_output_stream_t *mask_stream; char buffer[64]; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (_operation_supported (surface, op, source)); emit_alpha_filter (document); /* emit_paint() will output a pattern definition to * document->xml_node_defs so we need to write the mask element to * a temporary stream and then copy that to xml_node_defs. */ mask_stream = _cairo_memory_stream_create (); _cairo_output_stream_printf (mask_stream, "<mask id=\"mask%d\">\n" " <g filter=\"url(#alpha)\">\n", document->mask_id); emit_paint (mask_stream, surface, op, mask, NULL); _cairo_output_stream_printf (mask_stream, " </g>\n" "</mask>\n"); _cairo_memory_stream_copy (mask_stream, document->xml_node_defs); _cairo_output_stream_destroy (mask_stream); snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"", document->mask_id); emit_paint (surface->xml_node, surface, op, source, buffer); document->mask_id++; return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_svg_surface_stroke (void *abstract_dst, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *stroke_style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias){ cairo_svg_surface_t *surface = abstract_dst; cairo_status_t status; const char *line_cap, *line_join; unsigned int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, source); assert (_operation_supported (surface, op, source)); switch (stroke_style->line_cap) { case CAIRO_LINE_CAP_BUTT: line_cap = "butt"; break; case CAIRO_LINE_CAP_ROUND: line_cap = "round"; break; case CAIRO_LINE_CAP_SQUARE: line_cap = "square"; break; default: ASSERT_NOT_REACHED; } switch (stroke_style->line_join) { case CAIRO_LINE_JOIN_MITER: line_join = "miter"; break; case CAIRO_LINE_JOIN_ROUND: line_join = "round"; break; case CAIRO_LINE_JOIN_BEVEL: line_join = "bevel"; break; default: ASSERT_NOT_REACHED; } _cairo_output_stream_printf (surface->xml_node, "<path style=\"fill: none; " "stroke-width: %f; " "stroke-linecap: %s; " "stroke-linejoin: %s; ", stroke_style->line_width, line_cap, line_join); emit_pattern (surface, source, surface->xml_node, TRUE); emit_operator (surface->xml_node, surface, op); if (stroke_style->num_dashes > 0) { _cairo_output_stream_printf (surface->xml_node, "stroke-dasharray: "); for (i = 0; i < stroke_style->num_dashes; i++) { _cairo_output_stream_printf (surface->xml_node, "%f", stroke_style->dash[i]); if (i + 1 < stroke_style->num_dashes) _cairo_output_stream_printf (surface->xml_node, ","); else _cairo_output_stream_printf (surface->xml_node, "; "); } if (stroke_style->dash_offset != 0.0) { _cairo_output_stream_printf (surface->xml_node, "stroke-dashoffset: %f; ", stroke_style->dash_offset); } } _cairo_output_stream_printf (surface->xml_node, "stroke-miterlimit: %f;\" ", stroke_style->miter_limit); status = emit_path (surface->xml_node, path, ctm_inverse); emit_transform (surface->xml_node, " transform", "/>\n", ctm); return status;}static cairo_int_status_t_cairo_svg_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *pattern, const cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font){ cairo_svg_surface_t *surface = abstract_surface; cairo_svg_document_t *document = surface->document; cairo_path_fixed_t path; cairo_status_t status; unsigned int font_id, subset_id, subset_glyph_index; int i; if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) return _analyze_operation (surface, op, pattern); assert (_operation_supported (surface, op, pattern)); if (num_glyphs <= 0) return CAIRO_STATUS_SUCCESS; /* FIXME it's probably possible to apply a pattern of a gradient to * a group of symbols, but I don't know how yet. Gradients or patterns * are translated by x and y properties of use element. */ if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) goto FALLBACK; _cairo_output_stream_printf (surface->xml_node, "<g style=\""); emit_pattern (surface, pattern, surface->xml_node, FALSE); _cairo_output_stream_printf (surface->xml_node, "\">\n"); for (i = 0; i < num_glyphs; i++) { status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets, scaled_font, glyphs[i].index, &font_id, &subset_id, &subset_glyph_index); if (status) { glyphs += i; num_glyphs -= i; goto FALLBACK; } _cairo_output_stream_printf (surface->xml_node, " <use xlink:href=\"#glyph%d-%d\" " "x=\"%f\" y=\"%f\"/>\n", font_id, subset_glyph_index, glyphs[i].x, glyphs[i].y); } _cairo_output_stream_printf (surface->xml_node, "</g>\n"); return CAIRO_STATUS_SUCCESS;FALLBACK: _cairo_path_fixed_init (&path); status = _cairo_scaled_font_glyph_path (scaled_font,(cairo_glyph_t *) glyphs, num_glyphs, &path); if (status) return status; status = _cairo_svg_surface_fill (abstract_surface, op, pattern, &path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL); _cairo_path_fixed_fini (&path); return status;}static cairo_int_status_t_cairo_svg_surface_intersect_clip_path (void *dst, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias){ cairo_svg_surface_t *surface = dst; cairo_svg_document_t *document = surface->document; cairo_status_t status; int i; if (path == NULL) { for (i = 0; i < surface->clip_level; i++) _cairo_output_stream_printf (surface->xml_node, "</g>\n"); surface->clip_level = 0; return CAIRO_STATUS_SUCCESS; } _cairo_output_stream_printf (document->xml_node_defs, "<clipPath id=\"clip%d\">\n" " <path ", document->clip_id); status = emit_path (document->xml_node_defs, path, NULL); _cairo_output_stream_printf (document->xml_node_defs, "/>\n" "</clipPath>\n"); _cairo_output_stream_printf (surface->xml_node, "<g clip-path=\"url(#clip%d)\" " "clip-rule=\"%s\">\n", document->clip_id, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); document->clip_id++; surface->clip_level++; return status;}static void_cairo_svg_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 const cairo_surface_backend_t cairo_svg_surface_backend = { CAIRO_SURFACE_TYPE_SVG, _cairo_svg_surface_create_similar, _cairo_svg_surface_finish, NULL, /* acquire_source_image */ NULL, /* release_source_image */ NULL, /* acquire_dest_image */ NULL, /* release_dest_image */ NULL, /* clone_similar */ NULL, /* _cairo_svg_surface_composite, */ NULL, /* _cairo_svg_surface_fill_rectangles, */ NULL, /* _cairo_svg_surface_composite_trapezoids,*/ NULL, /* copy_page */ NULL, /* show_page */ NULL, /* set_clip_region */ _cairo_svg_surface_intersect_clip_path, _cairo_svg_surface_get_extents, NULL, /* _cairo_svg_surface_old_show_glyphs, */ _cairo_svg_surface_get_font_options, NULL, /* flush */ NULL, /* mark dirty rectangle */ NULL, /* scaled font fini */ NULL, /* scaled glyph fini */ _cairo_svg_surface_paint, _cairo_svg_surface_mask, _cairo_svg_surface_stroke, _cairo_svg_surface_fill, _cairo_svg_surface_show_glyphs};static cairo_svg_document_t *_cairo_svg_document_create (cairo_output_stream_t *output_stream, double width, double height, cairo_svg_version_t version){ cairo_svg_document_t *document; document = malloc (sizeof (cairo_svg_document_t)); if (document == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return NULL; } /* The use of defs for font glyphs imposes no per-subset limit. */ document->font_subsets = _cairo_scaled_font_subsets_create (0); if (document->font_subsets == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); free (document); return NULL; } document->output_stream = output_stream; document->refcount = 1; document->owner = NULL; document->finished = FALSE; document->width = width; document->height = height; document->surface_id = 0; document->linear_pattern_id = 0; document->radial_pattern_id = 0; document->pattern_id = 0; document->filter_id = 0; document->clip_id = 0; document->mask_id = 0; document->xml_node_defs = _cairo_memory_stream_create (); document->xml_node_glyphs = _cairo_memory_stream_create (); document->alpha_filter = FALSE; _cairo_array_init (&document->meta_snapshots, sizeof (cairo_meta_snapshot_t)); document->svg_version = version; return document;}static cairo_svg_document_t *_cairo_svg_document_reference (cairo_svg_document_t *document){ document->refcount++; return document;}static void_cairo_svg_document_destroy (cairo_svg_document_t *document){ document->refcount--; if (document->refcount > 0) return; _cairo_svg_document_finish (document); free (document);}static cairo_status_t_cairo_svg_document_finish (cairo_svg_document_t *document){ cairo_status_t status; cairo_output_stream_t *output = document->output_stream; cairo_meta_snapshot_t *snapshot; cairo_svg_surface_t *surface; unsigned int i; if (document->finished) return CAIRO_STATUS_SUCCESS; _cairo_output_stream_printf (output, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<svg xmlns=\"http://www.w3.org/2000/svg\" " "xmlns:xlink=\"http://www.w3.org/1999/xlink\" " "width=\"%fpt\" height=\"%fpt\" " "viewBox=\"0 0 %f %f\" version=\"%s\">\n", document->width, document->height, document->width, document->height, _cairo_svg_internal_version_strings [document->svg_version]); _cairo_svg_document_emit_font_subsets (document); if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 || _cairo_memory_stream_length (document->xml_node_defs) > 0) { _cairo_output_stream_printf (output, "<defs>\n"); if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0) { _cairo_output_stream_printf (output, "<g>\n"); _cairo_memory_stream_copy (document->xml_node_glyphs, output); _cairo_output_stream_printf (output, "</g>\n"); } _cairo_memory_stream_copy (document->xml_node_defs, output); _cairo_output_stream_printf (output, "</defs>\n"); } surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner); _cairo_output_stream_printf (output, "<g id=\"surface%d\" " "clip-path=\"url(#clip%d)\">\n", surface->id, surface->base_clip); _cairo_memory_stream_copy (surface->xml_node, output); for (i = 0; i < surface->clip_level; i++) _cairo_output_stream_printf (output, "</g>\n"); _cairo_output_stream_printf (output, "</g>\n</svg>\n"); _cairo_output_stream_destroy (document->xml_node_glyphs); _cairo_output_stream_destroy (document->xml_node_defs); status = _cairo_output_stream_get_status (output); _cairo_output_stream_destroy (output); for (i = 0; i < document->meta_snapshots.num_elements; i++) { snapshot = _cairo_array_index (&document->meta_snapshots, i); cairo_surface_destroy ((cairo_surface_t *) snapshot->meta); } _cairo_array_fini (&document->meta_snapshots); document->finished = TRUE; return status;}static void_cairo_svg_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode){ cairo_svg_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode;}static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = { NULL /*_cairo_svg_surface_start_page*/, _cairo_svg_surface_set_paginated_mode};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -