---------------------------------------------------------------------------- David Ashley (DA) Wed Aug 24 09:38:36 PDT 2005 dash@xdr.com Current version 119. Made some tweaks in the configure.in to allow for easier cross compilation. ---------------------------------------------------------------------------- David Ashley (DA) Thu Aug 4 13:11:23 PDT 2005 dash@xdr.com Current version 118. Minor change to gradient handling with USER space coordinate system. Inkscape on windows doesn't give you the option of choosing user or bbox coordinates for gradients. ---------------------------------------------------------------------------- David Ashley (DA) Fri Jul 15 13:01:37 PDT 2005 dash@xdr.com Current version 117. Added the function SVG_SetClipping to explicitly set the clipping limits of the surface to be rendered into. They default to the whole surface. ---------------------------------------------------------------------------- David Ashley (DA) Tue May 17 07:56:53 PDT 2005 dash@xdr.com Current version 116. Changed to LGPL license from GPL, to allow linking of this library in non-free programs. The request to change was made by Asko Kauppi NOTE embedded within this library is the font engine from Freetype, I use it for rendering anti-aliased polygons. I'm proceeding under the assumption that that sourcecode was also released under LGPL. If not then this library's change to LGPL isn't valid, at least for those pieces. I'm not a lawyer. Use my contributions to this code however the hell you want to. And if you fix anything or add new features, please pass them back to me to make the library better for everyone. ---------------------------------------------------------------------------- David Ashley (DA) Tue Apr 5 07:38:46 PDT 2005 dash@xdr.com Current version 115. Jens (last name unknown) reported problems with tux.svg from inkscape's pages. It turns out the paint must be implemented as a stack such that BeginElement and EndElement must push/pop the current paint. The tux.svg had a problem with the black body not rendered as black but yellow. The stack business is just a theory but when I made the change tux.svg renders correctly. I included it in the svg directory. ---------------------------------------------------------------------------- David Ashley (DA) Tue Mar 22 18:48:18 PST 2005 dash@xdr.com Current version 114. Grabbed more code from libsvg-cairo-0.1.5, to get viewbox working. Implemented ellipse as rounded rectangle. ---------------------------------------------------------------------------- David Ashley (DA) Sun Mar 20 19:59:04 PST 2005 dash@xdr.com Current version 113. Ripped code from libsvg-cairo-0.1.5 to handle elliptical arcs + rounded rectangles. It almost slotted in without changes. ---------------------------------------------------------------------------- David Ashley (DA) Sat Mar 19 17:45:29 PST 2005 dash@xdr.com Current version 112. Reworked the coords for the gradients. The object coordinates should be based on the bounding box, however the bounding box is in the original coordinate system (before transformations). It seems to work perfectly for object coordinates, but is still off on user space coordinates. Or at least it doesn't match what inkscape renders. The SVG gradient transformation matrix is odd, it seems like the matrix is intended to let you go from gradient coordinates (0.0, 0.0) to (1.0, 1.0) to pixel coordinates, which is useless. So we've got to invert the matrix so we can go from pixel coordinates to gradient coordinates. Anyway this fixes the problem with radial gradients always being circular, when instead they should be oval (possibly) when using object coordinates. ---------------------------------------------------------------------------- David Ashley (DA) Sun Feb 20 20:25:32 PST 2005 dash@xdr.com Current version is 111. This one has my attempt at an autoconf/automake configure script. I don't know if it'll work well. Main issue is it might not detect the libxml2 correctly...Feedback is welcome to dash@xdr.com. Removed the png + jpeg requirements from the libsvg. If you want to load those formats, use SDL_image. I think it's just crazy trying to incorporate images in with SVG. If the image files could be embedded in the SVG file that would be one thing, but the code in libsvg was doing fopen() to load the image files. I think one SVG file should be sufficient unto itself to define the graphic. I took those library dependencies out because I know I'm never going to use an SVG that will refer to a bitmap image in it, and it is a headache getting the build correct for these extra libraries. YMMV. ---------------------------------------------------------------------------- David Ashley (DA) Fri Feb 18 17:49:08 PST 2005 Current version is 110. Added flags that can be set on the SDL_svg_context, flag SDL_SVG_FLAG_COMPOSITE which means render into the target surface such that the surface can then be rendered onto another surface, with appropriate alpha + color values. SO: SVG rendering with SDL_SVG_FLAG_COMPOSITE ---> Surface --> Other surface will be identical to SVG rendering without SDL_SVG_FLAG_COMPOSITE --> Other surface Without this the alpha and color values won't be correct. The whole point is to make a handy SDL_Surface that can be used as a quick element, like a widget or icon or something, to be drawn onto the screen. Auto detects bit depth, 16 and 32 bits are supported. The compositing 16 bit colordot hasn't been written yet. ---------------------------------------------------------------------------- David Ashley (DA) Thu Feb 17 17:52:46 PST 2005 Current version is 109. Major breakthrough!!!! We now have good anti-aliasing on SVG renders. It occured to me that the rendering engine used by SDL_ttf was pretty good at drawing very large glyphs. So I dug into that and it's using freetype. So I dug into freetype code and found there is a nifty renderer that handles anti-aliasing. It's even coded so that it can be a standalone renderer. So I hooked it into the SDL_svg project, replacing my effort. My hat's off to the authors (David Turner, Robert Wilhelm, and Werner Lemberg). I've reproduced the code intact here (ftimage.h, ftgrays.h, ftgrays.c). I was able to pass the bezier curve burden onto this rendering engine also. I made very slight changes to the original freetype source files: 1) renamed the gray engine to svg_ft_grays_raster from ft_grays_raster, this is because I'm using this in an application that is also using SDL_ttf and so freetype, and the common name was causing trouble. 2) Modified ftgrays.h so in standalone mode it #defines some items that were generating errors (FT_BEGIN_HEADER and FT_END_HEADER). Their approach to the code is excellent, it was very easy to hook it in. ---------------------------------------------------------------------------- David Ashley (DA) Mon Feb 7 19:05:40 PST 2005 Current version is 108. Added some anti-aliasing on the leading and trailing pixels of each span. This helps vertical tending lines but not horizontal tending lines. ---------------------------------------------------------------------------- David Ashley (DA) Sun Feb 6 18:10:56 PST 2005 Current version is 107. There's a new SVG_Version() function that returns the version. Modified the vector function v2 and got rid of all the xin, xout business, now the v2 function only outputs one x for every line. I looked at the SDL_gfx filledpolygon function for ideas, the algorithm looked like it could use a lot of optimization. For every single row of the polygon the function iterates over the whole list of polygon points to determine where that row is crossed. Lots of divides/interpolation. Also there is no mechanism to handle the fill rule (winding vs odd/even). It would only be odd/even. The filled polygon isn't anti-aliased. SDL_gfx can only anti-alias the outline of a polygon. I think the decision not to rely on SDL_gfx was correct. ---------------------------------------------------------------------------- David Ashley (DA) Fri Jan 21 17:15:33 PST 2005 Current version is 106, however this isn't stored anywhere. Moved lots of internal stuff out of the header file and into internals.h. Added SVG_LoadBuffer function. ---------------------------------------------------------------------------- David Ashley (DA) Wed Jan 19 21:18:32 PST 2005 Improved y clipping. There was a dropout problem on the top row. ---------------------------------------------------------------------------- David Ashley (DA) Sun Jan 16 20:29:38 PST 2005 Current version is 105, however this isn't stored anywhere. Got rid of #include from header file, so other programs that make use of SDL_svg.h don't need to worry about svg.h. ---------------------------------------------------------------------------- David Ashley (DA) Sun Jan 16 15:24:12 PST 2005 Current version is 104, however this isn't stored anywhere. Got rid of FillColor, just pull the color + alpha from the paint. It's not clear why all the rendering functions have an opacity passed in, but there is also a set_fil_opacity function. ---------------------------------------------------------------------------- David Ashley (DA) Sun Jan 16 11:47:57 PST 2005 Current version is 103, however this isn't stored anywhere. I fixed the span dropout in svg/filltest.svg where there is an element with 2 paths, both clockwise, one inside the other, and the inside path has a long horizontal strip, and the fill is winding. The problem was in how I manage a row on a local maximum or minimum, the direction of the span wasn't accurate. ---------------------------------------------------------------------------- David Ashley (DA) Sun Jan 16 08:10:08 PST 2005 Current version is 102, however this isn't stored anywhere. I further improved the spanning m echanics, so as pairs of spans come in I immediately convert them to run lists, so the only growable piece are the run linsts. Currently set to a maximum of 32 runs but there is no bounds checking going on. Came up with a fix for the problem with multiple separate paths in the same element, when converting each path to a span just reverse the "sense" of all the spans for rows below the starting point's row. If you start at 9 O'clock and run a path clockwise in a circle, the upper half will have spans all pointing left to right, but the bottom half will have spans pointing right to left. We just doctor up everything below the initial row, so all spans end up pointing left to right. If we do this for each separate path, we solve the problem, so it doesn't matter where on the path you start the "sense" of the spans will all be consistent. There is an edge case if you move down from the first row, you need to reverse the first row itself also. If you move up from the first row, you don't want to reverse the first row itself. There is still some span problem as shown by the svg/filltest.svg example, in the lower left case there is a strip that isn't rendered. I haven't figured out what is causing this. I think the current code is a lot cleaner. A bounds check can be added to the mergespans function to prevent writing off the end of the runs table in a row. ---------------------------------------------------------------------------- David Ashley (DA) Sat Jan 15 21:36:15 PST 2005 Current version is 101, however this isn't stored anywhere. I improved the spanning mechanism. My previous method didn't handle a path composed of multiple separate paths. The letter 'O' would be a case in point. Now a MoveTo will add a path stop, as well as an explicit closepath or the renderpath. The fix meant traversing all paths and building up the spantab, before doing any rendering at all. I had been doing a path, rendering it, doing a path, rendering it...that isn't the intent if the subpaths are in the same element. This fixes the problem with the bored_dog_01.svg. ---------------------------------------------------------------------------- David Ashley (DA) Sun Jan 9 11:26:19 PST 2005 Current version is 100, however this isn't stored anywhere. I pulled libsvg into the project for safekeeping, and modified the Makefiles to work on standard linux. They'll need tweaking. An autoconf would be nice but I can't be bothered. Project depends on libxml2, libpng, libjpeg, zlib and SDL. I pulled some svg test files off of openclipart.org and stuck them in the svg directory. To build go into the SDL_svg/libsvg directory and do make all then make install Then go into the top directory SDL_svg and do make all then make install The test program SDL_svg/obj/svgtest can be used to pop up a window and show an svg program. The bored_dog_01.svg shows the deficiencies in my spanning algorithm. I haven't dug into it but it's probably the multiple paths as part of the same element. With my algorithm the "sense" of the spans will get confused for multiple separate paths. It's probably fixable. ---------------------------------------------------------------------------- David Ashley (DA) 20041228(2) I implemented the fill_rule business. However I realize my implementation won't work for objects composed of multiple paths, because the path won't be continuous. Each span being left-to-right vs right-to-left is only consistent along a single path. In fact I'm not even sure of that... ---------------------------------------------------------------------------- David Ashley (DA) 20041228 Regarding transforms it's clear the rendering engine has to maintain a matrix stack. libsvg is nice enough to send the transform matrix down before sending any graphics primitives, that surprised me. The order isn't necessarily the same in the xml file - a path can be followed by a transform matrix. If libsvg were true to form it would put the burden of storing up the path on the rendering engine, just like everything else. Another burden on the rendering engine: The svg_length_t has a length and a units value. So each rendering engine needs to know how to convert units. What a pain. The rendering primitives are composed of mixtures of svg_length_t's and double's. Why does MoveTo or LineTo take 2 doubles, but a rectangle takes svg_length_t's? My implementation of the spans has lots of voodoo. The thing works though. The general theory is to define the shape to be painted (solid) you just step along the path in the same direction, returning to your starting point. The system keeps track of every time a row is entered and exited. Pairs of enter/exit, enter/exit define a span, and it is either left to right or right to left depending on the coordinates. The direction assists in determining the winding number of the spans. There is special case code to handle extrema in Y, the bottom or top point would end up just being a single enter/exit, but it needs to be treated as 2 enter/exits. After the path has been followed and we know all the crossings for each row, we convert each row to run lengths. We start with a huge run length of 0. Every pair of enter/exits defines a span, and the winding number +1 or -1 is determined whether the span is left to right or right to left. Each span modifies the table of run lengths, for example: -----------------------> this is a +1 span <--------- this is a -1 span becomes 111111000000000011111111 or 6 (1) 10 (0) 8 (1) Now depending on the winding rule the check can be made to render all strips that are non-zero (NONZERO) or odd (EVEN_ODD). Currently the code is in generatespans and it is hardcoded to the EVEN_ODD, it's a trivial fix to support the winding rule and it would have been easier than writing out the last sentence almost. One optimization that could be done is instead of storing up all the line crossings for each row in the spantab, as each pair of enter/exit crossings come in, we build up the run length table right there. We'd only need to store 2 xin/xout pairs and a count of spans. As it is we've got 2 tables that can grow to indefinite size for each row of the bitmap. We can reduce that to just one. Actually in the implementation the final rendering pass builds up the run lengths for each row, renders the pixels, then throws the information away. I think it would be better to build up the run lengths as possible. Anti-aliasing isn't attempted. I think a first step towards this would be using floats instead of ints for the xin/xout and run lengths. Then the fractional part of the start and end of the run length would determine the alpha for the starting and ending pixels on that span. This would allow for anti-aliasing in X. Y I have no clue how to handle with this architecture. Beggers can't be choosers. The libsvg probably ought to just be copied directly into this source tree, in case they change it and break something. It's pretty small anyway. It depends on libxml2 and that's probably pretty stable. The current version has a quicky hack to handle the Rect object. It handles the gradients ok but not curved corners. It hasn't been tested much. Gradients seem to be off somehow, probably related to BBOX coordinates, the control points for the linear gradient are probably not scaled right. Or maybe I'm supposed to scale each user coordinate in X and Y before applying the gradients. There is some evidence in this, if you take a radial gradient my rendering always shows a perfect circle, but it is supposed to sometimes be an oval. Regarding getting rid of the SDL_gfx dependency--depending on that library was going down a wrong path. Sure it handles one simple case -- anti aliased solid colored polygon. What about gradients? Patterns fills? It's a dead end. So fully implementing SVG would require modifying SDL_gfx to add gradient functionality. So now you've got some independent project that must be modified in order for SDL_svg to function. Great. That's a recipe for disaster. Instead it would be more practical to pull in rendering code from SDL_gfx and use that as a reference. I opted to just start from scratch CurveTo: This is a real hack. Currently only qubic beziers are handled and the curve is rendered by just taking 16 steps along the curve, drawing line segments. There are better recursive algorithms but I can't be bothered to clean this up. It works well enough for our application. ---------------------------------------------------------------------------- David Ashley (DA) 20041221 Multiple paths can be sent down by libsvg before the RenderPath gets called. So it's N * ( MoveTo, N2 * ( CurveTo | LineTo ), ClosePath ), RenderPath However sometimes you don't get a ClosePath at all before RenderPath, so RenderPath has to close it automatically. ---- The whole libsvg architecture is suspect. SVG objects have a fill as well as an outline, each with its own characteristics. This implementation currently only deals with the fill of the body of the object, and makes no attempt to draw the outline. libsvg could have been more intelligent so it handles the outline itself, it can translate the outline into a collection of MoveTo, LineTo + CurveTo. That way the rendering engine would only have to deal with the problem of filling a shape with a gradient. The burden is illustrated if you set the stroke width of an object to something thicker than a pixel. Suddenly the stroke itself becomes something of large area, and the renderer now has to deal with all the issues of following the path but some distance inside and outside of it to make it thicker, and all the problems of end cap, joins and more. This could be handled in the libsvg itself. All different rendering engines now need to handle the problem independently. Another issue are the primitives such as ellipse or rectangle. There doesn't need to be a separate handler function for these. The rectangle can be done by libsvg sending down a MoveTo then 3 LineTo's. The ellipse can be done with a MoveTo and several CurveTo's to approximate the ellipse. This is another case where the rendering engine has to worry about stuff that it shouldn't have to. All libsvg seems to get you is parsing the SVG XML file. ----------------------------------------------------------------------------