diff options
author | Graeme Geldenhuys <graeme@mastermaths.co.za> | 2012-11-22 11:48:47 +0000 |
---|---|---|
committer | Graeme Geldenhuys <graeme@mastermaths.co.za> | 2012-11-22 11:48:47 +0000 |
commit | af45f95f16cee22f8f012f706f4d0a42eaeb68fa (patch) | |
tree | c572c1cc6a7d3bb12874d8f9b9363312b275e328 /src/corelib/render/software/svg | |
parent | 9c62dfaf7217557f08a3d33b20bb302874960f87 (diff) | |
download | fpGUI-af45f95f16cee22f8f012f706f4d0a42eaeb68fa.tar.xz |
Fixes line ending issues
Diffstat (limited to 'src/corelib/render/software/svg')
-rw-r--r-- | src/corelib/render/software/svg/agg_svg_exception.pas | 344 | ||||
-rw-r--r-- | src/corelib/render/software/svg/agg_svg_parser.pas | 2772 | ||||
-rw-r--r-- | src/corelib/render/software/svg/agg_svg_path_renderer.pas | 1786 | ||||
-rw-r--r-- | src/corelib/render/software/svg/agg_svg_path_tokenizer.pas | 650 |
4 files changed, 2776 insertions, 2776 deletions
diff --git a/src/corelib/render/software/svg/agg_svg_exception.pas b/src/corelib/render/software/svg/agg_svg_exception.pas index 0a52836e..97ebe3e5 100644 --- a/src/corelib/render/software/svg/agg_svg_exception.pas +++ b/src/corelib/render/software/svg/agg_svg_exception.pas @@ -1,172 +1,172 @@ -//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 24.04.2006-Milano: Unit port establishment
-//
-{ agg_svg_exception.pas }
-unit
- agg_svg_exception ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- SysUtils ,
- agg_basics ;
-
-{ TYPES DEFINITION }
-type
- svg_exception_ptr = ^svg_exception;
- svg_exception = class(Exception )
- m_msg : pointer;
-
- constructor Construct; overload;
- constructor Construct(fmt : PChar ); overload;
- constructor Construct(exc : svg_exception_ptr ); overload;
-
- procedure Free;
- function _msg : char_ptr;
-
- end;
-
-{ GLOBAL PROCEDURES }
- function get_double(ptr : agg_basics.char_ptr ) : double;
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor svg_exception.Construct;
-begin
- m_msg:=NIL;
-
-end;
-
-{ CONSTRUCT }
-constructor svg_exception.Construct(fmt : PChar );
-var
- max : int;
-
-begin
- m_msg:=NIL;
-
- if agg_getmem(m_msg ,4096 ) then
- begin
- max:=StrLen(fmt );
-
- if max > 4095 then
- max:=4095;
-
- move(fmt[0 ] ,m_msg^ ,max );
-
- int8_ptr(ptrcomp(m_msg ) + max )^:=0;
-
- end;
-
-end;
-
-{ CONSTRUCT }
-constructor svg_exception.Construct(exc : svg_exception_ptr );
-var
- max : int;
-
-begin
- m_msg:=NIL;
-
- if (exc <> NIL ) and
- (exc.m_msg <> NIL ) then
- if agg_getmem(m_msg ,4096 ) then
- begin
- max:=StrLen(exc.m_msg );
-
- if max > 4095 then
- max:=4095;
-
- move(exc.m_msg^ ,m_msg^ ,max );
-
- int8_ptr(ptrcomp(m_msg ) + max )^:=0;
-
- end;
-
-end;
-
-{ FREE }
-procedure svg_exception.Free;
-begin
- if m_msg <> NIL then
- agg_freemem(m_msg ,4096 );
-
-end;
-
-{ _MSG }
-function svg_exception._msg;
-begin
- result:=char_ptr(m_msg );
-
-end;
-
-{ GET_DOUBLE }
-function get_double;
-var
- buf : array[0..49 ] of char;
- dst ,
- max : char_ptr;
- err : integer;
-
-begin
- dst:=@buf[0 ];
- max:=@buf[48 ];
-
- while ptr^ <> #0 do
- begin
- case ptr^ of
- '-' ,'.' ,'0'..'9' :
- if dst <> max then
- begin
- dst^:=ptr^;
-
- inc(ptrcomp(dst ) );
-
- end
- else
- break;
-
- else
- break;
-
- end;
-
- inc(ptrcomp(ptr ) );
-
- end;
-
- dst^:=#0;
-
- val(PChar(@buf[0 ] ) ,result ,err );
-
-end;
-
-END.
-
+//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 (Public License) +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) +// Pascal Port By: Milan Marusinec alias Milano +// milan@marusinec.sk +// http://www.aggpas.org +// Copyright (c) 2005-2006 +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +// +// [Pascal Port History] ----------------------------------------------------- +// +// 23.06.2006-Milano: ptrcomp adjustments +// 24.04.2006-Milano: Unit port establishment +// +{ agg_svg_exception.pas } +unit + agg_svg_exception ; + +INTERFACE + +{$I agg_mode.inc } + +uses + SysUtils , + agg_basics ; + +{ TYPES DEFINITION } +type + svg_exception_ptr = ^svg_exception; + svg_exception = class(Exception ) + m_msg : pointer; + + constructor Construct; overload; + constructor Construct(fmt : PChar ); overload; + constructor Construct(exc : svg_exception_ptr ); overload; + + procedure Free; + function _msg : char_ptr; + + end; + +{ GLOBAL PROCEDURES } + function get_double(ptr : agg_basics.char_ptr ) : double; + + +IMPLEMENTATION +{ LOCAL VARIABLES & CONSTANTS } +{ UNIT IMPLEMENTATION } +{ CONSTRUCT } +constructor svg_exception.Construct; +begin + m_msg:=NIL; + +end; + +{ CONSTRUCT } +constructor svg_exception.Construct(fmt : PChar ); +var + max : int; + +begin + m_msg:=NIL; + + if agg_getmem(m_msg ,4096 ) then + begin + max:=StrLen(fmt ); + + if max > 4095 then + max:=4095; + + move(fmt[0 ] ,m_msg^ ,max ); + + int8_ptr(ptrcomp(m_msg ) + max )^:=0; + + end; + +end; + +{ CONSTRUCT } +constructor svg_exception.Construct(exc : svg_exception_ptr ); +var + max : int; + +begin + m_msg:=NIL; + + if (exc <> NIL ) and + (exc.m_msg <> NIL ) then + if agg_getmem(m_msg ,4096 ) then + begin + max:=StrLen(exc.m_msg ); + + if max > 4095 then + max:=4095; + + move(exc.m_msg^ ,m_msg^ ,max ); + + int8_ptr(ptrcomp(m_msg ) + max )^:=0; + + end; + +end; + +{ FREE } +procedure svg_exception.Free; +begin + if m_msg <> NIL then + agg_freemem(m_msg ,4096 ); + +end; + +{ _MSG } +function svg_exception._msg; +begin + result:=char_ptr(m_msg ); + +end; + +{ GET_DOUBLE } +function get_double; +var + buf : array[0..49 ] of char; + dst , + max : char_ptr; + err : integer; + +begin + dst:=@buf[0 ]; + max:=@buf[48 ]; + + while ptr^ <> #0 do + begin + case ptr^ of + '-' ,'.' ,'0'..'9' : + if dst <> max then + begin + dst^:=ptr^; + + inc(ptrcomp(dst ) ); + + end + else + break; + + else + break; + + end; + + inc(ptrcomp(ptr ) ); + + end; + + dst^:=#0; + + val(PChar(@buf[0 ] ) ,result ,err ); + +end; + +END. + diff --git a/src/corelib/render/software/svg/agg_svg_parser.pas b/src/corelib/render/software/svg/agg_svg_parser.pas index a2ec372a..0dce2706 100644 --- a/src/corelib/render/software/svg/agg_svg_parser.pas +++ b/src/corelib/render/software/svg/agg_svg_parser.pas @@ -1,1386 +1,1386 @@ -//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 03.01.2007-Milano: Adjustments for ExpatWrap (Win,Linux & Mac)
-// 23.06.2006-Milano: ptrcomp adjustments
-// 24.04.2006-Milano: Unit port establishment
-//
-{ agg_svg_parser.pas }
-unit
- agg_svg_parser ;
-
-INTERFACE
-
-{$DEFINE EXPAT_WRAPPER }
-{$I agg_mode.inc }
-
-uses
- SysUtils ,
- agg_basics ,
- agg_color ,
- agg_svg_path_tokenizer ,
- agg_svg_path_renderer ,
- agg_svg_exception ,
- agg_trans_affine ,
- agg_math_stroke ,
- expat ,
- file_utils_ ;
-
-{ TYPES DEFINITION }
-const
- buf_size = 512;
-
-type
- parser_ptr = ^parser;
- parser = object
- m_path : path_renderer_ptr;
- m_tokenizer : path_tokenizer;
-
- m_buf ,
- m_title : char_ptr;
-
- m_title_len : unsigned;
- m_title_flag ,
- m_path_flag : boolean;
- m_attr_name ,
- m_attr_value : char_ptr;
-
- m_attr_name_len ,
- m_attr_name_aloc ,
- m_attr_value_len ,
- m_attr_value_aloc : unsigned;
-
- constructor Construct(path : path_renderer_ptr );
- destructor Destruct;
-
- procedure parse(fname : shortstring );
- function title : char_ptr;
-
- // XML event handlers
- procedure parse_attr (attr : char_ptr_ptr ); overload;
- procedure parse_path (attr : char_ptr_ptr );
- procedure parse_poly (attr : char_ptr_ptr; close_flag : boolean );
- procedure parse_rect (attr : char_ptr_ptr );
- procedure parse_line (attr : char_ptr_ptr );
- procedure parse_style (str : agg_basics.char_ptr );
- procedure parse_transform(str : agg_basics.char_ptr );
-
- function parse_matrix (str : agg_basics.char_ptr ) : unsigned;
- function parse_translate(str : agg_basics.char_ptr ) : unsigned;
- function parse_rotate (str : agg_basics.char_ptr ) : unsigned;
- function parse_scale (str : agg_basics.char_ptr ) : unsigned;
- function parse_skew_x (str : agg_basics.char_ptr ) : unsigned;
- function parse_skew_y (str : agg_basics.char_ptr ) : unsigned;
-
- function parse_attr (name ,value : agg_basics.char_ptr ) : boolean; overload;
- function parse_name_value(nv_start ,nv_end : agg_basics.char_ptr ) : boolean;
-
- procedure copy_name (start ,end_ : agg_basics.char_ptr );
- procedure copy_value(start ,end_ : agg_basics.char_ptr );
-
- end;
-
-{ GLOBAL PROCEDURES }
- procedure start_element(data : pointer; el : char_ptr; attr : char_ptr_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
- procedure end_element (data : pointer; el : char_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
- procedure content (data : pointer; s : char_ptr; len : int ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-type
- named_color_ptr = ^named_color;
- named_color = record
- name : array[0..21 ] of char;
-
- r ,g ,b ,a : int8u;
-
- end;
-
-const
- colors_num = 148;
-
- colors : array[0..colors_num - 1 ] of named_color =
- ((name:'aliceblue'; r:240; g:248; b:255; a:255 ) ,
- (name:'antiquewhite'; r:250; g:235; b:215; a:255 ) ,
- (name:'aqua'; r:0; g:255; b:255; a:255 ) ,
- (name:'aquamarine'; r:127; g:255; b:212; a:255 ) ,
- (name:'azure'; r:240; g:255; b:255; a:255 ) ,
- (name:'beige'; r:245; g:245; b:220; a:255 ) ,
- (name:'bisque'; r:255; g:228; b:196; a:255 ) ,
- (name:'black'; r:0; g:0; b:0; a:255 ) ,
- (name:'blanchedalmond'; r:255; g:235; b:205; a:255 ) ,
- (name:'blue'; r:0; g:0; b:255; a:255 ) ,
- (name:'blueviolet'; r:138; g:43; b:226; a:255 ) ,
- (name:'brown'; r:165; g:42; b:42; a:255 ) ,
- (name:'burlywood'; r:222; g:184; b:135; a:255 ) ,
- (name:'cadetblue'; r:95; g:158; b:160; a:255 ) ,
- (name:'chartreuse'; r:127; g:255; b:0; a:255 ) ,
- (name:'chocolate'; r:210; g:105; b:30; a:255 ) ,
- (name:'coral'; r:255; g:127; b:80; a:255 ) ,
- (name:'cornflowerblue'; r:100; g:149; b:237; a:255 ) ,
- (name:'cornsilk'; r:255; g:248; b:220; a:255 ) ,
- (name:'crimson'; r:220; g:20; b:60; a:255 ) ,
- (name:'cyan'; r:0; g:255; b:255; a:255 ) ,
- (name:'darkblue'; r:0; g:0; b:139; a:255 ) ,
- (name:'darkcyan'; r:0; g:139; b:139; a:255 ) ,
- (name:'darkgoldenrod'; r:184; g:134; b:11; a:255 ) ,
- (name:'darkgray'; r:169; g:169; b:169; a:255 ) ,
- (name:'darkgreen'; r:0; g:100; b:0; a:255 ) ,
- (name:'darkgrey'; r:169; g:169; b:169; a:255 ) ,
- (name:'darkkhaki'; r:189; g:183; b:107; a:255 ) ,
- (name:'darkmagenta'; r:139; g:0; b:139; a:255 ) ,
- (name:'darkolivegreen'; r:85; g:107; b:47; a:255 ) ,
- (name:'darkorange'; r:255; g:140; b:0; a:255 ) ,
- (name:'darkorchid'; r:153; g:50; b:204; a:255 ) ,
- (name:'darkred'; r:139; g:0; b:0; a:255 ) ,
- (name:'darksalmon'; r:233; g:150; b:122; a:255 ) ,
- (name:'darkseagreen'; r:143; g:188; b:143; a:255 ) ,
- (name:'darkslateblue'; r:72; g:61; b:139; a:255 ) ,
- (name:'darkslategray'; r:47; g:79; b:79; a:255 ) ,
- (name:'darkslategrey'; r:47; g:79; b:79; a:255 ) ,
- (name:'darkturquoise'; r:0; g:206; b:209; a:255 ) ,
- (name:'darkviolet'; r:148; g:0; b:211; a:255 ) ,
- (name:'deeppink'; r:255; g:20; b:147; a:255 ) ,
- (name:'deepskyblue'; r:0; g:191; b:255; a:255 ) ,
- (name:'dimgray'; r:105; g:105; b:105; a:255 ) ,
- (name:'dimgrey'; r:105; g:105; b:105; a:255 ) ,
- (name:'dodgerblue'; r:30; g:144; b:255; a:255 ) ,
- (name:'firebrick'; r:178; g:34; b:34; a:255 ) ,
- (name:'floralwhite'; r:255; g:250; b:240; a:255 ) ,
- (name:'forestgreen'; r:34; g:139; b:34; a:255 ) ,
- (name:'fuchsia'; r:255; g:0; b:255; a:255 ) ,
- (name:'gainsboro'; r:220; g:220; b:220; a:255 ) ,
- (name:'ghostwhite'; r:248; g:248; b:255; a:255 ) ,
- (name:'gold'; r:255; g:215; b:0; a:255 ) ,
- (name:'goldenrod'; r:218; g:165; b:32; a:255 ) ,
- (name:'gray'; r:128; g:128; b:128; a:255 ) ,
- (name:'green'; r:0; g:128; b:0; a:255 ) ,
- (name:'greenyellow'; r:173; g:255; b:47; a:255 ) ,
- (name:'grey'; r:128; g:128; b:128; a:255 ) ,
- (name:'honeydew'; r:240; g:255; b:240; a:255 ) ,
- (name:'hotpink'; r:255; g:105; b:180; a:255 ) ,
- (name:'indianred'; r:205; g:92; b:92; a:255 ) ,
- (name:'indigo'; r:75; g:0; b:130; a:255 ) ,
- (name:'ivory'; r:255; g:255; b:240; a:255 ) ,
- (name:'khaki'; r:240; g:230; b:140; a:255 ) ,
- (name:'lavender'; r:230; g:230; b:250; a:255 ) ,
- (name:'lavenderblush'; r:255; g:240; b:245; a:255 ) ,
- (name:'lawngreen'; r:124; g:252; b:0; a:255 ) ,
- (name:'lemonchiffon'; r:255; g:250; b:205; a:255 ) ,
- (name:'lightblue'; r:173; g:216; b:230; a:255 ) ,
- (name:'lightcoral'; r:240; g:128; b:128; a:255 ) ,
- (name:'lightcyan'; r:224; g:255; b:255; a:255 ) ,
- (name:'lightgoldenrodyellow'; r:250; g:250; b:210; a:255 ) ,
- (name:'lightgray'; r:211; g:211; b:211; a:255 ) ,
- (name:'lightgreen'; r:144; g:238; b:144; a:255 ) ,
- (name:'lightgrey'; r:211; g:211; b:211; a:255 ) ,
- (name:'lightpink'; r:255; g:182; b:193; a:255 ) ,
- (name:'lightsalmon'; r:255; g:160; b:122; a:255 ) ,
- (name:'lightseagreen'; r:32; g:178; b:170; a:255 ) ,
- (name:'lightskyblue'; r:135; g:206; b:250; a:255 ) ,
- (name:'lightslategray'; r:119; g:136; b:153; a:255 ) ,
- (name:'lightslategrey'; r:119; g:136; b:153; a:255 ) ,
- (name:'lightsteelblue'; r:176; g:196; b:222; a:255 ) ,
- (name:'lightyellow'; r:255; g:255; b:224; a:255 ) ,
- (name:'lime'; r:0; g:255; b:0; a:255 ) ,
- (name:'limegreen'; r:50; g:205; b:50; a:255 ) ,
- (name:'linen'; r:250; g:240; b:230; a:255 ) ,
- (name:'magenta'; r:255; g:0; b:255; a:255 ) ,
- (name:'maroon'; r:128; g:0; b:0; a:255 ) ,
- (name:'mediumaquamarine'; r:102; g:205; b:170; a:255 ) ,
- (name:'mediumblue'; r:0; g:0; b:205; a:255 ) ,
- (name:'mediumorchid'; r:186; g:85; b:211; a:255 ) ,
- (name:'mediumpurple'; r:147; g:112; b:219; a:255 ) ,
- (name:'mediumseagreen'; r:60; g:179; b:113; a:255 ) ,
- (name:'mediumslateblue'; r:123; g:104; b:238; a:255 ) ,
- (name:'mediumspringgreen'; r:0; g:250; b:154; a:255 ) ,
- (name:'mediumturquoise'; r:72; g:209; b:204; a:255 ) ,
- (name:'mediumvioletred'; r:199; g:21; b:133; a:255 ) ,
- (name:'midnightblue'; r:25; g:25; b:112; a:255 ) ,
- (name:'mintcream'; r:245; g:255; b:250; a:255 ) ,
- (name:'mistyrose'; r:255; g:228; b:225; a:255 ) ,
- (name:'moccasin'; r:255; g:228; b:181; a:255 ) ,
- (name:'navajowhite'; r:255; g:222; b:173; a:255 ) ,
- (name:'navy'; r:0; g:0; b:128; a:255 ) ,
- (name:'oldlace'; r:253; g:245; b:230; a:255 ) ,
- (name:'olive'; r:128; g:128; b:0; a:255 ) ,
- (name:'olivedrab'; r:107; g:142; b:35; a:255 ) ,
- (name:'orange'; r:255; g:165; b:0; a:255 ) ,
- (name:'orangered'; r:255; g:69; b:0; a:255 ) ,
- (name:'orchid'; r:218; g:112; b:214; a:255 ) ,
- (name:'palegoldenrod'; r:238; g:232; b:170; a:255 ) ,
- (name:'palegreen'; r:152; g:251; b:152; a:255 ) ,
- (name:'paleturquoise'; r:175; g:238; b:238; a:255 ) ,
- (name:'palevioletred'; r:219; g:112; b:147; a:255 ) ,
- (name:'papayawhip'; r:255; g:239; b:213; a:255 ) ,
- (name:'peachpuff'; r:255; g:218; b:185; a:255 ) ,
- (name:'peru'; r:205; g:133; b:63; a:255 ) ,
- (name:'pink'; r:255; g:192; b:203; a:255 ) ,
- (name:'plum'; r:221; g:160; b:221; a:255 ) ,
- (name:'powderblue'; r:176; g:224; b:230; a:255 ) ,
- (name:'purple'; r:128; g:0; b:128; a:255 ) ,
- (name:'red'; r:255; g:0; b:0; a:255 ) ,
- (name:'rosybrown'; r:188; g:143; b:143; a:255 ) ,
- (name:'royalblue'; r:65; g:105; b:225; a:255 ) ,
- (name:'saddlebrown'; r:139; g:69; b:19; a:255 ) ,
- (name:'salmon'; r:250; g:128; b:114; a:255 ) ,
- (name:'sandybrown'; r:244; g:164; b:96; a:255 ) ,
- (name:'seagreen'; r:46; g:139; b:87; a:255 ) ,
- (name:'seashell'; r:255; g:245; b:238; a:255 ) ,
- (name:'sienna'; r:160; g:82; b:45; a:255 ) ,
- (name:'silver'; r:192; g:192; b:192; a:255 ) ,
- (name:'skyblue'; r:135; g:206; b:235; a:255 ) ,
- (name:'slateblue'; r:106; g:90; b:205; a:255 ) ,
- (name:'slategray'; r:112; g:128; b:144; a:255 ) ,
- (name:'slategrey'; r:112; g:128; b:144; a:255 ) ,
- (name:'snow'; r:255; g:250; b:250; a:255 ) ,
- (name:'springgreen'; r:0; g:255; b:127; a:255 ) ,
- (name:'steelblue'; r:70; g:130; b:180; a:255 ) ,
- (name:'tan'; r:210; g:180; b:140; a:255 ) ,
- (name:'teal'; r:0; g:128; b:128; a:255 ) ,
- (name:'thistle'; r:216; g:191; b:216; a:255 ) ,
- (name:'tomato'; r:255; g:99; b:71; a:255 ) ,
- (name:'turquoise'; r:64; g:224; b:208; a:255 ) ,
- (name:'violet'; r:238; g:130; b:238; a:255 ) ,
- (name:'wheat'; r:245; g:222; b:179; a:255 ) ,
- (name:'white'; r:255; g:255; b:255; a:255 ) ,
- (name:'whitesmoke'; r:245; g:245; b:245; a:255 ) ,
- (name:'yellow'; r:255; g:255; b:0; a:255 ) ,
- (name:'yellowgreen'; r:154; g:205; b:50; a:255 ) ,
- (name:'zzzzzzzzzzz'; r:0; g:0; b:0; a:0 ) );
-
- pageEqHigh : shortstring =
- #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
- #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
- #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
- #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
- #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
- #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
- #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
- #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
- #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
- #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
- #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
- #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
-
-{ UNIT IMPLEMENTATION }
-{ START_ELEMENT }
-procedure start_element;
-var
- this : parser_ptr;
-
-begin
- this:=parser_ptr(data );
-
- if StrComp(PChar(el ) ,'title' ) = 0 then
- this.m_title_flag:=true
- else
- if StrComp(PChar(el ) ,'g' ) = 0 then
- begin
- this.m_path.push_attr;
- this.parse_attr(attr );
-
- end
- else
- if StrComp(PChar(el ) ,'path' ) = 0 then
- begin
- if this.m_path_flag then
- raise svg_exception.Construct(PChar('start_element: Nested path' ) );
-
- this.m_path.begin_path;
- this.parse_path(attr );
- this.m_path.end_path;
-
- this.m_path_flag:=true;
-
- end
- else
- if StrComp(PChar(el ) ,'rect' ) = 0 then
- this.parse_rect(attr )
- else
- if StrComp(PChar(el ) ,'line' ) = 0 then
- this.parse_line(attr )
- else
- if StrComp(PChar(el ) ,'polyline' ) = 0 then
- this.parse_poly(attr ,false )
- else
- if StrComp(PChar(el ) ,'polygon' ) = 0 then
- this.parse_poly(attr ,true );
-
- //else
- // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
- // begin
- // end
- //...
-
-end;
-
-{ END_ELEMENT }
-procedure end_element;
-var
- this : parser_ptr;
-
-begin
- this:=parser_ptr(data );
-
- if StrComp(PChar(el ) ,'title' ) = 0 then
- this.m_title_flag:=false
- else
- if StrComp(PChar(el ) ,'g' ) = 0 then
- this.m_path.pop_attr
- else
- if StrComp(PChar(el ) ,'path' ) = 0 then
- this.m_path_flag:=false;
-
- //else
- // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
- // begin
- // end
- // ...
-
-end;
-
-{ CONTENT }
-procedure content;
-var
- this : parser_ptr;
-
-begin
- this:=parser_ptr(data );
-
-// m_title_flag signals that the <title> tag is being parsed now.
-// The following code concatenates the pieces of content of the <title> tag.
- if this.m_title_flag then
- begin
- if len + this.m_title_len > 255 then
- len:=255 - this.m_title_len;
-
- if len > 0 then
- begin
- move(
- s^ ,
- char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^ ,
- len );
-
- inc(this.m_title_len ,len );
-
- char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^:=#0;
-
- end;
-
- end;
-
-end;
-
-{ hex_unsigned }
-function hex_unsigned(hexstr : agg_basics.char_ptr ) : unsigned;
-
-function xyint(x ,y : integer ) : integer;
-var
- f : integer;
- m : boolean;
-
-begin
- m:=false;
-
- if y < 0 then
- begin
- y:=y * -1;
- m:=true;
-
- end;
-
- result:=x;
-
- if y > 1 then
- for f:=1 to y - 1 do
- result:=result * x;
-
- if m then
- result:=result * -1;
-
-end;
-
-var
- h : shortstring;
- fcb : byte;
- yps ,
- mul ,
- num : unsigned;
-
-label
- Err ,Esc ;
-
-const
- hex : string[16 ] = '0123456789ABCDEF';
-
-begin
- h:='';
-
- while hexstr^ <> #0 do
- begin
- h:=h + pageEqHigh[byte(hexstr^ ) ];
-
- inc(ptrcomp(hexstr ) );
-
- end;
-
- if length(h ) > 0 then
- begin
- case h[length(h ) ] of
- '0'..'9' ,'A'..'F' :
- else
- goto Err;
-
- end;
-
- num:=pos(h[length(h ) ] ,hex ) - 1;
- yps:=2;
- mul:=xyint(4 ,yps );
-
- if length(h ) > 1 then
- for fcb:=length(h ) - 1 downto 1 do
- begin
- case h[fcb ] of
- '0'..'9' ,'A'..'F' :
- else
- goto Err;
-
- end;
-
- inc(num ,(pos(h[fcb ] ,hex ) - 1 ) * mul );
- inc(yps ,2 );
-
- mul:=xyint(4 ,yps );
-
- end;
-
- goto Esc;
-
- end;
-
-Err:
- num:=0;
-
-Esc:
- result:=num;
-
-end;
-
-{ parse_color }
-function parse_color(str : agg_basics.char_ptr ) : aggclr;
-var
- u : unsigned;
- p : named_color_ptr;
- m : shortstring;
-
-begin
- while str^ = ' ' do
- inc(ptrcomp(str ) );
-
- if str^ = '#' then
- begin
- inc(ptrcomp(str ) );
-
- u:=hex_unsigned(str );
-
- result.Construct(rgb8_packed(u ) );
-
- end
- else
- begin
- p:=NIL;
-
- for u:=0 to colors_num - 1 do
- if StrComp(colors[u ].name ,PChar(str ) ) = 0 then
- begin
- p:=@colors[u ];
-
- break;
-
- end;
-
- if p = NIL then
- begin
- m:='parse_color: Invalid color name ' + StrPas(PChar(str ) ) + #0;
-
- raise svg_exception.Construct(PChar(@m[1 ] ) );
-
- end;
-
- result.ConstrInt(p.r ,p.g ,p.b ,p.a );
-
- end;
-
-end;
-
-{ parse_double }
-function parse_double(str : agg_basics.char_ptr ) : double;
-begin
- while str^ = ' ' do
- inc(ptrcomp(str ) );
-
- result:=get_double(pointer(PChar(str ) ) );
-
-end;
-
-{ islower }
-function islower(ch : char ) : boolean;
-begin
- case ch of
- #97..#122 :
- result:=true;
-
- else
- result:=false;
-
- end;
-
-end;
-
-{ is_numeric }
-function is_numeric(ch : char ) : boolean;
-begin
- result:=Pos(ch ,'0123456789+-.eE' ) <> 0;
-
-end;
-
-{ parse_transform_args }
-function parse_transform_args(str : agg_basics.char_ptr; args : double_ptr; max_na : unsigned; na : unsigned_ptr ) : unsigned;
-var
- ptr ,end_ : agg_basics.char_ptr;
-
-begin
- na^:=0;
- ptr:=str;
-
- while (ptr^ <> #0 ) and
- (ptr^ <> '(' ) do
- inc(ptrcomp(ptr ) );
-
- if ptr^ = #0 then
- raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
-
- end_:=ptr;
-
- while (end_^ <> #0 ) and
- (end_^ <> ')' ) do
- inc(ptrcomp(end_ ) );
-
- if end_^ = #0 then
- raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
-
- while ptrcomp(ptr ) < ptrcomp(end_ ) do
- if is_numeric(ptr^ ) then
- begin
- if na^ >= max_na then
- raise svg_exception.Construct(PChar('parse_transform_args: Too many arguments' ) );
-
- double_ptr(ptrcomp(args ) + na^ * sizeof(double ) )^:=get_double(ptr );
-
- inc(na^ );
-
- while (ptrcomp(ptr ) < ptrcomp(end_ ) ) and
- is_numeric(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- end
- else
- inc(ptrcomp(ptr ) );
-
- result:=unsigned(ptrcomp(end_ ) - ptrcomp(str ) );
-
-end;
-
-{ CONSTRUCT }
-constructor parser.Construct;
-begin
- m_path:=path;
-
- m_tokenizer.Construct;
-
- agg_getmem(pointer(m_buf ) ,buf_size );
- agg_getmem(pointer(m_title ) ,256 );
-
- m_title_len :=0;
- m_title_flag:=false;
- m_path_flag :=false;
-
- m_attr_name_aloc :=128;
- m_attr_value_aloc:=1024;
-
- agg_getmem(pointer(m_attr_name ) ,m_attr_name_aloc );
- agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
-
- m_attr_name_len :=127;
- m_attr_value_len:=1023;
-
- m_title^:=#0;
-
-end;
-
-{ DESTRUCT }
-destructor parser.Destruct;
-begin
- agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
- agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
- agg_freemem(pointer(m_title ) ,256 );
- agg_freemem(pointer(m_buf ) ,buf_size );
-
-end;
-
-{ PARSE }
-procedure parser.parse;
-var
- msg : array[0..1023 ] of char;
-
- p : XML_Parser;
- af : api_file;
- ts : char_ptr;
-
- done : boolean;
- len : int;
-
-begin
- p:=XML_ParserCreate(NIL );
-
- if p = NIL then
- raise svg_exception.Construct(PChar('Couldn''t allocate memory for parser' ) );
-
- XML_SetUserData (p ,@self );
- XML_SetElementHandler (p ,@start_element ,@end_element );
- XML_SetCharacterDataHandler(p ,@content );
-
- fname:=fname + #0;
-
- dec(byte(fname[0 ] ) );
-
- if not api_open_file(af ,fname ) then
- begin
- sprintf(@msg[0 ] ,'Couldn''t open file %s' ,unsigned(@fname[1 ] ) );
-
- XML_ParserFree(p );
-
- raise svg_exception.Construct(PChar(@msg[0 ] ) );
-
- end;
-
- done:=false;
-
- repeat
- api_read_file(af ,m_buf ,buf_size ,len );
-
- done:=len < buf_size;
-
- if XML_Parse(p ,pointer(m_buf ) ,len ,int(done ) ) = XML_STATUS_ERROR then
- begin
- api_close_file(af );
- XML_ParserFree(p );
-
- sprintf(
- @msg[0 ] ,
- '%s at line ' ,
- unsigned(
- XML_ErrorString(
- int(XML_GetErrorCode(p ) ) ) ) );
-
- sprintf(
- @msg[StrLen(msg ) ] ,
- '%d'#13 ,
- XML_GetCurrentLineNumber(p ) );
-
- raise svg_exception.Construct(PChar(@msg[0 ] ) );
-
- end;
-
- until done;
-
- api_close_file(af );
- XML_ParserFree(p );
-
- ts:=m_title;
-
- while ts^ <> #0 do
- begin
- if byte(ts^ ) < byte(' ' ) then
- ts^:=' ';
-
- inc(ptrcomp(ts ) );
-
- end;
-
-end;
-
-{ TITLE }
-function parser.title;
-begin
- result:=m_title;
-
-end;
-
-{ PARSE_ATTR }
-procedure parser.parse_attr(attr : char_ptr_ptr );
-var
- i : int;
-
-begin
- i:=0;
-
- while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
- begin
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'style' ) = 0 then
- parse_style(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ )
- else
- parse_attr(
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- inc(i ,2 );
-
- end;
-
-end;
-
-{ PARSE_PATH }
-procedure parser.parse_path;
-var
- i : int;
-
- tmp : array[0..3 ] of agg_basics.char_ptr;
-
-begin
- i:=0;
-
- while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
- begin
- // The <path> tag can consist of the path itself ("d=")
- // as well as of other parameters like "style=", "transform=", etc.
- // In the last case we simply rely on the function of parsing
- // attributes (see 'else' branch).
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'d' ) = 0 then
- begin
- m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- m_path.parse_path(@m_tokenizer );
-
- end
- else
- begin
- // Create a temporary single pair "name-value" in order
- // to avoid multiple calls for the same attribute.
- tmp[0 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^;
- tmp[1 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^;
- tmp[2 ]:=NIL;
- tmp[3 ]:=NIL;
-
- parse_attr(@tmp );
-
- end;
-
- inc(i ,2 );
-
- end;
-
-end;
-
-{ PARSE_POLY }
-procedure parser.parse_poly;
-var
- i : int;
-
- x ,y : double;
-
-begin
- x:=0.0;
- y:=0.0;
-
- m_path.begin_path;
-
- i:=0;
-
- while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
- begin
- if not parse_attr(
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
- if StrComp(PChar(agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'points' ) = 0 then
- begin
- m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if not m_tokenizer.next then
- raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
-
- x:=m_tokenizer.last_number;
-
- if not m_tokenizer.next then
- raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
-
- y:=m_tokenizer.last_number;
-
- m_path.move_to(x ,y );
-
- while m_tokenizer.next do
- begin
- x:=m_tokenizer.last_number;
-
- if not m_tokenizer.next then
- raise svg_exception.Construct(PChar('parse_poly: Odd number of coordinates' ) );
-
- y:=m_tokenizer.last_number;
-
- m_path.line_to(x ,y );
-
- end;
-
- end;
-
- inc(i ,2 );
-
- end;
-
- m_path.end_path;
-
-end;
-
-{ PARSE_RECT }
-procedure parser.parse_rect;
-var
- i : int;
-
- x ,y ,w ,h : double;
-
-begin
- x:=0.0;
- y:=0.0;
- w:=0.0;
- h:=0.0;
-
- m_path.begin_path;
-
- i:=0;
-
- while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
- begin
- if not parse_attr(
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
- begin
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x' ) = 0 then
- x:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y' ) = 0 then
- y:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'width' ) = 0 then
- w:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'height' ) = 0 then
- h:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- // rx - to be implemented
- // ry - to be implemented
-
- end;
-
- inc(i ,2 );
-
- end;
-
- if (w <> 0.0 ) and
- (h <> 0.0 ) then
- begin
- if w < 0.0 then
- raise svg_exception.Construct(PChar('parse_rect: Invalid width: ' ) );
-
- if h < 0.0 then
- raise svg_exception.Construct(PChar('parse_rect: Invalid height: ' ) );
-
- m_path.move_to(x ,y );
- m_path.line_to(x + w ,y );
- m_path.line_to(x + w ,y + h );
- m_path.line_to(x ,y + h );
- m_path.close_subpath;
-
- end;
-
- m_path.end_path;
-
-end;
-
-{ PARSE_LINE }
-procedure parser.parse_line;
-var
- i : int;
-
- x1 ,y1 ,x2 ,y2 : double;
-
-begin
- x1:=0.0;
- y1:=0.0;
- x2:=0.0;
- y2:=0.0;
-
- m_path.begin_path;
-
- i:=0;
-
- while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
- begin
- if not parse_attr(
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
- agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
- begin
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x1' ) = 0 then
- x1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y1' ) = 0 then
- y1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x2' ) = 0 then
- x2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y2' ) = 0 then
- y2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
-
- end;
-
- inc(i ,2 );
-
- end;
-
- m_path.move_to(x1 ,y1 );
- m_path.line_to(x2 ,y2 );
- m_path.end_path;
-
-end;
-
-{ PARSE_STYLE }
-procedure parser.parse_style;
-var
- nv_start ,nv_end : agg_basics.char_ptr;
-
-begin
- while str^ <> #0 do
- begin
- // Left Trim
- while (str^ <> #0 ) and
- (str^ = ' ' ) do
- inc(ptrcomp(str ) );
-
- nv_start:=str;
-
- while (str^ <> #0 ) and
- (str^ <> ';' ) do
- inc(ptrcomp(str ) );
-
- nv_end:=str;
-
- // Right Trim
- while (ptrcomp(nv_end ) > ptrcomp(nv_start ) ) and
- ((nv_end^ = ';' ) or
- (nv_end^ = ' ' ) ) do
- dec(ptrcomp(nv_end ) );
-
- inc(ptrcomp(nv_end ) );
-
- parse_name_value(nv_start ,nv_end );
-
- if str^ <> #0 then
- inc(ptrcomp(str ) );
-
- end;
-
-end;
-
-{ PARSE_TRANSFORM }
-procedure parser.parse_transform;
-begin
- while str^ <> #0 do
- begin
- if islower(str^ ) then
- if StrLComp(PChar(str ) ,'matrix' ,6 ) = 0 then
- inc(ptrcomp(str ) ,parse_matrix(str ) )
- else
- if StrLComp(PChar(str ) ,'translate' ,9 ) = 0 then
- inc(ptrcomp(str ) ,parse_translate(str ) )
- else
- if StrLComp(PChar(str ) ,'rotate' ,6 ) = 0 then
- inc(ptrcomp(str ) ,parse_rotate(str ) )
- else
- if StrLComp(PChar(str ) ,'scale' ,5 ) = 0 then
- inc(ptrcomp(str ) ,parse_scale(str ) )
- else
- if StrLComp(PChar(str ) ,'skewX' ,5 ) = 0 then
- inc(ptrcomp(str ) ,parse_skew_x(str ) )
- else
- if StrLComp(PChar(str ) ,'skewY' ,5 ) = 0 then
- inc(ptrcomp(str ) ,parse_skew_y(str ) )
- else
- inc(ptrcomp(str ) )
-
- else
- inc(ptrcomp(str ) );
-
- end;
-
-end;
-
-{ PARSE_MATRIX }
-function parser.parse_matrix;
-var
- args : array[0..5 ] of double;
-
- na ,len : unsigned;
-
- ta : trans_affine;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@args ,6 ,@na );
-
- if na <> 6 then
- raise svg_exception.Construct(PChar('parse_matrix: Invalid number of arguments' ) );
-
- ta.Construct(args[0 ] ,args[1 ] ,args[2 ] ,args[3 ] ,args[4 ] ,args[5 ] );
-
- m_path.transform.premultiply(@ta );
-
- result:=len;
-
-end;
-
-{ PARSE_TRANSLATE }
-function parser.parse_translate;
-var
- args : array[0..1 ] of double;
-
- na ,len : unsigned;
-
- tat : trans_affine_translation;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@args ,2 ,@na );
-
- if na = 1 then
- args[1 ]:=0.0;
-
- tat.Construct(args[0 ] ,args[1 ] );
-
- m_path.transform.premultiply(@tat );
-
- result:=len;
-
-end;
-
-{ PARSE_ROTATE }
-function parser.parse_rotate;
-var
- args : array[0..2 ] of double;
-
- na ,len : unsigned;
-
- tar : trans_affine_rotation;
-
- tat ,t : trans_affine_translation;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@args ,3 ,@na );
-
- if na = 1 then
- begin
- tar.Construct(deg2rad(args[0 ] ) );
-
- m_path.transform.premultiply(@tar );
-
- end
- else
- if na = 3 then
- begin
- t.Construct(-args[1 ] ,-args[2 ] );
-
- tar.Construct(deg2rad(args[0 ] ) );
- tat.Construct(args[1 ] ,args[2 ] );
-
- t.multiply(@tar );
- t.multiply(@tat );
-
- m_path.transform.premultiply(@t );
-
- end
- else
- raise svg_exception.Construct(PChar('parse_rotate: Invalid number of arguments' ) );
-
- result:=len;
-
-end;
-
-{ PARSE_SCALE }
-function parser.parse_scale;
-var
- args : array[0..1 ] of double;
-
- na ,len : unsigned;
-
- tas : trans_affine_scaling;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@args ,2 ,@na );
-
- if na = 1 then
- args[1 ]:=args[0 ];
-
- tas.Construct(args[0 ] ,args[1 ] );
-
- m_path.transform.premultiply(@tas );
-
- result:=len;
-
-end;
-
-{ PARSE_SKEW_X }
-function parser.parse_skew_x;
-var
- arg : double;
-
- na ,len : unsigned;
-
- tas : trans_affine_skewing;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@arg ,1 ,@na );
-
- tas.Construct(deg2rad(arg ) ,0.0 );
-
- m_path.transform.premultiply(@tas );
-
- result:=len;
-
-end;
-
-{ PARSE_SKEW_Y }
-function parser.parse_skew_y;
-var
- arg : double;
-
- na ,len : unsigned;
-
- tas : trans_affine_skewing;
-
-begin
- na :=0;
- len:=parse_transform_args(str ,@arg ,1 ,@na );
-
- tas.Construct(0.0 ,deg2rad(arg ) );
-
- m_path.transform.premultiply(@tas );
-
- result:=len;
-
-end;
-
-{ PARSE_ATTR }
-function parser.parse_attr(name ,value : agg_basics.char_ptr ) : boolean;
-var
- clr : aggclr;
-
-begin
- result:=true;
-
- if StrComp(PChar(name ) ,'style' ) = 0 then
- parse_style(value )
- else
- if StrComp(PChar(name ) ,'fill' ) = 0 then
- if StrComp(PChar(value ) ,'none' ) = 0 then
- m_path.fill_none
- else
- begin
- clr:=parse_color(value );
-
- m_path.fill(@clr );
-
- end
- else
- if StrComp(PChar(name ) ,'fill-opacity' ) = 0 then
- m_path.fill_opacity(parse_double(value ) )
- else
- if StrComp(PChar(name ) ,'stroke' ) = 0 then
- if StrComp(PChar(value ) ,'none' ) = 0 then
- m_path.stroke_none
- else
- begin
- clr:=parse_color(value );
-
- m_path.stroke(@clr );
-
- end
- else
- if StrComp(PChar(name ) ,'stroke-width' ) = 0 then
- m_path.stroke_width(parse_double(value ) )
- else
- if StrComp(PChar(name ) ,'stroke-linecap' ) = 0 then
- begin
- if StrComp(PChar(value ) ,'butt' ) = 0 then
- m_path.line_cap(butt_cap )
- else
- if StrComp(PChar(value ) ,'round' ) = 0 then
- m_path.line_cap(round_cap )
- else
- if StrComp(PChar(value ) ,'square' ) = 0 then
- m_path.line_cap(square_cap );
-
- end
- else
- if StrComp(PChar(name ) ,'stroke-linejoin' ) = 0 then
- begin
- if StrComp(PChar(value ) ,'miter' ) = 0 then
- m_path.line_join(miter_join )
- else
- if StrComp(PChar(value ) ,'round' ) = 0 then
- m_path.line_join(round_join )
- else
- if StrComp(PChar(value ) ,'bevel' ) = 0 then
- m_path.line_join(bevel_join );
-
- end
- else
- if StrComp(PChar(name ) ,'stroke-miterlimit' ) = 0 then
- m_path.miter_limit(parse_double(value ) )
- else
- if StrComp(PChar(name ) ,'stroke-opacity' ) = 0 then
- m_path.stroke_opacity(parse_double(value ) )
- else
- if StrComp(PChar(name ) ,'transform' ) = 0 then
- parse_transform(value )
-
- //else
- // if StrComp(PChar(el ) ,'<OTHER_ATTRIBUTES>' ) = 0 then
- // begin
- // end
- // ...
-
- else
- result:=false;
-
-end;
-
-{ PARSE_NAME_VALUE }
-function parser.parse_name_value;
-var
- str ,val : agg_basics.char_ptr;
-
-begin
- str:=nv_start;
-
- while (ptrcomp(str ) < ptrcomp(nv_end ) ) and
- (str^ <> ':' ) do
- inc(ptrcomp(str ) );
-
- val:=str;
-
-// Right Trim
- while (ptrcomp(str ) > ptrcomp(nv_start ) ) and
- ((str^ = ':' ) or
- (str^ = ' ' ) ) do
- dec(ptrcomp(str ) );
-
- inc(ptrcomp(str ) );
-
- copy_name(nv_start ,str );
-
- while (ptrcomp(val ) < ptrcomp(nv_end ) ) and
- ((val^ = ':' ) or
- (val^ = ' ' ) ) do
- inc(ptrcomp(val ) );
-
- copy_value(val ,nv_end );
-
- result:=parse_attr(agg_basics.char_ptr(m_attr_name ) ,agg_basics.char_ptr(m_attr_value ) );
-
-end;
-
-{ COPY_NAME }
-procedure parser.copy_name;
-var
- len : unsigned;
-
-begin
- len:=ptrcomp(end_ ) - ptrcomp(start );
-
- if (m_attr_name_len = 0 ) or
- (len > m_attr_name_len ) then
- begin
- agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
-
- m_attr_name_aloc:=len + 1;
-
- agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
-
- m_attr_name_len:=len;
-
- end;
-
- if len <> 0 then
- move(start^ ,m_attr_name^ ,len );
-
- char_ptr(ptrcomp(m_attr_name ) + len )^:=#0;
-
-end;
-
-{ COPY_VALUE }
-procedure parser.copy_value;
-var
- len : unsigned;
-
-begin
- len:=ptrcomp(end_ ) - ptrcomp(start );
-
- if (m_attr_value_len = 0 ) or
- (len > m_attr_value_len ) then
- begin
- agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
-
- m_attr_value_aloc:=len + 1;
-
- agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
-
- m_attr_value_len:=len;
-
- end;
-
- if len <> 0 then
- move(start^ ,m_attr_value^ ,len );
-
- char_ptr(ptrcomp(m_attr_value ) + len )^:=#0;
-
-end;
-
-END.
-
+//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 (Public License) +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) +// Pascal Port By: Milan Marusinec alias Milano +// milan@marusinec.sk +// http://www.aggpas.org +// Copyright (c) 2005-2006 +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +// +// [Pascal Port History] ----------------------------------------------------- +// +// 03.01.2007-Milano: Adjustments for ExpatWrap (Win,Linux & Mac) +// 23.06.2006-Milano: ptrcomp adjustments +// 24.04.2006-Milano: Unit port establishment +// +{ agg_svg_parser.pas } +unit + agg_svg_parser ; + +INTERFACE + +{$DEFINE EXPAT_WRAPPER } +{$I agg_mode.inc } + +uses + SysUtils , + agg_basics , + agg_color , + agg_svg_path_tokenizer , + agg_svg_path_renderer , + agg_svg_exception , + agg_trans_affine , + agg_math_stroke , + expat , + file_utils_ ; + +{ TYPES DEFINITION } +const + buf_size = 512; + +type + parser_ptr = ^parser; + parser = object + m_path : path_renderer_ptr; + m_tokenizer : path_tokenizer; + + m_buf , + m_title : char_ptr; + + m_title_len : unsigned; + m_title_flag , + m_path_flag : boolean; + m_attr_name , + m_attr_value : char_ptr; + + m_attr_name_len , + m_attr_name_aloc , + m_attr_value_len , + m_attr_value_aloc : unsigned; + + constructor Construct(path : path_renderer_ptr ); + destructor Destruct; + + procedure parse(fname : shortstring ); + function title : char_ptr; + + // XML event handlers + procedure parse_attr (attr : char_ptr_ptr ); overload; + procedure parse_path (attr : char_ptr_ptr ); + procedure parse_poly (attr : char_ptr_ptr; close_flag : boolean ); + procedure parse_rect (attr : char_ptr_ptr ); + procedure parse_line (attr : char_ptr_ptr ); + procedure parse_style (str : agg_basics.char_ptr ); + procedure parse_transform(str : agg_basics.char_ptr ); + + function parse_matrix (str : agg_basics.char_ptr ) : unsigned; + function parse_translate(str : agg_basics.char_ptr ) : unsigned; + function parse_rotate (str : agg_basics.char_ptr ) : unsigned; + function parse_scale (str : agg_basics.char_ptr ) : unsigned; + function parse_skew_x (str : agg_basics.char_ptr ) : unsigned; + function parse_skew_y (str : agg_basics.char_ptr ) : unsigned; + + function parse_attr (name ,value : agg_basics.char_ptr ) : boolean; overload; + function parse_name_value(nv_start ,nv_end : agg_basics.char_ptr ) : boolean; + + procedure copy_name (start ,end_ : agg_basics.char_ptr ); + procedure copy_value(start ,end_ : agg_basics.char_ptr ); + + end; + +{ GLOBAL PROCEDURES } + procedure start_element(data : pointer; el : char_ptr; attr : char_ptr_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF } + procedure end_element (data : pointer; el : char_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF } + procedure content (data : pointer; s : char_ptr; len : int ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF } + + +IMPLEMENTATION +{ LOCAL VARIABLES & CONSTANTS } +type + named_color_ptr = ^named_color; + named_color = record + name : array[0..21 ] of char; + + r ,g ,b ,a : int8u; + + end; + +const + colors_num = 148; + + colors : array[0..colors_num - 1 ] of named_color = + ((name:'aliceblue'; r:240; g:248; b:255; a:255 ) , + (name:'antiquewhite'; r:250; g:235; b:215; a:255 ) , + (name:'aqua'; r:0; g:255; b:255; a:255 ) , + (name:'aquamarine'; r:127; g:255; b:212; a:255 ) , + (name:'azure'; r:240; g:255; b:255; a:255 ) , + (name:'beige'; r:245; g:245; b:220; a:255 ) , + (name:'bisque'; r:255; g:228; b:196; a:255 ) , + (name:'black'; r:0; g:0; b:0; a:255 ) , + (name:'blanchedalmond'; r:255; g:235; b:205; a:255 ) , + (name:'blue'; r:0; g:0; b:255; a:255 ) , + (name:'blueviolet'; r:138; g:43; b:226; a:255 ) , + (name:'brown'; r:165; g:42; b:42; a:255 ) , + (name:'burlywood'; r:222; g:184; b:135; a:255 ) , + (name:'cadetblue'; r:95; g:158; b:160; a:255 ) , + (name:'chartreuse'; r:127; g:255; b:0; a:255 ) , + (name:'chocolate'; r:210; g:105; b:30; a:255 ) , + (name:'coral'; r:255; g:127; b:80; a:255 ) , + (name:'cornflowerblue'; r:100; g:149; b:237; a:255 ) , + (name:'cornsilk'; r:255; g:248; b:220; a:255 ) , + (name:'crimson'; r:220; g:20; b:60; a:255 ) , + (name:'cyan'; r:0; g:255; b:255; a:255 ) , + (name:'darkblue'; r:0; g:0; b:139; a:255 ) , + (name:'darkcyan'; r:0; g:139; b:139; a:255 ) , + (name:'darkgoldenrod'; r:184; g:134; b:11; a:255 ) , + (name:'darkgray'; r:169; g:169; b:169; a:255 ) , + (name:'darkgreen'; r:0; g:100; b:0; a:255 ) , + (name:'darkgrey'; r:169; g:169; b:169; a:255 ) , + (name:'darkkhaki'; r:189; g:183; b:107; a:255 ) , + (name:'darkmagenta'; r:139; g:0; b:139; a:255 ) , + (name:'darkolivegreen'; r:85; g:107; b:47; a:255 ) , + (name:'darkorange'; r:255; g:140; b:0; a:255 ) , + (name:'darkorchid'; r:153; g:50; b:204; a:255 ) , + (name:'darkred'; r:139; g:0; b:0; a:255 ) , + (name:'darksalmon'; r:233; g:150; b:122; a:255 ) , + (name:'darkseagreen'; r:143; g:188; b:143; a:255 ) , + (name:'darkslateblue'; r:72; g:61; b:139; a:255 ) , + (name:'darkslategray'; r:47; g:79; b:79; a:255 ) , + (name:'darkslategrey'; r:47; g:79; b:79; a:255 ) , + (name:'darkturquoise'; r:0; g:206; b:209; a:255 ) , + (name:'darkviolet'; r:148; g:0; b:211; a:255 ) , + (name:'deeppink'; r:255; g:20; b:147; a:255 ) , + (name:'deepskyblue'; r:0; g:191; b:255; a:255 ) , + (name:'dimgray'; r:105; g:105; b:105; a:255 ) , + (name:'dimgrey'; r:105; g:105; b:105; a:255 ) , + (name:'dodgerblue'; r:30; g:144; b:255; a:255 ) , + (name:'firebrick'; r:178; g:34; b:34; a:255 ) , + (name:'floralwhite'; r:255; g:250; b:240; a:255 ) , + (name:'forestgreen'; r:34; g:139; b:34; a:255 ) , + (name:'fuchsia'; r:255; g:0; b:255; a:255 ) , + (name:'gainsboro'; r:220; g:220; b:220; a:255 ) , + (name:'ghostwhite'; r:248; g:248; b:255; a:255 ) , + (name:'gold'; r:255; g:215; b:0; a:255 ) , + (name:'goldenrod'; r:218; g:165; b:32; a:255 ) , + (name:'gray'; r:128; g:128; b:128; a:255 ) , + (name:'green'; r:0; g:128; b:0; a:255 ) , + (name:'greenyellow'; r:173; g:255; b:47; a:255 ) , + (name:'grey'; r:128; g:128; b:128; a:255 ) , + (name:'honeydew'; r:240; g:255; b:240; a:255 ) , + (name:'hotpink'; r:255; g:105; b:180; a:255 ) , + (name:'indianred'; r:205; g:92; b:92; a:255 ) , + (name:'indigo'; r:75; g:0; b:130; a:255 ) , + (name:'ivory'; r:255; g:255; b:240; a:255 ) , + (name:'khaki'; r:240; g:230; b:140; a:255 ) , + (name:'lavender'; r:230; g:230; b:250; a:255 ) , + (name:'lavenderblush'; r:255; g:240; b:245; a:255 ) , + (name:'lawngreen'; r:124; g:252; b:0; a:255 ) , + (name:'lemonchiffon'; r:255; g:250; b:205; a:255 ) , + (name:'lightblue'; r:173; g:216; b:230; a:255 ) , + (name:'lightcoral'; r:240; g:128; b:128; a:255 ) , + (name:'lightcyan'; r:224; g:255; b:255; a:255 ) , + (name:'lightgoldenrodyellow'; r:250; g:250; b:210; a:255 ) , + (name:'lightgray'; r:211; g:211; b:211; a:255 ) , + (name:'lightgreen'; r:144; g:238; b:144; a:255 ) , + (name:'lightgrey'; r:211; g:211; b:211; a:255 ) , + (name:'lightpink'; r:255; g:182; b:193; a:255 ) , + (name:'lightsalmon'; r:255; g:160; b:122; a:255 ) , + (name:'lightseagreen'; r:32; g:178; b:170; a:255 ) , + (name:'lightskyblue'; r:135; g:206; b:250; a:255 ) , + (name:'lightslategray'; r:119; g:136; b:153; a:255 ) , + (name:'lightslategrey'; r:119; g:136; b:153; a:255 ) , + (name:'lightsteelblue'; r:176; g:196; b:222; a:255 ) , + (name:'lightyellow'; r:255; g:255; b:224; a:255 ) , + (name:'lime'; r:0; g:255; b:0; a:255 ) , + (name:'limegreen'; r:50; g:205; b:50; a:255 ) , + (name:'linen'; r:250; g:240; b:230; a:255 ) , + (name:'magenta'; r:255; g:0; b:255; a:255 ) , + (name:'maroon'; r:128; g:0; b:0; a:255 ) , + (name:'mediumaquamarine'; r:102; g:205; b:170; a:255 ) , + (name:'mediumblue'; r:0; g:0; b:205; a:255 ) , + (name:'mediumorchid'; r:186; g:85; b:211; a:255 ) , + (name:'mediumpurple'; r:147; g:112; b:219; a:255 ) , + (name:'mediumseagreen'; r:60; g:179; b:113; a:255 ) , + (name:'mediumslateblue'; r:123; g:104; b:238; a:255 ) , + (name:'mediumspringgreen'; r:0; g:250; b:154; a:255 ) , + (name:'mediumturquoise'; r:72; g:209; b:204; a:255 ) , + (name:'mediumvioletred'; r:199; g:21; b:133; a:255 ) , + (name:'midnightblue'; r:25; g:25; b:112; a:255 ) , + (name:'mintcream'; r:245; g:255; b:250; a:255 ) , + (name:'mistyrose'; r:255; g:228; b:225; a:255 ) , + (name:'moccasin'; r:255; g:228; b:181; a:255 ) , + (name:'navajowhite'; r:255; g:222; b:173; a:255 ) , + (name:'navy'; r:0; g:0; b:128; a:255 ) , + (name:'oldlace'; r:253; g:245; b:230; a:255 ) , + (name:'olive'; r:128; g:128; b:0; a:255 ) , + (name:'olivedrab'; r:107; g:142; b:35; a:255 ) , + (name:'orange'; r:255; g:165; b:0; a:255 ) , + (name:'orangered'; r:255; g:69; b:0; a:255 ) , + (name:'orchid'; r:218; g:112; b:214; a:255 ) , + (name:'palegoldenrod'; r:238; g:232; b:170; a:255 ) , + (name:'palegreen'; r:152; g:251; b:152; a:255 ) , + (name:'paleturquoise'; r:175; g:238; b:238; a:255 ) , + (name:'palevioletred'; r:219; g:112; b:147; a:255 ) , + (name:'papayawhip'; r:255; g:239; b:213; a:255 ) , + (name:'peachpuff'; r:255; g:218; b:185; a:255 ) , + (name:'peru'; r:205; g:133; b:63; a:255 ) , + (name:'pink'; r:255; g:192; b:203; a:255 ) , + (name:'plum'; r:221; g:160; b:221; a:255 ) , + (name:'powderblue'; r:176; g:224; b:230; a:255 ) , + (name:'purple'; r:128; g:0; b:128; a:255 ) , + (name:'red'; r:255; g:0; b:0; a:255 ) , + (name:'rosybrown'; r:188; g:143; b:143; a:255 ) , + (name:'royalblue'; r:65; g:105; b:225; a:255 ) , + (name:'saddlebrown'; r:139; g:69; b:19; a:255 ) , + (name:'salmon'; r:250; g:128; b:114; a:255 ) , + (name:'sandybrown'; r:244; g:164; b:96; a:255 ) , + (name:'seagreen'; r:46; g:139; b:87; a:255 ) , + (name:'seashell'; r:255; g:245; b:238; a:255 ) , + (name:'sienna'; r:160; g:82; b:45; a:255 ) , + (name:'silver'; r:192; g:192; b:192; a:255 ) , + (name:'skyblue'; r:135; g:206; b:235; a:255 ) , + (name:'slateblue'; r:106; g:90; b:205; a:255 ) , + (name:'slategray'; r:112; g:128; b:144; a:255 ) , + (name:'slategrey'; r:112; g:128; b:144; a:255 ) , + (name:'snow'; r:255; g:250; b:250; a:255 ) , + (name:'springgreen'; r:0; g:255; b:127; a:255 ) , + (name:'steelblue'; r:70; g:130; b:180; a:255 ) , + (name:'tan'; r:210; g:180; b:140; a:255 ) , + (name:'teal'; r:0; g:128; b:128; a:255 ) , + (name:'thistle'; r:216; g:191; b:216; a:255 ) , + (name:'tomato'; r:255; g:99; b:71; a:255 ) , + (name:'turquoise'; r:64; g:224; b:208; a:255 ) , + (name:'violet'; r:238; g:130; b:238; a:255 ) , + (name:'wheat'; r:245; g:222; b:179; a:255 ) , + (name:'white'; r:255; g:255; b:255; a:255 ) , + (name:'whitesmoke'; r:245; g:245; b:245; a:255 ) , + (name:'yellow'; r:255; g:255; b:0; a:255 ) , + (name:'yellowgreen'; r:154; g:205; b:50; a:255 ) , + (name:'zzzzzzzzzzz'; r:0; g:0; b:0; a:0 ) ); + + pageEqHigh : shortstring = + #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 + + #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 + + #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 + + #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 + + #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 + + #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 + + #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 + + #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 + + #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 + + #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 + + #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 + + #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 + + #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 + + #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 + + #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 + + #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255; + +{ UNIT IMPLEMENTATION } +{ START_ELEMENT } +procedure start_element; +var + this : parser_ptr; + +begin + this:=parser_ptr(data ); + + if StrComp(PChar(el ) ,'title' ) = 0 then + this.m_title_flag:=true + else + if StrComp(PChar(el ) ,'g' ) = 0 then + begin + this.m_path.push_attr; + this.parse_attr(attr ); + + end + else + if StrComp(PChar(el ) ,'path' ) = 0 then + begin + if this.m_path_flag then + raise svg_exception.Construct(PChar('start_element: Nested path' ) ); + + this.m_path.begin_path; + this.parse_path(attr ); + this.m_path.end_path; + + this.m_path_flag:=true; + + end + else + if StrComp(PChar(el ) ,'rect' ) = 0 then + this.parse_rect(attr ) + else + if StrComp(PChar(el ) ,'line' ) = 0 then + this.parse_line(attr ) + else + if StrComp(PChar(el ) ,'polyline' ) = 0 then + this.parse_poly(attr ,false ) + else + if StrComp(PChar(el ) ,'polygon' ) = 0 then + this.parse_poly(attr ,true ); + + //else + // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then + // begin + // end + //... + +end; + +{ END_ELEMENT } +procedure end_element; +var + this : parser_ptr; + +begin + this:=parser_ptr(data ); + + if StrComp(PChar(el ) ,'title' ) = 0 then + this.m_title_flag:=false + else + if StrComp(PChar(el ) ,'g' ) = 0 then + this.m_path.pop_attr + else + if StrComp(PChar(el ) ,'path' ) = 0 then + this.m_path_flag:=false; + + //else + // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then + // begin + // end + // ... + +end; + +{ CONTENT } +procedure content; +var + this : parser_ptr; + +begin + this:=parser_ptr(data ); + +// m_title_flag signals that the <title> tag is being parsed now. +// The following code concatenates the pieces of content of the <title> tag. + if this.m_title_flag then + begin + if len + this.m_title_len > 255 then + len:=255 - this.m_title_len; + + if len > 0 then + begin + move( + s^ , + char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^ , + len ); + + inc(this.m_title_len ,len ); + + char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^:=#0; + + end; + + end; + +end; + +{ hex_unsigned } +function hex_unsigned(hexstr : agg_basics.char_ptr ) : unsigned; + +function xyint(x ,y : integer ) : integer; +var + f : integer; + m : boolean; + +begin + m:=false; + + if y < 0 then + begin + y:=y * -1; + m:=true; + + end; + + result:=x; + + if y > 1 then + for f:=1 to y - 1 do + result:=result * x; + + if m then + result:=result * -1; + +end; + +var + h : shortstring; + fcb : byte; + yps , + mul , + num : unsigned; + +label + Err ,Esc ; + +const + hex : string[16 ] = '0123456789ABCDEF'; + +begin + h:=''; + + while hexstr^ <> #0 do + begin + h:=h + pageEqHigh[byte(hexstr^ ) ]; + + inc(ptrcomp(hexstr ) ); + + end; + + if length(h ) > 0 then + begin + case h[length(h ) ] of + '0'..'9' ,'A'..'F' : + else + goto Err; + + end; + + num:=pos(h[length(h ) ] ,hex ) - 1; + yps:=2; + mul:=xyint(4 ,yps ); + + if length(h ) > 1 then + for fcb:=length(h ) - 1 downto 1 do + begin + case h[fcb ] of + '0'..'9' ,'A'..'F' : + else + goto Err; + + end; + + inc(num ,(pos(h[fcb ] ,hex ) - 1 ) * mul ); + inc(yps ,2 ); + + mul:=xyint(4 ,yps ); + + end; + + goto Esc; + + end; + +Err: + num:=0; + +Esc: + result:=num; + +end; + +{ parse_color } +function parse_color(str : agg_basics.char_ptr ) : aggclr; +var + u : unsigned; + p : named_color_ptr; + m : shortstring; + +begin + while str^ = ' ' do + inc(ptrcomp(str ) ); + + if str^ = '#' then + begin + inc(ptrcomp(str ) ); + + u:=hex_unsigned(str ); + + result.Construct(rgb8_packed(u ) ); + + end + else + begin + p:=NIL; + + for u:=0 to colors_num - 1 do + if StrComp(colors[u ].name ,PChar(str ) ) = 0 then + begin + p:=@colors[u ]; + + break; + + end; + + if p = NIL then + begin + m:='parse_color: Invalid color name ' + StrPas(PChar(str ) ) + #0; + + raise svg_exception.Construct(PChar(@m[1 ] ) ); + + end; + + result.ConstrInt(p.r ,p.g ,p.b ,p.a ); + + end; + +end; + +{ parse_double } +function parse_double(str : agg_basics.char_ptr ) : double; +begin + while str^ = ' ' do + inc(ptrcomp(str ) ); + + result:=get_double(pointer(PChar(str ) ) ); + +end; + +{ islower } +function islower(ch : char ) : boolean; +begin + case ch of + #97..#122 : + result:=true; + + else + result:=false; + + end; + +end; + +{ is_numeric } +function is_numeric(ch : char ) : boolean; +begin + result:=Pos(ch ,'0123456789+-.eE' ) <> 0; + +end; + +{ parse_transform_args } +function parse_transform_args(str : agg_basics.char_ptr; args : double_ptr; max_na : unsigned; na : unsigned_ptr ) : unsigned; +var + ptr ,end_ : agg_basics.char_ptr; + +begin + na^:=0; + ptr:=str; + + while (ptr^ <> #0 ) and + (ptr^ <> '(' ) do + inc(ptrcomp(ptr ) ); + + if ptr^ = #0 then + raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) ); + + end_:=ptr; + + while (end_^ <> #0 ) and + (end_^ <> ')' ) do + inc(ptrcomp(end_ ) ); + + if end_^ = #0 then + raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) ); + + while ptrcomp(ptr ) < ptrcomp(end_ ) do + if is_numeric(ptr^ ) then + begin + if na^ >= max_na then + raise svg_exception.Construct(PChar('parse_transform_args: Too many arguments' ) ); + + double_ptr(ptrcomp(args ) + na^ * sizeof(double ) )^:=get_double(ptr ); + + inc(na^ ); + + while (ptrcomp(ptr ) < ptrcomp(end_ ) ) and + is_numeric(ptr^ ) do + inc(ptrcomp(ptr ) ); + + end + else + inc(ptrcomp(ptr ) ); + + result:=unsigned(ptrcomp(end_ ) - ptrcomp(str ) ); + +end; + +{ CONSTRUCT } +constructor parser.Construct; +begin + m_path:=path; + + m_tokenizer.Construct; + + agg_getmem(pointer(m_buf ) ,buf_size ); + agg_getmem(pointer(m_title ) ,256 ); + + m_title_len :=0; + m_title_flag:=false; + m_path_flag :=false; + + m_attr_name_aloc :=128; + m_attr_value_aloc:=1024; + + agg_getmem(pointer(m_attr_name ) ,m_attr_name_aloc ); + agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc ); + + m_attr_name_len :=127; + m_attr_value_len:=1023; + + m_title^:=#0; + +end; + +{ DESTRUCT } +destructor parser.Destruct; +begin + agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc ); + agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc ); + agg_freemem(pointer(m_title ) ,256 ); + agg_freemem(pointer(m_buf ) ,buf_size ); + +end; + +{ PARSE } +procedure parser.parse; +var + msg : array[0..1023 ] of char; + + p : XML_Parser; + af : api_file; + ts : char_ptr; + + done : boolean; + len : int; + +begin + p:=XML_ParserCreate(NIL ); + + if p = NIL then + raise svg_exception.Construct(PChar('Couldn''t allocate memory for parser' ) ); + + XML_SetUserData (p ,@self ); + XML_SetElementHandler (p ,@start_element ,@end_element ); + XML_SetCharacterDataHandler(p ,@content ); + + fname:=fname + #0; + + dec(byte(fname[0 ] ) ); + + if not api_open_file(af ,fname ) then + begin + sprintf(@msg[0 ] ,'Couldn''t open file %s' ,unsigned(@fname[1 ] ) ); + + XML_ParserFree(p ); + + raise svg_exception.Construct(PChar(@msg[0 ] ) ); + + end; + + done:=false; + + repeat + api_read_file(af ,m_buf ,buf_size ,len ); + + done:=len < buf_size; + + if XML_Parse(p ,pointer(m_buf ) ,len ,int(done ) ) = XML_STATUS_ERROR then + begin + api_close_file(af ); + XML_ParserFree(p ); + + sprintf( + @msg[0 ] , + '%s at line ' , + unsigned( + XML_ErrorString( + int(XML_GetErrorCode(p ) ) ) ) ); + + sprintf( + @msg[StrLen(msg ) ] , + '%d'#13 , + XML_GetCurrentLineNumber(p ) ); + + raise svg_exception.Construct(PChar(@msg[0 ] ) ); + + end; + + until done; + + api_close_file(af ); + XML_ParserFree(p ); + + ts:=m_title; + + while ts^ <> #0 do + begin + if byte(ts^ ) < byte(' ' ) then + ts^:=' '; + + inc(ptrcomp(ts ) ); + + end; + +end; + +{ TITLE } +function parser.title; +begin + result:=m_title; + +end; + +{ PARSE_ATTR } +procedure parser.parse_attr(attr : char_ptr_ptr ); +var + i : int; + +begin + i:=0; + + while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do + begin + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'style' ) = 0 then + parse_style(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) + else + parse_attr( + agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ , + agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + inc(i ,2 ); + + end; + +end; + +{ PARSE_PATH } +procedure parser.parse_path; +var + i : int; + + tmp : array[0..3 ] of agg_basics.char_ptr; + +begin + i:=0; + + while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do + begin + // The <path> tag can consist of the path itself ("d=") + // as well as of other parameters like "style=", "transform=", etc. + // In the last case we simply rely on the function of parsing + // attributes (see 'else' branch). + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'d' ) = 0 then + begin + m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + m_path.parse_path(@m_tokenizer ); + + end + else + begin + // Create a temporary single pair "name-value" in order + // to avoid multiple calls for the same attribute. + tmp[0 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^; + tmp[1 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^; + tmp[2 ]:=NIL; + tmp[3 ]:=NIL; + + parse_attr(@tmp ); + + end; + + inc(i ,2 ); + + end; + +end; + +{ PARSE_POLY } +procedure parser.parse_poly; +var + i : int; + + x ,y : double; + +begin + x:=0.0; + y:=0.0; + + m_path.begin_path; + + i:=0; + + while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do + begin + if not parse_attr( + agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ , + agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then + if StrComp(PChar(agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'points' ) = 0 then + begin + m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if not m_tokenizer.next then + raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) ); + + x:=m_tokenizer.last_number; + + if not m_tokenizer.next then + raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) ); + + y:=m_tokenizer.last_number; + + m_path.move_to(x ,y ); + + while m_tokenizer.next do + begin + x:=m_tokenizer.last_number; + + if not m_tokenizer.next then + raise svg_exception.Construct(PChar('parse_poly: Odd number of coordinates' ) ); + + y:=m_tokenizer.last_number; + + m_path.line_to(x ,y ); + + end; + + end; + + inc(i ,2 ); + + end; + + m_path.end_path; + +end; + +{ PARSE_RECT } +procedure parser.parse_rect; +var + i : int; + + x ,y ,w ,h : double; + +begin + x:=0.0; + y:=0.0; + w:=0.0; + h:=0.0; + + m_path.begin_path; + + i:=0; + + while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do + begin + if not parse_attr( + agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ , + agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then + begin + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x' ) = 0 then + x:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y' ) = 0 then + y:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'width' ) = 0 then + w:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'height' ) = 0 then + h:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + // rx - to be implemented + // ry - to be implemented + + end; + + inc(i ,2 ); + + end; + + if (w <> 0.0 ) and + (h <> 0.0 ) then + begin + if w < 0.0 then + raise svg_exception.Construct(PChar('parse_rect: Invalid width: ' ) ); + + if h < 0.0 then + raise svg_exception.Construct(PChar('parse_rect: Invalid height: ' ) ); + + m_path.move_to(x ,y ); + m_path.line_to(x + w ,y ); + m_path.line_to(x + w ,y + h ); + m_path.line_to(x ,y + h ); + m_path.close_subpath; + + end; + + m_path.end_path; + +end; + +{ PARSE_LINE } +procedure parser.parse_line; +var + i : int; + + x1 ,y1 ,x2 ,y2 : double; + +begin + x1:=0.0; + y1:=0.0; + x2:=0.0; + y2:=0.0; + + m_path.begin_path; + + i:=0; + + while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do + begin + if not parse_attr( + agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ , + agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then + begin + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x1' ) = 0 then + x1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y1' ) = 0 then + y1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x2' ) = 0 then + x2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y2' ) = 0 then + y2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ); + + end; + + inc(i ,2 ); + + end; + + m_path.move_to(x1 ,y1 ); + m_path.line_to(x2 ,y2 ); + m_path.end_path; + +end; + +{ PARSE_STYLE } +procedure parser.parse_style; +var + nv_start ,nv_end : agg_basics.char_ptr; + +begin + while str^ <> #0 do + begin + // Left Trim + while (str^ <> #0 ) and + (str^ = ' ' ) do + inc(ptrcomp(str ) ); + + nv_start:=str; + + while (str^ <> #0 ) and + (str^ <> ';' ) do + inc(ptrcomp(str ) ); + + nv_end:=str; + + // Right Trim + while (ptrcomp(nv_end ) > ptrcomp(nv_start ) ) and + ((nv_end^ = ';' ) or + (nv_end^ = ' ' ) ) do + dec(ptrcomp(nv_end ) ); + + inc(ptrcomp(nv_end ) ); + + parse_name_value(nv_start ,nv_end ); + + if str^ <> #0 then + inc(ptrcomp(str ) ); + + end; + +end; + +{ PARSE_TRANSFORM } +procedure parser.parse_transform; +begin + while str^ <> #0 do + begin + if islower(str^ ) then + if StrLComp(PChar(str ) ,'matrix' ,6 ) = 0 then + inc(ptrcomp(str ) ,parse_matrix(str ) ) + else + if StrLComp(PChar(str ) ,'translate' ,9 ) = 0 then + inc(ptrcomp(str ) ,parse_translate(str ) ) + else + if StrLComp(PChar(str ) ,'rotate' ,6 ) = 0 then + inc(ptrcomp(str ) ,parse_rotate(str ) ) + else + if StrLComp(PChar(str ) ,'scale' ,5 ) = 0 then + inc(ptrcomp(str ) ,parse_scale(str ) ) + else + if StrLComp(PChar(str ) ,'skewX' ,5 ) = 0 then + inc(ptrcomp(str ) ,parse_skew_x(str ) ) + else + if StrLComp(PChar(str ) ,'skewY' ,5 ) = 0 then + inc(ptrcomp(str ) ,parse_skew_y(str ) ) + else + inc(ptrcomp(str ) ) + + else + inc(ptrcomp(str ) ); + + end; + +end; + +{ PARSE_MATRIX } +function parser.parse_matrix; +var + args : array[0..5 ] of double; + + na ,len : unsigned; + + ta : trans_affine; + +begin + na :=0; + len:=parse_transform_args(str ,@args ,6 ,@na ); + + if na <> 6 then + raise svg_exception.Construct(PChar('parse_matrix: Invalid number of arguments' ) ); + + ta.Construct(args[0 ] ,args[1 ] ,args[2 ] ,args[3 ] ,args[4 ] ,args[5 ] ); + + m_path.transform.premultiply(@ta ); + + result:=len; + +end; + +{ PARSE_TRANSLATE } +function parser.parse_translate; +var + args : array[0..1 ] of double; + + na ,len : unsigned; + + tat : trans_affine_translation; + +begin + na :=0; + len:=parse_transform_args(str ,@args ,2 ,@na ); + + if na = 1 then + args[1 ]:=0.0; + + tat.Construct(args[0 ] ,args[1 ] ); + + m_path.transform.premultiply(@tat ); + + result:=len; + +end; + +{ PARSE_ROTATE } +function parser.parse_rotate; +var + args : array[0..2 ] of double; + + na ,len : unsigned; + + tar : trans_affine_rotation; + + tat ,t : trans_affine_translation; + +begin + na :=0; + len:=parse_transform_args(str ,@args ,3 ,@na ); + + if na = 1 then + begin + tar.Construct(deg2rad(args[0 ] ) ); + + m_path.transform.premultiply(@tar ); + + end + else + if na = 3 then + begin + t.Construct(-args[1 ] ,-args[2 ] ); + + tar.Construct(deg2rad(args[0 ] ) ); + tat.Construct(args[1 ] ,args[2 ] ); + + t.multiply(@tar ); + t.multiply(@tat ); + + m_path.transform.premultiply(@t ); + + end + else + raise svg_exception.Construct(PChar('parse_rotate: Invalid number of arguments' ) ); + + result:=len; + +end; + +{ PARSE_SCALE } +function parser.parse_scale; +var + args : array[0..1 ] of double; + + na ,len : unsigned; + + tas : trans_affine_scaling; + +begin + na :=0; + len:=parse_transform_args(str ,@args ,2 ,@na ); + + if na = 1 then + args[1 ]:=args[0 ]; + + tas.Construct(args[0 ] ,args[1 ] ); + + m_path.transform.premultiply(@tas ); + + result:=len; + +end; + +{ PARSE_SKEW_X } +function parser.parse_skew_x; +var + arg : double; + + na ,len : unsigned; + + tas : trans_affine_skewing; + +begin + na :=0; + len:=parse_transform_args(str ,@arg ,1 ,@na ); + + tas.Construct(deg2rad(arg ) ,0.0 ); + + m_path.transform.premultiply(@tas ); + + result:=len; + +end; + +{ PARSE_SKEW_Y } +function parser.parse_skew_y; +var + arg : double; + + na ,len : unsigned; + + tas : trans_affine_skewing; + +begin + na :=0; + len:=parse_transform_args(str ,@arg ,1 ,@na ); + + tas.Construct(0.0 ,deg2rad(arg ) ); + + m_path.transform.premultiply(@tas ); + + result:=len; + +end; + +{ PARSE_ATTR } +function parser.parse_attr(name ,value : agg_basics.char_ptr ) : boolean; +var + clr : aggclr; + +begin + result:=true; + + if StrComp(PChar(name ) ,'style' ) = 0 then + parse_style(value ) + else + if StrComp(PChar(name ) ,'fill' ) = 0 then + if StrComp(PChar(value ) ,'none' ) = 0 then + m_path.fill_none + else + begin + clr:=parse_color(value ); + + m_path.fill(@clr ); + + end + else + if StrComp(PChar(name ) ,'fill-opacity' ) = 0 then + m_path.fill_opacity(parse_double(value ) ) + else + if StrComp(PChar(name ) ,'stroke' ) = 0 then + if StrComp(PChar(value ) ,'none' ) = 0 then + m_path.stroke_none + else + begin + clr:=parse_color(value ); + + m_path.stroke(@clr ); + + end + else + if StrComp(PChar(name ) ,'stroke-width' ) = 0 then + m_path.stroke_width(parse_double(value ) ) + else + if StrComp(PChar(name ) ,'stroke-linecap' ) = 0 then + begin + if StrComp(PChar(value ) ,'butt' ) = 0 then + m_path.line_cap(butt_cap ) + else + if StrComp(PChar(value ) ,'round' ) = 0 then + m_path.line_cap(round_cap ) + else + if StrComp(PChar(value ) ,'square' ) = 0 then + m_path.line_cap(square_cap ); + + end + else + if StrComp(PChar(name ) ,'stroke-linejoin' ) = 0 then + begin + if StrComp(PChar(value ) ,'miter' ) = 0 then + m_path.line_join(miter_join ) + else + if StrComp(PChar(value ) ,'round' ) = 0 then + m_path.line_join(round_join ) + else + if StrComp(PChar(value ) ,'bevel' ) = 0 then + m_path.line_join(bevel_join ); + + end + else + if StrComp(PChar(name ) ,'stroke-miterlimit' ) = 0 then + m_path.miter_limit(parse_double(value ) ) + else + if StrComp(PChar(name ) ,'stroke-opacity' ) = 0 then + m_path.stroke_opacity(parse_double(value ) ) + else + if StrComp(PChar(name ) ,'transform' ) = 0 then + parse_transform(value ) + + //else + // if StrComp(PChar(el ) ,'<OTHER_ATTRIBUTES>' ) = 0 then + // begin + // end + // ... + + else + result:=false; + +end; + +{ PARSE_NAME_VALUE } +function parser.parse_name_value; +var + str ,val : agg_basics.char_ptr; + +begin + str:=nv_start; + + while (ptrcomp(str ) < ptrcomp(nv_end ) ) and + (str^ <> ':' ) do + inc(ptrcomp(str ) ); + + val:=str; + +// Right Trim + while (ptrcomp(str ) > ptrcomp(nv_start ) ) and + ((str^ = ':' ) or + (str^ = ' ' ) ) do + dec(ptrcomp(str ) ); + + inc(ptrcomp(str ) ); + + copy_name(nv_start ,str ); + + while (ptrcomp(val ) < ptrcomp(nv_end ) ) and + ((val^ = ':' ) or + (val^ = ' ' ) ) do + inc(ptrcomp(val ) ); + + copy_value(val ,nv_end ); + + result:=parse_attr(agg_basics.char_ptr(m_attr_name ) ,agg_basics.char_ptr(m_attr_value ) ); + +end; + +{ COPY_NAME } +procedure parser.copy_name; +var + len : unsigned; + +begin + len:=ptrcomp(end_ ) - ptrcomp(start ); + + if (m_attr_name_len = 0 ) or + (len > m_attr_name_len ) then + begin + agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc ); + + m_attr_name_aloc:=len + 1; + + agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc ); + + m_attr_name_len:=len; + + end; + + if len <> 0 then + move(start^ ,m_attr_name^ ,len ); + + char_ptr(ptrcomp(m_attr_name ) + len )^:=#0; + +end; + +{ COPY_VALUE } +procedure parser.copy_value; +var + len : unsigned; + +begin + len:=ptrcomp(end_ ) - ptrcomp(start ); + + if (m_attr_value_len = 0 ) or + (len > m_attr_value_len ) then + begin + agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc ); + + m_attr_value_aloc:=len + 1; + + agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc ); + + m_attr_value_len:=len; + + end; + + if len <> 0 then + move(start^ ,m_attr_value^ ,len ); + + char_ptr(ptrcomp(m_attr_value ) + len )^:=#0; + +end; + +END. + diff --git a/src/corelib/render/software/svg/agg_svg_path_renderer.pas b/src/corelib/render/software/svg/agg_svg_path_renderer.pas index c1fa0614..76735424 100644 --- a/src/corelib/render/software/svg/agg_svg_path_renderer.pas +++ b/src/corelib/render/software/svg/agg_svg_path_renderer.pas @@ -1,893 +1,893 @@ -//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 24.04.2006-Milano: Unit port establishment
-//
-{ agg_svg_path_renderer.pas }
-unit
- agg_svg_path_renderer ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- agg_basics ,
- agg_path_storage ,
- agg_conv_transform ,
- agg_conv_stroke ,
- agg_conv_contour ,
- agg_conv_curve ,
- agg_color ,
- agg_array ,
- agg_bounding_rect ,
- agg_rasterizer_scanline_aa ,
- agg_vertex_source ,
- agg_svg_path_tokenizer ,
- agg_svg_exception ,
- agg_trans_affine ,
- agg_math_stroke ,
- agg_scanline ,
- agg_renderer_scanline ,
- agg_render_scanlines ;
-
-{ TYPES DEFINITION }
-type
- conv_count = object(vertex_source )
- m_source : vertex_source_ptr;
- m_count : unsigned;
-
- constructor Construct(vs : vertex_source_ptr );
-
- procedure count_(n : unsigned );
- function _count : unsigned;
-
- procedure rewind(path_id : unsigned ); virtual;
- function vertex(x ,y : double_ptr ) : unsigned; virtual;
-
- end;
-
-// Basic path attributes
- path_attributes_ptr = ^path_attributes;
- path_attributes = object
- index : unsigned;
-
- fill_color ,
- stroke_color : aggclr;
- fill_flag ,
- stroke_flag ,
- even_odd_flag : boolean;
-
- line_join ,
- line_cap : unsigned;
- miter_limit ,
- stroke_width : double;
-
- transform : trans_affine;
-
- // Empty constructor
- constructor Construct; overload;
-
- // Copy constructor
- constructor Construct(attr : path_attributes_ptr ); overload;
-
- // Copy constructor with new index value
- constructor Construct(attr : path_attributes_ptr; idx : unsigned ); overload;
-
- end;
-
-// Path container and renderer.
- path_renderer_ptr = ^path_renderer;
- path_renderer = object(unsigned_list )
- m_storage : path_storage;
- m_attr_storage ,
- m_attr_stack : pod_deque;
- m_transform : trans_affine;
-
- m_curved : conv_curve;
- m_curved_count : conv_count;
-
- m_curved_stroked : conv_stroke;
- m_curved_stroked_trans : conv_transform;
-
- m_curved_trans : conv_transform;
- m_curved_trans_contour : conv_contour;
-
- constructor Construct;
- destructor Destruct;
-
- procedure remove_all;
-
- // Use these functions as follows:
- // begin_path when the XML tag <path> comes ("start_element" handler)
- // parse_path on "d=" tag attribute
- // end_path when parsing of the entire tag is done.
- procedure begin_path;
- procedure parse_path(tok : path_tokenizer_ptr );
- procedure end_path;
-
- // The following functions are essentially a "reflection" of
- // the respective SVG path commands.
- procedure move_to (x ,y : double; rel : boolean = false ); // M, m
- procedure line_to (x ,y : double; rel : boolean = false ); // L, l
- procedure hline_to(x : double; rel : boolean = false ); // H, h
- procedure vline_to(y : double; rel : boolean = false ); // V, v
-
- procedure curve3(x1 ,y1 ,x ,y : double; rel : boolean = false ); overload; // Q, q
- procedure curve3(x ,y : double; rel : boolean = false ); overload; // T, t
- procedure curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // C, c
- procedure curve4(x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // S, s
-
- procedure close_subpath; // Z, z
-
- procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0; solid_path : boolean = true );
- function vertex_count : unsigned;
-
- // Call these functions on <g> tag (start_element, end_element respectively)
- procedure push_attr;
- procedure pop_attr;
-
- // Attribute setting functions
- procedure fill (f : aggclr_ptr );
- procedure stroke (s : aggclr_ptr );
- procedure even_odd (flag : boolean );
- procedure stroke_width(w : double );
-
- procedure fill_none;
- procedure stroke_none;
-
- procedure fill_opacity (op : double );
- procedure stroke_opacity(op : double );
- procedure line_join (join : unsigned );
- procedure line_cap (cap : unsigned );
- procedure miter_limit (ml : double );
-
- function transform : trans_affine_ptr;
-
- // Make all polygons CCW-oriented
- procedure arrange_orientations;
-
- // Expand all polygons
- procedure expand(value : double );
-
- function array_operator(idx : unsigned ) : unsigned; virtual;
- procedure bounding_rect (x1 ,y1 ,x2 ,y2 : double_ptr );
-
- // Rendering. One can specify two additional parameters:
- // trans_affine and opacity. They can be used to transform the whole
- // image and/or to make it translucent.
- procedure render(
- ras : rasterizer_scanline_ptr;
- sl : scanline_ptr;
- ren : renderer_scanline_ptr;
- mtx : trans_affine_ptr;
- cb : rect_ptr;
- opacity : double = 1.0 );
-
- // Private
- function cur_attr : path_attributes_ptr;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor conv_count.Construct;
-begin
- m_source:=vs;
- m_count :=0;
-
-end;
-
-{ COUNT_ }
-procedure conv_count.count_;
-begin
- m_count:=n;
-
-end;
-
-{ _COUNT }
-function conv_count._count;
-begin
- result:=m_count;
-
-end;
-
-{ REWIND }
-procedure conv_count.rewind;
-begin
- m_source.rewind(path_id );
-
-end;
-
-{ VERTEX }
-function conv_count.vertex;
-begin
- inc(m_count );
-
- result:=m_source.vertex(x ,y );
-
-end;
-
-{ CONSTRUCT }
-constructor path_attributes.Construct;
-begin
- index:=0;
-
- fill_color.ConstrInt (0 ,0 ,0 );
- stroke_color.ConstrInt(0 ,0 ,0 );
-
- fill_flag :=true;
- stroke_flag :=false;
- even_odd_flag:=false;
- line_join :=miter_join;
- line_cap :=butt_cap;
- miter_limit :=4.0;
- stroke_width :=1.0;
-
- transform.Construct;
-
-end;
-
-{ CONSTRUCT }
-constructor path_attributes.Construct(attr : path_attributes_ptr );
-begin
- index:=attr.index;
-
- fill_color.Construct (@attr.fill_color );
- stroke_color.Construct(@attr.stroke_color );
-
- fill_flag :=attr.fill_flag;
- stroke_flag :=attr.stroke_flag;
- even_odd_flag:=attr.even_odd_flag;
- line_join :=attr.line_join;
- line_cap :=attr.line_cap;
- miter_limit :=attr.miter_limit;
- stroke_width :=attr.stroke_width;
-
- transform.Construct;
- transform.assign_all(@attr.transform );
-
-end;
-
-{ CONSTRUCT }
-constructor path_attributes.Construct(attr : path_attributes_ptr; idx : unsigned );
-begin
- index:=idx;
-
- fill_color.Construct (@attr.fill_color );
- stroke_color.Construct(@attr.stroke_color );
-
- fill_flag :=attr.fill_flag;
- stroke_flag :=attr.stroke_flag;
- even_odd_flag:=attr.even_odd_flag;
- line_join :=attr.line_join;
- line_cap :=attr.line_cap;
- miter_limit :=attr.miter_limit;
- stroke_width :=attr.stroke_width;
-
- transform.Construct;
- transform.assign_all(@attr.transform );
-
-end;
-
-{ CONSTRUCT }
-constructor path_renderer.Construct;
-begin
- m_storage.Construct;
- m_attr_storage.Construct(sizeof(path_attributes ) );
- m_attr_stack.Construct(sizeof(path_attributes ) );
- m_transform.Construct;
-
- m_curved.Construct (@m_storage );
- m_curved_count.Construct(@m_curved );
-
- m_curved_stroked.Construct (@m_curved_count );
- m_curved_stroked_trans.Construct(@m_curved_stroked ,@m_transform );
-
- m_curved_trans.Construct (@m_curved_count ,@m_transform );
- m_curved_trans_contour.Construct(@m_curved_trans );
-
-end;
-
-{ DESTRUCT }
-destructor path_renderer.Destruct;
-begin
- m_curved_trans_contour.Destruct;
- m_curved_stroked.Destruct;
- m_curved.Destruct;
-
- m_attr_stack.Destruct;
- m_attr_storage.Destruct;
- m_storage.Destruct;
-
-end;
-
-{ REMOVE_ALL }
-procedure path_renderer.remove_all;
-begin
- m_storage.remove_all;
- m_attr_storage.remove_all;
- m_attr_stack.remove_all;
- m_transform.reset;
-
-end;
-
-{ BEGIN_PATH }
-procedure path_renderer.begin_path;
-var
- idx : unsigned;
- attr : path_attributes;
-
-begin
- push_attr;
-
- idx:=m_storage.start_new_path;
-
- attr.Construct(cur_attr ,idx );
-
- m_attr_storage.add(@attr );
-
-end;
-
-{ PARSE_PATH }
-procedure path_renderer.parse_path;
-var
- arg : array[0..9 ] of double;
- i : unsigned;
- cmd : char;
- buf : array[0..99 ] of char;
-
-begin
- while tok.next do
- begin
- cmd:=tok.last_command;
-
- case cmd of
- 'M' ,'m' :
- begin
- arg[0 ]:=tok.last_number;
- arg[1 ]:=tok.next(cmd );
-
- move_to(arg[0 ] ,arg[1 ] ,cmd = 'm' );
-
- end;
-
- 'L' ,'l' :
- begin
- arg[0 ]:=tok.last_number;
- arg[1 ]:=tok.next(cmd );
-
- line_to(arg[0 ] ,arg[1 ] ,cmd = 'l' );
-
- end;
-
- 'V' ,'v' :
- vline_to(tok.last_number ,cmd = 'v' );
-
- 'H' ,'h' :
- hline_to(tok.last_number ,cmd = 'h' );
-
- 'Q' ,'q' :
- begin
- arg[0 ]:=tok.last_number;
-
- for i:=1 to 3 do
- arg[i ]:=tok.next(cmd );
-
- curve3(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 'q' );
-
- end;
-
- 'T' ,'t' :
- begin
- arg[0 ]:=tok.last_number;
- arg[1 ]:=tok.next(cmd );
-
- curve3(arg[0 ] ,arg[1 ] ,cmd = 't' );
-
- end;
-
- 'C' ,'c' :
- begin
- arg[0 ]:=tok.last_number;
-
- for i:=1 to 5 do
- arg[i ]:=tok.next(cmd );
-
- curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,arg[4 ] ,arg[5 ] ,cmd = 'c' );
-
- end;
-
- 'S' ,'s' :
- begin
- arg[0 ]:=tok.last_number;
-
- for i:=1 to 3 do
- arg[i ]:=tok.next(cmd );
-
- curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 's' );
-
- end;
-
- 'A' ,'a' :
- raise svg_exception.Construct(PChar('parse_path: Command A: NOT IMPLEMENTED YET' ) );
-
- 'Z' ,'z' :
- close_subpath;
-
- else
- begin
- sprintf(@buf[0 ] ,'parse_path: Invalid Command %c' ,unsigned(cmd ) );
-
- raise svg_exception.Construct(PChar(@buf[0 ] ) );
-
- end;
-
- end;
-
- end;
-
-end;
-
-{ END_PATH }
-procedure path_renderer.end_path;
-var
- idx : unsigned;
- attr : path_attributes;
-
-begin
- if m_attr_storage.size = 0 then
- raise svg_exception(PChar('end_path : The path was not begun' ) );
-
- attr.Construct(cur_attr );
-
- idx :=path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) ).index;
- attr.index:=idx;
-
- move(
- pointer(@attr )^ ,
- path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) )^ ,
- sizeof(path_attributes ) );
-
- pop_attr;
-
-end;
-
-{ MOVE_TO }
-procedure path_renderer.move_to;
-begin
- if rel then
- m_storage.rel_to_abs(@x ,@y );
-
- m_storage.move_to(x ,y );
-
-end;
-
-{ LINE_TO }
-procedure path_renderer.line_to;
-begin
- if rel then
- m_storage.rel_to_abs(@x ,@y );
-
- m_storage.line_to(x ,y );
-
-end;
-
-{ HLINE_TO }
-procedure path_renderer.hline_to;
-var
- x2 ,y2 : double;
-
-begin
- x2:=0.0;
- y2:=0.0;
-
- if m_storage.total_vertices <> 0 then
- begin
- m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 );
-
- if rel then
- x:=x + x2;
-
- m_storage.line_to(x ,y2 );
-
- end;
-
-end;
-
-{ VLINE_TO }
-procedure path_renderer.vline_to;
-var
- x2 ,y2 : double;
-
-begin
- x2:=0.0;
- y2:=0.0;
-
- if m_storage.total_vertices <> 0 then
- begin
- m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 );
-
- if rel then
- y:=y + y2;
-
- m_storage.line_to(x2 ,y );
-
- end;
-
-end;
-
-{ CURVE3 }
-procedure path_renderer.curve3(x1 ,y1 ,x ,y : double; rel : boolean = false );
-begin
- if rel then
- begin
- m_storage.rel_to_abs(@x1 ,@y1 );
- m_storage.rel_to_abs(@x ,@y );
-
- end;
-
- m_storage.curve3(x1 ,y1 ,x ,y );
-
-end;
-
-{ CURVE3 }
-procedure path_renderer.curve3(x ,y : double; rel : boolean = false );
-begin
-// raise exception("curve3(x, y) : NOT IMPLEMENTED YET");
- if rel then
- m_storage.curve3_rel(x ,y )
- else
- m_storage.curve3(x ,y );
-
-end;
-
-{ CURVE4 }
-procedure path_renderer.curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false );
-begin
- if rel then
- begin
- m_storage.rel_to_abs(@x1 ,@y1 );
- m_storage.rel_to_abs(@x2 ,@y2 );
- m_storage.rel_to_abs(@x ,@y );
-
- end;
-
- m_storage.curve4(x1 ,y1 ,x2 ,y2 ,x ,y );
-
-end;
-
-{ CURVE4 }
-procedure path_renderer.curve4(x2 ,y2 ,x ,y : double; rel : boolean = false );
-begin
-//throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET");
- if rel then
- m_storage.curve4_rel(x2 ,y2 ,x ,y )
- else
- m_storage.curve4(x2 ,y2 ,x ,y );
-
-end;
-
-{ CLOSE_SUBPATH }
-procedure path_renderer.close_subpath;
-begin
- m_storage.end_poly(path_flags_close );
-
-end;
-
-{ ADD_PATH }
-procedure path_renderer.add_path;
-begin
- m_storage.add_path(vs ,path_id ,solid_path );
-
-end;
-
-{ VERTEX_COUNT }
-function path_renderer.vertex_count;
-begin
- result:=m_curved_count._count;
-
-end;
-
-{ PUSH_ATTR }
-procedure path_renderer.push_attr;
-var
- attr : path_attributes;
-
-begin
- if m_attr_stack.size <> 0 then
- m_attr_stack.add(
- m_attr_stack.array_operator(m_attr_stack.size - 1 ) )
- else
- begin
- attr.Construct;
-
- m_attr_stack.add(@attr );
-
- end;
-
-end;
-
-{ POP_ATTR }
-procedure path_renderer.pop_attr;
-begin
- if m_attr_stack.size = 0 then
- raise svg_exception(PChar('pop_attr : Attribute stack is empty' ) );
-
- m_attr_stack.remove_last;
-
-end;
-
-{ FILL }
-procedure path_renderer.fill;
-var
- attr : path_attributes_ptr;
-
-begin
- attr:=cur_attr;
-
- attr.fill_color:=f^;
- attr.fill_flag :=true;
-
-end;
-
-{ STROKE }
-procedure path_renderer.stroke;
-var
- attr : path_attributes_ptr;
-
-begin
- attr:=cur_attr;
-
- attr.stroke_color:=s^;
- attr.stroke_flag :=true;
-
-end;
-
-{ EVEN_ODD }
-procedure path_renderer.even_odd;
-begin
- cur_attr.even_odd_flag:=flag;
-
-end;
-
-{ STROKE_WIDTH }
-procedure path_renderer.stroke_width;
-var
- attr : path_attributes_ptr;
-
-begin
- attr:=cur_attr;
-
- attr.stroke_width:=w;
- attr.stroke_flag :=true;
-
-end;
-
-{ FILL_NONE }
-procedure path_renderer.fill_none;
-begin
- cur_attr.fill_flag:=false;
-
-end;
-
-{ STROKE_NONE }
-procedure path_renderer.stroke_none;
-begin
- cur_attr.stroke_flag:=false;
-
-end;
-
-{ FILL_OPACITY }
-procedure path_renderer.fill_opacity;
-begin
- cur_attr.fill_color.opacity_(op );
-
-end;
-
-{ STROKE_OPACITY }
-procedure path_renderer.stroke_opacity;
-begin
- cur_attr.stroke_color.opacity_(op );
-
-end;
-
-{ LINE_JOIN }
-procedure path_renderer.line_join;
-begin
- cur_attr.line_join:=join;
-
-end;
-
-{ LINE_CAP }
-procedure path_renderer.line_cap;
-begin
- cur_attr.line_cap:=cap;
-
-end;
-
-{ MITER_LIMIT }
-procedure path_renderer.miter_limit;
-begin
- cur_attr.miter_limit:=ml;
-
-end;
-
-{ TRANSFORM }
-function path_renderer.transform;
-begin
- result:=@cur_attr.transform;
-
-end;
-
-{ ARRANGE_ORIENTATIONS }
-procedure path_renderer.arrange_orientations;
-begin
- m_storage.arrange_orientations_all_paths(path_flags_ccw );
-
-end;
-
-{ EXPAND }
-procedure path_renderer.expand;
-begin
- m_curved_trans_contour.width_(value );
-
-end;
-
-{ ARRAY_OPERATOR }
-function path_renderer.array_operator;
-begin
- m_transform.assign_all(
- @path_attributes_ptr(
- m_attr_storage.array_operator(idx ) ).transform );
-
- result:=path_attributes_ptr(m_attr_storage.array_operator(idx ) ).index;
-
-end;
-
-{ BOUNDING_RECT }
-procedure path_renderer.bounding_rect;
-var
- trans : conv_transform;
-
-begin
- trans.Construct(@m_storage ,@m_transform );
-
- bounding_rect_ul(
- @trans ,@self ,0 ,m_attr_storage.size ,x1 ,y1 ,x2 ,y2 );
-
-end;
-
-{ RENDER }
-procedure path_renderer.render;
-var
- i : unsigned;
-
- scl : double;
-
- attr : path_attributes_ptr;
-
- color : aggclr;
-
-begin
- ras.clip_box (cb.x1 ,cb.y1 ,cb.x2 ,cb.y2 );
- m_curved_count.count_(0 );
-
- i:=0;
-
- while i < m_attr_storage.size do
- begin
- attr:=path_attributes_ptr(m_attr_storage.array_operator(i ) );
-
- m_transform.assign_all(@attr.transform );
- m_transform.multiply (mtx );
-
- scl:=m_transform.scale;
-
- //m_curved.approximation_method(curve_inc );
-
- m_curved.approximation_scale_(scl );
- m_curved.angle_tolerance_ (0.0 );
-
- color.Construct;
-
- if attr.fill_flag then
- begin
- ras.reset;
-
- if attr.even_odd_flag then
- ras.filling_rule(fill_even_odd )
- else
- ras.filling_rule(fill_non_zero );
-
- if Abs(m_curved_trans_contour._width ) < 0.0001 then
- ras.add_path(@m_curved_trans ,attr.index )
- else
- begin
- m_curved_trans_contour.miter_limit_(attr.miter_limit );
-
- ras.add_path(@m_curved_trans_contour ,attr.index );
-
- end;
-
- color:=attr.fill_color;
-
- color.opacity_ (color._opacity * opacity );
- ren.color_ (@color );
- render_scanlines(ras ,sl ,ren );
-
- end;
-
- if attr.stroke_flag then
- begin
- m_curved_stroked.width_(attr.stroke_width );
-
- //m_curved_stroked.line_join_((attr.line_join == miter_join) ? miter_join_round : attr.line_join);
-
- m_curved_stroked.line_join_ (attr.line_join );
- m_curved_stroked.line_cap_ (attr.line_cap );
- m_curved_stroked.miter_limit_ (attr.miter_limit );
- m_curved_stroked.approximation_scale_(scl );
-
- // If the *visual* line width is considerable we
- // turn on processing of curve cusps.
- //---------------------
- if attr.stroke_width * scl > 1.0 then
- m_curved.angle_tolerance_(0.2 );
-
- ras.reset;
- ras.filling_rule(fill_non_zero );
- ras.add_path (@m_curved_stroked_trans ,attr.index );
-
- color:=attr.stroke_color;
-
- color.opacity_ (color._opacity * opacity);
- ren.color_ (@color );
- render_scanlines(ras ,sl ,ren );
-
- end;
-
- inc(i );
-
- end;
-
-end;
-
-{ CUR_ATTR }
-function path_renderer.cur_attr;
-begin
- if m_attr_stack.size = 0 then
- raise svg_exception.Construct(PChar('cur_attr : Attribute stack is empty' ) );
-
- result:=
- path_attributes_ptr(
- m_attr_stack.array_operator(m_attr_stack.size - 1 ) );
-
-end;
-
-END.
-
+//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 (Public License) +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) +// Pascal Port By: Milan Marusinec alias Milano +// milan@marusinec.sk +// http://www.aggpas.org +// Copyright (c) 2005-2006 +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +// +// [Pascal Port History] ----------------------------------------------------- +// +// 24.04.2006-Milano: Unit port establishment +// +{ agg_svg_path_renderer.pas } +unit + agg_svg_path_renderer ; + +INTERFACE + +{$I agg_mode.inc } + +uses + agg_basics , + agg_path_storage , + agg_conv_transform , + agg_conv_stroke , + agg_conv_contour , + agg_conv_curve , + agg_color , + agg_array , + agg_bounding_rect , + agg_rasterizer_scanline_aa , + agg_vertex_source , + agg_svg_path_tokenizer , + agg_svg_exception , + agg_trans_affine , + agg_math_stroke , + agg_scanline , + agg_renderer_scanline , + agg_render_scanlines ; + +{ TYPES DEFINITION } +type + conv_count = object(vertex_source ) + m_source : vertex_source_ptr; + m_count : unsigned; + + constructor Construct(vs : vertex_source_ptr ); + + procedure count_(n : unsigned ); + function _count : unsigned; + + procedure rewind(path_id : unsigned ); virtual; + function vertex(x ,y : double_ptr ) : unsigned; virtual; + + end; + +// Basic path attributes + path_attributes_ptr = ^path_attributes; + path_attributes = object + index : unsigned; + + fill_color , + stroke_color : aggclr; + fill_flag , + stroke_flag , + even_odd_flag : boolean; + + line_join , + line_cap : unsigned; + miter_limit , + stroke_width : double; + + transform : trans_affine; + + // Empty constructor + constructor Construct; overload; + + // Copy constructor + constructor Construct(attr : path_attributes_ptr ); overload; + + // Copy constructor with new index value + constructor Construct(attr : path_attributes_ptr; idx : unsigned ); overload; + + end; + +// Path container and renderer. + path_renderer_ptr = ^path_renderer; + path_renderer = object(unsigned_list ) + m_storage : path_storage; + m_attr_storage , + m_attr_stack : pod_deque; + m_transform : trans_affine; + + m_curved : conv_curve; + m_curved_count : conv_count; + + m_curved_stroked : conv_stroke; + m_curved_stroked_trans : conv_transform; + + m_curved_trans : conv_transform; + m_curved_trans_contour : conv_contour; + + constructor Construct; + destructor Destruct; + + procedure remove_all; + + // Use these functions as follows: + // begin_path when the XML tag <path> comes ("start_element" handler) + // parse_path on "d=" tag attribute + // end_path when parsing of the entire tag is done. + procedure begin_path; + procedure parse_path(tok : path_tokenizer_ptr ); + procedure end_path; + + // The following functions are essentially a "reflection" of + // the respective SVG path commands. + procedure move_to (x ,y : double; rel : boolean = false ); // M, m + procedure line_to (x ,y : double; rel : boolean = false ); // L, l + procedure hline_to(x : double; rel : boolean = false ); // H, h + procedure vline_to(y : double; rel : boolean = false ); // V, v + + procedure curve3(x1 ,y1 ,x ,y : double; rel : boolean = false ); overload; // Q, q + procedure curve3(x ,y : double; rel : boolean = false ); overload; // T, t + procedure curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // C, c + procedure curve4(x2 ,y2 ,x ,y : double; rel : boolean = false ); overload; // S, s + + procedure close_subpath; // Z, z + + procedure add_path(vs : vertex_source_ptr; path_id : unsigned = 0; solid_path : boolean = true ); + function vertex_count : unsigned; + + // Call these functions on <g> tag (start_element, end_element respectively) + procedure push_attr; + procedure pop_attr; + + // Attribute setting functions + procedure fill (f : aggclr_ptr ); + procedure stroke (s : aggclr_ptr ); + procedure even_odd (flag : boolean ); + procedure stroke_width(w : double ); + + procedure fill_none; + procedure stroke_none; + + procedure fill_opacity (op : double ); + procedure stroke_opacity(op : double ); + procedure line_join (join : unsigned ); + procedure line_cap (cap : unsigned ); + procedure miter_limit (ml : double ); + + function transform : trans_affine_ptr; + + // Make all polygons CCW-oriented + procedure arrange_orientations; + + // Expand all polygons + procedure expand(value : double ); + + function array_operator(idx : unsigned ) : unsigned; virtual; + procedure bounding_rect (x1 ,y1 ,x2 ,y2 : double_ptr ); + + // Rendering. One can specify two additional parameters: + // trans_affine and opacity. They can be used to transform the whole + // image and/or to make it translucent. + procedure render( + ras : rasterizer_scanline_ptr; + sl : scanline_ptr; + ren : renderer_scanline_ptr; + mtx : trans_affine_ptr; + cb : rect_ptr; + opacity : double = 1.0 ); + + // Private + function cur_attr : path_attributes_ptr; + + end; + +{ GLOBAL PROCEDURES } + + +IMPLEMENTATION +{ LOCAL VARIABLES & CONSTANTS } +{ UNIT IMPLEMENTATION } +{ CONSTRUCT } +constructor conv_count.Construct; +begin + m_source:=vs; + m_count :=0; + +end; + +{ COUNT_ } +procedure conv_count.count_; +begin + m_count:=n; + +end; + +{ _COUNT } +function conv_count._count; +begin + result:=m_count; + +end; + +{ REWIND } +procedure conv_count.rewind; +begin + m_source.rewind(path_id ); + +end; + +{ VERTEX } +function conv_count.vertex; +begin + inc(m_count ); + + result:=m_source.vertex(x ,y ); + +end; + +{ CONSTRUCT } +constructor path_attributes.Construct; +begin + index:=0; + + fill_color.ConstrInt (0 ,0 ,0 ); + stroke_color.ConstrInt(0 ,0 ,0 ); + + fill_flag :=true; + stroke_flag :=false; + even_odd_flag:=false; + line_join :=miter_join; + line_cap :=butt_cap; + miter_limit :=4.0; + stroke_width :=1.0; + + transform.Construct; + +end; + +{ CONSTRUCT } +constructor path_attributes.Construct(attr : path_attributes_ptr ); +begin + index:=attr.index; + + fill_color.Construct (@attr.fill_color ); + stroke_color.Construct(@attr.stroke_color ); + + fill_flag :=attr.fill_flag; + stroke_flag :=attr.stroke_flag; + even_odd_flag:=attr.even_odd_flag; + line_join :=attr.line_join; + line_cap :=attr.line_cap; + miter_limit :=attr.miter_limit; + stroke_width :=attr.stroke_width; + + transform.Construct; + transform.assign_all(@attr.transform ); + +end; + +{ CONSTRUCT } +constructor path_attributes.Construct(attr : path_attributes_ptr; idx : unsigned ); +begin + index:=idx; + + fill_color.Construct (@attr.fill_color ); + stroke_color.Construct(@attr.stroke_color ); + + fill_flag :=attr.fill_flag; + stroke_flag :=attr.stroke_flag; + even_odd_flag:=attr.even_odd_flag; + line_join :=attr.line_join; + line_cap :=attr.line_cap; + miter_limit :=attr.miter_limit; + stroke_width :=attr.stroke_width; + + transform.Construct; + transform.assign_all(@attr.transform ); + +end; + +{ CONSTRUCT } +constructor path_renderer.Construct; +begin + m_storage.Construct; + m_attr_storage.Construct(sizeof(path_attributes ) ); + m_attr_stack.Construct(sizeof(path_attributes ) ); + m_transform.Construct; + + m_curved.Construct (@m_storage ); + m_curved_count.Construct(@m_curved ); + + m_curved_stroked.Construct (@m_curved_count ); + m_curved_stroked_trans.Construct(@m_curved_stroked ,@m_transform ); + + m_curved_trans.Construct (@m_curved_count ,@m_transform ); + m_curved_trans_contour.Construct(@m_curved_trans ); + +end; + +{ DESTRUCT } +destructor path_renderer.Destruct; +begin + m_curved_trans_contour.Destruct; + m_curved_stroked.Destruct; + m_curved.Destruct; + + m_attr_stack.Destruct; + m_attr_storage.Destruct; + m_storage.Destruct; + +end; + +{ REMOVE_ALL } +procedure path_renderer.remove_all; +begin + m_storage.remove_all; + m_attr_storage.remove_all; + m_attr_stack.remove_all; + m_transform.reset; + +end; + +{ BEGIN_PATH } +procedure path_renderer.begin_path; +var + idx : unsigned; + attr : path_attributes; + +begin + push_attr; + + idx:=m_storage.start_new_path; + + attr.Construct(cur_attr ,idx ); + + m_attr_storage.add(@attr ); + +end; + +{ PARSE_PATH } +procedure path_renderer.parse_path; +var + arg : array[0..9 ] of double; + i : unsigned; + cmd : char; + buf : array[0..99 ] of char; + +begin + while tok.next do + begin + cmd:=tok.last_command; + + case cmd of + 'M' ,'m' : + begin + arg[0 ]:=tok.last_number; + arg[1 ]:=tok.next(cmd ); + + move_to(arg[0 ] ,arg[1 ] ,cmd = 'm' ); + + end; + + 'L' ,'l' : + begin + arg[0 ]:=tok.last_number; + arg[1 ]:=tok.next(cmd ); + + line_to(arg[0 ] ,arg[1 ] ,cmd = 'l' ); + + end; + + 'V' ,'v' : + vline_to(tok.last_number ,cmd = 'v' ); + + 'H' ,'h' : + hline_to(tok.last_number ,cmd = 'h' ); + + 'Q' ,'q' : + begin + arg[0 ]:=tok.last_number; + + for i:=1 to 3 do + arg[i ]:=tok.next(cmd ); + + curve3(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 'q' ); + + end; + + 'T' ,'t' : + begin + arg[0 ]:=tok.last_number; + arg[1 ]:=tok.next(cmd ); + + curve3(arg[0 ] ,arg[1 ] ,cmd = 't' ); + + end; + + 'C' ,'c' : + begin + arg[0 ]:=tok.last_number; + + for i:=1 to 5 do + arg[i ]:=tok.next(cmd ); + + curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,arg[4 ] ,arg[5 ] ,cmd = 'c' ); + + end; + + 'S' ,'s' : + begin + arg[0 ]:=tok.last_number; + + for i:=1 to 3 do + arg[i ]:=tok.next(cmd ); + + curve4(arg[0 ] ,arg[1 ] ,arg[2 ] ,arg[3 ] ,cmd = 's' ); + + end; + + 'A' ,'a' : + raise svg_exception.Construct(PChar('parse_path: Command A: NOT IMPLEMENTED YET' ) ); + + 'Z' ,'z' : + close_subpath; + + else + begin + sprintf(@buf[0 ] ,'parse_path: Invalid Command %c' ,unsigned(cmd ) ); + + raise svg_exception.Construct(PChar(@buf[0 ] ) ); + + end; + + end; + + end; + +end; + +{ END_PATH } +procedure path_renderer.end_path; +var + idx : unsigned; + attr : path_attributes; + +begin + if m_attr_storage.size = 0 then + raise svg_exception(PChar('end_path : The path was not begun' ) ); + + attr.Construct(cur_attr ); + + idx :=path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) ).index; + attr.index:=idx; + + move( + pointer(@attr )^ , + path_attributes_ptr(m_attr_storage.array_operator(m_attr_storage.size - 1 ) )^ , + sizeof(path_attributes ) ); + + pop_attr; + +end; + +{ MOVE_TO } +procedure path_renderer.move_to; +begin + if rel then + m_storage.rel_to_abs(@x ,@y ); + + m_storage.move_to(x ,y ); + +end; + +{ LINE_TO } +procedure path_renderer.line_to; +begin + if rel then + m_storage.rel_to_abs(@x ,@y ); + + m_storage.line_to(x ,y ); + +end; + +{ HLINE_TO } +procedure path_renderer.hline_to; +var + x2 ,y2 : double; + +begin + x2:=0.0; + y2:=0.0; + + if m_storage.total_vertices <> 0 then + begin + m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 ); + + if rel then + x:=x + x2; + + m_storage.line_to(x ,y2 ); + + end; + +end; + +{ VLINE_TO } +procedure path_renderer.vline_to; +var + x2 ,y2 : double; + +begin + x2:=0.0; + y2:=0.0; + + if m_storage.total_vertices <> 0 then + begin + m_storage.vertex_(m_storage.total_vertices - 1 ,@x2 ,@y2 ); + + if rel then + y:=y + y2; + + m_storage.line_to(x2 ,y ); + + end; + +end; + +{ CURVE3 } +procedure path_renderer.curve3(x1 ,y1 ,x ,y : double; rel : boolean = false ); +begin + if rel then + begin + m_storage.rel_to_abs(@x1 ,@y1 ); + m_storage.rel_to_abs(@x ,@y ); + + end; + + m_storage.curve3(x1 ,y1 ,x ,y ); + +end; + +{ CURVE3 } +procedure path_renderer.curve3(x ,y : double; rel : boolean = false ); +begin +// raise exception("curve3(x, y) : NOT IMPLEMENTED YET"); + if rel then + m_storage.curve3_rel(x ,y ) + else + m_storage.curve3(x ,y ); + +end; + +{ CURVE4 } +procedure path_renderer.curve4(x1 ,y1 ,x2 ,y2 ,x ,y : double; rel : boolean = false ); +begin + if rel then + begin + m_storage.rel_to_abs(@x1 ,@y1 ); + m_storage.rel_to_abs(@x2 ,@y2 ); + m_storage.rel_to_abs(@x ,@y ); + + end; + + m_storage.curve4(x1 ,y1 ,x2 ,y2 ,x ,y ); + +end; + +{ CURVE4 } +procedure path_renderer.curve4(x2 ,y2 ,x ,y : double; rel : boolean = false ); +begin +//throw exception("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET"); + if rel then + m_storage.curve4_rel(x2 ,y2 ,x ,y ) + else + m_storage.curve4(x2 ,y2 ,x ,y ); + +end; + +{ CLOSE_SUBPATH } +procedure path_renderer.close_subpath; +begin + m_storage.end_poly(path_flags_close ); + +end; + +{ ADD_PATH } +procedure path_renderer.add_path; +begin + m_storage.add_path(vs ,path_id ,solid_path ); + +end; + +{ VERTEX_COUNT } +function path_renderer.vertex_count; +begin + result:=m_curved_count._count; + +end; + +{ PUSH_ATTR } +procedure path_renderer.push_attr; +var + attr : path_attributes; + +begin + if m_attr_stack.size <> 0 then + m_attr_stack.add( + m_attr_stack.array_operator(m_attr_stack.size - 1 ) ) + else + begin + attr.Construct; + + m_attr_stack.add(@attr ); + + end; + +end; + +{ POP_ATTR } +procedure path_renderer.pop_attr; +begin + if m_attr_stack.size = 0 then + raise svg_exception(PChar('pop_attr : Attribute stack is empty' ) ); + + m_attr_stack.remove_last; + +end; + +{ FILL } +procedure path_renderer.fill; +var + attr : path_attributes_ptr; + +begin + attr:=cur_attr; + + attr.fill_color:=f^; + attr.fill_flag :=true; + +end; + +{ STROKE } +procedure path_renderer.stroke; +var + attr : path_attributes_ptr; + +begin + attr:=cur_attr; + + attr.stroke_color:=s^; + attr.stroke_flag :=true; + +end; + +{ EVEN_ODD } +procedure path_renderer.even_odd; +begin + cur_attr.even_odd_flag:=flag; + +end; + +{ STROKE_WIDTH } +procedure path_renderer.stroke_width; +var + attr : path_attributes_ptr; + +begin + attr:=cur_attr; + + attr.stroke_width:=w; + attr.stroke_flag :=true; + +end; + +{ FILL_NONE } +procedure path_renderer.fill_none; +begin + cur_attr.fill_flag:=false; + +end; + +{ STROKE_NONE } +procedure path_renderer.stroke_none; +begin + cur_attr.stroke_flag:=false; + +end; + +{ FILL_OPACITY } +procedure path_renderer.fill_opacity; +begin + cur_attr.fill_color.opacity_(op ); + +end; + +{ STROKE_OPACITY } +procedure path_renderer.stroke_opacity; +begin + cur_attr.stroke_color.opacity_(op ); + +end; + +{ LINE_JOIN } +procedure path_renderer.line_join; +begin + cur_attr.line_join:=join; + +end; + +{ LINE_CAP } +procedure path_renderer.line_cap; +begin + cur_attr.line_cap:=cap; + +end; + +{ MITER_LIMIT } +procedure path_renderer.miter_limit; +begin + cur_attr.miter_limit:=ml; + +end; + +{ TRANSFORM } +function path_renderer.transform; +begin + result:=@cur_attr.transform; + +end; + +{ ARRANGE_ORIENTATIONS } +procedure path_renderer.arrange_orientations; +begin + m_storage.arrange_orientations_all_paths(path_flags_ccw ); + +end; + +{ EXPAND } +procedure path_renderer.expand; +begin + m_curved_trans_contour.width_(value ); + +end; + +{ ARRAY_OPERATOR } +function path_renderer.array_operator; +begin + m_transform.assign_all( + @path_attributes_ptr( + m_attr_storage.array_operator(idx ) ).transform ); + + result:=path_attributes_ptr(m_attr_storage.array_operator(idx ) ).index; + +end; + +{ BOUNDING_RECT } +procedure path_renderer.bounding_rect; +var + trans : conv_transform; + +begin + trans.Construct(@m_storage ,@m_transform ); + + bounding_rect_ul( + @trans ,@self ,0 ,m_attr_storage.size ,x1 ,y1 ,x2 ,y2 ); + +end; + +{ RENDER } +procedure path_renderer.render; +var + i : unsigned; + + scl : double; + + attr : path_attributes_ptr; + + color : aggclr; + +begin + ras.clip_box (cb.x1 ,cb.y1 ,cb.x2 ,cb.y2 ); + m_curved_count.count_(0 ); + + i:=0; + + while i < m_attr_storage.size do + begin + attr:=path_attributes_ptr(m_attr_storage.array_operator(i ) ); + + m_transform.assign_all(@attr.transform ); + m_transform.multiply (mtx ); + + scl:=m_transform.scale; + + //m_curved.approximation_method(curve_inc ); + + m_curved.approximation_scale_(scl ); + m_curved.angle_tolerance_ (0.0 ); + + color.Construct; + + if attr.fill_flag then + begin + ras.reset; + + if attr.even_odd_flag then + ras.filling_rule(fill_even_odd ) + else + ras.filling_rule(fill_non_zero ); + + if Abs(m_curved_trans_contour._width ) < 0.0001 then + ras.add_path(@m_curved_trans ,attr.index ) + else + begin + m_curved_trans_contour.miter_limit_(attr.miter_limit ); + + ras.add_path(@m_curved_trans_contour ,attr.index ); + + end; + + color:=attr.fill_color; + + color.opacity_ (color._opacity * opacity ); + ren.color_ (@color ); + render_scanlines(ras ,sl ,ren ); + + end; + + if attr.stroke_flag then + begin + m_curved_stroked.width_(attr.stroke_width ); + + //m_curved_stroked.line_join_((attr.line_join == miter_join) ? miter_join_round : attr.line_join); + + m_curved_stroked.line_join_ (attr.line_join ); + m_curved_stroked.line_cap_ (attr.line_cap ); + m_curved_stroked.miter_limit_ (attr.miter_limit ); + m_curved_stroked.approximation_scale_(scl ); + + // If the *visual* line width is considerable we + // turn on processing of curve cusps. + //--------------------- + if attr.stroke_width * scl > 1.0 then + m_curved.angle_tolerance_(0.2 ); + + ras.reset; + ras.filling_rule(fill_non_zero ); + ras.add_path (@m_curved_stroked_trans ,attr.index ); + + color:=attr.stroke_color; + + color.opacity_ (color._opacity * opacity); + ren.color_ (@color ); + render_scanlines(ras ,sl ,ren ); + + end; + + inc(i ); + + end; + +end; + +{ CUR_ATTR } +function path_renderer.cur_attr; +begin + if m_attr_stack.size = 0 then + raise svg_exception.Construct(PChar('cur_attr : Attribute stack is empty' ) ); + + result:= + path_attributes_ptr( + m_attr_stack.array_operator(m_attr_stack.size - 1 ) ); + +end; + +END. + diff --git a/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas b/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas index e96df6a9..4e5d8c0d 100644 --- a/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas +++ b/src/corelib/render/software/svg/agg_svg_path_tokenizer.pas @@ -1,325 +1,325 @@ -//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 24.04.2006-Milano: Unit port establishment
-//
-{ agg_svg_path_tokenizer.pas }
-unit
- agg_svg_path_tokenizer ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- agg_basics ,
- agg_svg_exception ;
-
-{ TYPES DEFINITION }
-const
- s_commands = '+-MmZzLlHhVvCcSsQqTtAaFfPp';
- s_numeric = '.Ee0123456789';
- s_separators = ' ,'#9#10#13;
-
-type
-// SVG path tokenizer.
-// Example:
-//
-// agg::svg::path_tokenizer tok;
-//
-// tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 ");
-// while(tok.next())
-// {
-// printf("command='%c' number=%f\n",
-// tok.last_command(),
-// tok.last_number());
-// }
-//
-// The tokenizer does all the routine job of parsing the SVG paths.
-// It doesn't recognize any graphical primitives, it even doesn't know
-// anything about pairs of coordinates (X,Y). The purpose of this class
-// is to tokenize the numeric values and commands. SVG paths can
-// have single numeric values for Horizontal or Vertical line_to commands
-// as well as more than two coordinates (4 or 6) for Bezier curves
-// depending on the semantics of the command.
-// The behaviour is as follows:
-//
-// Each call to next() returns true if there's new command or new numeric
-// value or false when the path ends. How to interpret the result
-// depends on the sematics of the command. For example, command "C"
-// (cubic Bezier curve) implies 6 floating point numbers preceded by this
-// command. If the command assumes no arguments (like z or Z) the
-// the last_number() values won't change, that is, last_number() always
-// returns the last recognized numeric value, so does last_command().
- path_tokenizer_ptr = ^path_tokenizer;
- path_tokenizer = object
- m_separators_mask ,
- m_commands_mask ,
- m_numeric_mask : array[0..256 div 8 - 1 ] of char;
-
- m_path : char_ptr;
- m_last_number : double;
- m_last_command : char;
-
- constructor Construct;
-
- procedure set_path_str(str : char_ptr );
-
- function next : boolean; overload;
- function next(cmd : char ) : double; overload;
-
- function last_command : char;
- function last_number : double;
-
- procedure init_char_mask(mask ,char_set : char_ptr );
-
- function contains_ (mask : char_ptr; c : unsigned ) : boolean;
- function is_command (c : unsigned ) : boolean;
- function is_numeric (c : unsigned ) : boolean;
- function is_separator(c : unsigned ) : boolean;
- function parse_number : boolean;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor path_tokenizer.Construct;
-begin
- m_path :=NIL;
- m_last_command:=#0;
- m_last_number :=0.0;
-
- init_char_mask(@m_commands_mask[0 ] ,@s_commands[1 ] );
- init_char_mask(@m_numeric_mask[0 ] ,@s_numeric[1 ] );
- init_char_mask(@m_separators_mask[0 ] ,@s_separators[1 ] );
-
-end;
-
-{ SET_PATH_STR }
-procedure path_tokenizer.set_path_str;
-begin
- m_path :=str;
- m_last_command:=#0;
- m_last_number :=0.0;
-
-end;
-
-{ NEXT }
-function path_tokenizer.next : boolean;
-var
- buf : array[0..99 ] of char;
-
-begin
- result:=false;
-
- if m_path = NIL then
- result:=false;
-
-// Skip all white spaces and other garbage
- while (m_path^ <> #0 ) and
- not is_command(unsigned(m_path^ ) ) and
- not is_numeric(unsigned(m_path^ ) ) do
- begin
- if not is_separator(unsigned(m_path^ ) ) then
- begin
- sprintf(@buf[0 ] ,'path_tokenizer::next : Invalid Character %c' ,unsigned(m_path^ ) );
-
- raise svg_exception.Construct(PChar(@buf[0 ] ) );
-
- end;
-
- inc(ptrcomp(m_path ) );
-
- end;
-
- if m_path^ = #0 then
- exit;
-
- if is_command(unsigned(m_path^ ) ) then
- begin
- // Check if the command is a numeric sign character
- if (m_path^ = '-' ) or
- (m_path^ = '+' ) then
- begin
- result:=parse_number;
-
- exit;
-
- end;
-
- m_last_command:=m_path^;
-
- inc(ptrcomp(m_path ) );
-
- while (m_path^ <> #0 ) and
- is_separator(unsigned(m_path^ ) ) do
- inc(ptrcomp(m_path ) );
-
- if m_path^ = #0 then
- begin
- result:=true;
-
- exit;
-
- end;
-
- end;
-
- result:=parse_number;
-
-end;
-
-{ NEXT }
-function path_tokenizer.next(cmd : char ) : double;
-var
- buf : array[0..99 ] of char;
-
-begin
- if not next then
- raise svg_exception.Construct(PChar('parse_path: Unexpected end of path' ) );
-
- if last_command <> cmd then
- begin
- sprintf(@buf[0 ] ,'parse_path: Command %c: bad or missing parameters' ,unsigned(cmd ) );
-
- raise svg_exception.Construct(PChar(@buf[0 ] ) );
-
- end;
-
- result:=last_number;
-
-end;
-
-{ LAST_COMMAND }
-function path_tokenizer.last_command;
-begin
- result:=m_last_command;
-
-end;
-
-{ LAST_NUMBER }
-function path_tokenizer.last_number;
-begin
- result:=m_last_number;
-
-end;
-
-{ INIT_CHAR_MASK }
-procedure path_tokenizer.init_char_mask;
-var
- c : unsigned;
-
-begin
- fillchar(mask^ ,256 div 8 ,0 );
-
- while char_set^ <> #0 do
- begin
- c:=int8u_ptr(char_set )^;
-
- int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^:=
- int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^ or (1 shl (c and 7 ) );
-
- inc(ptrcomp(char_set ) );
-
- end;
-
-end;
-
-{ CONTAINS_ }
-function path_tokenizer.contains_;
-begin
- result:=
- (int8u_ptr(ptrcomp(mask ) + (c shr 3 ) and (256 div 8 - 1 ) )^ and
- (1 shl (c and 7 ) ) ) <> 0;
-
-end;
-
-{ IS_COMMAND }
-function path_tokenizer.is_command;
-begin
- result:=contains_(@m_commands_mask[0 ] ,c );
-
-end;
-
-{ IS_NUMERIC }
-function path_tokenizer.is_numeric;
-begin
- result:=contains_(@m_numeric_mask[0 ] ,c );
-
-end;
-
-{ IS_SEPARATOR }
-function path_tokenizer.is_separator;
-begin
- result:=contains_(@m_separators_mask[0 ] ,c );
-
-end;
-
-{ PARSE_NUMBER }
-function path_tokenizer.parse_number;
-var
- buf : array[0..255 ] of char; // Should be enough for any number
-
- buf_ptr : char_ptr;
-
-begin
- buf_ptr:=@buf[0 ];
-
-// Copy all sign characters
- while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and
- ((m_path^ = '-' ) or
- (m_path^ = '+' ) ) do
- begin
- buf_ptr^:=m_path^;
-
- inc(ptrcomp(buf_ptr ) );
- inc(ptrcomp(m_path ) );
-
- end;
-
-// Copy all numeric characters
- while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and
- is_numeric(unsigned(m_path^ ) ) do
- begin
- buf_ptr^:=m_path^;
-
- inc(ptrcomp(buf_ptr ) );
- inc(ptrcomp(m_path ) );
-
- end;
-
- buf_ptr^:=#0;
-
- m_last_number:=get_double(pointer(PChar(@buf[0 ] ) ) );
-
- result:=true;
-
-end;
-
-END.
-
+//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 (Public License) +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) +// Pascal Port By: Milan Marusinec alias Milano +// milan@marusinec.sk +// http://www.aggpas.org +// Copyright (c) 2005-2006 +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +// +// [Pascal Port History] ----------------------------------------------------- +// +// 23.06.2006-Milano: ptrcomp adjustments +// 24.04.2006-Milano: Unit port establishment +// +{ agg_svg_path_tokenizer.pas } +unit + agg_svg_path_tokenizer ; + +INTERFACE + +{$I agg_mode.inc } + +uses + agg_basics , + agg_svg_exception ; + +{ TYPES DEFINITION } +const + s_commands = '+-MmZzLlHhVvCcSsQqTtAaFfPp'; + s_numeric = '.Ee0123456789'; + s_separators = ' ,'#9#10#13; + +type +// SVG path tokenizer. +// Example: +// +// agg::svg::path_tokenizer tok; +// +// tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 "); +// while(tok.next()) +// { +// printf("command='%c' number=%f\n", +// tok.last_command(), +// tok.last_number()); +// } +// +// The tokenizer does all the routine job of parsing the SVG paths. +// It doesn't recognize any graphical primitives, it even doesn't know +// anything about pairs of coordinates (X,Y). The purpose of this class +// is to tokenize the numeric values and commands. SVG paths can +// have single numeric values for Horizontal or Vertical line_to commands +// as well as more than two coordinates (4 or 6) for Bezier curves +// depending on the semantics of the command. +// The behaviour is as follows: +// +// Each call to next() returns true if there's new command or new numeric +// value or false when the path ends. How to interpret the result +// depends on the sematics of the command. For example, command "C" +// (cubic Bezier curve) implies 6 floating point numbers preceded by this +// command. If the command assumes no arguments (like z or Z) the +// the last_number() values won't change, that is, last_number() always +// returns the last recognized numeric value, so does last_command(). + path_tokenizer_ptr = ^path_tokenizer; + path_tokenizer = object + m_separators_mask , + m_commands_mask , + m_numeric_mask : array[0..256 div 8 - 1 ] of char; + + m_path : char_ptr; + m_last_number : double; + m_last_command : char; + + constructor Construct; + + procedure set_path_str(str : char_ptr ); + + function next : boolean; overload; + function next(cmd : char ) : double; overload; + + function last_command : char; + function last_number : double; + + procedure init_char_mask(mask ,char_set : char_ptr ); + + function contains_ (mask : char_ptr; c : unsigned ) : boolean; + function is_command (c : unsigned ) : boolean; + function is_numeric (c : unsigned ) : boolean; + function is_separator(c : unsigned ) : boolean; + function parse_number : boolean; + + end; + +{ GLOBAL PROCEDURES } + + +IMPLEMENTATION +{ LOCAL VARIABLES & CONSTANTS } +{ UNIT IMPLEMENTATION } +{ CONSTRUCT } +constructor path_tokenizer.Construct; +begin + m_path :=NIL; + m_last_command:=#0; + m_last_number :=0.0; + + init_char_mask(@m_commands_mask[0 ] ,@s_commands[1 ] ); + init_char_mask(@m_numeric_mask[0 ] ,@s_numeric[1 ] ); + init_char_mask(@m_separators_mask[0 ] ,@s_separators[1 ] ); + +end; + +{ SET_PATH_STR } +procedure path_tokenizer.set_path_str; +begin + m_path :=str; + m_last_command:=#0; + m_last_number :=0.0; + +end; + +{ NEXT } +function path_tokenizer.next : boolean; +var + buf : array[0..99 ] of char; + +begin + result:=false; + + if m_path = NIL then + result:=false; + +// Skip all white spaces and other garbage + while (m_path^ <> #0 ) and + not is_command(unsigned(m_path^ ) ) and + not is_numeric(unsigned(m_path^ ) ) do + begin + if not is_separator(unsigned(m_path^ ) ) then + begin + sprintf(@buf[0 ] ,'path_tokenizer::next : Invalid Character %c' ,unsigned(m_path^ ) ); + + raise svg_exception.Construct(PChar(@buf[0 ] ) ); + + end; + + inc(ptrcomp(m_path ) ); + + end; + + if m_path^ = #0 then + exit; + + if is_command(unsigned(m_path^ ) ) then + begin + // Check if the command is a numeric sign character + if (m_path^ = '-' ) or + (m_path^ = '+' ) then + begin + result:=parse_number; + + exit; + + end; + + m_last_command:=m_path^; + + inc(ptrcomp(m_path ) ); + + while (m_path^ <> #0 ) and + is_separator(unsigned(m_path^ ) ) do + inc(ptrcomp(m_path ) ); + + if m_path^ = #0 then + begin + result:=true; + + exit; + + end; + + end; + + result:=parse_number; + +end; + +{ NEXT } +function path_tokenizer.next(cmd : char ) : double; +var + buf : array[0..99 ] of char; + +begin + if not next then + raise svg_exception.Construct(PChar('parse_path: Unexpected end of path' ) ); + + if last_command <> cmd then + begin + sprintf(@buf[0 ] ,'parse_path: Command %c: bad or missing parameters' ,unsigned(cmd ) ); + + raise svg_exception.Construct(PChar(@buf[0 ] ) ); + + end; + + result:=last_number; + +end; + +{ LAST_COMMAND } +function path_tokenizer.last_command; +begin + result:=m_last_command; + +end; + +{ LAST_NUMBER } +function path_tokenizer.last_number; +begin + result:=m_last_number; + +end; + +{ INIT_CHAR_MASK } +procedure path_tokenizer.init_char_mask; +var + c : unsigned; + +begin + fillchar(mask^ ,256 div 8 ,0 ); + + while char_set^ <> #0 do + begin + c:=int8u_ptr(char_set )^; + + int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^:= + int8u_ptr(ptrcomp(mask ) + (c shr 3 ) )^ or (1 shl (c and 7 ) ); + + inc(ptrcomp(char_set ) ); + + end; + +end; + +{ CONTAINS_ } +function path_tokenizer.contains_; +begin + result:= + (int8u_ptr(ptrcomp(mask ) + (c shr 3 ) and (256 div 8 - 1 ) )^ and + (1 shl (c and 7 ) ) ) <> 0; + +end; + +{ IS_COMMAND } +function path_tokenizer.is_command; +begin + result:=contains_(@m_commands_mask[0 ] ,c ); + +end; + +{ IS_NUMERIC } +function path_tokenizer.is_numeric; +begin + result:=contains_(@m_numeric_mask[0 ] ,c ); + +end; + +{ IS_SEPARATOR } +function path_tokenizer.is_separator; +begin + result:=contains_(@m_separators_mask[0 ] ,c ); + +end; + +{ PARSE_NUMBER } +function path_tokenizer.parse_number; +var + buf : array[0..255 ] of char; // Should be enough for any number + + buf_ptr : char_ptr; + +begin + buf_ptr:=@buf[0 ]; + +// Copy all sign characters + while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and + ((m_path^ = '-' ) or + (m_path^ = '+' ) ) do + begin + buf_ptr^:=m_path^; + + inc(ptrcomp(buf_ptr ) ); + inc(ptrcomp(m_path ) ); + + end; + +// Copy all numeric characters + while (ptrcomp(buf_ptr ) < ptrcomp(@buf[0 ] ) + 255 ) and + is_numeric(unsigned(m_path^ ) ) do + begin + buf_ptr^:=m_path^; + + inc(ptrcomp(buf_ptr ) ); + inc(ptrcomp(m_path ) ); + + end; + + buf_ptr^:=#0; + + m_last_number:=get_double(pointer(PChar(@buf[0 ] ) ) ); + + result:=true; + +end; + +END. + |