The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Object.vala in libbirdfont/Svg

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/Svg/Object.vala.
Linear gradients and matrix tranform on gradients
1 /* 2 Copyright (C) 2016 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Cairo; 16 using Math; 17 18 namespace BirdFont { 19 20 public abstract class Object : GLib.Object { 21 bool open = false; 22 23 public bool visible = true; 24 public SvgStyle style = new SvgStyle (); 25 public Gee.ArrayList<SvgTransform> transforms = new Gee.ArrayList<SvgTransform> (); 26 27 public virtual Color? color { get; set; } // FIXME: keep this in svg style 28 public virtual Color? stroke_color { get; set; } 29 public virtual Gradient? gradient { get; set; } 30 31 /** Path boundaries */ 32 public virtual double xmax { get; set; } 33 public virtual double xmin { get; set; } 34 public virtual double ymax { get; set; } 35 public virtual double ymin { get; set; } 36 37 public virtual double rotation { get; set; } 38 public virtual double stroke { get; set; } 39 public virtual LineCap line_cap { get; set; default = LineCap.BUTT; } 40 public virtual bool fill { get; set; } 41 42 public Object () { 43 } 44 45 public Object.create_copy (Object o) { 46 open = o.open; 47 } 48 49 public void set_open (bool open) { 50 this.open = open; 51 } 52 53 public bool is_open () { 54 return open; 55 } 56 57 public abstract void update_region_boundaries (); 58 public abstract bool is_over (double x, double y); 59 public abstract void draw (Context cr, Color? c = null); 60 public abstract Object copy (); 61 public abstract void move (double dx, double dy); 62 public abstract void rotate (double theta, double xc, double yc); 63 public abstract bool is_empty (); 64 public abstract void resize (double ratio_x, double ratio_y); 65 66 public static void copy_attributes (Object from, Object to) { 67 to.open = from.open; 68 69 to.color = from.color; 70 to.stroke_color = from.stroke_color; 71 to.gradient = from.gradient; 72 73 to.xmax = from.xmax; 74 to.xmin = from.xmin; 75 to.ymax = from.ymax; 76 to.ymin = from.ymin; 77 78 to.rotation = from.rotation; 79 to.stroke = from.stroke; 80 to.line_cap = from.line_cap; 81 to.fill = from.fill; 82 } 83 84 public virtual string to_string () { 85 return "Object"; 86 } 87 88 public void fill_and_stroke (Context cr) { 89 Color fill, stroke; 90 bool need_fill = style.fill_gradient != null || style.fill != null; 91 bool need_stroke = style.stroke_gradient != null || style.stroke != null; 92 93 cr.set_line_width (style.stroke_width); 94 95 if (style.fill_gradient != null) { 96 apply_gradient (cr, (!) style.fill_gradient); 97 } 98 99 if (style.fill != null) { 100 fill = (!) style.fill; 101 cr.set_source_rgba (fill.r, fill.g, fill.b, fill.a); 102 } 103 104 if (need_fill) { 105 if (need_stroke) { 106 cr.fill_preserve (); 107 } else { 108 cr.fill (); 109 } 110 } 111 112 if (style.stroke_gradient != null) { 113 apply_gradient (cr, (!) style.stroke_gradient); 114 } 115 116 if (style.stroke != null) { 117 stroke = (!) style.stroke; 118 cr.set_source_rgba (stroke.r, stroke.g, stroke.b, stroke.a); 119 } 120 121 if (need_stroke) { 122 cr.stroke (); 123 } 124 } 125 126 public void apply_gradient (Context cr, Gradient? gradient) { 127 Cairo.Pattern pattern; 128 Gradient g; 129 130 if (gradient != null) { 131 g = (!) gradient; 132 133 pattern = new Cairo.Pattern.linear ( 134 g.x1, 135 g.y1, 136 g.x2, 137 g.y2); 138 139 foreach (Stop s in g.stops) { 140 Color c = s.color; 141 pattern.add_color_stop_rgba (s.offset, c.r, c.g, c.b, c.a); 142 } 143 144 cr.set_source (pattern); 145 } 146 } 147 148 public void apply_transform (Context cr) { 149 foreach (SvgTransform transform in transforms) { 150 if (transform.type == TransformType.SCALE) { 151 if (transform.arguments.size == 1) { 152 double s = transform.arguments.get_double (0); 153 cr.scale (s, s); 154 } else if (transform.arguments.size == 2) { 155 double s0 = transform.arguments.get_double (0); 156 double s1 = transform.arguments.get_double (1); 157 cr.scale (s0, s1); 158 } 159 } else if (transform.type == TransformType.TRANSLATE) { 160 if (transform.arguments.size == 1) { 161 double s = transform.arguments.get_double (0); 162 cr.translate (s, 0); 163 } else if (transform.arguments.size == 2) { 164 double s0 = transform.arguments.get_double (0); 165 double s1 = transform.arguments.get_double (1); 166 cr.translate (s0, s1); 167 } 168 } else if (transform.type == TransformType.MATRIX) { 169 if (transform.arguments.size == 1) { 170 double s0 = transform.arguments.get_double (0); 171 double s1 = transform.arguments.get_double (1); 172 double s2 = transform.arguments.get_double (2); 173 double s3 = transform.arguments.get_double (3); 174 double s4 = transform.arguments.get_double (4); 175 double s5 = transform.arguments.get_double (5); 176 177 Matrix matrix = Matrix (s0, s1, s2, s3, s4, s5); 178 cr.set_matrix (matrix); 179 } 180 } 181 } 182 } 183 } 184 185 } 186