1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.3 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // SVG path renderer. 17 // 18 //---------------------------------------------------------------------------- 19 20 #include <stdio.h> 21 #include "agg_svg_path_renderer.h" 22 23 namespace mapserver 24 { 25 namespace svg 26 { 27 28 //------------------------------------------------------------------------ path_renderer()29 path_renderer::path_renderer() : 30 m_curved(m_storage), 31 m_curved_count(m_curved), 32 33 m_curved_stroked(m_curved_count), 34 m_curved_stroked_trans(m_curved_stroked, m_transform), 35 36 m_curved_trans(m_curved_count, m_transform), 37 m_curved_trans_contour(m_curved_trans) 38 { 39 m_curved_trans_contour.auto_detect_orientation(false); 40 } 41 42 //------------------------------------------------------------------------ remove_all()43 void path_renderer::remove_all() 44 { 45 m_storage.remove_all(); 46 m_attr_storage.remove_all(); 47 m_attr_stack.remove_all(); 48 m_transform.reset(); 49 } 50 51 //------------------------------------------------------------------------ begin_path()52 void path_renderer::begin_path() 53 { 54 push_attr(); 55 unsigned idx = m_storage.start_new_path(); 56 m_attr_storage.add(path_attributes(cur_attr(), idx)); 57 } 58 59 //------------------------------------------------------------------------ end_path()60 void path_renderer::end_path() 61 { 62 if(m_attr_storage.size() == 0) 63 { 64 throw exception("end_path : The path was not begun"); 65 } 66 path_attributes attr = cur_attr(); 67 unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index; 68 attr.index = idx; 69 m_attr_storage[m_attr_storage.size() - 1] = attr; 70 pop_attr(); 71 } 72 73 //------------------------------------------------------------------------ move_to(double x,double y,bool rel)74 void path_renderer::move_to(double x, double y, bool rel) // M, m 75 { 76 if(rel) m_storage.rel_to_abs(&x, &y); 77 m_storage.move_to(x, y); 78 } 79 80 //------------------------------------------------------------------------ line_to(double x,double y,bool rel)81 void path_renderer::line_to(double x, double y, bool rel) // L, l 82 { 83 if(rel) m_storage.rel_to_abs(&x, &y); 84 m_storage.line_to(x, y); 85 } 86 87 //------------------------------------------------------------------------ hline_to(double x,bool rel)88 void path_renderer::hline_to(double x, bool rel) // H, h 89 { 90 double x2 = 0.0; 91 double y2 = 0.0; 92 if(m_storage.total_vertices()) 93 { 94 m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); 95 if(rel) x += x2; 96 m_storage.line_to(x, y2); 97 } 98 } 99 100 //------------------------------------------------------------------------ vline_to(double y,bool rel)101 void path_renderer::vline_to(double y, bool rel) // V, v 102 { 103 double x2 = 0.0; 104 double y2 = 0.0; 105 if(m_storage.total_vertices()) 106 { 107 m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); 108 if(rel) y += y2; 109 m_storage.line_to(x2, y); 110 } 111 } 112 113 //------------------------------------------------------------------------ curve3(double x1,double y1,double x,double y,bool rel)114 void path_renderer::curve3(double x1, double y1, // Q, q 115 double x, double y, bool rel) 116 { 117 if(rel) 118 { 119 m_storage.rel_to_abs(&x1, &y1); 120 m_storage.rel_to_abs(&x, &y); 121 } 122 m_storage.curve3(x1, y1, x, y); 123 } 124 125 //------------------------------------------------------------------------ curve3(double x,double y,bool rel)126 void path_renderer::curve3(double x, double y, bool rel) // T, t 127 { 128 // throw exception("curve3(x, y) : NOT IMPLEMENTED YET"); 129 if(rel) 130 { 131 m_storage.curve3_rel(x, y); 132 } else 133 { 134 m_storage.curve3(x, y); 135 } 136 } 137 138 //------------------------------------------------------------------------ curve4(double x1,double y1,double x2,double y2,double x,double y,bool rel)139 void path_renderer::curve4(double x1, double y1, // C, c 140 double x2, double y2, 141 double x, double y, bool rel) 142 { 143 if(rel) 144 { 145 m_storage.rel_to_abs(&x1, &y1); 146 m_storage.rel_to_abs(&x2, &y2); 147 m_storage.rel_to_abs(&x, &y); 148 } 149 m_storage.curve4(x1, y1, x2, y2, x, y); 150 } 151 152 //------------------------------------------------------------------------ curve4(double x2,double y2,double x,double y,bool rel)153 void path_renderer::curve4(double x2, double y2, // S, s 154 double x, double y, bool rel) 155 { 156 //throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET"); 157 if(rel) 158 { 159 m_storage.curve4_rel(x2, y2, x, y); 160 } else 161 { 162 m_storage.curve4(x2, y2, x, y); 163 } 164 } 165 166 //------------------------------------------------------------------------ close_subpath()167 void path_renderer::close_subpath() 168 { 169 m_storage.end_poly(path_flags_close); 170 } 171 172 //------------------------------------------------------------------------ cur_attr()173 path_attributes& path_renderer::cur_attr() 174 { 175 if(m_attr_stack.size() == 0) 176 { 177 throw exception("cur_attr : Attribute stack is empty"); 178 } 179 return m_attr_stack[m_attr_stack.size() - 1]; 180 } 181 182 //------------------------------------------------------------------------ push_attr()183 void path_renderer::push_attr() 184 { 185 m_attr_stack.add(m_attr_stack.size() ? 186 m_attr_stack[m_attr_stack.size() - 1] : 187 path_attributes()); 188 } 189 190 //------------------------------------------------------------------------ pop_attr()191 void path_renderer::pop_attr() 192 { 193 if(m_attr_stack.size() == 0) 194 { 195 throw exception("pop_attr : Attribute stack is empty"); 196 } 197 m_attr_stack.remove_last(); 198 } 199 200 //------------------------------------------------------------------------ fill(const rgba8 & f)201 void path_renderer::fill(const rgba8& f) 202 { 203 path_attributes& attr = cur_attr(); 204 attr.fill_color = f; 205 attr.fill_flag = true; 206 } 207 208 //------------------------------------------------------------------------ stroke(const rgba8 & s)209 void path_renderer::stroke(const rgba8& s) 210 { 211 path_attributes& attr = cur_attr(); 212 attr.stroke_color = s; 213 attr.stroke_flag = true; 214 } 215 216 //------------------------------------------------------------------------ even_odd(bool flag)217 void path_renderer::even_odd(bool flag) 218 { 219 cur_attr().even_odd_flag = flag; 220 } 221 222 //------------------------------------------------------------------------ stroke_width(double w)223 void path_renderer::stroke_width(double w) 224 { 225 cur_attr().stroke_width = w; 226 } 227 228 //------------------------------------------------------------------------ fill_none()229 void path_renderer::fill_none() 230 { 231 cur_attr().fill_flag = false; 232 } 233 234 //------------------------------------------------------------------------ stroke_none()235 void path_renderer::stroke_none() 236 { 237 cur_attr().stroke_flag = false; 238 } 239 240 //------------------------------------------------------------------------ fill_opacity(double op)241 void path_renderer::fill_opacity(double op) 242 { 243 cur_attr().fill_color.opacity(op); 244 } 245 246 //------------------------------------------------------------------------ stroke_opacity(double op)247 void path_renderer::stroke_opacity(double op) 248 { 249 cur_attr().stroke_color.opacity(op); 250 } 251 252 //------------------------------------------------------------------------ line_join(line_join_e join)253 void path_renderer::line_join(line_join_e join) 254 { 255 cur_attr().line_join = join; 256 } 257 258 //------------------------------------------------------------------------ line_cap(line_cap_e cap)259 void path_renderer::line_cap(line_cap_e cap) 260 { 261 cur_attr().line_cap = cap; 262 } 263 264 //------------------------------------------------------------------------ miter_limit(double ml)265 void path_renderer::miter_limit(double ml) 266 { 267 cur_attr().miter_limit = ml; 268 } 269 270 //------------------------------------------------------------------------ transform()271 trans_affine& path_renderer::transform() 272 { 273 return cur_attr().transform; 274 } 275 276 //------------------------------------------------------------------------ parse_path(path_tokenizer & tok)277 void path_renderer::parse_path(path_tokenizer& tok) 278 { 279 while(tok.next()) 280 { 281 double arg[10]; 282 char cmd = tok.last_command(); 283 unsigned i; 284 switch(cmd) 285 { 286 case 'M': case 'm': 287 arg[0] = tok.last_number(); 288 arg[1] = tok.next(cmd); 289 move_to(arg[0], arg[1], cmd == 'm'); 290 break; 291 292 case 'L': case 'l': 293 arg[0] = tok.last_number(); 294 arg[1] = tok.next(cmd); 295 line_to(arg[0], arg[1], cmd == 'l'); 296 break; 297 298 case 'V': case 'v': 299 vline_to(tok.last_number(), cmd == 'v'); 300 break; 301 302 case 'H': case 'h': 303 hline_to(tok.last_number(), cmd == 'h'); 304 break; 305 306 case 'Q': case 'q': 307 arg[0] = tok.last_number(); 308 for(i = 1; i < 4; i++) 309 { 310 arg[i] = tok.next(cmd); 311 } 312 curve3(arg[0], arg[1], arg[2], arg[3], cmd == 'q'); 313 break; 314 315 case 'T': case 't': 316 arg[0] = tok.last_number(); 317 arg[1] = tok.next(cmd); 318 curve3(arg[0], arg[1], cmd == 't'); 319 break; 320 321 case 'C': case 'c': 322 arg[0] = tok.last_number(); 323 for(i = 1; i < 6; i++) 324 { 325 arg[i] = tok.next(cmd); 326 } 327 curve4(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], cmd == 'c'); 328 break; 329 330 case 'S': case 's': 331 arg[0] = tok.last_number(); 332 for(i = 1; i < 4; i++) 333 { 334 arg[i] = tok.next(cmd); 335 } 336 curve4(arg[0], arg[1], arg[2], arg[3], cmd == 's'); 337 break; 338 339 case 'A': case 'a': 340 throw exception("parse_path: Command A: NOT IMPLEMENTED YET"); 341 342 case 'Z': case 'z': 343 close_subpath(); 344 break; 345 346 default: 347 { 348 char buf[100]; 349 sprintf(buf, "parse_path: Invalid Command %c", cmd); 350 throw exception(buf); 351 } 352 } 353 } 354 } 355 356 } 357 } 358 359