blob: 7e30391afefada705f94a8719a63add4e029d6ab [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_COMPUTE_SVG_SVG_H_
#define SRC_GRAPHICS_LIB_COMPUTE_SVG_SVG_H_
//
//
//
#include <stdbool.h>
#include <stdint.h>
//
// This is a minimalist SVG parser that creates a representation of the
// input document as three parallel lists of the following types:
//
// - Path items:
// Corresponding to SVG path/shape elements as they appear in the
// document (i.e. without any transforms applied).
//
// - Raster items:
// Corresponding to rasterization attributes of the paths above (i.e.
// transforms or path fill / path stroke operations).
//
// - Layer items:
// Corresponding to presentation attributes (e.g. color, opacity, fill
// rule) of the rasters above.
//
// Each item is stored as an array of simple tagged structs describing
// 'commands' from the input SVG document. See the definitions of
// svg_{path,raster,layer}_cmd below for details.
//
// The number of items in each list can be retrieved by calling
// svg_{path,raster,layer}_count(), and each individual item can be enumerated
// (as a series of commands) with svg_iterator_create_for_{path,raster,layer}().
//
// Each list stores its items' in a single concatenated array of commands in
// memory. This allows enumerating the whole list as a series of commands too,
// since each item type has specific 'begin' and 'end' tags.
// See svg_iterator_create_for_all_{paths,rasters,layers}().
//
// The following table lists which SVG elements are associated with the
// path, raster and layer lists:
//
// element attributes : id
// container elements : svg, g
// path elements : circle, ellipse, line, path, polygon, polyline, rect
// raster attributes : transform, fill|stroke|marker, style props (*)
// layer attributes : fill-rule, opacities, colors or gradient references, style props (*)
//
// See svg2spinel.[c|h] for an example of how to decode the commands.
//
// Limitations:
//
// The parser can parse basic SVG docs and has the following
// limitations:
//
// - Doesn't support CSS styling
// - Doesn't support hrefs
// - Doesn't support text
//
#ifdef __cplusplus
extern "C" {
#endif
//
//
//
struct svg;
union svg_path_cmd;
union svg_raster_cmd;
union svg_layer_cmd;
//
// Open and parse an SVG doc from a filename.
//
// File I/O and parsing errors result in an error message and NULL is
// returned.
//
struct svg *
svg_open(char const * const filename, bool const is_verbose);
//
// Parse an SVG doc from a zero-terminated byte array.
//
// Parsing errors result in an error message and NULL is returned.
//
struct svg *
svg_parse(char const * doc, const bool is_verbose);
//
// Dispose of the SVG doc.
//
void
svg_dispose(struct svg * const sd);
//
// Return the number of entries in each list.
//
extern uint32_t
svg_path_count(struct svg const * const sd);
extern uint32_t
svg_raster_count(struct svg const * const sd);
extern uint32_t
svg_layer_count(struct svg const * const sd);
//
// Path iteration
//
struct svg_path_iterator;
// Create new iterator to loop over all commands of a given path, or if
// |path_index| is UINT32_MAX, all path commands in the document.
extern struct svg_path_iterator *
svg_path_iterator_create(struct svg const * const sd, uint32_t const path_index);
// Return next path command. Return false at the end of the list,
// otherwise set |*cmd| and return true.
extern bool
svg_path_iterator_next(struct svg_path_iterator * iterator, union svg_path_cmd const ** cmd);
// Destroy a path iterator instance.
extern void
svg_path_iterator_dispose(struct svg_path_iterator * iterator);
//
// Raster iteration
//
struct svg_raster_iterator;
// Create new iterator to loop over all commands of a given raster, or if
// |raster_index| is UINT32_MAX, all raster commands in the document.
extern struct svg_raster_iterator *
svg_raster_iterator_create(struct svg const * const sd, uint32_t const raster_index);
extern bool
svg_raster_iterator_next(struct svg_raster_iterator * iterator, union svg_raster_cmd const ** cmd);
// Destroy a raster iterator instance.
extern void
svg_raster_iterator_dispose(struct svg_raster_iterator * iterator);
//
// Layer iteration
//
struct svg_layer_iterator;
extern struct svg_layer_iterator *
svg_layer_iterator_create(struct svg const * const sd, uint32_t const layer_index);
extern bool
svg_layer_iterator_next(struct svg_layer_iterator * iterator, union svg_layer_cmd const ** cmd);
extern void
svg_layer_iterator_dispose(struct svg_layer_iterator * iterator);
//
// SVG COLOR
//
// An SVG color is stored as a big-endian R8:G8:B8 value.
//
// 0 8 16 24
// +---+---+---+
// | B | G | R |
// +---+---+---+
//
typedef uint32_t svg_color_t;
//
// PATH COMMAND TYPES
//
typedef enum svg_path_cmd_type
{
//
SVG_PATH_CMD_BEGIN,
SVG_PATH_CMD_END,
// SVG PATH OBJECTS
SVG_PATH_CMD_CIRCLE,
SVG_PATH_CMD_ELLIPSE,
SVG_PATH_CMD_LINE,
SVG_PATH_CMD_POLYGON,
SVG_PATH_CMD_POLYLINE,
SVG_PATH_CMD_RECT,
// POLY POINT
SVG_PATH_CMD_POLY_POINT,
SVG_PATH_CMD_POLY_END,
// GEOMETRY COMMANDS
SVG_PATH_CMD_PATH_BEGIN,
SVG_PATH_CMD_PATH_END,
SVG_PATH_CMD_MOVE_TO,
SVG_PATH_CMD_MOVE_TO_REL,
SVG_PATH_CMD_CLOSE_UPPER,
SVG_PATH_CMD_CLOSE,
SVG_PATH_CMD_LINE_TO,
SVG_PATH_CMD_LINE_TO_REL,
SVG_PATH_CMD_HLINE_TO,
SVG_PATH_CMD_HLINE_TO_REL,
SVG_PATH_CMD_VLINE_TO,
SVG_PATH_CMD_VLINE_TO_REL,
SVG_PATH_CMD_CUBIC_TO,
SVG_PATH_CMD_CUBIC_TO_REL,
SVG_PATH_CMD_CUBIC_SMOOTH_TO,
SVG_PATH_CMD_CUBIC_SMOOTH_TO_REL,
SVG_PATH_CMD_QUAD_TO,
SVG_PATH_CMD_QUAD_TO_REL,
SVG_PATH_CMD_QUAD_SMOOTH_TO,
SVG_PATH_CMD_QUAD_SMOOTH_TO_REL,
SVG_PATH_CMD_RAT_CUBIC_TO,
SVG_PATH_CMD_RAT_CUBIC_TO_REL,
SVG_PATH_CMD_RAT_QUAD_TO,
SVG_PATH_CMD_RAT_QUAD_TO_REL,
SVG_PATH_CMD_ARC_TO,
SVG_PATH_CMD_ARC_TO_REL,
} svg_path_cmd_type;
//
// PATH COMMAND STRUCTS
//
struct svg_path_point
{
float x;
float y;
};
//
struct svg_path_cmd_begin
{
svg_path_cmd_type type;
};
struct svg_path_cmd_end
{
svg_path_cmd_type type;
uint32_t path_index;
};
struct svg_path_cmd_circle
{
svg_path_cmd_type type;
float cx;
float cy;
float r;
};
struct svg_path_cmd_ellipse
{
svg_path_cmd_type type;
float cx;
float cy;
float rx;
float ry;
};
struct svg_path_cmd_line
{
svg_path_cmd_type type;
float x1;
float y1;
float x2;
float y2;
};
struct svg_path_cmd_polygon
{
svg_path_cmd_type type;
};
struct svg_path_cmd_polyline
{
svg_path_cmd_type type;
};
struct svg_path_cmd_poly_point
{
svg_path_cmd_type type;
float x;
float y;
};
struct svg_path_cmd_poly_end
{
svg_path_cmd_type type;
};
struct svg_path_cmd_rect
{
svg_path_cmd_type type;
float x;
float y;
float width;
float height;
float rx;
float ry;
};
struct svg_path_cmd_path_begin
{
svg_path_cmd_type type;
};
struct svg_path_cmd_path_end
{
svg_path_cmd_type type;
};
struct svg_path_cmd_move_to
{
svg_path_cmd_type type;
float x;
float y;
};
struct svg_path_cmd_close
{
svg_path_cmd_type type;
};
struct svg_path_cmd_line_to
{
svg_path_cmd_type type;
float x;
float y;
};
struct svg_path_cmd_coord_to
{
svg_path_cmd_type type;
float c;
};
struct svg_path_cmd_hline_to
{
svg_path_cmd_type type;
float c;
};
struct svg_path_cmd_vline_to
{
svg_path_cmd_type type;
float c;
};
struct svg_path_cmd_cubic_to
{
svg_path_cmd_type type;
float x1;
float y1;
float x2;
float y2;
float x;
float y;
};
struct svg_path_cmd_cubic_smooth_to
{
svg_path_cmd_type type;
float x2;
float y2;
float x;
float y;
};
struct svg_path_cmd_quad_to
{
svg_path_cmd_type type;
float x1;
float y1;
float x;
float y;
};
struct svg_path_cmd_quad_smooth_to
{
svg_path_cmd_type type;
float x;
float y;
};
struct svg_path_cmd_rat_cubic_to
{
svg_path_cmd_type type;
float x1;
float y1;
float x2;
float y2;
float x;
float y;
float w1;
float w2;
};
struct svg_path_cmd_rat_quad_to
{
svg_path_cmd_type type;
float x1;
float y1;
float x;
float y;
float w1;
};
struct svg_path_cmd_arc_to
{
svg_path_cmd_type type;
float rx;
float ry;
float x_axis_rotation;
float large_arc_flag;
float sweep_flag;
float x;
float y;
};
//
//
//
union svg_path_cmd
{
svg_path_cmd_type type;
struct svg_path_cmd_begin begin;
struct svg_path_cmd_end end;
struct svg_path_cmd_circle circle;
struct svg_path_cmd_ellipse ellipse;
struct svg_path_cmd_line line;
struct svg_path_cmd_polygon polygon;
struct svg_path_cmd_polyline polyline;
struct svg_path_cmd_poly_point poly_point;
struct svg_path_cmd_rect rect;
struct svg_path_cmd_path_begin path_begin;
struct svg_path_cmd_path_end path_end;
struct svg_path_cmd_move_to move_to;
struct svg_path_cmd_close close;
struct svg_path_cmd_line_to line_to;
struct svg_path_cmd_hline_to hline_to;
struct svg_path_cmd_vline_to vline_to;
struct svg_path_cmd_cubic_to cubic_to;
struct svg_path_cmd_cubic_smooth_to cubic_smooth_to;
struct svg_path_cmd_quad_to quad_to;
struct svg_path_cmd_quad_smooth_to quad_smooth_to;
struct svg_path_cmd_rat_cubic_to rat_cubic_to;
struct svg_path_cmd_rat_quad_to rat_quad_to;
struct svg_path_cmd_arc_to arc_to;
};
//
// RASTER COMMAND TYPES
//
typedef enum svg_raster_cmd_type
{
//
SVG_RASTER_CMD_BEGIN,
SVG_RASTER_CMD_END,
// RASTERIZE PATH
SVG_RASTER_CMD_FILL,
SVG_RASTER_CMD_STROKE,
SVG_RASTER_CMD_MARKER,
//
SVG_RASTER_CMD_STROKE_WIDTH,
// TRANSFORM PATH BEFORE RASTERIZING
SVG_RASTER_CMD_TRANSFORM_PROJECT, // 8 float
SVG_RASTER_CMD_TRANSFORM_MATRIX, // 6 float
SVG_RASTER_CMD_TRANSFORM_TRANSLATE, // 2 float
SVG_RASTER_CMD_TRANSFORM_SCALE, // 2 float
SVG_RASTER_CMD_TRANSFORM_ROTATE, // 3 float
SVG_RASTER_CMD_TRANSFORM_SKEW_X, // 1 float
SVG_RASTER_CMD_TRANSFORM_SKEW_Y, // 1 float
// DROP TRANSFORM FROM HOST'S TRANSFORM STACK
SVG_RASTER_CMD_TRANSFORM_DROP
} svg_raster_cmd_type;
//
// RASTER COMMAND STRUCTS
//
struct svg_raster_cmd_begin
{
svg_raster_cmd_type type;
};
struct svg_raster_cmd_end
{
svg_raster_cmd_type type;
uint32_t raster_index;
};
struct svg_raster_cmd_fsm
{
svg_raster_cmd_type type;
uint32_t path_index;
};
struct svg_raster_cmd_fill
{
svg_raster_cmd_type type;
uint32_t path_index;
};
struct svg_raster_cmd_stroke
{
svg_raster_cmd_type type;
uint32_t path_index;
};
struct svg_raster_cmd_marker
{
svg_raster_cmd_type type;
uint32_t path_index;
};
struct svg_raster_cmd_stroke_width
{
svg_raster_cmd_type type;
float stroke_width;
};
struct svg_raster_cmd_transform_project
{
svg_raster_cmd_type type;
float sx;
float shy;
float shx;
float sy;
float tx;
float ty;
float w0;
float w1;
};
struct svg_raster_cmd_transform_matrix
{
svg_raster_cmd_type type;
float sx;
float shy;
float shx;
float sy;
float tx;
float ty;
};
struct svg_raster_cmd_transform_translate
{
svg_raster_cmd_type type;
float tx;
float ty;
};
struct svg_raster_cmd_transform_scale
{
svg_raster_cmd_type type;
float sx;
float sy;
};
struct svg_raster_cmd_transform_rotate
{
svg_raster_cmd_type type;
float d;
float cx;
float cy;
};
struct svg_raster_cmd_transform_skew_x
{
svg_raster_cmd_type type;
float d;
};
struct svg_raster_cmd_transform_skew_y
{
svg_raster_cmd_type type;
float d;
};
struct svg_raster_cmd_transform_drop
{
svg_raster_cmd_type type;
};
//
//
//
union svg_raster_cmd
{
svg_raster_cmd_type type;
struct svg_raster_cmd_begin begin;
struct svg_raster_cmd_end end;
struct svg_raster_cmd_fsm fsm;
struct svg_raster_cmd_fill fill;
struct svg_raster_cmd_stroke stroke;
struct svg_raster_cmd_marker marker;
struct svg_raster_cmd_stroke_width stroke_width; // stroke_* attributes
struct svg_raster_cmd_transform_project project;
struct svg_raster_cmd_transform_matrix matrix;
struct svg_raster_cmd_transform_translate translate;
struct svg_raster_cmd_transform_scale scale;
struct svg_raster_cmd_transform_rotate rotate;
struct svg_raster_cmd_transform_skew_x skew_x;
struct svg_raster_cmd_transform_skew_y skew_y;
struct svg_raster_cmd_transform_drop drop;
};
//
// LAYER COMMAND TYPES
//
typedef enum svg_fill_rule_op
{
SVG_FILL_RULE_OP_EVENODD,
SVG_FILL_RULE_OP_NONZERO
} svg_fill_rule_op;
//
typedef enum svg_layer_cmd_type
{
//
SVG_LAYER_CMD_BEGIN,
SVG_LAYER_CMD_END,
// PLACE RASTER ON LAYER
SVG_LAYER_CMD_PLACE, // { rasterId index tx ty }
// LAYER PAINT SETTINGS
SVG_LAYER_CMD_OPACITY,
SVG_LAYER_CMD_FILL_RULE,
SVG_LAYER_CMD_FILL_COLOR,
SVG_LAYER_CMD_FILL_OPACITY,
SVG_LAYER_CMD_STROKE_COLOR,
SVG_LAYER_CMD_STROKE_OPACITY,
} svg_layer_cmd_type;
//
// LAYER COMMAND STRUCTS
//
struct svg_layer_cmd_begin
{
svg_layer_cmd_type type;
uint32_t layer_index;
};
struct svg_layer_cmd_end
{
svg_layer_cmd_type type;
};
struct svg_layer_cmd_place
{
svg_layer_cmd_type type;
uint32_t raster_index;
int tx;
int ty;
};
struct svg_layer_cmd_opacity
{
svg_layer_cmd_type type;
float opacity;
};
struct svg_layer_cmd_fill_rule
{
svg_layer_cmd_type type;
svg_fill_rule_op fill_rule;
};
struct svg_layer_cmd_fill_color
{
svg_layer_cmd_type type;
svg_color_t fill_color;
};
struct svg_layer_cmd_fill_opacity
{
svg_layer_cmd_type type;
float fill_opacity;
};
struct svg_layer_cmd_stroke_color
{
svg_layer_cmd_type type;
svg_color_t stroke_color;
};
struct svg_layer_cmd_stroke_opacity
{
svg_layer_cmd_type type;
float stroke_opacity;
};
//
//
//
union svg_layer_cmd
{
svg_layer_cmd_type type;
struct svg_layer_cmd_begin begin;
struct svg_layer_cmd_end end;
struct svg_layer_cmd_place place;
struct svg_layer_cmd_opacity opacity;
struct svg_layer_cmd_fill_rule fill_rule;
struct svg_layer_cmd_fill_color fill_color;
struct svg_layer_cmd_fill_opacity fill_opacity;
struct svg_layer_cmd_stroke_color stroke_color;
struct svg_layer_cmd_stroke_opacity stroke_opacity;
};
//
//
//
#ifdef __cplusplus
}
#endif
//
//
//
#endif // SRC_GRAPHICS_LIB_COMPUTE_SVG_SVG_H_