1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4 (Public License)
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6 // Pascal Port By: Milan Marusinec alias Milano
7 // milan@marusinec.sk
8 // http://www.aggpas.org
9 // Copyright (c) 2005-2006
10 //
11 // Permission to copy, use, modify, sell and distribute this software
12 // is granted provided this copyright notice appears in all copies.
13 // This software is provided "as is" without express or implied
14 // warranty, and with no claim as to its suitability for any purpose.
15 //
16 //----------------------------------------------------------------------------
17 // Contact: mcseem@antigrain.com
18 // mcseemagg@yahoo.com
19 // http://www.antigrain.com
20 //
21 // [Pascal Port History] -----------------------------------------------------
22 //
23 // 03.01.2007-Milano: Adjustments for ExpatWrap (Win,Linux & Mac)
24 // 23.06.2006-Milano: ptrcomp adjustments
25 // 24.04.2006-Milano: Unit port establishment
26 //
27 { agg_svg_parser.pas }
28 unit
29 agg_svg_parser ;
30
31 INTERFACE
32
33 {$DEFINE EXPAT_WRAPPER }
34 {$I agg_mode.inc }
35
36 uses
37 SysUtils ,
38 agg_basics ,
39 agg_color ,
40 agg_svg_path_tokenizer ,
41 agg_svg_path_renderer ,
42 agg_svg_exception ,
43 agg_trans_affine ,
44 agg_math_stroke ,
45 expat ,
46 file_utils_ ;
47
48 { TYPES DEFINITION }
49 const
50 buf_size = 512;
51
52 type
53 parser_ptr = ^parser;
54 parser = object
55 m_path : path_renderer_ptr;
56 m_tokenizer : path_tokenizer;
57
58 m_buf ,
59 m_title : char_ptr;
60
61 m_title_len : unsigned;
62 m_title_flag ,
63 m_path_flag : boolean;
64 m_attr_name ,
65 m_attr_value : char_ptr;
66
67 m_attr_name_len ,
68 m_attr_name_aloc ,
69 m_attr_value_len ,
70 m_attr_value_aloc : unsigned;
71
72 constructor Construct(path : path_renderer_ptr );
73 destructor Destruct;
74
75 procedure parse(fname : shortstring );
titlenull76 function title : char_ptr;
77
78 // XML event handlers
79 procedure parse_attr (attr : char_ptr_ptr ); overload;
80 procedure parse_path (attr : char_ptr_ptr );
81 procedure parse_poly (attr : char_ptr_ptr; close_flag : boolean );
82 procedure parse_rect (attr : char_ptr_ptr );
83 procedure parse_line (attr : char_ptr_ptr );
84 procedure parse_style (str : agg_basics.char_ptr );
85 procedure parse_transform(str : agg_basics.char_ptr );
86
parse_matrixnull87 function parse_matrix (str : agg_basics.char_ptr ) : unsigned;
parse_translatenull88 function parse_translate(str : agg_basics.char_ptr ) : unsigned;
parse_rotatenull89 function parse_rotate (str : agg_basics.char_ptr ) : unsigned;
parse_scalenull90 function parse_scale (str : agg_basics.char_ptr ) : unsigned;
parse_skew_xnull91 function parse_skew_x (str : agg_basics.char_ptr ) : unsigned;
parse_skew_ynull92 function parse_skew_y (str : agg_basics.char_ptr ) : unsigned;
93
parse_attrnull94 function parse_attr (name ,value : agg_basics.char_ptr ) : boolean; overload;
parse_name_valuenull95 function parse_name_value(nv_start ,nv_end : agg_basics.char_ptr ) : boolean;
96
97 procedure copy_name (start ,end_ : agg_basics.char_ptr );
98 procedure copy_value(start ,end_ : agg_basics.char_ptr );
99
100 end;
101
102 { GLOBAL PROCEDURES }
103 procedure start_element(data : pointer; el : char_ptr; attr : char_ptr_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
104 procedure end_element (data : pointer; el : char_ptr ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
105 procedure content (data : pointer; s : char_ptr; len : int ); {$IFDEF EXPAT_WRAPPER }cdecl; {$ENDIF }
106
107
108 IMPLEMENTATION
109 { LOCAL VARIABLES & CONSTANTS }
110 type
111 named_color_ptr = ^named_color;
112 named_color = record
113 name : array[0..21 ] of char;
114
115 r ,g ,b ,a : int8u;
116
117 end;
118
119 const
120 colors_num = 148;
121
122 colors : array[0..colors_num - 1 ] of named_color =
123 ((name:'aliceblue'; r:240; g:248; b:255; a:255 ) ,
124 (name:'antiquewhite'; r:250; g:235; b:215; a:255 ) ,
125 (name:'aqua'; r:0; g:255; b:255; a:255 ) ,
126 (name:'aquamarine'; r:127; g:255; b:212; a:255 ) ,
127 (name:'azure'; r:240; g:255; b:255; a:255 ) ,
128 (name:'beige'; r:245; g:245; b:220; a:255 ) ,
129 (name:'bisque'; r:255; g:228; b:196; a:255 ) ,
130 (name:'black'; r:0; g:0; b:0; a:255 ) ,
131 (name:'blanchedalmond'; r:255; g:235; b:205; a:255 ) ,
132 (name:'blue'; r:0; g:0; b:255; a:255 ) ,
133 (name:'blueviolet'; r:138; g:43; b:226; a:255 ) ,
134 (name:'brown'; r:165; g:42; b:42; a:255 ) ,
135 (name:'burlywood'; r:222; g:184; b:135; a:255 ) ,
136 (name:'cadetblue'; r:95; g:158; b:160; a:255 ) ,
137 (name:'chartreuse'; r:127; g:255; b:0; a:255 ) ,
138 (name:'chocolate'; r:210; g:105; b:30; a:255 ) ,
139 (name:'coral'; r:255; g:127; b:80; a:255 ) ,
140 (name:'cornflowerblue'; r:100; g:149; b:237; a:255 ) ,
141 (name:'cornsilk'; r:255; g:248; b:220; a:255 ) ,
142 (name:'crimson'; r:220; g:20; b:60; a:255 ) ,
143 (name:'cyan'; r:0; g:255; b:255; a:255 ) ,
144 (name:'darkblue'; r:0; g:0; b:139; a:255 ) ,
145 (name:'darkcyan'; r:0; g:139; b:139; a:255 ) ,
146 (name:'darkgoldenrod'; r:184; g:134; b:11; a:255 ) ,
147 (name:'darkgray'; r:169; g:169; b:169; a:255 ) ,
148 (name:'darkgreen'; r:0; g:100; b:0; a:255 ) ,
149 (name:'darkgrey'; r:169; g:169; b:169; a:255 ) ,
150 (name:'darkkhaki'; r:189; g:183; b:107; a:255 ) ,
151 (name:'darkmagenta'; r:139; g:0; b:139; a:255 ) ,
152 (name:'darkolivegreen'; r:85; g:107; b:47; a:255 ) ,
153 (name:'darkorange'; r:255; g:140; b:0; a:255 ) ,
154 (name:'darkorchid'; r:153; g:50; b:204; a:255 ) ,
155 (name:'darkred'; r:139; g:0; b:0; a:255 ) ,
156 (name:'darksalmon'; r:233; g:150; b:122; a:255 ) ,
157 (name:'darkseagreen'; r:143; g:188; b:143; a:255 ) ,
158 (name:'darkslateblue'; r:72; g:61; b:139; a:255 ) ,
159 (name:'darkslategray'; r:47; g:79; b:79; a:255 ) ,
160 (name:'darkslategrey'; r:47; g:79; b:79; a:255 ) ,
161 (name:'darkturquoise'; r:0; g:206; b:209; a:255 ) ,
162 (name:'darkviolet'; r:148; g:0; b:211; a:255 ) ,
163 (name:'deeppink'; r:255; g:20; b:147; a:255 ) ,
164 (name:'deepskyblue'; r:0; g:191; b:255; a:255 ) ,
165 (name:'dimgray'; r:105; g:105; b:105; a:255 ) ,
166 (name:'dimgrey'; r:105; g:105; b:105; a:255 ) ,
167 (name:'dodgerblue'; r:30; g:144; b:255; a:255 ) ,
168 (name:'firebrick'; r:178; g:34; b:34; a:255 ) ,
169 (name:'floralwhite'; r:255; g:250; b:240; a:255 ) ,
170 (name:'forestgreen'; r:34; g:139; b:34; a:255 ) ,
171 (name:'fuchsia'; r:255; g:0; b:255; a:255 ) ,
172 (name:'gainsboro'; r:220; g:220; b:220; a:255 ) ,
173 (name:'ghostwhite'; r:248; g:248; b:255; a:255 ) ,
174 (name:'gold'; r:255; g:215; b:0; a:255 ) ,
175 (name:'goldenrod'; r:218; g:165; b:32; a:255 ) ,
176 (name:'gray'; r:128; g:128; b:128; a:255 ) ,
177 (name:'green'; r:0; g:128; b:0; a:255 ) ,
178 (name:'greenyellow'; r:173; g:255; b:47; a:255 ) ,
179 (name:'grey'; r:128; g:128; b:128; a:255 ) ,
180 (name:'honeydew'; r:240; g:255; b:240; a:255 ) ,
181 (name:'hotpink'; r:255; g:105; b:180; a:255 ) ,
182 (name:'indianred'; r:205; g:92; b:92; a:255 ) ,
183 (name:'indigo'; r:75; g:0; b:130; a:255 ) ,
184 (name:'ivory'; r:255; g:255; b:240; a:255 ) ,
185 (name:'khaki'; r:240; g:230; b:140; a:255 ) ,
186 (name:'lavender'; r:230; g:230; b:250; a:255 ) ,
187 (name:'lavenderblush'; r:255; g:240; b:245; a:255 ) ,
188 (name:'lawngreen'; r:124; g:252; b:0; a:255 ) ,
189 (name:'lemonchiffon'; r:255; g:250; b:205; a:255 ) ,
190 (name:'lightblue'; r:173; g:216; b:230; a:255 ) ,
191 (name:'lightcoral'; r:240; g:128; b:128; a:255 ) ,
192 (name:'lightcyan'; r:224; g:255; b:255; a:255 ) ,
193 (name:'lightgoldenrodyellow'; r:250; g:250; b:210; a:255 ) ,
194 (name:'lightgray'; r:211; g:211; b:211; a:255 ) ,
195 (name:'lightgreen'; r:144; g:238; b:144; a:255 ) ,
196 (name:'lightgrey'; r:211; g:211; b:211; a:255 ) ,
197 (name:'lightpink'; r:255; g:182; b:193; a:255 ) ,
198 (name:'lightsalmon'; r:255; g:160; b:122; a:255 ) ,
199 (name:'lightseagreen'; r:32; g:178; b:170; a:255 ) ,
200 (name:'lightskyblue'; r:135; g:206; b:250; a:255 ) ,
201 (name:'lightslategray'; r:119; g:136; b:153; a:255 ) ,
202 (name:'lightslategrey'; r:119; g:136; b:153; a:255 ) ,
203 (name:'lightsteelblue'; r:176; g:196; b:222; a:255 ) ,
204 (name:'lightyellow'; r:255; g:255; b:224; a:255 ) ,
205 (name:'lime'; r:0; g:255; b:0; a:255 ) ,
206 (name:'limegreen'; r:50; g:205; b:50; a:255 ) ,
207 (name:'linen'; r:250; g:240; b:230; a:255 ) ,
208 (name:'magenta'; r:255; g:0; b:255; a:255 ) ,
209 (name:'maroon'; r:128; g:0; b:0; a:255 ) ,
210 (name:'mediumaquamarine'; r:102; g:205; b:170; a:255 ) ,
211 (name:'mediumblue'; r:0; g:0; b:205; a:255 ) ,
212 (name:'mediumorchid'; r:186; g:85; b:211; a:255 ) ,
213 (name:'mediumpurple'; r:147; g:112; b:219; a:255 ) ,
214 (name:'mediumseagreen'; r:60; g:179; b:113; a:255 ) ,
215 (name:'mediumslateblue'; r:123; g:104; b:238; a:255 ) ,
216 (name:'mediumspringgreen'; r:0; g:250; b:154; a:255 ) ,
217 (name:'mediumturquoise'; r:72; g:209; b:204; a:255 ) ,
218 (name:'mediumvioletred'; r:199; g:21; b:133; a:255 ) ,
219 (name:'midnightblue'; r:25; g:25; b:112; a:255 ) ,
220 (name:'mintcream'; r:245; g:255; b:250; a:255 ) ,
221 (name:'mistyrose'; r:255; g:228; b:225; a:255 ) ,
222 (name:'moccasin'; r:255; g:228; b:181; a:255 ) ,
223 (name:'navajowhite'; r:255; g:222; b:173; a:255 ) ,
224 (name:'navy'; r:0; g:0; b:128; a:255 ) ,
225 (name:'oldlace'; r:253; g:245; b:230; a:255 ) ,
226 (name:'olive'; r:128; g:128; b:0; a:255 ) ,
227 (name:'olivedrab'; r:107; g:142; b:35; a:255 ) ,
228 (name:'orange'; r:255; g:165; b:0; a:255 ) ,
229 (name:'orangered'; r:255; g:69; b:0; a:255 ) ,
230 (name:'orchid'; r:218; g:112; b:214; a:255 ) ,
231 (name:'palegoldenrod'; r:238; g:232; b:170; a:255 ) ,
232 (name:'palegreen'; r:152; g:251; b:152; a:255 ) ,
233 (name:'paleturquoise'; r:175; g:238; b:238; a:255 ) ,
234 (name:'palevioletred'; r:219; g:112; b:147; a:255 ) ,
235 (name:'papayawhip'; r:255; g:239; b:213; a:255 ) ,
236 (name:'peachpuff'; r:255; g:218; b:185; a:255 ) ,
237 (name:'peru'; r:205; g:133; b:63; a:255 ) ,
238 (name:'pink'; r:255; g:192; b:203; a:255 ) ,
239 (name:'plum'; r:221; g:160; b:221; a:255 ) ,
240 (name:'powderblue'; r:176; g:224; b:230; a:255 ) ,
241 (name:'purple'; r:128; g:0; b:128; a:255 ) ,
242 (name:'red'; r:255; g:0; b:0; a:255 ) ,
243 (name:'rosybrown'; r:188; g:143; b:143; a:255 ) ,
244 (name:'royalblue'; r:65; g:105; b:225; a:255 ) ,
245 (name:'saddlebrown'; r:139; g:69; b:19; a:255 ) ,
246 (name:'salmon'; r:250; g:128; b:114; a:255 ) ,
247 (name:'sandybrown'; r:244; g:164; b:96; a:255 ) ,
248 (name:'seagreen'; r:46; g:139; b:87; a:255 ) ,
249 (name:'seashell'; r:255; g:245; b:238; a:255 ) ,
250 (name:'sienna'; r:160; g:82; b:45; a:255 ) ,
251 (name:'silver'; r:192; g:192; b:192; a:255 ) ,
252 (name:'skyblue'; r:135; g:206; b:235; a:255 ) ,
253 (name:'slateblue'; r:106; g:90; b:205; a:255 ) ,
254 (name:'slategray'; r:112; g:128; b:144; a:255 ) ,
255 (name:'slategrey'; r:112; g:128; b:144; a:255 ) ,
256 (name:'snow'; r:255; g:250; b:250; a:255 ) ,
257 (name:'springgreen'; r:0; g:255; b:127; a:255 ) ,
258 (name:'steelblue'; r:70; g:130; b:180; a:255 ) ,
259 (name:'tan'; r:210; g:180; b:140; a:255 ) ,
260 (name:'teal'; r:0; g:128; b:128; a:255 ) ,
261 (name:'thistle'; r:216; g:191; b:216; a:255 ) ,
262 (name:'tomato'; r:255; g:99; b:71; a:255 ) ,
263 (name:'turquoise'; r:64; g:224; b:208; a:255 ) ,
264 (name:'violet'; r:238; g:130; b:238; a:255 ) ,
265 (name:'wheat'; r:245; g:222; b:179; a:255 ) ,
266 (name:'white'; r:255; g:255; b:255; a:255 ) ,
267 (name:'whitesmoke'; r:245; g:245; b:245; a:255 ) ,
268 (name:'yellow'; r:255; g:255; b:0; a:255 ) ,
269 (name:'yellowgreen'; r:154; g:205; b:50; a:255 ) ,
270 (name:'zzzzzzzzzzz'; r:0; g:0; b:0; a:0 ) );
271
272 pageEqHigh : shortstring =
273 #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
274 #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
275 #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
276 #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
277 #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
278 #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
279 #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
280 #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
281 #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
282 #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
283 #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
284 #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
285 #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
286 #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
287 #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
288 #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
289
290 { UNIT IMPLEMENTATION }
291 { START_ELEMENT }
292 procedure start_element;
293 var
294 this : parser_ptr;
295
296 begin
297 this:=parser_ptr(data );
298
299 if StrComp(PChar(el ) ,'title' ) = 0 then
300 this.m_title_flag:=true
301 else
302 if StrComp(PChar(el ) ,'g' ) = 0 then
303 begin
304 this.m_path.push_attr;
305 this.parse_attr(attr );
306
307 end
308 else
309 if StrComp(PChar(el ) ,'path' ) = 0 then
310 begin
311 if this.m_path_flag then
312 raise svg_exception.Construct(PChar('start_element: Nested path' ) );
313
314 this.m_path.begin_path;
315 this.parse_path(attr );
316 this.m_path.end_path;
317
318 this.m_path_flag:=true;
319
320 end
321 else
322 if StrComp(PChar(el ) ,'rect' ) = 0 then
323 this.parse_rect(attr )
324 else
325 if StrComp(PChar(el ) ,'line' ) = 0 then
326 this.parse_line(attr )
327 else
328 if StrComp(PChar(el ) ,'polyline' ) = 0 then
329 this.parse_poly(attr ,false )
330 else
331 if StrComp(PChar(el ) ,'polygon' ) = 0 then
332 this.parse_poly(attr ,true );
333
334 //else
335 // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
336 // begin
337 // end
338 //...
339
340 end;
341
342 { END_ELEMENT }
343 procedure end_element;
344 var
345 this : parser_ptr;
346
347 begin
348 this:=parser_ptr(data );
349
350 if StrComp(PChar(el ) ,'title' ) = 0 then
351 this.m_title_flag:=false
352 else
353 if StrComp(PChar(el ) ,'g' ) = 0 then
354 this.m_path.pop_attr
355 else
356 if StrComp(PChar(el ) ,'path' ) = 0 then
357 this.m_path_flag:=false;
358
359 //else
360 // if StrComp(PChar(el ) ,'<OTHER_ELEMENTS>' ) = 0 then
361 // begin
362 // end
363 // ...
364
365 end;
366
367 { CONTENT }
368 procedure content;
369 var
370 this : parser_ptr;
371
372 begin
373 this:=parser_ptr(data );
374
375 // m_title_flag signals that the <title> tag is being parsed now.
376 // The following code concatenates the pieces of content of the <title> tag.
377 if this.m_title_flag then
378 begin
379 if len + this.m_title_len > 255 then
380 len:=255 - this.m_title_len;
381
382 if len > 0 then
383 begin
384 move(
385 s^ ,
386 char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^ ,
387 len );
388
389 inc(this.m_title_len ,len );
390
391 char_ptr(ptrcomp(this.m_title ) + this.m_title_len )^:=#0;
392
393 end;
394
395 end;
396
397 end;
398
399 { hex_unsigned }
hex_unsignednull400 function hex_unsigned(hexstr : agg_basics.char_ptr ) : unsigned;
401
xyintnull402 function xyint(x ,y : integer ) : integer;
403 var
404 f : integer;
405 m : boolean;
406
407 begin
408 m:=false;
409
410 if y < 0 then
411 begin
412 y:=y * -1;
413 m:=true;
414
415 end;
416
417 result:=x;
418
419 if y > 1 then
420 for f:=1 to y - 1 do
421 result:=result * x;
422
423 if m then
424 result:=result * -1;
425
426 end;
427
428 var
429 h : shortstring;
430 fcb : byte;
431 yps ,
432 mul ,
433 num : unsigned;
434
435 label
436 Err ,Esc ;
437
438 const
439 hex : string[16 ] = '0123456789ABCDEF';
440
441 begin
442 h:='';
443
444 while hexstr^ <> #0 do
445 begin
446 h:=h + pageEqHigh[byte(hexstr^ ) ];
447
448 inc(ptrcomp(hexstr ) );
449
450 end;
451
452 if length(h ) > 0 then
453 begin
454 case h[length(h ) ] of
455 '0'..'9' ,'A'..'F' :
456 else
457 goto Err;
458
459 end;
460
461 num:=pos(h[length(h ) ] ,hex ) - 1;
462 yps:=2;
463 mul:=xyint(4 ,yps );
464
465 if length(h ) > 1 then
466 for fcb:=length(h ) - 1 downto 1 do
467 begin
468 case h[fcb ] of
469 '0'..'9' ,'A'..'F' :
470 else
471 goto Err;
472
473 end;
474
475 inc(num ,(pos(h[fcb ] ,hex ) - 1 ) * mul );
476 inc(yps ,2 );
477
478 mul:=xyint(4 ,yps );
479
480 end;
481
482 goto Esc;
483
484 end;
485
486 Err:
487 num:=0;
488
489 Esc:
490 result:=num;
491
492 end;
493
494 { parse_color }
parse_colornull495 function parse_color(str : agg_basics.char_ptr ) : aggclr;
496 var
497 u : unsigned;
498 p : named_color_ptr;
499 m : shortstring;
500
501 begin
502 while str^ = ' ' do
503 inc(ptrcomp(str ) );
504
505 if str^ = '#' then
506 begin
507 inc(ptrcomp(str ) );
508
509 u:=hex_unsigned(str );
510
511 result.Construct(rgb8_packed(u ) );
512
513 end
514 else
515 begin
516 p:=NIL;
517
518 for u:=0 to colors_num - 1 do
519 if StrComp(colors[u ].name ,PChar(str ) ) = 0 then
520 begin
521 p:=@colors[u ];
522
523 break;
524
525 end;
526
527 if p = NIL then
528 begin
529 m:='parse_color: Invalid color name ' + StrPas(PChar(str ) ) + #0;
530
531 raise svg_exception.Construct(PChar(@m[1 ] ) );
532
533 end;
534
535 result.ConstrInt(p.r ,p.g ,p.b ,p.a );
536
537 end;
538
539 end;
540
541 { parse_double }
parse_doublenull542 function parse_double(str : agg_basics.char_ptr ) : double;
543 begin
544 while str^ = ' ' do
545 inc(ptrcomp(str ) );
546
547 result:=get_double(pointer(PChar(str ) ) );
548
549 end;
550
551 { islower }
islowernull552 function islower(ch : char ) : boolean;
553 begin
554 case ch of
555 #97..#122 :
556 result:=true;
557
558 else
559 result:=false;
560
561 end;
562
563 end;
564
565 { is_numeric }
is_numericnull566 function is_numeric(ch : char ) : boolean;
567 begin
568 result:=Pos(ch ,'0123456789+-.eE' ) <> 0;
569
570 end;
571
572 { parse_transform_args }
parse_transform_argsnull573 function parse_transform_args(str : agg_basics.char_ptr; args : double_ptr; max_na : unsigned; na : unsigned_ptr ) : unsigned;
574 var
575 ptr ,end_ : agg_basics.char_ptr;
576
577 begin
578 na^:=0;
579 ptr:=str;
580
581 while (ptr^ <> #0 ) and
582 (ptr^ <> '(' ) do
583 inc(ptrcomp(ptr ) );
584
585 if ptr^ = #0 then
586 raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
587
588 end_:=ptr;
589
590 while (end_^ <> #0 ) and
591 (end_^ <> ')' ) do
592 inc(ptrcomp(end_ ) );
593
594 if end_^ = #0 then
595 raise svg_exception.Construct(PChar('parse_transform_args: Invalid syntax' ) );
596
597 while ptrcomp(ptr ) < ptrcomp(end_ ) do
598 if is_numeric(ptr^ ) then
599 begin
600 if na^ >= max_na then
601 raise svg_exception.Construct(PChar('parse_transform_args: Too many arguments' ) );
602
603 double_ptr(ptrcomp(args ) + na^ * sizeof(double ) )^:=get_double(ptr );
604
605 inc(na^ );
606
607 while (ptrcomp(ptr ) < ptrcomp(end_ ) ) and
608 is_numeric(ptr^ ) do
609 inc(ptrcomp(ptr ) );
610
611 end
612 else
613 inc(ptrcomp(ptr ) );
614
615 result:=unsigned(ptrcomp(end_ ) - ptrcomp(str ) );
616
617 end;
618
619 { CONSTRUCT }
620 constructor parser.Construct;
621 begin
622 m_path:=path;
623
624 m_tokenizer.Construct;
625
626 agg_getmem(pointer(m_buf ) ,buf_size );
627 agg_getmem(pointer(m_title ) ,256 );
628
629 m_title_len :=0;
630 m_title_flag:=false;
631 m_path_flag :=false;
632
633 m_attr_name_aloc :=128;
634 m_attr_value_aloc:=1024;
635
636 agg_getmem(pointer(m_attr_name ) ,m_attr_name_aloc );
637 agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
638
639 m_attr_name_len :=127;
640 m_attr_value_len:=1023;
641
642 m_title^:=#0;
643
644 end;
645
646 { DESTRUCT }
647 destructor parser.Destruct;
648 begin
649 agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
650 agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
651 agg_freemem(pointer(m_title ) ,256 );
652 agg_freemem(pointer(m_buf ) ,buf_size );
653
654 end;
655
656 { PARSE }
657 procedure parser.parse;
658 var
659 msg : array[0..1023 ] of char;
660
661 p : XML_Parser;
662 af : api_file;
663 ts : char_ptr;
664
665 done : boolean;
666 len : int;
667
668 begin
669 p:=XML_ParserCreate(NIL );
670
671 if p = NIL then
672 raise svg_exception.Construct(PChar('Couldn''t allocate memory for parser' ) );
673
674 XML_SetUserData (p ,@self );
675 XML_SetElementHandler (p ,@start_element ,@end_element );
676 XML_SetCharacterDataHandler(p ,@content );
677
678 fname:=fname + #0;
679
680 dec(byte(fname[0 ] ) );
681
682 if not api_open_file(af ,fname ) then
683 begin
684 sprintf(@msg[0 ] ,'Couldn''t open file %s' ,unsigned(@fname[1 ] ) );
685
686 XML_ParserFree(p );
687
688 raise svg_exception.Construct(PChar(@msg[0 ] ) );
689
690 end;
691
692 done:=false;
693
694 repeat
695 api_read_file(af ,m_buf ,buf_size ,len );
696
697 done:=len < buf_size;
698
699 if XML_Parse(p ,pointer(m_buf ) ,len ,int(done ) ) = XML_STATUS_ERROR then
700 begin
701 api_close_file(af );
702 XML_ParserFree(p );
703
704 sprintf(
705 @msg[0 ] ,
706 '%s at line ' ,
707 unsigned(
708 XML_ErrorString(
709 int(XML_GetErrorCode(p ) ) ) ) );
710
711 sprintf(
712 @msg[StrLen(msg ) ] ,
713 '%d'#13 ,
714 XML_GetCurrentLineNumber(p ) );
715
716 raise svg_exception.Construct(PChar(@msg[0 ] ) );
717
718 end;
719
720 until done;
721
722 api_close_file(af );
723 XML_ParserFree(p );
724
725 ts:=m_title;
726
727 while ts^ <> #0 do
728 begin
729 if byte(ts^ ) < byte(' ' ) then
730 ts^:=' ';
731
732 inc(ptrcomp(ts ) );
733
734 end;
735
736 end;
737
738 { TITLE }
parser.titlenull739 function parser.title;
740 begin
741 result:=m_title;
742
743 end;
744
745 { PARSE_ATTR }
746 procedure parser.parse_attr(attr : char_ptr_ptr );
747 var
748 i : int;
749
750 begin
751 i:=0;
752
753 while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
754 begin
755 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'style' ) = 0 then
756 parse_style(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ )
757 else
758 parse_attr(
759 agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
760 agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
761
762 inc(i ,2 );
763
764 end;
765
766 end;
767
768 { PARSE_PATH }
769 procedure parser.parse_path;
770 var
771 i : int;
772
773 tmp : array[0..3 ] of agg_basics.char_ptr;
774
775 begin
776 i:=0;
777
778 while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
779 begin
780 // The <path> tag can consist of the path itself ("d=")
781 // as well as of other parameters like "style=", "transform=", etc.
ofnull782 // In the last case we simply rely on the function of parsing
783 // attributes (see 'else' branch).
784 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'d' ) = 0 then
785 begin
786 m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
787
788 m_path.parse_path(@m_tokenizer );
789
790 end
791 else
792 begin
793 // Create a temporary single pair "name-value" in order
794 // to avoid multiple calls for the same attribute.
795 tmp[0 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^;
796 tmp[1 ]:=agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^;
797 tmp[2 ]:=NIL;
798 tmp[3 ]:=NIL;
799
800 parse_attr(@tmp );
801
802 end;
803
804 inc(i ,2 );
805
806 end;
807
808 end;
809
810 { PARSE_POLY }
811 procedure parser.parse_poly;
812 var
813 i : int;
814
815 x ,y : double;
816
817 begin
818 x:=0.0;
819 y:=0.0;
820
821 m_path.begin_path;
822
823 i:=0;
824
825 while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
826 begin
827 if not parse_attr(
828 agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
829 agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
830 if StrComp(PChar(agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'points' ) = 0 then
831 begin
832 m_tokenizer.set_path_str(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
833
834 if not m_tokenizer.next then
835 raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
836
837 x:=m_tokenizer.last_number;
838
839 if not m_tokenizer.next then
840 raise svg_exception.Construct(PChar('parse_poly: Too few coordinates' ) );
841
842 y:=m_tokenizer.last_number;
843
844 m_path.move_to(x ,y );
845
846 while m_tokenizer.next do
847 begin
848 x:=m_tokenizer.last_number;
849
850 if not m_tokenizer.next then
851 raise svg_exception.Construct(PChar('parse_poly: Odd number of coordinates' ) );
852
853 y:=m_tokenizer.last_number;
854
855 m_path.line_to(x ,y );
856
857 end;
858
859 end;
860
861 inc(i ,2 );
862
863 end;
864
865 m_path.end_path;
866
867 end;
868
869 { PARSE_RECT }
870 procedure parser.parse_rect;
871 var
872 i : int;
873
874 x ,y ,w ,h : double;
875
876 begin
877 x:=0.0;
878 y:=0.0;
879 w:=0.0;
880 h:=0.0;
881
882 m_path.begin_path;
883
884 i:=0;
885
886 while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
887 begin
888 if not parse_attr(
889 agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
890 agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
891 begin
892 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x' ) = 0 then
893 x:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
894
895 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y' ) = 0 then
896 y:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
897
898 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'width' ) = 0 then
899 w:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
900
901 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'height' ) = 0 then
902 h:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
903
904 // rx - to be implemented
905 // ry - to be implemented
906
907 end;
908
909 inc(i ,2 );
910
911 end;
912
913 if (w <> 0.0 ) and
914 (h <> 0.0 ) then
915 begin
916 if w < 0.0 then
917 raise svg_exception.Construct(PChar('parse_rect: Invalid width: ' ) );
918
919 if h < 0.0 then
920 raise svg_exception.Construct(PChar('parse_rect: Invalid height: ' ) );
921
922 m_path.move_to(x ,y );
923 m_path.line_to(x + w ,y );
924 m_path.line_to(x + w ,y + h );
925 m_path.line_to(x ,y + h );
926 m_path.close_subpath;
927
928 end;
929
930 m_path.end_path;
931
932 end;
933
934 { PARSE_LINE }
935 procedure parser.parse_line;
936 var
937 i : int;
938
939 x1 ,y1 ,x2 ,y2 : double;
940
941 begin
942 x1:=0.0;
943 y1:=0.0;
944 x2:=0.0;
945 y2:=0.0;
946
947 m_path.begin_path;
948
949 i:=0;
950
951 while char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ <> NIL do
952 begin
953 if not parse_attr(
954 agg_basics.char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ,
955 agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ ) then
956 begin
957 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x1' ) = 0 then
958 x1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
959
960 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y1' ) = 0 then
961 y1:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
962
963 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'x2' ) = 0 then
964 x2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
965
966 if StrComp(PChar(char_ptr_ptr(ptrcomp(attr ) + i * sizeof(char_ptr ) )^ ) ,'y2' ) = 0 then
967 y2:=parse_double(agg_basics.char_ptr_ptr(ptrcomp(attr ) + (i + 1 ) * sizeof(char_ptr ) )^ );
968
969 end;
970
971 inc(i ,2 );
972
973 end;
974
975 m_path.move_to(x1 ,y1 );
976 m_path.line_to(x2 ,y2 );
977 m_path.end_path;
978
979 end;
980
981 { PARSE_STYLE }
982 procedure parser.parse_style;
983 var
984 nv_start ,nv_end : agg_basics.char_ptr;
985
986 begin
987 while str^ <> #0 do
988 begin
989 // Left Trim
990 while (str^ <> #0 ) and
991 (str^ = ' ' ) do
992 inc(ptrcomp(str ) );
993
994 nv_start:=str;
995
996 while (str^ <> #0 ) and
997 (str^ <> ';' ) do
998 inc(ptrcomp(str ) );
999
1000 nv_end:=str;
1001
1002 // Right Trim
1003 while (ptrcomp(nv_end ) > ptrcomp(nv_start ) ) and
1004 ((nv_end^ = ';' ) or
1005 (nv_end^ = ' ' ) ) do
1006 dec(ptrcomp(nv_end ) );
1007
1008 inc(ptrcomp(nv_end ) );
1009
1010 parse_name_value(nv_start ,nv_end );
1011
1012 if str^ <> #0 then
1013 inc(ptrcomp(str ) );
1014
1015 end;
1016
1017 end;
1018
1019 { PARSE_TRANSFORM }
1020 procedure parser.parse_transform;
1021 begin
1022 while str^ <> #0 do
1023 begin
1024 if islower(str^ ) then
1025 if StrLComp(PChar(str ) ,'matrix' ,6 ) = 0 then
1026 inc(ptrcomp(str ) ,parse_matrix(str ) )
1027 else
1028 if StrLComp(PChar(str ) ,'translate' ,9 ) = 0 then
1029 inc(ptrcomp(str ) ,parse_translate(str ) )
1030 else
1031 if StrLComp(PChar(str ) ,'rotate' ,6 ) = 0 then
1032 inc(ptrcomp(str ) ,parse_rotate(str ) )
1033 else
1034 if StrLComp(PChar(str ) ,'scale' ,5 ) = 0 then
1035 inc(ptrcomp(str ) ,parse_scale(str ) )
1036 else
1037 if StrLComp(PChar(str ) ,'skewX' ,5 ) = 0 then
1038 inc(ptrcomp(str ) ,parse_skew_x(str ) )
1039 else
1040 if StrLComp(PChar(str ) ,'skewY' ,5 ) = 0 then
1041 inc(ptrcomp(str ) ,parse_skew_y(str ) )
1042 else
1043 inc(ptrcomp(str ) )
1044
1045 else
1046 inc(ptrcomp(str ) );
1047
1048 end;
1049
1050 end;
1051
1052 { PARSE_MATRIX }
parser.parse_matrixnull1053 function parser.parse_matrix;
1054 var
1055 args : array[0..5 ] of double;
1056
1057 na ,len : unsigned;
1058
1059 ta : trans_affine;
1060
1061 begin
1062 na :=0;
1063 len:=parse_transform_args(str ,@args ,6 ,@na );
1064
1065 if na <> 6 then
1066 raise svg_exception.Construct(PChar('parse_matrix: Invalid number of arguments' ) );
1067
1068 ta.Construct(args[0 ] ,args[1 ] ,args[2 ] ,args[3 ] ,args[4 ] ,args[5 ] );
1069
1070 m_path.transform.premultiply(@ta );
1071
1072 result:=len;
1073
1074 end;
1075
1076 { PARSE_TRANSLATE }
parser.parse_translatenull1077 function parser.parse_translate;
1078 var
1079 args : array[0..1 ] of double;
1080
1081 na ,len : unsigned;
1082
1083 tat : trans_affine_translation;
1084
1085 begin
1086 na :=0;
1087 len:=parse_transform_args(str ,@args ,2 ,@na );
1088
1089 if na = 1 then
1090 args[1 ]:=0.0;
1091
1092 tat.Construct(args[0 ] ,args[1 ] );
1093
1094 m_path.transform.premultiply(@tat );
1095
1096 result:=len;
1097
1098 end;
1099
1100 { PARSE_ROTATE }
parser.parse_rotatenull1101 function parser.parse_rotate;
1102 var
1103 args : array[0..2 ] of double;
1104
1105 na ,len : unsigned;
1106
1107 tar : trans_affine_rotation;
1108
1109 tat ,t : trans_affine_translation;
1110
1111 begin
1112 na :=0;
1113 len:=parse_transform_args(str ,@args ,3 ,@na );
1114
1115 if na = 1 then
1116 begin
1117 tar.Construct(deg2rad(args[0 ] ) );
1118
1119 m_path.transform.premultiply(@tar );
1120
1121 end
1122 else
1123 if na = 3 then
1124 begin
1125 t.Construct(-args[1 ] ,-args[2 ] );
1126
1127 tar.Construct(deg2rad(args[0 ] ) );
1128 tat.Construct(args[1 ] ,args[2 ] );
1129
1130 t.multiply(@tar );
1131 t.multiply(@tat );
1132
1133 m_path.transform.premultiply(@t );
1134
1135 end
1136 else
1137 raise svg_exception.Construct(PChar('parse_rotate: Invalid number of arguments' ) );
1138
1139 result:=len;
1140
1141 end;
1142
1143 { PARSE_SCALE }
parser.parse_scalenull1144 function parser.parse_scale;
1145 var
1146 args : array[0..1 ] of double;
1147
1148 na ,len : unsigned;
1149
1150 tas : trans_affine_scaling;
1151
1152 begin
1153 na :=0;
1154 len:=parse_transform_args(str ,@args ,2 ,@na );
1155
1156 if na = 1 then
1157 args[1 ]:=args[0 ];
1158
1159 tas.Construct(args[0 ] ,args[1 ] );
1160
1161 m_path.transform.premultiply(@tas );
1162
1163 result:=len;
1164
1165 end;
1166
1167 { PARSE_SKEW_X }
parser.parse_skew_xnull1168 function parser.parse_skew_x;
1169 var
1170 arg : double;
1171
1172 na ,len : unsigned;
1173
1174 tas : trans_affine_skewing;
1175
1176 begin
1177 na :=0;
1178 len:=parse_transform_args(str ,@arg ,1 ,@na );
1179
1180 tas.Construct(deg2rad(arg ) ,0.0 );
1181
1182 m_path.transform.premultiply(@tas );
1183
1184 result:=len;
1185
1186 end;
1187
1188 { PARSE_SKEW_Y }
parser.parse_skew_ynull1189 function parser.parse_skew_y;
1190 var
1191 arg : double;
1192
1193 na ,len : unsigned;
1194
1195 tas : trans_affine_skewing;
1196
1197 begin
1198 na :=0;
1199 len:=parse_transform_args(str ,@arg ,1 ,@na );
1200
1201 tas.Construct(0.0 ,deg2rad(arg ) );
1202
1203 m_path.transform.premultiply(@tas );
1204
1205 result:=len;
1206
1207 end;
1208
1209 { PARSE_ATTR }
parser.parse_attrnull1210 function parser.parse_attr(name ,value : agg_basics.char_ptr ) : boolean;
1211 var
1212 clr : aggclr;
1213
1214 begin
1215 result:=true;
1216
1217 if StrComp(PChar(name ) ,'style' ) = 0 then
1218 parse_style(value )
1219 else
1220 if StrComp(PChar(name ) ,'fill' ) = 0 then
1221 if StrComp(PChar(value ) ,'none' ) = 0 then
1222 m_path.fill_none
1223 else
1224 begin
1225 clr:=parse_color(value );
1226
1227 m_path.fill(@clr );
1228
1229 end
1230 else
1231 if StrComp(PChar(name ) ,'fill-opacity' ) = 0 then
1232 m_path.fill_opacity(parse_double(value ) )
1233 else
1234 if StrComp(PChar(name ) ,'stroke' ) = 0 then
1235 if StrComp(PChar(value ) ,'none' ) = 0 then
1236 m_path.stroke_none
1237 else
1238 begin
1239 clr:=parse_color(value );
1240
1241 m_path.stroke(@clr );
1242
1243 end
1244 else
1245 if StrComp(PChar(name ) ,'stroke-width' ) = 0 then
1246 m_path.stroke_width(parse_double(value ) )
1247 else
1248 if StrComp(PChar(name ) ,'stroke-linecap' ) = 0 then
1249 begin
1250 if StrComp(PChar(value ) ,'butt' ) = 0 then
1251 m_path.line_cap(butt_cap )
1252 else
1253 if StrComp(PChar(value ) ,'round' ) = 0 then
1254 m_path.line_cap(round_cap )
1255 else
1256 if StrComp(PChar(value ) ,'square' ) = 0 then
1257 m_path.line_cap(square_cap );
1258
1259 end
1260 else
1261 if StrComp(PChar(name ) ,'stroke-linejoin' ) = 0 then
1262 begin
1263 if StrComp(PChar(value ) ,'miter' ) = 0 then
1264 m_path.line_join(miter_join )
1265 else
1266 if StrComp(PChar(value ) ,'round' ) = 0 then
1267 m_path.line_join(round_join )
1268 else
1269 if StrComp(PChar(value ) ,'bevel' ) = 0 then
1270 m_path.line_join(bevel_join );
1271
1272 end
1273 else
1274 if StrComp(PChar(name ) ,'stroke-miterlimit' ) = 0 then
1275 m_path.miter_limit(parse_double(value ) )
1276 else
1277 if StrComp(PChar(name ) ,'stroke-opacity' ) = 0 then
1278 m_path.stroke_opacity(parse_double(value ) )
1279 else
1280 if StrComp(PChar(name ) ,'transform' ) = 0 then
1281 parse_transform(value )
1282
1283 //else
1284 // if StrComp(PChar(el ) ,'<OTHER_ATTRIBUTES>' ) = 0 then
1285 // begin
1286 // end
1287 // ...
1288
1289 else
1290 result:=false;
1291
1292 end;
1293
1294 { PARSE_NAME_VALUE }
parser.parse_name_valuenull1295 function parser.parse_name_value;
1296 var
1297 str ,val : agg_basics.char_ptr;
1298
1299 begin
1300 str:=nv_start;
1301
1302 while (ptrcomp(str ) < ptrcomp(nv_end ) ) and
1303 (str^ <> ':' ) do
1304 inc(ptrcomp(str ) );
1305
1306 val:=str;
1307
1308 // Right Trim
1309 while (ptrcomp(str ) > ptrcomp(nv_start ) ) and
1310 ((str^ = ':' ) or
1311 (str^ = ' ' ) ) do
1312 dec(ptrcomp(str ) );
1313
1314 inc(ptrcomp(str ) );
1315
1316 copy_name(nv_start ,str );
1317
1318 while (ptrcomp(val ) < ptrcomp(nv_end ) ) and
1319 ((val^ = ':' ) or
1320 (val^ = ' ' ) ) do
1321 inc(ptrcomp(val ) );
1322
1323 copy_value(val ,nv_end );
1324
1325 result:=parse_attr(agg_basics.char_ptr(m_attr_name ) ,agg_basics.char_ptr(m_attr_value ) );
1326
1327 end;
1328
1329 { COPY_NAME }
1330 procedure parser.copy_name;
1331 var
1332 len : unsigned;
1333
1334 begin
1335 len:=ptrcomp(end_ ) - ptrcomp(start );
1336
1337 if (m_attr_name_len = 0 ) or
1338 (len > m_attr_name_len ) then
1339 begin
1340 agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
1341
1342 m_attr_name_aloc:=len + 1;
1343
1344 agg_freemem(pointer(m_attr_name ) ,m_attr_name_aloc );
1345
1346 m_attr_name_len:=len;
1347
1348 end;
1349
1350 if len <> 0 then
1351 move(start^ ,m_attr_name^ ,len );
1352
1353 char_ptr(ptrcomp(m_attr_name ) + len )^:=#0;
1354
1355 end;
1356
1357 { COPY_VALUE }
1358 procedure parser.copy_value;
1359 var
1360 len : unsigned;
1361
1362 begin
1363 len:=ptrcomp(end_ ) - ptrcomp(start );
1364
1365 if (m_attr_value_len = 0 ) or
1366 (len > m_attr_value_len ) then
1367 begin
1368 agg_freemem(pointer(m_attr_value ) ,m_attr_value_aloc );
1369
1370 m_attr_value_aloc:=len + 1;
1371
1372 agg_getmem(pointer(m_attr_value ) ,m_attr_value_aloc );
1373
1374 m_attr_value_len:=len;
1375
1376 end;
1377
1378 if len <> 0 then
1379 move(start^ ,m_attr_value^ ,len );
1380
1381 char_ptr(ptrcomp(m_attr_value ) + len )^:=#0;
1382
1383 end;
1384
1385 END.
1386
1387