News and History

In the article I tried to summarize my experience and observations
concerning the situation with text rasterization in Windows and Linux.
The article also contains demo applications to play with my method
of RGB sub-pixel text rendering. I admit some statements may sound
questionable, so, I appreciate any comments, criticism, and discussions.
Please post your comments to the Mailing List.

I expect to renew active development of AGG in September, 2007.

October 23, 2006 Changing the license

Released version 2.5 under the GNU GPL license. Essentially it's the same as
agg-2.4, so, no efforts to migrate are necessary. However, from now on
all changes and bug fixes will be done in agg-2.5. I do not expect any massive
changes in agg-2.5, only minor ones. Most probably Version 2.6 will have some
differences, in particular, I'm going to make the use of floating point
arithmetic more flexible.

Current AGG users who are willing to continue using AGG under the old terms
and conditions are encouraged to contact me and I will consider their requests.

AGG v 2.4 remains available under the old terms and conditions.

June 19, 2006 Update.

Radial gradient functoin with focal point is rewritten. Now it
works about two times faster than the old one. See gradient_radial_focus.

New utility class template is added, gradient_lut. It allows you to easily
create a color LUT for gradients from a set of color stops as they are
defined in SVG, section Gradients and Patterns.

New Demo gradient_focal.cpp. It's evolved from testing code and
performance measurements. In particular, it shows you how to calculate
the parameters of a radial gradient with a separate focal point, considering
arbitrary affine transformations. In this example the window resizing
transformations are taken into account. It also demonstrates the use case
of gradient_lut and gamma correction.

New class template row_accessor is added, thanks to David Piepgrass.
Instead of keeping the pointers to each row it calculates the pixel
addresses directly, performing one extra multiplication. It doesn't affect
the performance on regular rendering operations, but still there's some
slowdown on massive pixel operations, such as Bresenham line, blur, image
transformations with nearest neighbor and bilinear filters. So, now you can
choose between row_ptr_cache and row_accessor. There's a typedef in
renderin_buffer.h that can be redefined by default in agg_config.h. This
file contains some user definitions and supposed to be fully replaced by
your own if necessary.
The rendering_buffer is used only in short hand typedefs like pixfmt_rgba32.
In your applications you can use both, row_ptr_cache and row_accessor,
depending on your needs. The tip is: for the target rendering buffer you can
freely use row_accessor, for stack_blur, recursive_blur and source images
in image transformers it makes sense to use row_ptr_cache sometimes.
Remember, you can attach as many row accessors to one physical buffer
as you need and as many pixel formats as you need.

Added word explicit to all constructors that have one argument and
store a pointer in the object. It prevents from implicit type casting via
temporary objects that potentially results in undefined behavior.
Thanks to Vladimir Alemasov for reporting the problem.

June 11, 2006 Update and new demo examples.

New Demo rasterizer_compound.cpp demonstrates a rather advanced
technique of using
the compound rasterizer. The idea is you assign styles to the polygons
(left=style, right=-1) and rasterize this "multi-styled" compound shape
as a whole. If the polygons in the shape overlap, the greater styles have
higher priority. That is, the result is as if greater styles were painted
last, but the geometry is flattened before rendering. It means there are
no pixels will be painted twice. Then the style are associated with colors,
gradients, images, etc. in a special style handler. It simulates
Constructive Solid Geometry so that, you can, for example draw a translucent
fill plus translucent stroke without the overlapped part of the fill being
visible through the stroke.

Added new overloaded function attach() to all pixel level renderers.
it has the following signature:template<class PixFmt>bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2);
That is, now you can attach pixfmt_nnnn to some existing
one as a child. It still requires a separate rendering_buffer
object, but will use the shared frame buffer. See example in
Demo blur.cpp.

Added new file agg_blur.h and fast blur functionality.
There two algorithms
are used: Stack Blur by Mario Klingemann and Fast Recursive Gaussian Filter, described
here
and here (PDF). The speed of both methods does not depend on the filter radius.
Mario's method works 3-5 times faster; it doesn't produce exactly Gaussian
response, but pretty fair for most practical purposes. The recursive filter
uses floating point arithmetic and works slower. But it is true Gaussian filter,
with theoretically infinite impulse response. The radius (actually 2*sigma value)
can be fractional and the filter produces quite adequate result.
There are two class templates: stack_blur and recursive_blur. stack_blur
is parametrized by color type and calculator type. The calculator
can be: stack_blur_calc_rgba, stack_blur_calc_rgb, and
stack_blur_calc_gray. They are parametrized by the basic data
type that is typically unsigned for rgba8 and int64u for
rgba16.recursive_blur is also parametrized by the color type and
calculator type. The calculator can be: recursive_blur_calc_rgba,
recursive_blur_calc_rgb, and recursive_blur_calc_gray. They
are parametrized by float or double. It's better to use
doubles because the algorithm is very sensitive to precision.
Also, there are optimized versions for RGBA32, RGB24,
and GRAY8 formats. They are: stack_blur_rgba32, stack_blur_rgb24,
and stack_blur_gray8 respectively. These functions work only with
8 bits per component colors and with blur radius not exeeded 254.
Many thanks to Mario Klingemann who generously permitted me to
include his algorithm into AGG.

May 8, 2006AGG v2.4 is released! After a while of
silence AGG is here again. That was the time of active
development and you will have to make some changes in your
code too. Hopefully it isn't that hard. See AGG Version 2.4 Release Notes
for details. Below there's a brief description of the
achievements.

Low level renderers (pixfmt) now have a possibility to use
a custom class-accessor to pixel data.

Redesigned image and pattern filters and resamplers. Now
they are considerably generalized and in fact, images and patterns
are now combined into single classes. You can use custom pixel
accessors for the images.

The major breaktrough is rendering of Flash compound shapes.
Now AGG provides two ways of Flash rendering. One is pretty
simple and in fact, was available before (well, almost), the
other is more complex, but allows you to have absolutely
flawless result. It's demonstrated in
Demo flash_rasterizer.cpp. The simple method, that
decomposes the shape into separate multiply connected polygons
is in Demo flash_rasterizer2.cpp.

Added function transform() to font engines. Now you can set
internal affine transformations. They work before the
glyphs are cached, which means you can now use rotated text
together with fast raster cache. It works only with
glyph_ren_outline, glyph_ren_agg_mono, and glyph_ren_agg_gray8.
It's impossible to use it with glyph_ren_native_mono and
glyph_ren_native_gray8 because the font engine already receives
bitmaps. Also, as the practice showed it's a bad idea to use
embedded font engine transformations in both, FreeType and Win32,
because it doesn't work well with hints in certain cases.

Note that the internal transformer is included into the font
signature to locate the cache pool. It means that it's a bad
idea to use it often. If you need to draw 360 lines of text
rotated with 1° step, the internal transformer will work
very slow because it will create a new cache pool every time
you change the angle. For this case it's much better to use
vector cache (glyph_ren_outline) and transform the glyphs
externally.

The usecase of the internal transformer is basically to display
a whole rotated page of text. Also note that if the angle differs
from 0°, 90°, 180°, or 270°, there's some positioning
inaccuracy appears when you use raster cache. It's because
pre-rasterized glyphs cannot be positioned with subpixel
accuracy.

Gouraud shader is modified again. First of all, the calls to
floor() were replaced to just manual rounding. It's
much faster on some compilers (Microsoft). Functions floor()
and ceil() work terribly slow. Johan Paulsson has
discovered this problem.
Also, thre were some inconsiderable algorithmic modifications
that resulted in more accurate rendering. Still, there're some
artifacts possible if the triangles are too narrow (narrower than
one pixel).

Fixed a bug in bezier_arc. It produced NaN or -NaN in cases of
zero sweep angle, that resulted in infinite values in consecutive
converters. Thanks to Richard Smolak for reporting it.

All anonymous enums now have names :-)
It was some interference of questionable C++ constructs from Boost
with unnamed enums in GNU C++ v4. Most probably it's a bug in GCC,
but I decided to make it GCC compliant because it doesn't affect
anyhow other compilers. Thanks to Artem Pavlenko for reporting it.

After discussion with Marco Manfredini I still decided to keep
the basic compositing formula the same, that is, alpha = (255 + alpha * cover) / 256
Marco is right of course, he has provided more accurate
formula with rounding: int q=alpha*cover+128; return (q+(q«8))»8;
But one extra shift operation is critical on Pentium-4
processors. The used formula isn't correct, but it gives
appropriate result for the cost of only one extra addition.
Anyway, thanks Marco for the correct formula, I will keep it
in mind for future.

Modified the "overlay" and "hard-light" compositing operations.
Now they are fully compliant with SVG anf PDF. Actually,
the "soft-light" and "hard-light" operations produce almost
opposite results, probably because of some mistake introduced
by Adobe engineers. However, for the compatibility and historical
reasons it works as described in SVG:http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html

Modified class alpha_mask_u8. It was my old bug that I used a simple
blending formula:alpha = (alpha * cover) / 256
The correct one is:alpha = (alpha * cover) / 255
But it works much slower. To keep it fast and reasonably accurate
I now use:alpha = (255 + alpha * cover) / 256
Thanks to Antti Nivala for highlighting it.

August 21, 2005 Bugfix

Fixed a bug in path_storage:arrange_orientations() and arrange_orientations_all_paths().
It was rewritten and simplified. Thanks to Stephan Assmus for
finding it.

Fixed the formula for "soft-light" color compositing. Thanks
to Craig Northway for providing the info. Now "soft-light"
works correctly, but still, there is an issue with "hard-light"
and "overlay":http://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html.
The "hard-light" formula produces "overlay" result and vice versa,
but Craig claims that both formulae are correct. If they are, the
demo pictures are incorrect.

Improved the stroker algorithm (it will pursue me for the rest
of my life, and I accept my fate). Now you have the following
values for the inner join types:inner_bevelinner_miterinner_jaginner_round
Only inner_round produces the flawless result in all cases,
But it also produces a lot of inner edges. I hope one day I can
implement a filter that simulates the non-zero fill behaviour.
You can see the difference between the methods in the bezier_div.cpp
example.

Mauricio Piacentini (http://www.tabuleiro.com) has made a great
contribution. He added directory examples/sdl and created a single
Makefile to build all the examples. This Makefile even attempts to
download the supplementary files from Antigrain.com. That's very cool!
Our applause to Mauricio! Now the directory linux_sdl is obsolete and
will be removed in the next release.
Here's what Mauricio writes.

To build all examples using SDL (Mac or Linux) just type:

cd /examples/sdl
make
Individual examples can be built with

make aa_test

In the same way the native Carbon examples can be built with

cd /examples/macosx_carbon
make

In both cases the static library will be built (if it was not already)
from the existing global Makefile in /src/.

The Makefiles for both SDL and Carbon will also attempt to download the
required .bmp files if they are not found in the system for a given
example. If the files could not be fetched (wget) the user will receive
a message explaining where to download the samples from (sphere.bmp,
etc.) Since all programs reside in the same directory there is no need
to duplicate the .bmp files for each program that needs to use them.

Mauricio Piacentini also added examples/macosx_carbon using
the very same technique. So that, from now on you can compile AGG
examples on MacOS X with GCC. I will do the same thing with X11
demo examples in the next release (not sure how soon). That's a
great clean-up.

July 1, 2005 Update

Added new article, Adaptive Subdivision of Bezier Curves. That was a very challenging
research, so I decided to describe all my throes of composition.
If you don't read it I'll be upset. :) Please mail me your comments,
suggestions, criticism.

As the result of the research I have removed curve4_div1 and curve4_div3
and replaced it with curve4_div that encapsulates all the ideas.

Added new classes of Bezier curves approximation: curve3_div and
curve4_div. The old ones renamed to curve3_inc and curve4_inc.
For the sake of compatibility there are typedefs curve3
and curve4. New classes work pretty well with very long curves
and the number of points is proportional to the logarithm of the
curve length keeping the approximation error the same. It allows
for handling very large arcs and ellipses, with radius of 10,000,000
or more.

Added template parameters Curve3 and Curve4 to conv_curve.
Also added methods to access the curve interpolators. So that,
you can set parameters, such as angle_tolerance(). By
default conv_curve now uses curve3_div and curve4_div.

Added new demo example Demo bezier_div.cpp that demonstrates
the new adaptive subdivision method.

Improved stroke math. First, changed method of estimation of the
angle step for round joins and caps. Now it produces much less
number of points keeping arcs pretty accurate. The new formula
is:da = acos(width / (width + 0.125 / approximation_scale)) * 2;

Added new types of inner joins for strokes, see inner_join_e.
By default there inner_miter is used in conv_stroke and
conv_contour. inner_jag simulates the behaviour as if each
line segment was covered by a rectangle placed along that segment
and the outer jags were filled according to the line_join_e
type. This is the most accurate inner join method that is consistent
with the stroker in the Adobe 2D engine. But it produces a lot
of false line segments, so that, there's another inner_smart
type that works as inner_jag only near line caps. It can produce
some defects on very thick lines, but it happens very rear. A
perfect stroker is impossible or it will work terribly slow. Even
Adobe stroker can produce defects. The following SVG path
fails to draw correct stroke:<path d="M 475, 157 C 200, 100, 453, 100, 222, 157"
fill="none" stroke="green" stroke-width="100"/>
You can play with different types of joins in
Demo bezier_div.cpp.

June 8, 2005 Update

Added function besj() to agg_math.h, so that we now don't depend
on Bessel functions j0, j1, jn. The problem was with Borland C++.
Many thanks to Andy Wilk.

Fixed a bug in conv_bspline that resulted in an infinite loop when
the source contained only 2 points. Thanks to Sergey Yershov.

Added operations to trans_affine: "/", "/=", and functions
multiply_inv() and premultiply_inv().
Actually, there's no division operation on matrices, they
just multiply the matrix by the inverse matrix. It's
convenient when you need to remove temporarily some transformation
from a sequence of affine calculations.

Redesigned rasterizer_scanline_aa in such a way that it can
work with 24 bit screen coordinates. So that, you can now use
AGG to render images wider than 32767 pixels. Of course, it
requires dividing the whole buffer into horizontal bands.
The performance of the rasterizer is now even better,
not considerablaby, just about 3-5%.
Also added classes scanline32_u, scanline32_p, and scanline32_bin
that support 32 bit coordinates.
They are fully compatible with the existing scanline containers
but works slightly slower. Accordingly modified files
agg_scanline_storage_bin.h and agg_scanline_storage_aa.h.
This work has been sponsored by Liberty Technology Systems, Inc.,
see AGG Sponsors and visit http://www.lib-sys.com.

Added new demo example: Demo compositing.cpp that demonstrates all
available modes and how to use them.

Removed vertex_iterators as they were never used and there is no reason
to use them. If you really need to use the iterator semantics you can
always incorporate Iterator Adaptors from BOOST by Dave Abrahams.
The changes should not affect your code, but you might have to remove
#include "agg_vertex_iterator.h" from your files as this line
could be added to your code by copy-pasting from AGG examples.

Removed transformations from the font engines. The problem was with both,
FreeType and Win32 font engines. They produced differentfont hinting for
flip_y=false and flip_y=true. Flipping was implemented
using the internal transformation mechanisms, but it resulted in some
nontrivial problems with hinting. The embedded transformations are pretty
much useless, especially with hinting. From now on if you want to draw
transformed text you will have to use the vector cache and AGG
transformers. In practice all AGG users did namely so.

Renamed "id" to "path_id" to make the code compliant with Objective-C.
Many thanks to Sergey Yershov who successfully tested and used AGG on
MacOS with Cocoa.

April 28, 2005 AGG is updated.

Removed renderer_scanline_aa_opaque and renderer_scanline_bin_opaque.
As the practice shows they are useless, but require a lot of code.
The only purpose of them was to ignore the alpha channel and consider
it as 1.0 with slightly better performance. Instead, Added
renderer_scanline_bin_copy that performs direct copying of color
information to the buffer (no blending). Many thanks to
Jiri Krivanek for the help with it.

The scanline rasterizer was redesigned. Now it uses a faster
soring algorithm (a combination of the Radix sort and Quick sort).
The sorting part works about twice faster that is noticeable when
rendering thin lines (10-15% overall improvement).

Improved the performance of alpha-blending. Function
blend_from now works about 40% faster on RGBA buffers.

The basic interger types can be redefined from the compiler
command line or by generating file agg_config.h. By default
this file is empty, and the 64-bit integers are defined
as before, that is, __int64 for MSVC and long long
for all other compilers. In most cases it's fair enough.
Also see comments in agg_config.h. From now on the 64-bit
types are legalized in the official package. The testing
version with a suffix has been removed. See Download.

Finally implemented images transformations with resampling
to achieve best possible quality when creating thumbnails.
Currently it's implemented only for RGB color space, but the
rest of the job is simple and will be done soon.
There are two major transformation methods:span_image_resample_rgb_affinespan_image_resample_rgb
The differerence is that span_image_resample_rgb_affine works
with constant scale factors by X and Y, so, it's faster.span_image_resample_rgb allows you to have arbitrary local scale.
It's suitable for perspective transformations or any other ones
if you write an appropriate span interpolator. Currently there is
only perspective interpolator available.

Added new span interpolator classes:

span_interpolator_linear_subdiv. It works as span_interpolator_linear,
that is, it interpolates between the points along a straight line,
but it resynchronizes the result at every 8th, 16th, etc pixels
(defined by subdiv_shift). So that, it can be used together with
trans_perspective. It produces some inaccuracy, but speeds up
perspective image transformations almost twice!

Introduced new basic data types, int64, int64u. They are defined
as __int64 for MSVC and long long for all other compilers and
platforms. However, I temporarily created separate packages,
agg23a.zip and agg23a.tar.gz, see Download.
If there are no compatibility problems I'll include it into the
official package.

AGG has been tested on AmigaOS. Many thanks to Steven Solie,
http://www3.telus.net/public/ssolie
When building on AmigaOS 4.0 or higher type the following for
instructions on what targets are available.make -f Makefile.AmigaOS
To just build and install AGG into the standard AmigaOS SDK
ready for use type:make -f Makefile.AmigaOS install
If you just want to build one demo (e.g. lion) use:make -f Makefile.AmigaOS bin/lion

Changed agg_span_converter.h, added two arguments
(x,y) to function convert(). It allows you for
creating pipelines when generating spans.

Added agg_span_gradient_alpha.h that can be used to apply arbitrary
alpha gradients (transparency). This is a span converter that
can be used with any span generator, such as images, gradients,
gouraud shading, patterns, etc.

AGG code is cleaned up and now it's ANSI C++ standard compliant.
It can be compiled with g++ version 3.4. The problem was in classes
derived from template base.

Added support for MacOS, Carbon API and the building environment
for Code Warrior. Many thanks and regards to Hansruedi Baer
(http://www.karto.ethz.ch/baer/agg).
The project file is rather big (3MB), so it isn't included into
the main distribution package. Please download
http://www.antigrain.com/agg2.mcp.xml.zip and unzip it into
agg2/examples/macos_cw/agg2.mcp.xml.
Also, to build the SVG example, you need to obtain expat.lib and put it
to agg2/svg/macos_cw/expat.lib.
Download: http://www.antigrain.com/expat.lib.zip
If you don't need to compile the SVG example, just remove
svg_test from the project.

Finally! added support for FreeType font rendering engine
with cache. Now one can render any fonts very easily. The speed
is pretty good too. When caching vectorial glyphs, it's about 30-40
microseconds per glyph on a typical P-IV 2.0 GHz, when
caching scanline shapes, it's 3-4 microseconds.
See also Demo truetype_test.cpp.

Added support for TrueType fonts, based on WinAPI GetGlyphOutline().
There's a general caching system that can be used with any font source,
and two different font engine wrappers, for FreeType and Win32 API. One
can write his own font engine, based on some API or library.

June 4, 2004

Fixed a bug in the AGG Lite rasterizer. The rasterizer
did not produce any result if all poins of the polygon
fell to one pixel. See Download.

AGG is updated, see Download. There was fixed a bug in the
rasterizer and added
iterator-like methods to retrieve the scanlines. The work on
the scanline shape algebra (Intersection, Union, Substraction,
and Exclusive OR operations) is in progress.

May 9, 2004

AGG is updated. The alpha-mask classes were modified in order
to achieve better performance.

AGG is updated. Added new classes pixfmt_amask_adaptor and amask_no_clip_u8.
It allows you to use the alpha-mask with all possible primitives
and renderers. Besides, if the alpha-mask buffer is of the same
size as the main rendering buffer (usually it is) we don't have
to perform clipping for the alpha-mask, because all the primitives
are already clipped at the higher level, so, it works faster.
New demo example alpha_mask2.cpp is added.

The library has been updated, see the Download page.
There are some minor changes and
bug fix (not critical). The only change that affects
the interface is that there was removed the default value
of the 4-th template argument from span_gradient. Before there was
class ColorF = const ColorT*. It was
done in order to compile AGG successfully on SunOS.
It can affect your code if you use an array of 256 rgba8
values as a color function of gradients (most probably you do
because it's the easiest way). Just add
one extra argument const agg::rgba8* when declaring the
span_gradient.

Added new type of line joins to conv_stroke (vcgen_stroke to be
exact). Many thanks to Dirck Blaskey for the contribution.
Now there is one more type
join_miter_revert that is used for compatibility with the PDF
and SVG specifications. It works like miter_join, but when the
miter limit is exceeded it turns into the bevel_join. AGG type
of miter_join works smoother and (in my opinion) more
correct. See the conv_stroke.cpp example for details and demo.

The library and the demo examples were successfully compiled under
SunOS and Irix64. Page Demo is updated (actually,
written at last). There you can find screenshots, brief
description, and the executables for different hardware/OS
platforms.

The docs are in process. From now on I will update the documentation
pages, as well as the source files. I do not expect any changes in
code or interfaces; I'll just add some comments and cross references.

April 09, 2004. Antigrain.com reopened. I have created my own
documenting tool (see AGDoc Formatter), so that, now I can easily write new pages
and update the site. Actually, HTML with its terrible
syntax was the main obstacle to maintain the web-site.
All this time I've been working on new algorithms and the design of the library.
There are some things that were implemented: