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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
|
<html><head><title>Anti-Grain Geometry - Anti-Grain Geometry</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<link rel="stylesheet" type="text/css" href="ddj1.agdoc_files/agg.css">
</head><body><table width="640px"><tbody><tr><td><h1>Anti-Grain Geometry<span
class="subtitle"><br>High Fidelity 2D Graphics for C++</span></h1></td></tr></tbody></table>
<table class="toc" width="640px"><tbody><tr><td>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0001"><b>Introduction</b></a></div>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0002"><b>Brief Overview of Graphic Libraries</b></a></div>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0003"><b>The power of templates in C++</b></a></div>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0004"><b>The key features of AGG</b></a></div>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0005"><b>Architecture</b></a>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0006">Pixel Format Renderers</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0007">Alpha-Mask Adaptor</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0008">Basic Renderers</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0009">Scanline Renderer</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0010">Span Generator</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0011">Scanline Rasterizer</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0012">Outline Renderers</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0013">Outline Rasterizer</a></div>
<div style="margin-left: 2em; font-size: 12px;"><a
href="#toc0014">Vertex Conversion Pipeline</a></div></div>
<div style="margin-left: 2em; padding: 3px; font-size: 14px;"><a
href="#toc0015"><b>Example</b></a></div>
</td></tr></tbody></table>
<h2>Introduction<a name="toc0001"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>In
this article I would like to introduce my work called <b><nobr>Anti-Grain</nobr>
Geometry</b> (<b>AGG</b>).
It is an Open Source, free of charge 2D graphic library, written in
industrially standard C++.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Scalable
2D vector graphics is widely used in all kinds
of applications and now the performance of modern processors
makes it affordable to use <b>high quality</b> vector graphics.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>High
quality means multilevel Anti-Aliasing and subpixel accuracy.
Subpixel accuracy is often underestimated, but in general it's very
important to have a possibility of subpixel positioning.
It's especially important to be able to set fractional line width
that can be even less than one pixel. I would say that Anti-Aliased
rendering is practically useless without subpixel accuracy.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
first question that can arise is <i>“What is this needed for?”</i>
or even <i>“Is there a need of yet another reinvention of the wheel?”</i></p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
short answer is as follows.
Yes, there are many graphic standards, protocols and libraries, but
nothing that fits all my needs. It was my main motivation to start
<b>AGG</b>, namely, my exclusive requirements. Later other people
found it very interesting too.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>You
can think of <b>AGG</b> as of a rendering library that creates raster
images in memory from some vectorial representation. But this definition
is just the first approximation. In general, you can use any part of the
library, not obligatory as a rasterizer or renderer.
<b>AGG</b> can be used in many applications where there is a need for
high
quality and fast 2D graphics. It can be GIS/cartography applications,
fancy looking graphic user interfaces, different kinds of charts and
diagrams,
CAD/CAM, and so on. Besides, <b>AGG</b> is platform independent,
lightweight,
compact, and robust It also can be perfectly used in embedded systems
and mobile devices.</p></td></tr></tbody></table>
<br><h2>Brief Overview of Graphic Libraries<a name="toc0002"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>First,
let me briefly describe the existing tools
and libraries that can be used as 2D rendering engines.
The fastest software 2D renderer that produces images of
appropriate quality is well known Macromedia Flash viewer.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
other one is SVG standard from W3C committee,
<a href="http://www.w3.org/Graphics/SVG"><img
src="ddj1.agdoc_files/link.gif" border="0">http://www.w3.org/Graphics/SVG</a>/
for which we can find a number of
viewers (the most advanced one is Adobe SVG, <a
href="http://www.adobe.com/svg"><img src="ddj1.agdoc_files/link.gif"
border="0">http://www.adobe.com/svg</a>/).
But they both are “end-user” applications and cannot be used as
rendering libraries available from C++. SVG would be the best 2D
standard if there were available implementations that support the
whole SVG specification and provide appropriate quality, performance,
and consume reasonable amount of memory.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
most widely used industrial libraries available from many languages
are OpenGL, Apple Quartz and GDI+.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>OpenGL
is good and standard, but the quality of 2D graphics is very poor.
It's perfectly “hardware accelerated”, but there are no available
accelerators that produce any valuable quality of 2D graphics.
Alex Eddy has performed a research that clearly shows the lack of the
quality in most popular OpenGL accelerators.
<a href="http://homepage.mac.com/arekkusu/bugs/invariance"><img
src="ddj1.agdoc_files/link.gif" border="0">http://homepage.mac.com/arekkusu/bugs/invariance</a>/</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>GDI+
has also very poor quality of rendering, it's slow and
has too many bugs to be used in practice, not to mention
that it's available only on Microsoft Windows platform.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Apple
Quartz has the most advanced API and quality, but it's available
only on Apple computers.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>There
are two Open Source libraries, LibArt by Raph Levien
<a href="http://www.levien.com/libart"><img
src="ddj1.agdoc_files/link.gif" border="0">http://www.levien.com/libart</a>/
and Cairo Graphics, <a href="http://cairographics.org/"><img
src="ddj1.agdoc_files/link.gif" border="0">http://cairographics.org</a>/.
LibArt
development was abandoned some time ago, and the problems with
numerical stability don't allow you to use it in practice.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Cairo
Graphics is in active development and it is definitely worth
considering. Still, Cairo Graphics has certain limitations, mostly
because of its hardcoded rendering model.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Besides,
LibArt and Cairo Graphics are released under LGPL license
which is too restrictive in many cases.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Another
very good library is called ImageMagick (<a
href="http://www.imagemagick.org/"><img src="ddj1.agdoc_files/link.gif"
border="0">http://www.imagemagick.org</a>),
but its primary purpose is image processing.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
general problem of all existing graphic libraries and
tools is that they are too restrictive. They all are “black boxes”,
even open source ones.
I feel I need to explain this statement. Theoretically you can modify
an open source library in any way you want (assuming that it doesn't
contradict the license). But as soon as you modify a single byte you
create another branch of the library and have to take care of merging
your modifications with new versions from the authors. After some point
it becomes a nightmare. In my opinion the real “openness” of the library
appears when you can extend its functionality without having to modify a
single character in the distributed code. C++ allows us to do that.</p></td></tr></tbody></table>
<br><h2>The power of templates in C++<a name="toc0003"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p><b>AGG</b>
uses C++ class and function templates very actively. The same
functionality can be achieved using dynamic polymorphism, that is,
classes with overridden virtual functions. But the templates allow
you to optimize the code having very flexible and convenient design.
Polymorphic classes work quite well until a certain level of
detailization.
A typical task in vector graphics is to have a vertex conversion
pipeline.
For example, it can be some source of vectorial commands like
MoveTo/LineTo/CurveTo, then there is a converter that “flattens” curves,
then a stroke generator, then affine transformer and so on. In most
graphic
libraries the pipelines are hardcoded.
If we want it to be more flexible, that is, if we want to construct
custom
pipelines, you will have to use polymorphism. It's appropriate to have
one virtual call per vertex but can be too expensive to have a virtual
call per vertex per pipeline element. Another approach is to have
“static” polymorphism, that is, to use class templates. It does not
directly
allow you to construct pipelines dynamically, at run time, but in most
cases
you don't really need it. Most probably you only want to have a
possibility to
construct pipelines at compile time, and if you really need dynamic
polymorphism it's very easy to write polymorphic wrappers whose
interfaces
are compatible with what the templates expect. So that, in <b>AGG</b>
it's you who has full control upon the functionality and performance.
The very same approach is used in the raster part of the rendering
pipeline. You can write your own low level renderers that work with
different color spaces, your own gradient functions, your own span
generators, and so on. An implementation based on classical
polymorphic classes would cost you several virtual calls per each pixel,
while templates allow you to do so for no extra overhead.</p></td></tr></tbody></table>
<br><h2>The key features of AGG<a name="toc0004"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Below
I just enumerate the key features of the library, so that you
could have a general idea of where it can be useful for you.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p></p><ul
type="disc">
<li>Fast and high quality polygon rasterizer with 256 levels of
Anti-Aliasing. The non-zero and even-odd fill rules are applicable.</li>
<li>Customizable vector and raster pipelines.</li>
<li>Arbitrary gradients and Gouraud shading.</li>
<li>Image affine transformations with different kinds of interpolation,
from simple bilinear to high degree Lancosz and Blackman ones.</li>
<li>Pattern fill with arbitrary affine and perspective transformations
(can be used for texturing).</li>
<li>Perspective and bilinear transformations of vector and image data.</li>
<li>Stroke generator with different types of line joins and line caps.</li>
<li>Dash line generator.</li>
<li>Markers, such as arrowheads/arrow tails.</li>
<li>Fast vectorial polygon clipper to a rectangle.</li>
<li>Low-level clipping to multiple rectangular regions.</li>
<li>Alpha-Masking.</li>
<li>Fast Anti-Aliased line algorithm.</li>
<li>Arbitrary images as line patterns.</li>
<li>Rendering in separate color channels.</li>
<li>Boolean polygon operations (and, or, xor, sub) based on Alan Murta's
General Polygon Clipper.</li>
<li>Scanline Boolean Algebra. Performs boolean operations on rasterized
scanline shapes. Works in average 5-10 times faster than General
Polygon Clipper</li>
<li>Text support using FreeType library (<a
href="http://www.freetype.org/"><img src="ddj1.agdoc_files/link.gif"
border="0">http://www.freetype.org</a>) and
Windows API (<code>GetGlyphOutline()</code>).</li>
<li>Arbitrary non-linear transformations.</li></ul><p></p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
library and examples were successfully compiled and tested on the
following
platforms:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p></p><ul
type="disc">
<li>Microsoft Windows (95,98,NT4,2000,XP,2003). Compilers Microsoft
Visual C++
v5, v6, v7, Intel C++ v6, GNU C++ from v2.96 to v3.4.0</li>
<li>Linux, GNU C++</li>
<li>SunOS</li>
<li>SGI IRIX64</li>
<li>MacOS 9, MacOS X, Compilers Metrowerks CodeWarrior 8.3, GNU C++</li>
<li>QNX</li>
<li>BeOS</li>
<li>AmigaOS</li></ul><p></p></td></tr></tbody></table>
<br><h2>Architecture<a name="toc0005"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p><b>AGG</b>
doesn't have any predefined rendering model, it's like
"a tool to create other tools". The architecture and the
philosophy of the library is determined by the main goal
of its creation. The goal is to have a set of 2D tools united
with a common idea. You and only you define the resulting architecture
and
rendering model. <b>AGG</b> is open and flexible but not that
obvious and easy to use as other "conventional" libraries like
GDI+ or Quartz.
Besides, it makes sense to mention that <b>AGG</b> has some
restrictions too, but it's only because some algorithms and
design solutions are not yet implemented.
In particular, <b>AGG</b> currently supports only path-based model,
and there is no straight way to render graphics from Macromedia
Flash format. Flash is edge-based, so, you can render a multi-color
scene in one pass. In some cases it's better, but in general it's
more restrictive and more difficult in use. Currently we can say
that <b>AGG</b> is more SVG centric rather than Flash centric.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
following picture represents a typical architecture of a
rendering engine based on <b>AGG</b>.
</p></td></tr></tbody></table><table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/architecture.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<h3>Pixel Format Renderers<a name="toc0006"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Pixel
format renderers perform basic alpha-blending operations
in the resulting frame buffer. They do not perform any clipping,
thus, it's unsafe to use them directly, so, if the coordinates are
out of range it can result in undefined behaviour, most probably
segmentation fault. It doesn't mean that the design is bad, it
means that you can write your own color space and pixel format
renderers, and you don't need to worry about clipping because
it is already provided on a higher level.
It's quite possible to write a renderer to work in another color
space, say, XYZ or Lab, and define your own color type.
These additions will not affect anyhow the other parts of <b>AGG</b>.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Currently
<b>AGG</b> provides 15, 16, 24, and 32 bits RGB and RGBA
pixel formats.</p></td></tr></tbody></table>
<h3>Alpha-Mask Adaptor<a name="toc0007"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Alpha-mask
adaptor allows you to use an additional
transparency channel when rendering. Strictly speaking
there can be any kind of an adaptor. Alpha-mask is just
an example of it.</p></td></tr></tbody></table>
<h3>Basic Renderers<a name="toc0008"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
basic renderer (<a
href="http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html#renderer_base">renderer_base</a>)
accepts a pixel format
renderer as its template argument and it's main purpose is
level clipping. It provides essentially the same interface as
pixel format renderers.
Also, there is <a
href="http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html#renderer_mclip">renderer_mclip</a>
which is the same in use
but it can perform clipping to a number of arbitrary
rectangles.</p></td></tr></tbody></table>
<h3>Scanline Renderer<a name="toc0009"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>One
of the key concepts in <b>AGG</b> is the scanline. The scanline
is a container that consist of a number of horizontal spans that
can carry Anti-Aliasing information. The scanline
renderer decomposes provided scanline into a number of spans
and in simple cases (like solid fill) calls basic renderer.
In more complex cases it can call span generator.</p></td></tr></tbody></table>
<h3>Span Generator<a name="toc0010"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Span
Generator is used in all cases that are more difficult
than solid fill. It's a common mechanism that can produce
any kind of color spans, such as gradients, Gouraud shading,
image transformations, pattern fill, and so on. Particularly
this mechanism allows you to transform a part of the image
bounded with an arbitrary shape with Anti-Aliased edges.
The span generator can consist of the whole pipeline,
for example, there can be an image transformer plus alpha
(transparency) gradient.</p></td></tr></tbody></table>
<h3>Scanline Rasterizer<a name="toc0011"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
scanline rasterizer accepts a number of arbitrary polygons
as its input and produces anti-aliased scanlines. This is
the primary rendering technique in <b>AGG</b>. It means that
the only shape that can be rasterized is a polygon (poly-polygon
to be exact). If you need to draw a line you need to calculate
at least four points that define its outline. At the first sight
it can seem like an overkill, but it isn't. The main point is
that the algorithm uses subpixel accuracy and correctly rasterizes
any shapes, even when a single pixel is crossed by the edges many
times. It allows the result to remain consistent regardless
of the scale and the algorithm guarantees that there will be
no defects.
</p></td></tr></tbody></table><table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/subpixel_accuracy2.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
initial idea was taken from the rasterizer
of FreeType font engine by David Turner (<a
href="http://www.freetype.org/"><img src="ddj1.agdoc_files/link.gif"
border="0">http://www.freetype.org</a>).
David kindly allowed me to rewrite the rasterizer in C++ and
release the code independently.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Such
kind of the design (rasterizer <span class="larger">→</span>
scanline_renderer <span class="larger">→</span> base_renderer <span
class="larger">→</span> pixel_format)
allows us to implement very interesting algorithms, for example,
renderers optimized for LCD color triplets (like Microsoft ClearType)
and
it will be applicable to all primitives, not only for text.</p></td></tr></tbody></table>
<h3>Outline Renderers<a name="toc0012"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>This
is yet another algorithm of drawing Anti-Aliased lines.
The use of the algorithm is more limited than the scanline rasterizer,
but it also has many advantages.
</p><ul type="disc">
<li>It works about 2…3 times faster than the scanline rasterizer.</li>
<li>It allows you to have the Anti-Aliased area of any profile and
width.</li>
<li>The Anti-Aliasing algorithm is distance-based, unlike area-based
in the scanline rasterizer. In most cases it allows you to produce
better visual result.</li>
<li>Most importantly, the algorithm allows you to use an arbitrary
image as the line pattern.
This is the key capability when rendering high quality
geographic maps.
In general we can say that it's dedicated for fast drawing of
relatively thin polylines.</li></ul><p></p></td></tr></tbody></table>
<h3>Outline Rasterizer<a name="toc0013"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
outline rasterizer is just an adaptor that unifies the use of
the solid outline rasterizer and the one with image patterns.</p></td></tr></tbody></table>
<h3>Vertex Conversion Pipeline<a name="toc0014"></a></h3>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
vertex pipeline consists of a number of converters.
Each converter accepts an abstract Vertex Source as the input
and works as another Vertex Source. Usually graphic libraries
have hardcoded pipelines, typically they consist of a curve
decomposer (that converts curves to a number of short line segments),
affine transformer, dash generator, stroke generator,
and polygon clipper.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>In <b>AGG</b>
you can construct custom pipelines and there can be as many
pipelines as you need. Besides, the pipelines can have branches, in
other words you can extract vertices from any point of the pipeline.
The most important thing is you can combine the converters as
you want and get quite different results.</p></td></tr></tbody></table>
<br><h2>Example<a name="toc0015"></a></h2>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
example below demonstrates how to create basic types needed
for rendering and the effect of the pipelines. To keep the things
as simple as possible it will be a console application that
produces a raster file (result.ppm) that has a very simple format.
You can display this files with many kinds of viewers, for example,
IrfanView (<a href="http://www.irfanview.com/"><img
src="ddj1.agdoc_files/link.gif" border="0">http://www.irfanview.com</a>/).</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Also
I'd like to mention that it's not necessary for <b>AGG</b> to have
any building environment. It has automake/autoconfig files, but you
can do without them. Since <b>AGG</b> doesn't depend on any
platform-specific
tools you can just include all necessary source files into your
project/makefile and they will perfectly compile and work.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p><b>AGG</b>
is written according to the “Just Compile It” principle.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Type
(or take from the CD) the following code and name the file
<code>example_pipeline1.cpp</code>:</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre><span class="kw2">#include</span> <span class="op"><</span>stdio<span class="op">.</span>h<span class="op">></span>
<span class="kw2">#include</span> <span class="op"><</span>string<span class="op">.</span>h<span class="op">></span>
<span class="kw2">#include</span> <span class="str">"agg_pixfmt_rgb24.h"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_renderer_base.h.html">agg_renderer_base.h</a>"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html">agg_renderer_scanline.h</a>"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_scanline_u.h.html">agg_scanline_u.h</a>"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_rasterizer_scanline_aa.h.html">agg_rasterizer_scanline_aa.h</a>"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html">agg_path_storage.h</a>"</span>
<span class="kw1">enum</span>
<span class="op">{</span>
frame_width <span class="op">=</span> <span class="num">200</span><span class="op">,</span>
frame_height <span class="op">=</span> <span class="num">200</span>
<span class="op">}</span><span class="op">;</span>
<span class="rem">// Writing the buffer to a .PPM file, assuming it has</span>
<span class="rem">// RGB-structure, one byte per color component</span>
<span class="rem">//--------------------------------------------------</span>
<span class="kw1">bool</span> write_ppm<span class="op">(</span><span class="kw1">const</span> <span class="kw1">unsigned</span> <span class="kw1">char</span><span class="op">*</span> buf<span class="op">,</span>
<span class="kw1">unsigned</span> width<span class="op">,</span>
<span class="kw1">unsigned</span> height<span class="op">,</span>
<span class="kw1">const</span> <span class="kw1">char</span><span class="op">*</span> file_name<span class="op">)</span>
<span class="op">{</span>
FILE<span class="op">*</span> fd <span class="op">=</span> fopen<span class="op">(</span>file_name<span class="op">,</span> <span class="str">"wb"</span><span class="op">)</span><span class="op">;</span>
<span class="kw1">if</span><span class="op">(</span>fd<span class="op">)</span>
<span class="op">{</span>
fprintf<span class="op">(</span>fd<span class="op">,</span> <span class="str">"P6 %d %d 255 "</span><span class="op">,</span> width<span class="op">,</span> height<span class="op">)</span><span class="op">;</span>
fwrite<span class="op">(</span>buf<span class="op">,</span> <span class="num">1</span><span class="op">,</span> width <span class="op">*</span> height <span class="op">*</span> <span class="num">3</span><span class="op">,</span> fd<span class="op">)</span><span class="op">;</span>
fclose<span class="op">(</span>fd<span class="op">)</span><span class="op">;</span>
<span class="kw1">return</span> <span class="kw1">true</span><span class="op">;</span>
<span class="op">}</span>
<span class="kw1">return</span> <span class="kw1">false</span><span class="op">;</span>
<span class="op">}</span>
<span class="kw1">int</span> <span class="kw1">main</span><span class="op">(</span><span class="op">)</span>
<span class="op">{</span>
<span class="rem">// Allocate the frame buffer (in this case "manually")</span>
<span class="rem">// and create the rendering buffer object</span>
<span class="kw1">unsigned</span> <span class="kw1">char</span><span class="op">*</span> buffer <span class="op">=</span> <span class="kw1">new</span> <span class="kw1">unsigned</span> <span class="kw1">char</span><span class="op">[</span>frame_width <span class="op">*</span> frame_height <span class="op">*</span> <span class="num">3</span><span class="op">]</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html#rendering_buffer">rendering_buffer</a> rbuf<span class="op">(</span>buffer<span class="op">,</span>
frame_width<span class="op">,</span>
frame_height<span class="op">,</span>
frame_width <span class="op">*</span> <span class="num">3</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Create Pixel Format and Basic renderers</span>
<span class="rem">//--------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_pixfmt_rgb.h.html#pixfmt_rgb24">pixfmt_rgb24</a> pixf<span class="op">(</span>rbuf<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html#renderer_base">renderer_base</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_pixfmt_rgb.h.html#pixfmt_rgb24">pixfmt_rgb24</a><span class="op">></span> ren_base<span class="op">(</span>pixf<span class="op">)</span><span class="op">;</span>
<span class="rem">// At last we do some very simple things, like clear</span>
<span class="rem">//--------------------</span>
ren_base<span class="op">.</span>clear<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">255</span><span class="op">,</span> <span class="num">250</span><span class="op">,</span> <span class="num">230</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Create Scanline Container, Scanline Rasterizer,</span>
<span class="rem">// and Scanline Renderer for solid fill.</span>
<span class="rem">//--------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_scanline_u.h.html#scanline_u8">scanline_u8</a> sl<span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_rasterizer_scanline_aa.h.html#rasterizer_scanline_aa">rasterizer_scanline_aa</a><span class="op"><</span><span class="op">></span> ras<span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#renderer_scanline_aa_solid">renderer_scanline_aa_solid</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/doc/basic_renderers/basic_renderers.agdoc.html#renderer_base">renderer_base</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_pixfmt_rgb.h.html#pixfmt_rgb24">pixfmt_rgb24</a><span class="op">></span> <span class="op">></span> ren_sl<span class="op">(</span>ren_base<span class="op">)</span><span class="op">;</span>
<span class="rem">// Create Vertex Source (path) object, in our case it's</span>
<span class="rem">// <a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a> and form the path.</span>
<span class="rem">//--------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a> path<span class="op">;</span>
path<span class="op">.</span>remove_all<span class="op">(</span><span class="op">)</span><span class="op">;</span> <span class="rem">// Not obligatory in this case</span>
path<span class="op">.</span>move_to<span class="op">(</span><span class="num">10</span><span class="op">,</span> <span class="num">10</span><span class="op">)</span><span class="op">;</span>
path<span class="op">.</span>line_to<span class="op">(</span>frame_width<span class="op">-</span><span class="num">10</span><span class="op">,</span> <span class="num">10</span><span class="op">)</span><span class="op">;</span>
path<span class="op">.</span>line_to<span class="op">(</span>frame_width<span class="op">-</span><span class="num">10</span><span class="op">,</span> frame_height<span class="op">-</span><span class="num">10</span><span class="op">)</span><span class="op">;</span>
path<span class="op">.</span>line_to<span class="op">(</span><span class="num">10</span><span class="op">,</span> frame_height<span class="op">-</span><span class="num">10</span><span class="op">)</span><span class="op">;</span>
path<span class="op">.</span>line_to<span class="op">(</span><span class="num">10</span><span class="op">,</span> frame_height<span class="op">-</span><span class="num">20</span><span class="op">)</span><span class="op">;</span>
path<span class="op">.</span><a href="http://www.antigrain.com/__code/include/agg_curves.h.html#curve4">curve4</a><span class="op">(</span>frame_width<span class="op">-</span><span class="num">20</span><span class="op">,</span> frame_height<span class="op">-</span><span class="num">20</span><span class="op">,</span>
frame_width<span class="op">-</span><span class="num">20</span><span class="op">,</span> <span class="num">20</span><span class="op">,</span>
<span class="num">10</span><span class="op">,</span> <span class="num">20</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
<span class="rem">// Set the color and render the scanlines</span>
<span class="rem">//-----------------------</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">60</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">// Write the buffer to result.ppm and liberate memory.</span>
<span class="rem">//-----------------------</span>
write_ppm<span class="op">(</span>buffer<span class="op">,</span> frame_width<span class="op">,</span> frame_height<span class="op">,</span> <span class="str">"result.ppm"</span><span class="op">)</span><span class="op">;</span>
<span class="kw1">delete</span> <span class="op">[</span><span class="op">]</span> buffer<span class="op">;</span>
<span class="kw1">return</span> <span class="num">0</span><span class="op">;</span>
<span class="op">}</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Then
you can compile and link this code with <b>AGG</b>: using GNU C++:</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre>g++ -I/agg2/include example_pipeline1.cpp
/agg2/src/agg_rasterizer_scanline_aa.cpp
/agg2/src/agg_path_storage.cpp
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_bezier_arc.cpp.html">agg_bezier_arc.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_trans_affine.cpp.html">agg_trans_affine.cpp</a>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>or
Microsoft C++, v6 or later:</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre>cl -I/agg2/include example_pipeline1.cpp
/agg2/src/agg_rasterizer_scanline_aa.cpp
/agg2/src/agg_path_storage.cpp
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_bezier_arc.cpp.html">agg_bezier_arc.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_trans_affine.cpp.html">agg_trans_affine.cpp</a>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Of
course, you will need
to replace <code>“/agg2/”</code> to the actual path to the library.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
result.ppm should be as follows:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline1.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>You
can think that this code is too complex to produce this
simplest figure, but let us look at the following changes.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Currently
we have a null-pipeline, that is an empty one. In this case
all the points are interpreted like move-to/line-to commands. This is
why the call of <code>path.<a
href="http://www.antigrain.com/__code/include/agg_curves.h.html#curve4">curve4</a>()</code>
does not have any effect.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
first modification is to add the curve converter
(curve flattener in other words), that is, the one that decomposes
Bezier
curves to a number of short line segments (<code>example_pipeline2.cpp</code>):</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Add <code>#include
"<a
href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html">agg_conv_curve.h</a>"</code>
and change the following:
</p></td></tr></tbody></table><table width="640px" border="0"
cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> curve<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
ras<span class="op">.</span>add_path<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Also
add /agg2/src/<a
href="http://www.antigrain.com/__code/src/agg_curves.cpp.html">agg_curves.cpp</a>
to the compile list and see the result:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline2.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Then
let as draw a stroke (<code>example_pipeline3.cpp</code>):</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Add <code>#include
"<a
href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html">agg_conv_stroke.h</a>"</code>
and change the following:
</p></td></tr></tbody></table><table width="640px" border="0"
cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> curve<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> stroke<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
stroke<span class="op">.</span>width<span class="op">(</span><span class="num">6</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
ras<span class="op">.</span>add_path<span class="op">(</span>stroke<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Add
/agg2/src/<a
href="http://www.antigrain.com/__code/src/agg_vcgen_stroke.cpp.html">agg_vcgen_stroke.cpp</a>
to the compile list. The result is:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline3.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Of
course, you can set line width, line cap, and line join. Our polygon
is not closed, to close it just call:</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre> path<span class="op">.</span>close_polygon<span class="op">(</span><span class="op">)</span><span class="op">;</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline31.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>I
hope you get the idea of how to draw a filled polygon with a stroke.
Just in case let us see this code:</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> curve<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> stroke<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
stroke<span class="op">.</span>width<span class="op">(</span><span class="num">6</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the fill color and render the polygon:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">160</span><span class="op">,</span> <span class="num">180</span><span class="op">,</span> <span class="num">80</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the stroke color and render the stroke:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>stroke<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">100</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline4.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Here
we can see that the pipeline consists of two consecutive
converters (curve and stroke) and we can use both of them in the
very same way.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
next step is adding affine transformations and the main
question is where to add them. The answer is it depends.
You can add the affine transformer before the curve converter,
so that it will process very few points, but the stroke converter
will generate a stroke as if it were the original shape.
Let us see (<code>example_pipeline5.cpp</code>).</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
pipeline is:
</p></td></tr></tbody></table><table width="640px" border="0"
cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a> matrix<span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span><span class="op">-</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> <span class="op">-</span>frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_rotation">trans_affine_rotation</a><span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_basics.h.html#deg2rad">deg2rad</a><span class="op">(</span><span class="num">35</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_scaling">trans_affine_scaling</a><span class="op">(</span><span class="num">0</span><span class="op">.</span><span class="num">4</span><span class="op">,</span> <span class="num">0</span><span class="op">.</span><span class="num">75</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">,</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> trans<span class="op">(</span>path<span class="op">,</span> matrix<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">,</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> <span class="op">></span> curve<span class="op">(</span>trans<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> <span class="op">></span> <span class="op">></span> stroke<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
stroke<span class="op">.</span>width<span class="op">(</span><span class="num">6</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the fill color and render the polygon:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">160</span><span class="op">,</span> <span class="num">180</span><span class="op">,</span> <span class="num">80</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the stroke color and render the stroke:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>stroke<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">100</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>And
the result:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline5.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Now
let us modify the pipeline in such a way that the affine
transformer would be after the stroke generator (<code>example_pipeline6.cpp</code>)</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a> matrix<span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span><span class="op">-</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> <span class="op">-</span>frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_rotation">trans_affine_rotation</a><span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_basics.h.html#deg2rad">deg2rad</a><span class="op">(</span><span class="num">35</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_scaling">trans_affine_scaling</a><span class="op">(</span><span class="num">0</span><span class="op">.</span><span class="num">4</span><span class="op">,</span> <span class="num">0</span><span class="op">.</span><span class="num">75</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> curve<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> trans_curve<span class="op">(</span>curve<span class="op">,</span> matrix<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> stroke<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> trans_stroke<span class="op">(</span>stroke<span class="op">,</span> matrix<span class="op">)</span><span class="op">;</span>
stroke<span class="op">.</span>width<span class="op">(</span><span class="num">6</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the fill color and render the polygon:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>trans_curve<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">160</span><span class="op">,</span> <span class="num">180</span><span class="op">,</span> <span class="num">80</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the stroke color and render the stroke:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>trans_stroke<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">100</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline6.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Here
we actually have two pipelines, path<span class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span
class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a>,
the other one is path<span class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span
class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span
class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a>.
At the first sight it looks like now the stroke is thinner. But
it's more complex than that. Note that the width of the stroke is
not uniform. I intentionally set different scaling coefficients
by X and Y to demonstrate that you can control the result by
changing the order of the converters.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Note
that the pipeline branches after <a
href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a>.
For the sake
of efficiency it would be better to keep the fill pipeline as it was
in the previous example (path<span class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span
class="larger">→</span><a
href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a>).
This code
just demonstrates a possibility to have complex pipelines.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>In
the last example let us demonstrate some non-linear transformation
effects. It will be a circular warp magnifier. But since the
transformation is non-linear, we can't just transform vertices, we need
to prepare the initial path in such a way that the initial vectors
would consist of many short line segments. Of course, we could do
that when adding vertices to the path storage, but there is a better
way. We use an additional intermediate converter that segments long
vectors. It's <a
href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a>.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>We
also need to add two include files:
</p></td></tr></tbody></table><table width="640px" border="0"
cellpadding="0" cellspacing="0"><tbody><tr><td><pre><span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html">agg_conv_segmentator.h</a>"</span>
<span class="kw2">#include</span> <span class="str">"<a href="http://www.antigrain.com/__code/include/agg_trans_warp_magnifier.h.html">agg_trans_warp_magnifier.h</a>"</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>And
the pipelines look as follows (<code>example_pipeline7.cpp</code>):</p></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><pre> <span class="rem">// The vectorial pipeline</span>
<span class="rem">//-----------------------</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a> matrix<span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span><span class="op">-</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> <span class="op">-</span>frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_rotation">trans_affine_rotation</a><span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_basics.h.html#deg2rad">deg2rad</a><span class="op">(</span><span class="num">35</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_scaling">trans_affine_scaling</a><span class="op">(</span><span class="num">0</span><span class="op">.</span><span class="num">3</span><span class="op">,</span> <span class="num">0</span><span class="op">.</span><span class="num">45</span><span class="op">)</span><span class="op">;</span>
matrix <span class="op">*=</span> agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine_translation">trans_affine_translation</a><span class="op">(</span>frame_width<span class="op">/</span><span class="num">2</span><span class="op">,</span> frame_height<span class="op">/</span><span class="num">2</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_warp_magnifier.h.html#trans_warp_magnifier">trans_warp_magnifier</a> lens<span class="op">;</span>
lens<span class="op">.</span>center<span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">100</span><span class="op">)</span><span class="op">;</span>
lens<span class="op">.</span>magnification<span class="op">(</span><span class="num">3</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
lens<span class="op">.</span>radius<span class="op">(</span><span class="num">18</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> curve<span class="op">(</span>path<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> segm<span class="op">(</span>curve<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> trans_curve<span class="op">(</span>segm<span class="op">,</span> matrix<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_warp_magnifier.h.html#trans_warp_magnifier">trans_warp_magnifier</a><span class="op">></span> trans_warp<span class="op">(</span>trans_curve<span class="op">,</span> lens<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> <span class="op">></span> stroke<span class="op">(</span>segm<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> <span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span> trans_stroke<span class="op">(</span>stroke<span class="op">,</span> matrix<span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_transform.h.html#conv_transform">conv_transform</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_stroke.h.html#conv_stroke">conv_stroke</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_segmentator.h.html#conv_segmentator">conv_segmentator</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_conv_curve.h.html#conv_curve">conv_curve</a><span class="op"><</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_path_storage.h.html#path_storage">path_storage</a><span class="op">></span> <span class="op">></span> <span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_affine.h.html#trans_affine">trans_affine</a><span class="op">></span><span class="op">,</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_trans_warp_magnifier.h.html#trans_warp_magnifier">trans_warp_magnifier</a><span class="op">></span> trans_warp_stroke<span class="op">(</span>trans_stroke<span class="op">,</span> lens<span class="op">)</span><span class="op">;</span>
stroke<span class="op">.</span>width<span class="op">(</span><span class="num">6</span><span class="op">.</span><span class="num">0</span><span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the fill color and render the polygon:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>trans_warp<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">160</span><span class="op">,</span> <span class="num">180</span><span class="op">,</span> <span class="num">80</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">// Set the stroke color and render the stroke:</span>
<span class="rem">//-----------------------</span>
ras<span class="op">.</span>add_path<span class="op">(</span>trans_warp_stroke<span class="op">)</span><span class="op">;</span>
ren_sl<span class="op">.</span>color<span class="op">(</span>agg::<a href="http://www.antigrain.com/__code/include/agg_color_rgba.h.html#rgba8">rgba8</a><span class="op">(</span><span class="num">120</span><span class="op">,</span> <span class="num">100</span><span class="op">,</span> <span class="num">0</span><span class="op">)</span><span class="op">)</span><span class="op">;</span>
agg::<a href="http://www.antigrain.com/__code/include/agg_renderer_scanline.h.html#render_scanlines">render_scanlines</a><span class="op">(</span>ras<span class="op">,</span> sl<span class="op">,</span> ren_sl<span class="op">)</span><span class="op">;</span>
<span class="rem">//-----------------------</span>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
compilation command line is:
</p></td></tr></tbody></table><table width="640px" border="0"
cellpadding="0" cellspacing="0"><tbody><tr><td><pre>g++ -I/agg2/include example_pipeline7.cpp
/agg2/src/agg_rasterizer_scanline_aa.cpp
/agg2/src/agg_path_storage.cpp
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_bezier_arc.cpp.html">agg_bezier_arc.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_trans_affine.cpp.html">agg_trans_affine.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_curves.cpp.html">agg_curves.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_vcgen_stroke.cpp.html">agg_vcgen_stroke.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_vpgen_segmentator.cpp.html">agg_vpgen_segmentator.cpp</a>
/agg2/src/<a href="http://www.antigrain.com/__code/src/agg_trans_warp_magnifier.cpp.html">agg_trans_warp_magnifier.cpp</a>
</pre></td></tr></tbody></table><font style="margin-left: 1em;"><i></i></font>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
result:
</p></td></tr></tbody></table><table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/example_pipeline7.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>These
examples demonstrate the main principle of <b>AGG</b> design, that is
that you have full control upon your rendering model and required
capabilities. The declarations can look too complex, but first,
they can be simplified with the use of <code>typedef</code>s, and
second,
they usually are not seen outside. You just create a problem oriented
wrapper once and use it as a conventional graphic library.
The pipelines that support capabilities of SVG, GDI+, or say,
PDF are very simple. The last example just demonstrates that
it's very easy to extend the functionality. In the examples
the pipeline is defined statically, at the compile time, which
is suitable in most cases. But the template mechanism allows you
to write simple polymorphic wrappers and construct the pipelines
dynamically, at run-tume.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
raster pipelines are organized in a similar way, but they are
usually much simpler. After the vectorial shape is rasterized you can
do the following:</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p></p><ul
type="disc">
<li>Fill the shape with a solid color and possible transparency.</li>
<li>Fill with an arbitrary gradient. All possible transformations
are applicable to the gradients as well.</li>
<li>Fill the shape with a transformed image. There many different
Anti-Aliasing filter are available, from simple bilinear to
high degree Lancosz and Blackman ones.</li>
<li>Fill the shape with an arbitrary pattern.</li>
<li>Apply an alpha-mask.</li>
<li>Apply a number of Scanline Boolean Algebra operations, such as,
Intersection, Union, Difference, and XOR between two or more
scanline shapes.</li></ul><p></p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>The
number of possibilities is practically endless, and the point
is that you can always write your own algorithms and span
generators and insert them into the pipeline.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p><b>AGG</b>
has many other interesting algorithms, in particular, using
raster images as line patterns. This is a very powerful mechanism
for cartography and similar applications and I haven't seen
any valuable implementation of it so far.
</p></td></tr></tbody></table><table width="640px"><tbody><tr><td><center><img
src="ddj1.agdoc_files/line_patterns.gif" title="" border="0"><br><i></i></center></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>Currently
<b>AGG</b> is in active development, but its main interfaces
are pretty much stabilized.</p></td></tr></tbody></table>
<table width="640px"><tbody><tr><td style="text-align: justify;"><p>You
can find many other examples, including multi-platform
interactive ones on the Antigrain.com web site <a
href="http://antigrain.com/"><img src="ddj1.agdoc_files/link.gif"
border="0">http://antigrain.com</a>.
</p></td></tr></tbody></table><br><table style="margin: 0px;"
height="1px" width="640px" bgcolor="#583927" border="0" cellpadding="0"
cellspacing="0"><tbody><tr><td></td></tr></tbody></table>
<table width="640px" border="0" cellpadding="0" cellspacing="0">
<tbody><tr><td><center><span class="authors">
Copyright <span class="larger">©</span> 2002-2006
<a href="http://www.antigrain.com/mcseem/index.html"><b>Maxim Shemanarev</b></a>
</span></center></td></tr>
<tr><td><center><span class="authors">
Web Design and Programming
<a href="http://www.antigrain.com/mcseem/index.html"><b>Maxim Shemanarev</b></a>
</span></center></td></tr>
</tbody></table>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body></html>
|