<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7596298501677777346</id><updated>2012-01-09T13:35:38.081+01:00</updated><category term='scripting'/><category term='fog-svg'/><category term='assembler'/><category term='mathpresso'/><category term='fog'/><category term='c++'/><category term='blitjit'/><category term='fog-graphics'/><title type='text'>Fog-Framework Blog</title><subtitle type='html'>This is the official Fog-Framework blog. All materials and ideas related to Fog-Framework are published here.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-2664529497350238067</id><published>2011-08-08T22:19:00.008+02:00</published><updated>2011-08-08T23:33:18.321+02:00</updated><title type='text'>Quadratic Bézier Curves Stroker</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Stroking is a common task of every graphics library. When I started writing Fog-Framework, I used algorithms from &lt;a href="http://www.antigrain.com"&gt;antigrain&lt;/a&gt; to work with vector geometry. However, the antigrain can only stroke polygons, so quadratic and cubic Bézier curves must be first approximated into the line segments. When a graphics path is stroked, the information about curves is definitely lost, and very acute angles are not stroked properly unless very large value is used for property called approximation-scale (it's called flatness in other graphics libraries).&lt;/p&gt;

&lt;p&gt;This inaccuracy can lead into problems. For example to stroke a path twice the curve must be approximated into many line segments. More line segments means more vertices, which means more cpu power to transform them, for example.&lt;/p&gt;

&lt;p&gt;The purpose of this article is to demonstrate the work to replace the old polygon stroker with a new curve-to-curve stroker. The actual limitation is that current version (2011-08-08) can stroke quadratic Bézier curves only.&lt;/p&gt;

&lt;h2&gt;Background and Implementation Notes&lt;/h2&gt;

&lt;p&gt;The new curve-to-curve stroker is highly inspired by the work of Mike &amp;quot;Pomax&amp;quot; Kamermans, see his excellent resource &lt;a href="http://processingjs.nihongoresources.com/bezierinfo/"&gt;A primer on Bézier curves&lt;/a&gt;, section &lt;a href="http://processingjs.nihongoresources.com/bezierinfo/#offsets_s"&gt;How to scale curves&lt;/a&gt;. Please try the interactive example provided in the linked article. The quadratic Bézier curve scaling is definitely the way to go. This method is precise for &amp;quot;safe&amp;quot; curves, which are defined as curves where the angle between the two lines which define the curve is not acute. I found that this condition is not the best one and I adjusted the angle to 100 degrees.&lt;/p&gt;

&lt;p&gt;If the &amp;quot;safe&amp;quot; curve criteria is not met, then the curve must be subdivided into smaller ones. There are several ways how the subdivision criteria are created. The author of Bézier primer used subdivision based on curve extremas (curve is first rotated so extrema is always found, if curve is not degenerate), but I noticed that the offset of commonly used curves is not precise, so I adjusted the mechanism how the curve is subdivided and I added some conditions for subdivision. This means that Fog-Framework generates more curves, but I found it more precise (for me it's perfect).&lt;/p&gt;

&lt;h2&gt;Results&lt;/h2&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-f-ttXDAmZHo/TkBS-7vv7xI/AAAAAAAAAEU/KA8c05rnwSQ/s1600/QuadraticBezierStroke.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 356px; height: 400px;" src="http://1.bp.blogspot.com/-f-ttXDAmZHo/TkBS-7vv7xI/AAAAAAAAAEU/KA8c05rnwSQ/s400/QuadraticBezierStroke.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638597974611193618" /&gt;&lt;/a&gt;

&lt;p&gt;The results of new curve-to-curve stroker (left) vs the antigrain stroker (right). The number of resulting curve segments generated by new curve-to-curve stroker depends on the curvature of the original curve, the number of line segments generated by antigrain stroker depends on the curve length and the flatness which was set to 0.25 (the default value).&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-bvo9bRfvLwI/TkBTNCouCgI/AAAAAAAAAEc/flK_PGimKjs/s1600/QuadraticDegenerates.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 356px; height: 400px;" src="http://1.bp.blogspot.com/-bvo9bRfvLwI/TkBTNCouCgI/AAAAAAAAAEc/flK_PGimKjs/s400/QuadraticDegenerates.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5638598216978926082" /&gt;&lt;/a&gt;

&lt;p&gt;As can be seen, the degenerate cases are handled more precisely by curve-to-curve stroker, because the corners are approximated using curves, instead of lines. I think that the curve-to-curve stroker generates a lot of curves in this case, but the resulting shape looks better than shape approximated by using line segments only.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This is only the beginning of my stroker implementation. I'd like to post another article related to the stroking of cubic Bézier curves after finished. The final implementation will be part of Fog-Framework, so everyone can use it without restrictions.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-2664529497350238067?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/2664529497350238067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2011/08/quadratic-bezier-curves-stroker.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2664529497350238067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2664529497350238067'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2011/08/quadratic-bezier-curves-stroker.html' title='Quadratic Bézier Curves Stroker'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-f-ttXDAmZHo/TkBS-7vv7xI/AAAAAAAAAEU/KA8c05rnwSQ/s72-c/QuadraticBezierStroke.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-2466756571816206329</id><published>2011-02-25T00:19:00.004+01:00</published><updated>2011-03-28T03:30:35.879+02:00</updated><title type='text'>News</title><content type='html'>&lt;h2&gt;News&lt;/h2&gt;

&lt;p&gt;Some people are interested about the news in Fog-Framework, because the last commit is more than two months old. It's simple, I'm working on something really new that took me all the free time. I'd like to summarize my goals, my work and the future of Fog-Framework in this post.&lt;/p&gt;

&lt;p&gt;First of all, I'd like to highlight my primary goal - make the library usable for consumers! This is really my primary goal and all my work is focused on it. It means that API must be stabilized, conventions must be finished and long-time incomplete features completed. My second goal is to make the library really fast and full-featured. The speed is very important and the incoming changes increase the performance of the library a bit. I think that Fog-Framework is going to be the fastest open-source 2d graphics library available.&lt;/p&gt;

&lt;p&gt;The summary of incoming features:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Support for 32-bit integer, 32-bit/64-bit floating point geometry (integer geometry is limited and only used for basic shapes like rect/box).&lt;/li&gt;
 &lt;li&gt;Support for high-quality image formats (16-bit per component) including high-quality rasterizer, compositing and image-filtering.&lt;/li&gt;
 &lt;li&gt;Support for 24-bit RGB image format and 16-bit 555/565 image formats.&lt;/li&gt;
 &lt;li&gt;Support for LCD anti-aliasing and rasterization.&lt;/li&gt;
 &lt;li&gt;Increased number of compositing functions for SRC and SRC_OVER operators, reduced number of all other compositing operators (these are not so used).&lt;/li&gt;
 &lt;li&gt;Remove non-premultiplied ARGB format. It always caused problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course not everything is completed, but I did really progress to support all of these features and to allow creating additions in the future. The number of image formats will probably not grow, because I think that all (A)RGB formats are included. Only exceptions are HSV/CMYK and others, but do we need these?&lt;/p&gt;

&lt;p&gt;The summary of extensions which will be implemented this year:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Shaders - shader language which can be used as a source pattern generator, pixel compositor and image filter.&lt;/li&gt;
 &lt;li&gt;C/C++ plugins - custom pattern generator and compositor extensions written in C++.&lt;/li&gt;
 &lt;li&gt;JIT compiler - my long-time dream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's now really easy to think about shaders and C/C++ extensions, because I can simply use floating-point based mathematics for this purpose. The AHSV conversion will be possible on-the-fly so custom shaders / compositing can bring really cool effects for UI and other graphics.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;I know that these changes are huge. It took me a lot of time to refactor the library, create new API conventions and helper libraries (Fog-Face), but I'm sure that these steps were needed to make library more usable for various consumers and various demands. How many libraries support 64-bit image formats? How many libraries allow to use C++/Shader extensions? This all is going to be available in Fog - optimized to the death, portable and easy to use.&lt;/p&gt;

&lt;h2&gt;Other thinking&lt;/h2&gt;

&lt;p&gt;I saw many graphics libraries and it's interesting that Qt and Cairo is using division by 255 with floating-point precision (there is trick to do it fast). &lt;s&gt;I used that division in old code too, but now I changed everything to scale to 256, adding 1 to the component or alpha to make it 0...256. The main reason why the div255 is used is the fact, that image formats are based on BYTEs and only value from 0 to 255 can be stored in it&lt;/s&gt;.&lt;/p&gt;

&lt;p&gt;But the main problem is that when using fixed-point rasterizer, bilinear filter and all other effects/mathematics, the resulting scale is always from 0 to 256, inclusive. For example AGG rasterizer produces values from 0 to 256, but the 256 is saturated to 255 by sweep_scanline(). So I introduced some new span formats to use 0...256 scale (using WORD) and 0...65536 scale (using DWORD) and rasterizer is now able to create mask using non-saturated values. More memory impact is not visible, because each scanline produced by rasterizer is discarded after use. The positive thing is that blending is a bit faster, because division by 256 is really simple compared to optimized division by 255.&lt;/p&gt;

&lt;p&gt;Update: Now only mask is scaled, alpha-blending uses div255.&lt;/p&gt;

&lt;p&gt;I'd like to add specialized solid-color rasterizer that will be able to fill image directly without producing a scanline for some pixel formats. This should be faster and it's the upper limit where I can go keeping high-quality AGG rasterizer.&lt;/p&gt;

&lt;p&gt;And when the code will be ready? I hope that early. I need to integrate Fog-Framework with one commercial product I'm working on so I really need it to be stable and fast:)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-2466756571816206329?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/2466756571816206329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2011/02/news.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2466756571816206329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2466756571816206329'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2011/02/news.html' title='News'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-6305781331647181370</id><published>2010-10-22T00:59:00.014+02:00</published><updated>2010-11-13T00:03:04.491+01:00</updated><title type='text'>Vector geometry resources</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Small post about resources I found useful when working on Fog-Framework. Mainly about geometry - transforms, bezier curves, etc...&lt;/p&gt;

&lt;h2&gt;Code&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://tog.acm.org/resources/GraphicsGems/"&gt;Graphics Gems&lt;/a&gt; - Graphics Gems is not only about theory, but also about the code. You can found there bezier curve approximation, length and helpers, arc approximation and various algorithms that describes collision detection and intersection. The code is old, but the algorithms not.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://segfaultlabs.com/docs/quadratic-bezier-curve-length"&gt;Computing the Arc Length of Quadratic Bezier Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://steve.hollasch.net/cgindex/curves/cbezarclen.html"&gt;Computing the Arc Length of Cubic Bezier Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://antigrain.com"&gt;AntiGrain&lt;/a&gt; - Everybody already knows.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.freetype.org/"&gt;FreeType&lt;/a&gt; - Bézier curve approximation using fixed point, text hinting, ...&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/p/degrafa/source/browse/trunk/Degrafa/com/degrafa/"&gt;Degrafa&lt;/a&gt; - Graphics Framework for Flex&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Papers, Materials&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf"&gt;Rapid Termination Evaluation for Recursive Subdivision of Bezier Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/Bezier%20Offset%20Curves.pdf"&gt;Fast, precise flattening of cubic Bézier path and offset curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.cis.usouthal.edu/~hain/general/Theses/Ahmad_thesis.pdf"&gt;Approximation of a Bézier Curve with a Minimal Number of Line Segments&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.cis.usouthal.edu/~hain/general/Theses/Swaminadhan_thesis.pdf"&gt;Efficient Rendering of Thick Polylines&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.tinaja.com/glib/cubemath.pdf"&gt;The Math Behind
Bezier Cubic Splines&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.tinaja.com/glib/bezcirc2.pdf"&gt;How to determine the control points of a Bézier curve that approximates a small circular arc&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.tinaja.com/glib/nonlingr.pdf"&gt;Nonlinear Graphics Transforms&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.planetclegg.com/projects/WarpingTextToSplines.html"&gt;Warping Text to a Bézier Curves&lt;/a&gt;&lt;/li&gt;

 &lt;li&gt;&lt;a href="http://newton.kias.re.kr/~swchoi/homepage/offset_theory.pdf"&gt;Two-dimensional Offsets via Medial Axis Transform I: Mathematical Theory&lt;/a&gt;&lt;/li&gt;

 &lt;li&gt;&lt;a href="http://newton.kias.re.kr/~swchoi/homepage/offset_alg.pdf"&gt;Two-dimensional Offsets via Medial Axis Transform II: Algorithm&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.ganssle.com/approx/approx.pdf"&gt;A guide to approximations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Computer Aided Geometric Design (&lt;a href="http://cagd.cs.byu.edu/~557/"&gt;http://cagd.cs.byu.edu/~557/&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch1.pdf"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch2.pdf"&gt;Bezier Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch3.pdf"&gt;Polynomial Evaluation and Basis
Conversion&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch4.pdf"&gt;Forward Differencing&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch5.pdf"&gt;Properties of Blending Functions&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch6.pdf"&gt;B-Spline Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch7.pdf"&gt;Planar Curve Intersection&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch8.pdf"&gt;Offset Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch9.pdf"&gt;Polynomial Root Finding in
Bernstein Form&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch10.pdf"&gt;Polynomial Interpolation&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch11.pdf"&gt;Approximation&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch12.pdf"&gt;Interval Bezier Curves&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch13.pdf"&gt;Floating Point Error&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch14.pdf"&gt;Free-Form Deformation&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch15.pdf"&gt;Tensor-Product Surfaces&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch16.pdf"&gt;Algebraic Geometry for CAGD&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch17.pdf"&gt;Algebraic Geometry for CAGD&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://cagd.cs.byu.edu/~557/text/ch18.pdf"&gt;Genus and Parametrization of
Planar Algebraic Curves&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wiki:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve"&gt;Bézier curve&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Gaussian_quadrature"&gt;Gaussian quadrature (approximation)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Simpson%27s_rule"&gt;Simpson's rule (approximation)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm"&gt;De Casteljau's algorithm&lt;/a&gt;&lt;/li&gt;
 &lt;!--
 &lt;li&gt;&lt;a href=""&gt;&lt;/a&gt;&lt;/li&gt;
 --&gt;
&lt;/ul&gt;

&lt;h2&gt;Interactive&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.caffeineowl.com/graphics/2d/vectorial/bezierintro.html"&gt;Introduction to cubic and quadratic Bezier curves&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;More...&lt;/h2&gt;

&lt;p&gt;If you need more just google for them. If you think that I'm missing something just leave a note;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-6305781331647181370?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/6305781331647181370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/10/vector-geometry-resources.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6305781331647181370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6305781331647181370'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/10/vector-geometry-resources.html' title='Vector geometry resources'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-198882253933859232</id><published>2010-09-20T22:52:00.010+02:00</published><updated>2010-10-14T08:43:25.628+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>News, Class Naming Schema, Transforms</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Class naming schema describes how classes are named according to their features. Fog-Framework contains many version of classes describing the same problem. The main difference between them is, however, the data-type used to store class members. The main goal of this post is to introduce new class naming schema.&lt;/p&gt;

&lt;h2&gt;History&lt;/h2&gt;

&lt;p&gt;There were used several schemas in history, but it was never consistent in all library modules. For example &lt;code&gt;Point&lt;/code&gt; and &lt;code&gt;PointF&lt;/code&gt; were initial versions of vertex-based classes. &lt;code&gt;Point&lt;/code&gt; was integer version and &lt;code&gt;PointF&lt;/code&gt; was double-precision floating point version.&lt;/p&gt;

&lt;p&gt;This way was changed when I introduced classes to also work with points based on 32-bit float data type. The reason to add also this version is simple - OpenGL support and improving performance of Fog-Framework running by hardware without double-precision floating point unit.&lt;/p&gt;

&lt;p&gt;New scheme was to prefix class using the data-type. So &lt;code&gt;Point&lt;/code&gt; was changed to &lt;code&gt;IntPoint&lt;/code&gt; and &lt;code&gt;PointF&lt;/code&gt; was changed to &lt;code&gt;DoublePoint&lt;/code&gt;, introducing new class named &lt;code&gt;FloatPoint&lt;/code&gt;. This scheme was better, because you are always looking at the data-type, but it's longer and the prefix doesn't look good.&lt;/p&gt;

&lt;p&gt;There are several classes where schema was never applied. For example &lt;code&gt;Argb&lt;/code&gt; class describes color using scalar 32-bit number (8-bit per component), but how to name that if I want two versions, floating-point based and integer-based? &lt;code&gt;FloatArgb&lt;/code&gt; looks really weird to me so I started thinking about a good replacement.&lt;/p&gt;

&lt;h2&gt;Class Naming Schema&lt;/h2&gt;

&lt;p&gt;After some hours of work I decided to use suffix-form. Each class starts with its name and if there are several versions of it the suffix is added. Suffix always starts using Capitalized letter and can be only one character long. For example there are &lt;code&gt;PointI&lt;/code&gt;, &lt;code&gt;PointF&lt;/code&gt; and &lt;code&gt;PointD&lt;/code&gt; classes that represents point now.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Argb&lt;/code&gt; class was renamed to &lt;code&gt;ArgbI&lt;/code&gt; and &lt;code&gt;ArgbF&lt;/code&gt; class was introduced. I added more classes related to color management so there are also &lt;code&gt;AhsvF&lt;/code&gt; and &lt;code&gt;AcmykF&lt;/code&gt; classes.&lt;/p&gt;

&lt;p&gt;List of classes used for color management&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;ArgbI - ARGB color using 8-bit per entity (packed to 32-bit scalar).&lt;/li&gt;
 &lt;li&gt;ArgbF - ARGB color using 32-bit float per entity.&lt;/li&gt;
 &lt;li&gt;AhsvF - AHSV color using 32-bit float per entity.&lt;/li&gt;
 &lt;li&gt;AcmykF - ACMYK color using 32-bit float per entity.&lt;/li&gt;
 &lt;li&gt;Color - Class that can hold ArgbI, ArgbF, AhsvF or AcmykF.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;List of geometric classes:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;PointI - Point (X, Y) using 32-bit integers.&lt;/li&gt;
 &lt;li&gt;PointF - Point (X, Y) using 32-bit single-precision floats.&lt;/li&gt;
 &lt;li&gt;PointD - Point (X, Y) using 64-bit double-precision floats.&lt;/li&gt;

 &lt;li&gt;SizeI - Size (W, H) using 32-bit integers.&lt;/li&gt;
 &lt;li&gt;SizeF - Size (W, H) using 32-bit single-precision floats.&lt;/li&gt;
 &lt;li&gt;SizeD - Size (W, H) using 64-bit double-precision floats.&lt;/li&gt;

 &lt;li&gt;BoxI - Box (X1, Y1, X2, Y2) using 32-bit integers.&lt;/li&gt;
 &lt;li&gt;BoxF - Box (X1, Y1, X2, Y2) using 32-bit single-precision floats.&lt;/li&gt;
 &lt;li&gt;BoxD - Box (X1, Y1, X2, Y2) using 64-bit double-precision floats.&lt;/li&gt;

 &lt;li&gt;RectI - Rect (X, Y, W, H) using 32-bit integers.&lt;/li&gt;
 &lt;li&gt;RectF - Rect (X, Y, W, H) using 32-bit single-precision floats.&lt;/li&gt;
 &lt;li&gt;RectD - Rect (X, Y, W, H) using 64-bit double-precision floats.&lt;/li&gt;

 &lt;li&gt;TransformF - 3x3 matrix using 32-bit single-precision elements.&lt;/li&gt;
 &lt;li&gt;TransformD - 3x3 matrix using 64-bit double-precision elements.&lt;/li&gt;

 &lt;li&gt;PathF - Path using 32-bit single-precision vertices.&lt;/li&gt;
 &lt;li&gt;PathD - Path using 64-bit double-precision vertices.&lt;/li&gt;

 &lt;li&gt;PathBuilderF - Path-builder using 32-bit single-precision vertices.&lt;/li&gt;
 &lt;li&gt;PathBuilderD - Path-builder using 64-bit double-precision vertices.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Goals&lt;/h2&gt;

&lt;p&gt;The main reason to change the naming schema of classes was the future. Any class can be extended without worrying about syntax from now. For example 64-bit ARGB color can be added in the future (&lt;code&gt;ArgbD&lt;/code&gt;), without breaking the API and binary compatibility.&lt;/p&gt;

&lt;h2&gt;News - Transform&lt;/h2&gt;

&lt;p&gt;I'd sucessfully implemented new matrix classes called &lt;code&gt;Transform[F|D]&lt;/code&gt; which replaced &lt;code&gt;[Float|Double]Matrix&lt;/code&gt;. I used similar technique which can be found in Qt/Skia - optimizing matrix transformation / point transformation using a matrix type. The matrix types are identity, translation, scaling, rotation, affine and projection.&lt;/p&gt;

&lt;p&gt;As you noticed there is new transform not available before - Projection. The Transform class is 3x3 matrix that allows to produce nice transformations in perspective. This kind of transformation is available nearly in all other libraries&lt;/p&gt;

&lt;h2&gt;News - Color Management&lt;/h2&gt;

&lt;p&gt;There is also new &lt;code&gt;Color&lt;/code&gt; class that allows to store into it ARGB, AHSV or ACMYK color. The class remembers which color model was used to store a color so it should be suitable to planned PDF/PS support (CMYK enabled output files). This feature will be also used by Fog-Svg library.&lt;/p&gt;

&lt;h2&gt;Other Plans&lt;/h2&gt;

&lt;p&gt;Because I added some exciting features (3x3 transform) I need to rewrite some things to match and coöperate with the new API. The first candidate for rewriting is curve flattening code. It's still mainly original code from AntiGrain and it has some disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No clipping in the algorithm, must be clipped later.&lt;/li&gt;
&lt;li&gt;There are several papers that describe better algorithms (&lt;a href="http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/BezierFlattening.pdf"&gt;BezierFlattening&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Curve flattening + stroke generator should be done ideally together.&lt;/li&gt;
&lt;li&gt;Stroking to curves should be possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next big thing is to refactor a Painter and to improve a multithreaded rasterizer (after I removed rasterizer-pool there is extra cost to create/destroy rasterizer per paint command).&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Refactorization is good and I'm making it often, but the class naming schema breaks source/binary compatibility so it shouldn't be changed so often. I hope that I found the schema that will be used long time and that will be sufficient for all possible features which can be implemented later.&lt;/p&gt;

&lt;p&gt;&lt;s&gt;NOTE: These changes haven't been committed yet.&lt;/s&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-198882253933859232?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/198882253933859232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/09/news-class-naming-schema-transforms.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/198882253933859232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/198882253933859232'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/09/news-class-naming-schema-transforms.html' title='News, Class Naming Schema, Transforms'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-5303035767466866979</id><published>2010-08-31T23:57:00.009+02:00</published><updated>2010-09-01T01:16:35.148+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><title type='text'>Analytic Rasterizer Improvements</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This article covers possibilities to improve the analytic rasterizer implemented by &lt;a href="http://www.antigrain.com"&gt;AntiGrain&lt;/a&gt; (originally by freetype or libart). It's some time ago I posted a question in an antigrain mailing list, but it's probably very specific so nobody responded. It's all about compressing cell structures generated by the analytic rasterizer.&lt;/p&gt;

&lt;h2&gt;Explanation&lt;/h2&gt;

&lt;p&gt;Before I start I'd like to explain how antigrain rasterizer works. Please never cite this explanation, because it's not detailed and it can be crippled by my level of English.&lt;/p&gt;

&lt;p&gt;Imagine that you need to paint a triangle. Triangle is basic primitive and for each rasterizer it's a minimum. These steps are needed to rasterize it using an analytic method:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Serialize the input coordinates (this is your call to fillTriangle() for example)&lt;/li&gt;
 &lt;li&gt;Clip incoming vertices&lt;/li&gt;
 &lt;li&gt;Iterate over edges and create cells&lt;/li&gt;
 &lt;li&gt;Sort cells&lt;/li&gt;
 &lt;li&gt;Sweep and composite each scanline&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bunch of cells are generated for each rasterized edge. The count of cells is relative to the length of the edge. Please &lt;a href="http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm"&gt;read this article&lt;/a&gt; that covers the details.&lt;/p&gt;

&lt;p&gt;For us is important that original cell structure in antigrain looks like this:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
struct Cell
{
  int x;
  int y;
  int cover;
  int area;
};
&lt;/pre&gt;

&lt;p&gt;This structure takes 16 bytes for x86/x64/Arm/... platforms. It's needed to sort generated cells by Y and then by X. Antigrain solves this problem using this technique:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Sort first by Y using histogram. This is fastest than qsort and it's about two loops.&lt;/li&gt;
 &lt;li&gt;Sort by X using bubble sort or qsort (if there are many cells).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You have choice to store pointers into sorted array or to copy generated cells into it. It seems that pointers are better in 32-bit mode and to copy whole structure without Y member in 64-bit one. No proof for this, just my testing before I rewrote the rasterizer.&lt;/p&gt;

&lt;h2&gt;Improvements&lt;/h2&gt;

&lt;p&gt;The first improvement I made is structure compression. At this time I have two variants of Cell structure - CellD and CellQ. CellD is 32-bit DWORD and CellQ is 64-bit QWORD. I compressed the structures by the following way:&lt;/p&gt;

&lt;p&gt;DWORD (32-bit):&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;X - 13 bits (up to 8192 pixels in horizontal)&lt;/li&gt;
 &lt;li&gt;Cover - 10 bits&lt;/li&gt;
 &lt;li&gt;Area - 9 bits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;QWORD (64-bit):&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;X - 32 bits&lt;/li&gt;
 &lt;li&gt;Cover - 16 bits&lt;/li&gt;
 &lt;li&gt;Area - 16 bits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is stored 'area' member in the original antigrain cell which is calculated by 'cover * weight'. The result can take more than 16 bits so I'm storing the 'weight' instead, making the multiplication later in sweepScanline(). This trick allows to store one cell per 32-bit DWORD. This saves 75% space needed for a cell.&lt;/p&gt;

&lt;p&gt;Careful reader should notice that there is no 'y' member in the cells used by Fog. The reason is that the Fog rasterizer don't need it, because cells are immediately stored in a space reserved for each scanline. I'm using single linked lists of small chunks of cells (14-15). The linked list is allocated using 64-byte alignment to not disturb when fetching cells by a multi-threaded painter.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;Fog rasterizer is not sorting in Y direction, cells are already sorted.&lt;/li&gt;
 &lt;li&gt;Fog contains two cell structures - CellD and CellQ. CellD is expected to be used nearly by all paint calls.&lt;/li&gt;
 &lt;li&gt;Fog allocates cells per chunks. This means that if only two cells are needed for some scanline 14 or 15 cells are allocated.&lt;/li&gt;
 &lt;li&gt;The cell chunks overhead is about 7%. The cell compression rate is 74% for CellD and 47% for CellQ (including cell chunks overhead).
&lt;/ul&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The Fog performance is better than before and memory overhead per rasterizer was reduced. This is only the beginning, I have another ideas how to improve multi-threaded rasterizer performance and to reduce memory overhead when using it. Currently Fog is using new rasterizer per each shape rendered using multi-threaded painter engine, the ideal solution will be to use one rasterizer per multi-threaded worker.&lt;/p&gt;

&lt;p&gt;Another great improvement are rasterizers specialized for known shapes. I committed analytic rasterizer to fill rectangle (not axis aligned, sub-pixels are visible) some time ago. The performance of this rasterizer is really great, it's only about 50% slower than rasterizer used to fill axis-aligned rectangle, which is limited only by memory access speed.&lt;/p&gt;

&lt;p&gt;How to say more? I'm making improvements and I hope that my work will be actively used some day. I read about two core Arm processor so maybe high-quality multi-threaded painting engine is future also for embedded devices.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-5303035767466866979?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/5303035767466866979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/08/analytic-rasterizer-improvements.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5303035767466866979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5303035767466866979'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/08/analytic-rasterizer-improvements.html' title='Analytic Rasterizer Improvements'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-6110730048843251702</id><published>2010-08-31T23:38:00.005+02:00</published><updated>2010-08-31T23:57:12.844+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><title type='text'>Back in the School</title><content type='html'>&lt;h2&gt;Back in the School&lt;/h2&gt;

&lt;p&gt;It sounds unbelievable, but I'm back in the education system. After one year of working (I'm still working, this is just bonus) I decided to go back to school and to study. The reason is very simple - Fog-Framework. Yeah I'm going to work on Fog at school time and I really wonder about progress I can do.&lt;/p&gt;

&lt;p&gt;I have some plans with Fog, but my biggest effort is to complete Fog-Core and Fog-Graphics. These parts are important to me and are important to make library usable. I started some design and implementation notes in the wiki:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/p/fog/wiki/Design_Painter"&gt;Design - Painter&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/p/fog/wiki/Design_Shaders"&gt;Design - Shaders&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first thing I'd like to do is to switch into JIT compilation. I started writing Fog with this idea and I think that it's time to demonstrate the power of JIT in 2d graphics. The AsmJit tool is getting better and better and with 1.0 version I feel that it's the time to use it.&lt;/p&gt;

&lt;p&gt;The second thing I'd like to do is to redesign painter and complete all unfinished stuff:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Painter&lt;/li&gt;
 &lt;li&gt;Font support&lt;/li&gt;
 &lt;li&gt;Image and Path effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems that it's just three points, but it will be hard work and I'm looking forward to it!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-6110730048843251702?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/6110730048843251702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/08/back-in-school.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6110730048843251702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6110730048843251702'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/08/back-in-school.html' title='Back in the School'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-3358283415885277050</id><published>2010-08-06T11:57:00.005+02:00</published><updated>2010-08-08T14:05:24.146+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog - Performance of kiia rasterizer</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;My long-time TODO item was to implement KIIA rasterizer described &lt;a href="http://mlab.taik.fi/~kkallio/antialiasing/"&gt;here&lt;/a&gt;. If you download binaries pre-compiled for 32-bit Windows you should notice that the presented rasterizer is about 3 times faster than analytic rasterizer implemented in antigrain. The rasterizer uses classical approach - edges and AET (active edge table). Unlike the analytic rasterizer it needs scanlines to be rasterized from top-to-bottom direction (because of AET).&lt;/p&gt;

&lt;p&gt;The biggest problem that stopped me many times from adding implementation into Fog was that there are too many source files, macros and I hadn't time to make basic working implementation. Last three days I was without internet so I tried to port code into Fog-Framework. I created Rasterizer_Kiia.cpp/.h files, implemented even-odd filler for simple clipping and started testing.&lt;/p&gt;

&lt;h2&gt;Performance&lt;/h2&gt;

&lt;p&gt;I must really say that performance of KIIA rasterizer was not as expected. I expected at least 50% performance gain, but in many tests the results are nearly equal to Fog analytic rasterizer and in about half tests the results are worse. Only area where KIIA rasterizer performance was better is polygon rasterization test.&lt;/p&gt;

&lt;p&gt;Some FogBench results for comparison:&lt;/p&gt;

&lt;pre&gt;
FogBench - Fog-Framework performance suite (version 0.3)

Surface  : 640x480
Quantity : 1000

Processor:  Intel(R) Pentium(R) M processor 1.70GHz
Features1: MMX=yes, MMXExt=yes, 3dNow=no, 3dNowExt=no, SSE=yes
Features2: SSE2=yes, SSE3=no, SSSE3=no
CPU count: 1

Test                    |Size      |KIIA-8x         |Analytic
------------------------+----------+----------------+---------------
FillRect-Argb-Copy      |256x256   |    40.817 [ms] |    40.881 [ms]
FillRect-Argb-Over      |256x256   |   198.905 [ms] |   197.983 [ms]
FillRect-Grad-Copy      |256x256   |   209.977 [ms] |   210.027 [ms]
FillRect-Grad-Over      |256x256   |   647.795 [ms] |   631.185 [ms]
FillRectSubPX-Argb-Copy |256x256   |   189.941 [ms] |   110.987 [ms]
FillRectSubPX-Argb-Over |256x256   |   345.159 [ms] |   268.764 [ms]
FillRectSubPX-Grad-Copy |256x256   |   418.936 [ms] |   336.705 [ms]
FillRectSubPX-Grad-Over |256x256   |   774.359 [ms] |   696.499 [ms]
FillRectAffine-Argb-Copy|256x256   |   206.611 [ms] |   190.822 [ms]
FillRectAffine-Argb-Over|256x256   |   360.999 [ms] |   342.187 [ms]
FillRectAffine-Grad-Copy|256x256   |   431.458 [ms] |   414.006 [ms]
FillRectAffine-Grad-Over|256x256   |   781.907 [ms] |   766.389 [ms]
FillRound-Argb-Copy     |256x256   |   178.653 [ms] |   100.603 [ms]
FillRound-Argb-Over     |256x256   |   328.033 [ms] |   255.203 [ms]
FillRound-Grad-Copy     |256x256   |   394.408 [ms] |   333.215 [ms]
FillRound-Grad-Over     |256x256   |   755.879 [ms] |   691.855 [ms]
FillPolygon-Argb-Copy   |256x256   |   156.355 [ms] |   230.961 [ms]
FillPolygon-Argb-Over   |256x256   |   195.185 [ms] |   268.732 [ms]
FillPolygon-Grad-Copy   |256x256   |   220.645 [ms] |   293.397 [ms]
FillPolygon-Grad-Over   |256x256   |   283.699 [ms] |   358.786 [ms]
Image-Copy              |256x256   |    83.364 [ms] |    82.404 [ms]
Image-Over              |256x256   |   249.658 [ms] |   249.129 [ms]
ImageAffine-Copy        |256x256   |  1838.421 [ms] |  1844.663 [ms]
ImageAffine-Over        |256x256   |  2037.941 [ms] |  2015.771 [ms]
&lt;/pre&gt;

&lt;h2&gt;Notes&lt;/h2&gt;

&lt;p&gt;You should notice that only polygon test is faster when using the KIIA rasterizer. The polygon test consists of rendering 10 vertex polygons. Here the overhead to create edges and AET is minimal. Now look at the round benchmark results. Round shape is always divided into poly-line segments before rendering. Here the KIIA rasterizer should outperform the analytic rasterizer, but it didn't. The reason is that the poly-line segments representing flattened path are very small and there are a lot of them.&lt;/p&gt;

&lt;p&gt;The KIIA rasterizer is really better when generating polygon-only shapes. Bézier curves which are divided into several small poly-lines are not so efficient. The reason is that when using analytic rasterizer there is not so much difference between rasterizing a line or a bézier curve - the difference is only mathematics needed to divide a bézier curve into poly-line segments.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;My efforts to implement other rasterizers into Fog-Framework are probably over. I'm sure that I can more optimize the analytic one (I really hope I can increase the performance about another 30%) and the pipeline can stay as is. Also I think that there could be a problem in Fog-Framework itself - the rasterization is two-pass process. It's needed to rasterize and sweep-scanlines - adding support for another rasterizer means that I need to sweep result into scanline container first. After you have scanline you can do pixel-level compositing.&lt;/p&gt;

&lt;p&gt;So instead of providing more various quality rasterizers I'd like to optimize the current one. The output quality and performance of analytic rasterizer is excellent and optimizing some simple cases can outperform others.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-3358283415885277050?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/3358283415885277050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/08/fog-performance-of-kiia-rasterizer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/3358283415885277050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/3358283415885277050'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/08/fog-performance-of-kiia-rasterizer.html' title='Fog - Performance of kiia rasterizer'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-648573793210339345</id><published>2010-07-22T22:39:00.009+02:00</published><updated>2010-07-23T11:47:36.540+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>FogScript - Scripting with AngelScript</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;In previous post I introduced some type-safe scripting languages. I picked one and tried to connect Fog-Graphics into it. If I succeed or failed is summarized in next paragraphs.&lt;/p&gt;

&lt;p&gt;I started with angelscript, because it has interface to directly connect C/C++ functions with the scripting engine. To create bindings I wrote about 1500 lines in C++ without any other tool. The tooling is somewhat I don't like when talking about scripting languages, because some languages have really awful bindings API (Python is candidate here).&lt;/p&gt;

&lt;h2&gt;Fast introduction to AngelScript&lt;/h2&gt;

&lt;p&gt;When registering class with AngelScript you have three choices of class type:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Value type.&lt;/li&gt;
 &lt;li&gt;Reference type.&lt;/li&gt;
 &lt;li&gt;Reference type, garbage collected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Value type is type always passed as a value (like integer), reference type is dynamically allocated object controlled by the addRef/release methods (increasing/decreasing reference count) and garbage collected type is similar, but you are telling the engine that circular-references can happen.&lt;/p&gt;

&lt;p&gt;The most interesting is fact that your classes are controlled by references and garbage collector shouldn't run so often. This is because they are usually destroyed on end of their scope and there is nothing to collect.&lt;/p&gt;

&lt;p&gt;The differences between value and reference types in AngelScript:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Value type - The memory for an object is allocated by scripting engine, maybe on the stack like in C++ code. You can assign constructor, copy constructor, destructor and assign operator. Like in C++ if you don't provide them then the value content will be just uninitialized. One big thing to note is that &lt;b&gt;you can't convert value type to reference type&lt;/b&gt;!&lt;/li&gt;
 &lt;li&gt;Reference type - The memory for an object is allocated by you, scripting engine cares only about the pointer you return. You must provide two methods (addRef / release) to manage reference count of an object. If reference is decreased to zero you have to destroy it. Scripting engine will throw an exception if you try to access null object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Fog-Framework there are many types 'value' based - String, ByteArray, Stream, Image, and others are not references, but values (data internally shared by reference counts). In C++ it's without problem to work with these types, but when scripting many of these 'value' base types are mapped to 'reference' types. So Image is reference-based type in AngelScript. List of classes and their mappings is discussed in the &lt;i&gt;Mapped classes&lt;/i&gt; section. There is advantage that all reference-based types uses internally implicit data sharing and cow offered by Fog. This means that you can create an image in the scripting environment and get the instance without data-copy back into your application. Everything is transparent and atomic (like all containers in Fog).&lt;/p&gt;

&lt;h2&gt;FogScript == Fog-Framework + AngelScript&lt;/h2&gt;

&lt;p&gt;I decided to call my experiment as 'FogScript'. File extension used by scripts is '.fs', but of course there is no problem to execute any string or any other file extension. Using files is just convenient way for me to test more scripts.&lt;/p&gt;

&lt;p&gt;I created wrappers around AngelScript that will create AngelScript scripting engine and register Fog-Framework classes, there are some macros for registering types, classes and their methods, etc...&lt;/p&gt;

&lt;h2&gt;Mapped classes&lt;/h2&gt;

&lt;p&gt;All mapped classes to FogScript are without 'Fog' namespace. As a convenience I added a '@' symbol to each reference-based class type.&lt;/p&gt;

&lt;p&gt;List of mapped classes:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Fog-Core
  &lt;ul&gt;
   &lt;li&gt;ByteArray - value.&lt;/li&gt;
   &lt;li&gt;Math - global functions.&lt;/li&gt;
   &lt;li&gt;String - value, mapped to script string object.&lt;/li&gt;
   &lt;li&gt;Stream@ - reference.&lt;/li&gt;
  &lt;/ul&gt;
 &lt;/li&gt;
 &lt;li&gt;Fog-Graphics
  &lt;ul&gt;
   &lt;li&gt;Argb - value.&lt;/li&gt;
   &lt;li&gt;ArgbStop - value.&lt;/li&gt;
   &lt;li&gt;DoubleMatrix - value.&lt;/li&gt;
   &lt;li&gt;DoublePath@ - reference.&lt;/li&gt;
   &lt;li&gt;DoublePoint - value.&lt;/li&gt;
   &lt;li&gt;DoubleRect - value.&lt;/li&gt;
   &lt;li&gt;DoubleSize - value.&lt;/li&gt;
   &lt;li&gt;Font@ - reference.&lt;/li&gt;
   &lt;li&gt;Image@ - reference.&lt;/li&gt;
   &lt;li&gt;IntPoint - value.&lt;/li&gt;
   &lt;li&gt;IntRect - value.&lt;/li&gt;
   &lt;li&gt;IntSize - value.&lt;/li&gt;
   &lt;li&gt;Painter@ - reference.&lt;/li&gt;
   &lt;li&gt;Pattern@ - reference.&lt;/li&gt;
   &lt;li&gt;Region@ - reference.&lt;/li&gt;
  &lt;/ul&gt;
 &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Security (Unfinished)&lt;/h2&gt;

&lt;p&gt;Since it's possible to create and work with many classes introduced by Fog-Framework, it's needed to add some security restrictions. When scripting a part of your application you probably don't want to allow the script to access the filesystem, network, etc...&lt;/p&gt;

&lt;p&gt;I think that these security models will be enough for scripting purposes:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Sand-boxed - Script can access nothing, filesystem, network, ...&lt;/li&gt;
 &lt;li&gt;Restricted - Script has limited access to filesystem (list of directories to read, write, ...) and network.&lt;/li&gt;
 &lt;li&gt;Full - no limitation - any class available in Fog-Framework may be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Example&lt;/h2&gt;

&lt;p&gt;Ready to see FogScript in action? The example below demonstrates how to paint something and save it to file using FogScript:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
// Create a linear gradient pattern for a given bounding box.
Pattern@ makePattern(DoubleRect bb)
{
  Pattern@ p = Pattern();

  p.type = PATTERN_LINEAR_GRADIENT;
  p.setPoints(DoublePoint(bb.x, bb.y), DoublePoint(bb.x, bb.x+bb.h));
  p.addStop(ArgbStop(0.0, 0xFF7F0000));
  p.addStop(ArgbStop(0.5, 0xFFFF0000));
  p.addStop(ArgbStop(1.0, 0xFFFFFF00));

  return p;
}

// Create path that contains simple wheel.
DoublePath@ makeWheel(int points, double outerSize, double innerSize)
{
  DoublePath path;

  for (int i = 0; i &amp;lt;= points; i++)
  {
    double val = 3.141 * 2.0 * (double(i) / double(points));

    double xx = sin(val);
    double yy = cos(val);

    double x0 = 160 + xx * innerSize;
    double y0 = 160 + yy * innerSize;

    double x1 = 160 + xx * outerSize;
    double y1 = 160 + yy * outerSize;

    if (i == 0)
      path.moveTo(x1, y1);
    else
      path.curveTo(x0, y0, x1, y1);
  }

  return path;
}

// Script entry-point.
void main()
{
  Image@ image = Image(320, 320, IMAGE_FORMAT_PRGB32);

  Painter@ p = Painter(image);
  p.setSource(Argb(0xFFFFFFFF));
  p.fillAll();

  DoublePath@ path = DoublePath();

  path.addPath(makeWheel(6, 100, 50));
  path.addPath(makeWheel(6, 60, 30));
  path.close();

  p.setSource(makePattern(path.boundingRect));
  p.fillPath(path);

  p.setLineWidth(1.5);
  p.setSource(Argb(0xFF000000));
  p.drawPath(path);

  p.end();

  image.writeToFile("test.png");
}
&lt;/pre&gt;

&lt;p&gt;When running script using '&lt;code&gt;FogScript test.fs&lt;/code&gt;' it creates the test.png shown below:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_1uWuBHvqyec/TEjJZjZM1sI/AAAAAAAAAD4/eA5fRtA7HPE/s1600/test.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://1.bp.blogspot.com/_1uWuBHvqyec/TEjJZjZM1sI/AAAAAAAAAD4/eA5fRtA7HPE/s400/test.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5496864786040542914" /&gt;&lt;/a&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;FogScript is currently unfinished work. It's not project I want to publish at this time, but if there will be interest then I can commit it into Fog-SVN I'd like to see some feedback if this could be useful or not. The scripts look like the Fog-C++ code, but it's generally safe.&lt;/p&gt;

&lt;p&gt;The differences to other scripting languages / environments are that FogScript is integrated with Fog-Framework and it's purpose is to use it through it. I also think that adding security restrictions to scripting environment (and maybe Fog itself) is good idea. Of course you can map your own classes which can break it, but this is something I can't preclude.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-648573793210339345?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/648573793210339345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fogscript-scripting-with-angelscript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/648573793210339345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/648573793210339345'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fogscript-scripting-with-angelscript.html' title='FogScript - Scripting with AngelScript'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_1uWuBHvqyec/TEjJZjZM1sI/AAAAAAAAAD4/eA5fRtA7HPE/s72-c/test.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-3239302890465241098</id><published>2010-07-18T02:56:00.003+02:00</published><updated>2010-07-19T19:30:24.325+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>Type-safe scripting engines for C++</title><content type='html'>&lt;h2&gt;Intoduction&lt;/h2&gt;

&lt;p&gt;Looking for type-safe scripting engine easy embeddable in your C++ project? I did some research in this area and this post is summarization. There are many dynamically typed scripting engines that may be easily integrated into C/C++ projects including EcmaScript style languages (several implementations available) and languages with different syntax like Python, Ruby or Lua. Today I'd like to introduce some non-mainstream languages that are quite underestimated.
&lt;/p&gt;

&lt;h2&gt;Theory&lt;/h2&gt;

&lt;p&gt;Dynamically scripting languages are common, because the implementation is quite simple. Dynamic scripting language is usually only hash table, array and primitive types. There is no storage problem, because the data-length is normally platform pointer size (32-bit, 64-bit). There is no need for performance so this is usually enough. Binding to these languages are created through wrappers. Wrapper is a function that wraps your C/C++ function/member method into function that can be called by the scripting engine. There is also interface for registering classes - class consists of a name, constructor and destructor.&lt;/p&gt;

&lt;p&gt;It's simple, yeah, but the price is ... Price for what? Performance!&lt;/p&gt;

&lt;p&gt;I wrote that performance is usually not a problem when choosing scripting language, but de-facto it is. Look at the browser wars and impossible mission to improve javascript performance. There are large teams thats solving very complicated problems like static code-analysis, run-time code tracing, jit-compilation / patching, etc... Everything I'm talking about can be found in &lt;a href="http://code.google.com/p/v8/"&gt;V8 scripting engine&lt;/a&gt; and &lt;a href="http://www.mozilla.org/js/spidermonkey/"&gt;SpiderMonkey&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why I'm talking about this? Simply because when performance matters then there is no simple implementation anymore! Compiled V8 scripting engine is about 1MB (binary) while LUA is for example tens of KB only. Source code complexity is in similar ratio. I'm talking about the engine itself, not standard/ support libraries which can be written in C/C++ or using scripting language itself (for example Python contains standard library where the most of code is in Python itself).&lt;/p&gt;

&lt;p&gt;I'd like to summize static vs. dynamic typing in a following table&lt;/p&gt;

&lt;table class="table"&gt;
&lt;tbody&gt;
 &lt;tr&gt;
  &lt;td&gt;&amp;nbsp;&lt;/td&gt;
  &lt;td&gt;Type-safe scripting language:&lt;/td&gt;
  &lt;td&gt;Dynamic scripting language:&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Type safety:&lt;/td&gt;
  &lt;td&gt;Strong, errors are checked at compile-time.&lt;/td&gt;
  &lt;td&gt;None, errors are checked by the run-time.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Performance:&lt;/td&gt;
  &lt;td&gt;Execution speed can be improved by using jit-compilation to make it close to C/C++.&lt;/td&gt;
  &lt;td&gt;Jit-compilation can never help to make the language as fast as C, but helps a lot.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Memory footprint:&lt;/td&gt;
  &lt;td&gt;Smaller, maybe bigger than C/C++, but should be close.&lt;/td&gt;
  &lt;td&gt;Larger. Each variable contains type-id which must be stored with it. There are several workarounds, but it helps only for integer types and strings (used by all major ecmascript engines).&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Extensibility:&lt;/td&gt;
  &lt;td&gt;Depends to language implementation, the initial list of features is usually small. Multiple inheritance is problem (not available even in enterprise languages like Java/C#). Features like anonymous delegates and dynamic method invokation are not easy to implement. My experiences are that single-inheritance model is enough for all kind of projects.&lt;/td&gt;
  &lt;td&gt;Strong! This is area where dynamically typed languages win.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Portability:&lt;/td&gt;
  &lt;td&gt;Calling user functions without wrappers need portability layers for each platform. Using wrappers is portable.&lt;/td&gt;
  &lt;td&gt;All user C/C++ functions are wrapped through functions which can be called by the scripting engine (defined calling convention and function prototype).&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Initial development effort:&lt;/td&gt;
  &lt;td&gt;Large - language is not a hash-table, each new feature needs carefully designed virtual machine. Problem when compiling+running against different versions of modules can be hard to solve.&lt;/td&gt;
  &lt;td&gt;Small - look at LUA, it's simple and small.&lt;/td&gt;
 &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;Theory Summary&lt;/h2&gt;

&lt;p&gt;Let's summarize the differences. Type-safe languages should be generally faster with smaller memory footprint while dynamically typed languages should be slower, but more extensible. Usually the performance not matters when writing scripts in case that you making the bridge between application written in C/C++ and scriptable environment. But is really truth that performance isn't important? Maybe, problem solved? No!&lt;/p&gt;

&lt;p&gt;It's a matter of time until you write huge script code which needs architectural changes or refactorization, but refactorizing dynamically typed code without tools (and tell me which IDE can correctly refactor LUA/Python for example) could be initiation of troubles. In this area type-safe languages simply wins - you can refactor code, you can change architecture, but you can't compile wrong code which references non-existing classes/methods. This is addition to the performance reasons I talked about in the Introduction section.&lt;/p&gt;

&lt;h2&gt;Type-safe Scripting Languages&lt;/h2&gt;

&lt;h3&gt;&lt;a href="http://www.angelcode.com/angelscript/"&gt;AngelScript&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;The AngelScript scripting language is type-safe scripting language similar to C/C++. It is written in C++ and contains some key features:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Binding C/C++ functions/class methods without wrappers - scripting engine can call C/C++ function directly, several calling conventions are supported.&lt;/li&gt;
 &lt;li&gt;Scripting engine can work with UTF-8 and UTF-16 strings without recompilation, you must register your own string type (this is really useful).&lt;/li&gt;
 &lt;li&gt;There is no standard library, you must implement the functionality you need (good for embedding / sandboxing).&lt;/li&gt;
 &lt;li&gt;Project is maintained, there are new version each 3-6 months (mainly bugfixes).&lt;/li&gt;
 &lt;li&gt;Good license (MIT).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;No inheritance for C/C++ classes. This makes the scripting engine totally unuseful for GUI programming. It's planned for a long time, but not implemented. Single-inheritance model could be enough.&lt;/li&gt;
 &lt;li&gt;No jit-compiler. There is simple architecture for plugging some, but it's so simple to be useful and totally non-connected with the rest of the engine.&lt;/li&gt;
 &lt;li&gt;Only text exceptions, no try-catch blocks in the code. Exception is something that shouldn't happen and it's handled by the your C/C++ code.&lt;/li&gt;
 &lt;li&gt;Some useful things like including other scripts or metadata are handled by preprocessing original scripts. I think this should be part of core-api.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.angelcode.com/angelscript/"&gt;Home&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.gamedev.net/community/forums/forum.asp?forum_id=49"&gt;Forum&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.angelcode.com/angelscript/sdk/docs/manual/index.html"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://blog.jewe.org/?page_id=107"&gt;JewelScript&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;JewelScript is similar to AngelScript. The syntax is similar to C/C++, but there are some differences when defining functions and methods (class member function). Also the script engine is written in pure C.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;The language seems to be very complete and useful. New version (1.0) is really different to previous ones and features are amazing (&lt;a href="http://blog.jewe.org/?p=19"&gt;JewelScript feature overview&lt;/a&gt;).&lt;/li&gt;
 &lt;li&gt;Exposing native inheritance into scripting environment is possible.&lt;/li&gt;
 &lt;li&gt;Ability to use dynamic typing.&lt;/li&gt;
 &lt;li&gt;Anonymous delegates implemented in core language.&lt;/li&gt;
 &lt;li&gt;Project is maintained, but it's not so used as AngelScript. I found &lt;a href="http://jewelscript.suddenlaunch3.com/index.cgi?board=blog&amp;action=display&amp;num=1171295186"&gt;small message&lt;/a&gt; from the author (called Jewe). He would like to increase popularity of the scripting engine.&lt;/li&gt;
 &lt;li&gt;Class based exception handling.&lt;/li&gt;
 &lt;li&gt;Good license (zlib/libpng).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Unable to call native function/class method directly, need wrappers.&lt;/li&gt;
 &lt;li&gt;No jit-compiler.&lt;/li&gt;
 &lt;li&gt;String type can't be customized (I really like the idea from AngelScript).&lt;/li&gt;
 &lt;li&gt;Some built-in classes start with lowercase letter (scripting languages usually use capitalized class names and camelCase for function/method names).&lt;/li&gt;
 &lt;li&gt;There is standard library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://blog.jewe.org/?page_id=107"&gt;Home&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://jewelscript.suddenlaunch3.com/index.cgi"&gt;Forum&lt;/a&gt; (Outdated, Moved)&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.jewe.org/jewelscript/docs/jewelscript.pdf"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;a href="http://code.google.com/p/nullc/"&gt;NullC&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;NullC is quite new project. It's type-safe scripting engine and language similar to C/C++, there are only few differences. NullC is conceptually amazing project that contains jit-compiler for x86 platform and small IDE where simple scripts can be tested (including work with raster graphics and timers). Project is in the progress and it's not finished yet. When using JIT compiled code the code-execution is about 20 times faster than byte-code interpreter.&lt;/p&gt;

&lt;p&gt;Personally I think that when finished this project can compete with many scripting languages.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Language is complete and contains advanced features (for example auto type based on r-value).&lt;/li&gt;
 &lt;li&gt;Ability to use jit-compiler (32-bit x86 only at this time).&lt;/li&gt;
 &lt;li&gt;Exposing native inheritance into scripting environment is possible.&lt;/li&gt;
 &lt;li&gt;Author is active, new commits each week.&lt;/li&gt;
 &lt;li&gt;Good license (MIT).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Unable to call native function/class method directly, need wrappers.&lt;/li&gt;
 &lt;li&gt;Jit compiler is only for x86, but architectur is defined (matter of time).&lt;/li&gt;
 &lt;li&gt;No documentation at this time.&lt;/li&gt;
 &lt;li&gt;New project, needs some time to evolve.&lt;/li&gt;
 &lt;li&gt;Comes with standard library and some windows / gui classes. It's optional, but currently it's everything in one source-tree. I hope that this will be split from the project into additions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://code.google.com/p/nullc/"&gt;Home&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Too early to write an objective conclusion. I think that each scripting language mentioned here have use-cases. Each have also some marginal disadvantages - AngelScript and native-class inheritance, JewelScript and wrappers/string customization and NullC is too young project.&lt;/p&gt;

&lt;p&gt;I tried to connect Fog-Framework with AngelScript and it was quite easy. The only disadvantage that is limiting me is the no-inheritance model for native classes. I'd like to try JewelScript this week so I can compare these two engines.&lt;/p&gt;

&lt;p&gt;If you are looking for type-safe scripting engine, you should try all mentioned here and simply pick the best one.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-3239302890465241098?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/3239302890465241098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/type-safe-scripting-engines-for-c.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/3239302890465241098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/3239302890465241098'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/type-safe-scripting-engines-for-c.html' title='Type-safe scripting engines for C++'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-859386136772814487</id><published>2010-07-14T03:12:00.010+02:00</published><updated>2010-07-17T23:57:09.902+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='mathpresso'/><title type='text'>Using graphviz to visualize expression</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;I hacked &lt;a href="http://code.google.com/p/mathpresso/"&gt;MathPresso&lt;/a&gt; to generate output in a 'dot' language today. The 'dot' is part of a &lt;a href="http://www.graphviz.org/"&gt;graphviz&lt;/a&gt; package. It's a language and a tool (can be run from command line for example) which can generate graphics representation of the 'dot' input.&lt;/p&gt;

&lt;p&gt;Mathpresso is a mathematical expression parser, evaluator and jit-compiler. Visual representation of an expression is excellent for debugging purposes. It reveals how an expression was parsed and possibilities how an expression can be improved. Adding support for generating 'dot' output was 30-minutes action.&lt;/p&gt;

&lt;h2&gt;Expression Representation&lt;/h2&gt;

&lt;p&gt;Imagine the following expression:&lt;/p&gt;

&lt;pre class="lang-c"&gt;(x + y + z*2 + (x*z + z*1.5))&lt;/pre&gt;

&lt;p&gt;When using MathPresso the expression is parsed to an abstract-syntax-tree (AST). The AST is a hierarchic structure that can be manipulated and transformed. The MathPresso is currently only able to merge constants - for example expression '1+1' can be merged simply to '2'. Jit compilation is transformation of AST into a machine-code. Generating the 'dot' output is similar, but that the AST is transformed into the 'dot' language.&lt;/p&gt;

&lt;p&gt;The 'dot' representation of the expression:&lt;/p&gt;

&lt;pre class="lang-dot"&gt;
digraph G {
  node [shape=record];
  N_14 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;+|&amp;lt;R&amp;gt;"];
  N_14:L -&amp;gt; N_6:F0;
  N_14:R -&amp;gt; N_13:F0;
  N_6 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;+|&amp;lt;R&amp;gt;"];
  N_6:L -&amp;gt; N_2:F0;
  N_6:R -&amp;gt; N_5:F0;
  N_2 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;+|&amp;lt;R&amp;gt;"];
  N_2:L -&amp;gt; N_0:F0;
  N_2:R -&amp;gt; N_1:F0;
  N_0 [label="&amp;lt;F0&amp;gt;x"];
  N_1 [label="&amp;lt;F0&amp;gt;y"];
  N_5 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;*|&amp;lt;R&amp;gt;"];
  N_5:L -&amp;gt; N_3:F0;
  N_5:R -&amp;gt; N_4:F0;
  N_3 [label="&amp;lt;F0&amp;gt;z"];
  N_4 [label="&amp;lt;F0&amp;gt;2.000000"];
  N_13 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;+|&amp;lt;R&amp;gt;"];
  N_13:L -&amp;gt; N_9:F0;
  N_13:R -&amp;gt; N_12:F0;
  N_9 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;*|&amp;lt;R&amp;gt;"];
  N_9:L -&amp;gt; N_7:F0;
  N_9:R -&amp;gt; N_8:F0;
  N_7 [label="&amp;lt;F0&amp;gt;x"];
  N_8 [label="&amp;lt;F0&amp;gt;z"];
  N_12 [label="&amp;lt;L&amp;gt;|&amp;lt;F0&amp;gt;*|&amp;lt;R&amp;gt;"];
  N_12:L -&amp;gt; N_10:F0;
  N_12:R -&amp;gt; N_11:F0;
  N_10 [label="&amp;lt;F0&amp;gt;z"];
  N_11 [label="&amp;lt;F0&amp;gt;1.500000"];
}
&lt;/pre&gt;

&lt;p&gt;Executing &lt;code&gt;dot -T png -o ${FILE}.png ${FILE}.dot&lt;/code&gt; command will convert the .dot file into a .png:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_1uWuBHvqyec/TD0hWqDnBKI/AAAAAAAAADw/9DO5icKVpd4/s1600/dot.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 181px;" src="http://1.bp.blogspot.com/_1uWuBHvqyec/TD0hWqDnBKI/AAAAAAAAADw/9DO5icKVpd4/s400/dot.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5493583793592140962" /&gt;&lt;/a&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Graphviz is really strong tool. The 'dot' language syntax is quite simple and generating dot file from application is very easy (I did it using simple counter for IDs and string builder).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-859386136772814487?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/859386136772814487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/using-graphviz-to-visualize-expression.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/859386136772814487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/859386136772814487'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/using-graphviz-to-visualize-expression.html' title='Using graphviz to visualize expression'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_1uWuBHvqyec/TD0hWqDnBKI/AAAAAAAAADw/9DO5icKVpd4/s72-c/dot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-5923223279633629920</id><published>2010-07-12T13:03:00.010+02:00</published><updated>2010-07-26T16:29:08.508+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='assembler'/><title type='text'>AsmJit - Function calling finally supported</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;I spend some time by adding support for calling functions through &lt;code&gt;AsmJit::Compiler&lt;/code&gt; yesterday. The implementation is initial, but my first tests are showing that it's working. The biggest effort was to make the implementation correct and optimized.&lt;/p&gt;

&lt;p&gt;It was needed to address these problems:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Save all preserved registers (variables).&lt;/li&gt;
 &lt;li&gt;Move register parameters into correct location (spill+load or exchange).&lt;/li&gt;
 &lt;li&gt;Reserve stack needed to call a function. I'm using convention from 64-bit development, allocating stack for all functions in EFunction prolog/epilog.&lt;/li&gt;
 &lt;li&gt;Make implementation smart and generic - allowing to write custom calling conventions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Example&lt;/h2&gt;

&lt;p&gt;I wrote simple test-case which was tested under 32-bit Windows and 64-bit Linux. Both works very well.&lt;/p&gt;

&lt;pre class="lang-c"&gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#include &amp;lt;AsmJit/Compiler.h&amp;gt;
#include &amp;lt;AsmJit/Logger.h&amp;gt;
#include &amp;lt;AsmJit/MemoryManager.h&amp;gt;

// Type of generated function.
typedef int (*MyFn)(int, int, int);

// Function that is called inside the generated one.
static int calledFn(int a, int b, int c) { return (a + b) * c; }

int main(int argc, char* argv[])
{
  using namespace AsmJit;

  Compiler c;

  // Log compiler output.
  FileLogger logger(stderr);
  c.setLogger(&amp;amp;logger);

  c.newFunction(CALL_CONV_DEFAULT, FunctionBuilder3&amp;lt;int, int, int, int&amp;gt;());
  GPVar v0(c.argGP(0));
  GPVar v1(c.argGP(1));
  GPVar v2(c.argGP(2));

  // Just do something;)
  c.shl(v0, imm(1));
  c.shl(v1, imm(1));
  c.shl(v2, imm(1));

  // Call a function.
  GPVar address(c.newGP());
  c.mov(address, imm((sysint_t)(void*)calledFn));

  ECall* ctx = c.call(address);
  ctx-&gt;setPrototype(CALL_CONV_DEFAULT, FunctionBuilder3&amp;lt;int, int, int, int&amp;gt;());
  ctx-&gt;setArgument(0, v2);
  ctx-&gt;setArgument(1, v1);
  ctx-&gt;setArgument(2, v0);
  ctx-&gt;setReturn(v0);

  c.ret(v0);
  c.endFunction();

  // Make the function.
  MyFn fn = function_cast&lt;MyFn&gt;(c.make());

  printf("Result %u (expected 36)\n", fn(3, 2, 1));

  // Free the generated function if it's not needed anymore.
  MemoryManager::getGlobal()-&gt;free((void*)fn);

  return 0;
}
&lt;/pre&gt;

&lt;p&gt;The function call is generated and controlled using &lt;code&gt;ECall&lt;/code&gt; emittable. You get a context by calling &lt;code&gt;Compiler::call(const Operand&amp;amp; dst)&lt;/code&gt; which can be used to assign function calling convention, prototype, arguments and return value. Function builder is shared between EFunction (creating a function) and ECall (calling a function).&lt;/p&gt;

&lt;h2&gt;Generated Assembler&lt;/h2&gt;

&lt;p&gt;32-bit Windows-XP:&lt;/p&gt;

&lt;pre class="lang-asm"&gt;
; Prolog
push ebp
mov ebp, esp
push ebx
push esi
sub esp, 16
; Body
mov ecx, [ebp + 8]              ; Alloc arg_0
shl ecx, 1
mov edx, [ebp + 12]             ; Alloc arg_1
shl edx, 1
mov ebx, [ebp + 16]             ; Alloc arg_2
shl ebx, 1
mov esi, 4199552
; Function Call
mov [esp], ebx
mov [esp + 4], edx
mov [esp + 8], ecx
call esi
; Epilog
add esp, 16
pop esi
pop ebx
mov esp, ebp
pop ebp
ret
*** COMPILER SUCCESS (wrote 50 bytes).
&lt;/pre&gt;

&lt;p&gt;64-bit Gentoo-Linux:&lt;/p&gt;

&lt;pre class="lang-asm"&gt;
; Prolog
push rbp
mov rbp, rsp
; Body
shl edi, 1
shl esi, 1
shl edx, 1
mov rcx, 4199268
; Function Call
xchg rdi, edx
call rcx
; Epilog
mov rsp, rbp
pop rbp
ret
*** COMPILER SUCCESS (wrote 26 bytes).
&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I think that initial implementation is very good and helpful for AsmJit users. Calling functions through AsmJit is long-time demanded feature which was finally implemented!&lt;/p&gt;

&lt;p&gt;&lt;s&gt;Only the thing I'm not sure is the API, I think that &lt;code&gt;FunctionPrototype&lt;/code&gt; (AsmJit class) and function builder should contain also return value, currently only ECall contains it. This is main reason why there is no beta release yet, API will be probably changed.&lt;/s&gt;&lt;/p&gt;

&lt;p&gt;Solved: First argument for function builder is function return value.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-5923223279633629920?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/5923223279633629920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/asmjit-function-calling-finally.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5923223279633629920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5923223279633629920'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/asmjit-function-calling-finally.html' title='AsmJit - Function calling finally supported'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-806598216502637295</id><published>2010-07-11T20:42:00.005+02:00</published><updated>2010-07-12T14:39:35.592+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='blitjit'/><title type='text'>Fog-Graphics and JIT compilation</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;About one and half-year ago I wrote tool called AsmJit and released it to the public. It took me about one week to write the initial implementation which was completely rewritten two times. Currently I'm working on AsmJit-1.0-beta that will be the first Fog-Framework dependency. The reason is very simple - I want to remove all templates from rendering backend and replace them with BlitJit. BlitJit is experimental project which will be merged into Fog-Framework.&lt;/p&gt;

&lt;p&gt;All operators except CLEAR, SRC and SRC_OVER will be removed from run-time. These tree will remain, because these are the most common ones and compiling them using JIT compiler over and over is not good idea for application startup. All others will be JIT compiled.&lt;/p&gt;

&lt;h2&gt;Architecture&lt;/h2&gt;

&lt;p&gt;The Fog-Graphics pixel renderer architecture can be shown in list below:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Source generator/fetcher (Solid, Gradient or Texture).&lt;/li&gt;
 &lt;li&gt;Destination fetcher.&lt;/li&gt;
 &lt;li&gt;Compositor (With mask, Without mask).&lt;/li&gt;
 &lt;li&gt;Destination store.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If source color is solid these steps are all merged into single function. If source is gradient or texture then pipeline is split to fetch source and then do the rest.&lt;/p&gt;

&lt;p&gt;But if you understand mathematics then you can found one issue, to make this possible (merging the pipeline) you have to write many functions, because Fog-Framework supports 5 pixel formats and about 20 compositing operator. Also the gradient and texture fetchers are optimized and there are specialized versions (nearest neighbour filtering, bilinear filtering, downscale, upscale, vertical gradient, horizontal gradient and many others...). This simply means you it's not possible to merge everything into single monstrous function.&lt;/p&gt;

&lt;p&gt;Currently the Fog-Framework is about 1.5MB library when compiled by GCC. I think that for simple library it's a lot, but when you try to remove all compositing operators, the size is highly decreased! So the Fog is currently bloated by code that will run 0.001% times (SVG compositing operators are cool, but the most used operator is SRC_OVER, forever).&lt;/p&gt;

&lt;h2&gt;The Initial Idea Is Back!&lt;/h2&gt;

&lt;p&gt;When the Fog-Framework was in designing state, I planned to include JIT compiler that would be used to generate/optimize inner loops for pixel manipulation. Because I hadn't time to implement JIT compiler I used templates, but I'm not satisfied with the performance and I'm now thinking about JIT. This idea is also connected with shaders - JIT compiler will be used by Fog-Framework, it's only matter of time how many inner loops will be optimized.&lt;/p&gt;

&lt;p&gt;I'd like to summarize what everything will be possible with JIT compiler:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Introduce more pixel formats, planned are ARGB16_1555, RGB16_555, RGB16_565, RGB24, RGB48 and ARGB64/PRGB64.&lt;/li&gt;
 &lt;li&gt;Introduce more compositing operators, the rest of SVG is needed, custom operators would be possible.&lt;/li&gt;
 &lt;li&gt;Merge all steps of a pipeline into one single function, maximizing the performance.&lt;/li&gt;
 &lt;li&gt;About 50% smaller library, because redundant code will be removed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AsmJit is the future!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-806598216502637295?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/806598216502637295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fog-graphics-and-jit-compilation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/806598216502637295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/806598216502637295'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fog-graphics-and-jit-compilation.html' title='Fog-Graphics and JIT compilation'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-4508041871836791207</id><published>2010-07-07T14:28:00.006+02:00</published><updated>2010-07-12T14:40:07.463+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Developing with CMake under Windows</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This post is not related to the Fog-Framework, but I found always hard to work with open-source libraries under Windows OS. I'm talking about C/C++ development. If you want to use some open-source library, you have to build it yourself and install to some location where it can be found by your IDE/Compiler/Build-Tools.&lt;/p&gt;

&lt;p&gt;Fog-Framework is nearly zero-dependent library so I never go into troubles when configuring, building and running it. But yesterday I worked a bit on the AsmJit and Mathpresso and I found that the development is not so easy, notice that I'm talking about only two libraries and one dependency!&lt;/p&gt;

&lt;h2&gt;CMake&lt;/h2&gt;

&lt;p&gt;The first tool I used for cross-platform development is CMake. I think that the CMake syntax is awful (I blogged about two years ago about an idea of creating new cross-platform build tool based on V8 for project files in Czech, but this post is not about syntax). Although the syntax is awful and I really dislike it, the CMake is probably the best tool for cross-platform development I found.&lt;/p&gt;

&lt;h2&gt;My Solution&lt;/h2&gt;

&lt;p&gt;So here my solution I'm using to develop libraries / applications under Windows:&lt;/p&gt;

&lt;ol&gt;

&lt;li&gt;Create directory in the filesystem that will be used for installed libraries and binaries. Because I'm confortable with Linux and I'm using it for development I found the &lt;code&gt;C:\Opt&lt;/code&gt; directory very useful (naming and it's also short).&lt;/li&gt;

&lt;li&gt;Create basic directory structure in your folder, you need 'bin', 'lib' and 'include' subdirectories. If you created directory &lt;code&gt;C:\Opt&lt;/code&gt; then your file-system structure should look like this:
&lt;pre&gt;
C:\Opt\bin
C:\Opt\lib
C:\Opt\include
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;Now setup your PATH environment variable to C:\Opt\bin and C:\Opt\lib so Windows can find your libraries and binaries. If you never worked with environment variables before, go to START -&gt; Settings -&gt; Control Panel -&gt; System -&gt; Details -&gt; Environment Variables -&gt; PATH (the dialog to add the path is really small and can't be resized, urggggh)&lt;/li&gt;

&lt;li&gt;Now add environment variable called &lt;code&gt;CMAKE_LIBRARY_PATH&lt;/code&gt; and set it to &lt;code&gt;C:\Opt&lt;/code&gt;. If you don't want to pollute your environment variables too much, you can call &lt;code&gt;set CMAKE_LIBRARY_PATH=C:\Opt&lt;/code&gt; from command line to set it for current session. You could also set &lt;code&gt;CMAKE_INCLUDE_PATH&lt;/code&gt; to &lt;code&gt;C:\Opt\include&lt;/code&gt;, but I think that this is not needed.&lt;/li&gt;

&lt;li&gt;Now close all explorers and file managers, because new environment variable will be visible only for applications run after the change. So if you have for example CMD running, close it.&lt;/li&gt;

&lt;li&gt;Now CMake should find and use all compiled libraries added to C:\Opt. You can install all libraries to this location by running cmake script with &lt;code&gt;CMAKE_INSTALL_PREFIX=C:\Opt&lt;/code&gt;.&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I hope that there is better way how to do this. Personally I'm a little bit lazy and I really dislike to setup environment variables before each script invocation so I added all to environment variables.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-4508041871836791207?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/4508041871836791207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/developing-with-cmake-under-windows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/4508041871836791207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/4508041871836791207'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/developing-with-cmake-under-windows.html' title='Developing with CMake under Windows'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-6661666941304271391</id><published>2010-07-03T21:07:00.005+02:00</published><updated>2010-07-12T14:40:28.120+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog-SL - Fog and shaders</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;I know, no posts for a long time, but I can't stop a time! I'd like to present some news about Fog-Framework today. It's few weeks that Mike suggested very simple mechanism to enable writing extensions for Fog-Framework painter. The idea is that compositing operators are not designed to solve everything and when creating graphics you can simply get to situation that no operator can do what you need.&lt;/p&gt;

&lt;p&gt;There is one very simple solution to this problem - assigning functions where you can implement the functionality. This approach has advantage that it's nearly unlimited use-case, but it has also some disadvantages. The main disadvantage is that the function must match predefined pixel format(s) and must be written in C/C++. This is problem, because there is no way how to write shader in C/C++ that can be executed by a GPU. I'd like to add OpenGP/D3D backands early so I don't want to close that door.&lt;/p&gt;

&lt;h2&gt;Shaders&lt;/h2&gt;

&lt;p&gt;Yeah, the heading is correct! When talking with Mike I suggested that we can solve everything using some shader language. Currently we agreed that the language should be compatible to an OpenGL, so we choose subset of GLSL as the base for Fog shading language (FOG-SL, sounds good?;), but at this time I don't know if we end purely with this or we extend this language much more. The idea is simple, graphics hardware is powerful and some calculations (matrix multiplication) is really fast compared to CPU. This means that FOG-SL will be mainly designed to work with pixels (not vertex shaders at this time) and to generate source (pattern fetchers). I don't know if something like vertex shaders will be added into it.&lt;/p&gt;

&lt;h2&gt;AsmJit&lt;/h2&gt;

&lt;p&gt;The key part of any shading language is tokenizer, parser, optimizer and code-generator (very simplified). The AsmJit was choosen as a tool to generate machine code that can be run by a processor. The reason is simple - in computer graphics everything is run through inner-loops. Painting 100x100 rectangle means 10.000 pixel operations in total - 100 inner loops and 100 outer loops. The most optimized loop must be the inner one (SPAN structures are used for these, see FOG raster engine for mor edetails).&lt;/p&gt;

&lt;p&gt;Using AsmJit means also one big thing - First dependency that is not part of standard packages of target operating system. This is not problem for me, but may be for others. I'd like to highlight one thing here - Fog is currently very big library, because it contains many optimized compositing functions that were designed using templates. Each new compositing function or pixel-format means bigger binary size of Fog-Framework. Introducing shaders and JIT compilation I can shrink library size about 50% - just try to compile Fog using only SRC, SRC_OVER and CLEAR operators.&lt;/p&gt;

&lt;h2&gt;Advantages / Disadvantages&lt;/h2&gt;

&lt;p&gt;FOG-SL advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One shader code is compatible with all pixel formats (compiler can premultiply / demultiply pixels on-the-fly). This means that in future the 16-bit and 32-bit pixel formats can be added without breaking old code. We can also introduce high-quality flag to run shader using floating-point math.&lt;/li&gt;
&lt;li&gt;Shaders should be fast, because shader code is compiled into assembler and run directly by the CPU. The inner loops are inlined so simple shaders can run in hundreds frames per second (like code compiled by C++ compiler). JIT compilation also means that we can compile many compositing / shading functions on-the-fly so they don't have to be part of compiled Fog library&lt;/li&gt;
&lt;li&gt;Shaders should support subset of features available by GLSL so they would run on GPU in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FOG-SL disadvantages&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portability - this is only disadvantage known to me. Shader requires to write code-generator for each supported processor which is very time-consuming.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Thanks&lt;/h2&gt;

&lt;p&gt;Currently only Mike is working on shader branch, but I'd like to help with it when I get some free time. If you are integested about shaders and implementation in fog (FOG-SL) read Fog-dev mailing list.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-6661666941304271391?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/6661666941304271391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fog-sl-fog-and-shaders.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6661666941304271391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6661666941304271391'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/07/fog-sl-fog-and-shaders.html' title='Fog-SL - Fog and shaders'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-9085508933607329476</id><published>2010-05-12T02:50:00.004+02:00</published><updated>2010-10-31T15:20:12.867+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Visual Studio - MOVD impossible</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Today I looked at disassembly, the assembler code generated by Visual Studio 2005 and I'm quite frustrated how bad the code is. Currently the Visual Studio C++ Compiler can generate one of the most compact code, but SSE2 code generated using SSE2 intrinsics is really not good as expected.&lt;/p&gt;

&lt;p&gt;The problem is that there is not direct intrinsic to generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MOVD [mem], xmm&lt;/li&gt;
&lt;li&gt;MOVD xmm, [mem]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this instruction exists and it's very common to use it to load 4 bytes into a XMM register clearing all higher DWORDs. The code generated by Visual Studio looks like this:&lt;/p&gt;

&lt;pre&gt;
  MOV ecx, [eax]
  MOVD xmm, ecx
Instead of:
  MOVD xmm, [eax]
&lt;/pre&gt;

&lt;p&gt;This is very inefficient code. I have two problems with it - it uses general purpose register that can be used by other variable and it expands into two instructions that can't execute in parallel.&lt;/p&gt;

&lt;h2&gt;Links&lt;/h2&gt;

&lt;p&gt;I didn't find detailed info about this issue, but it's probably known one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.msdn.com/vcblog/archive/2009/11/02/visual-c-code-generation-in-visual-studio-2010.aspx"&gt;MSDN&lt;/a&gt; - See comments&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-9085508933607329476?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/9085508933607329476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/05/visual-studio-movd-impossible.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/9085508933607329476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/9085508933607329476'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/05/visual-studio-movd-impossible.html' title='Visual Studio - MOVD impossible'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-2076195014251176508</id><published>2010-04-24T04:38:00.011+02:00</published><updated>2010-04-25T02:13:30.204+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog - Rethinking span structures (internal)</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;My recent work on Fog-Graphics is about anti-aliased clipping. The work is slowly getting done and I'd like to share some knowledge about the refactorized span structures.&lt;/p&gt;

&lt;h2&gt;Span, what?&lt;/h2&gt;

&lt;p&gt;Span is very small structure (about 16 bytes) that holds information about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;X position - in code / literature it's usually &lt;code&gt;X&lt;/code&gt; or &lt;code&gt;X1&lt;/code&gt; member.&lt;/li&gt;
&lt;li&gt;Length - in code / literature it's usually &lt;code&gt;Length&lt;/code&gt; or &lt;code&gt;X2&lt;/code&gt; member.&lt;/li&gt;
&lt;li&gt;Mask - mask can be const or variant.&lt;/li&gt;
&lt;li&gt;Additional data - depends to library, engine, etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fog-Graphics span structure currently contains &lt;code&gt;next&lt;/code&gt; member - It's pointer to the next span or &lt;code&gt;NULL&lt;/code&gt; if the span is last. You can see this member probably only in Fog, but I have strong reasons to include this member instead of using &lt;code&gt;span[]&lt;/code&gt; arrays (statically or dynamically allocated). These reasons are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spans can be chained and implementation details (how chaining is done) is hidden to a consumer. Consumer is simply function or set of functions that use spans to do something, but given spans are not modified (In C/C++ the &lt;code&gt;const&lt;/code&gt; keyword is used to mark data as const).&lt;/li&gt;
&lt;li&gt;Customized memory management. When designing the API it took me a lot of time and thinking to make it this way. The reasons are that it's possible to combine spans used for clipping and spans used to sweep rasterized scanline. Currently rasterizer is using different memory management to sweep scanlines than clipper.&lt;/li&gt;
&lt;li&gt;Possibility to create another class based on span that holds additional information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The structure&lt;/h2&gt;

&lt;p&gt;So what span looks like? Look at code section below:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
struct SpanA8
{
  // ... Getters / Setters omitted ...

  int x1;
  int x2;
  uint8_t* mask;
  SpanA8* next;
};
&lt;/pre&gt;

&lt;p&gt;The position and length is encoded using &lt;code&gt;x1&lt;/code&gt; and &lt;code&gt;x2&lt;/code&gt; members. As everything in Fog and other graphics libraries, &lt;code&gt;x1&lt;/code&gt; is begin position that is inclusive, but x2 is end position that is excluded from the span. This is standard in computer graphics I will never break. The length can be simply calculated by &lt;code&gt;x2 - x1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another interesting member is a &lt;code&gt;mask&lt;/code&gt;. Here I'd like to talk more about it, because I created schema that allows me to encode constant mask in this pointer without referencing other memory location. If the pointer is smaller than 256 (0xFF) then the value means const mask value (In Fog this is called CMask). All other values are pointers to memory location containing the mask sequence. Because this can be error-prone and annoying to work with, I created getters and setters, so you never access members directly. There are assertions and incorrectly used span in debug mode will kill your application.&lt;/p&gt;

&lt;p&gt;And the last member is &lt;code&gt;next&lt;/code&gt; pointer. I don't know how much to say about it, it's simple single-linked list solution.&lt;/p&gt;

&lt;h2&gt;Differences to AntiGrain&lt;/h2&gt;

&lt;p&gt;AntiGrain rendering engine contains spans too, but encoded using different schema:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
struct SpanAgg
{
  int x;
  int len;
  uint8_t* mask;
};
&lt;/pre&gt;

&lt;p&gt;You can see that it's different to Fog span, and there are some quirks too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;x&lt;/code&gt; member is same as &lt;/code&gt;x1&lt;/code&gt; member.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;len&lt;/code&gt; member is length of span, but it can be negative! Negative length is encoding for constant mask. So to get length of span you need to check if it's negative first.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;mask&lt;/code&gt; member always points to memory location. If span is const mask then there is only one record at &lt;code&gt;mask[0]&lt;/code&gt;, if span is variant mask is sequence as in Fog.&lt;/li&gt;
&lt;li&gt;There is no something like &lt;code&gt;next&lt;/code&gt;. Spans in AntiGrain are continuous so you need to know how many spans you have and then you are simply using &lt;code&gt;span++&lt;/code&gt; to get another one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see that there are design and algorithmic differences. I think that my way performs better in Fog, because I'm not using templates for core classes and I need to use different memory allocators in specific sections. However, the scanline sweep mechanism need to do some extra work to set the &lt;code&gt;next&lt;/code&gt; member, but this is nothing compared to rasterization pipeline (I didn't notice slowdown or speed-up, it's simply different way that is better in Fog).&lt;/p&gt;

&lt;h2&gt;Memory Management&lt;/h2&gt;

&lt;p&gt;I talked about memory management, but I didn't summarize the goals and reasons why I need it.&lt;/p&gt;

&lt;p&gt;The rasterizer span allocator produces very short-life data used only once by a blitter. It's very inefficient to alloc/free (using dynamic memory allocator) the storage for each blit or for each scanline fetch. Instead there is a scanline container that is used together with rasterizer. The purpose of the scanline container is to allocate memory once and reuse it for the life of the container itself. Each multi-threaded painter context contains per thread scanline container.&lt;/p&gt;

&lt;p&gt;The oppossite is span allocator used by clipper. The clipper needs ability to allocate spans which life-time could be more than one graphics command. The clipper also needs to modify allocated spans (when doing intersections) with other clip requests (for example you can clip to circle and then to other circle again).&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This is all tonight. I hope that the new span architecture will increase code readability and robustness. I'm also planning to simplify and improve blitter performance when using patterns and rendering anti-aliased shapes.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-2076195014251176508?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/2076195014251176508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-rethinking-span-structures-internal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2076195014251176508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2076195014251176508'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-rethinking-span-structures-internal.html' title='Fog - Rethinking span structures (internal)'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-5356529038715614037</id><published>2010-04-15T04:09:00.011+02:00</published><updated>2012-01-09T13:35:38.091+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Using Fog with SDL</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://www.libsdl.org/"&gt;SDL&lt;/a&gt; is very popular library for the game development that allows direct access to the screen content. SDL is low-level library that is able to prepare window, allocate double-buffer, surfaces, create timers and much more. When it comes to painting, it contains only few low-level functions to blit one surface into another or to fill a rectangle with a single color.&lt;/p&gt;

&lt;p&gt;If you need to do more, you need to use additional libraries (SDL_image, SDL_gfx, SDL_ttf...) that were designed to solve exactly one problem (load or write images, draw primitives, draw text, etc...). The biggest problem is if you need more than only simple raster graphics or text rendering. Another problem can be many dependencies, for example SDL_ttf depends to freetype which depends to zlib, SDL_image needs libpng (which needs zlib) and libjpeg (if you want to use PNG or JPEGs), and so on...&lt;/p&gt;

&lt;p&gt;Fog-Framework tries to use operating-system libraries instead (you don't need FreeType under Windows, nor libpng, etc...), and one unified API. The Fog-G2d library is designed to be extensible, so you can use any other library that can provide you pixels buffer (and I didn't see library that not allows it). Only the requirement is that the pixel format of the buffer is compatible with the Fog (but Fog-G2d is designed to work with the most hardware pixel formats, so this really shouldn't be an issue).&lt;/p&gt;

&lt;h2&gt;Embedding&lt;/h2&gt;

&lt;p&gt;Lets talk about the embedding. Fog-Framework contains own windowing system and UI components, but you don't need to use them, you can use only Fog-G2d library without complications. Lets describe two ways for using other graphics libraries with Fog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adopting other data into Fog-Framework containers - Described in this article, see Fog::Image::adopt() and Fog::Painter::begin() methods for more. The Fog::ImageBits structure is always used to do the connection.&lt;/li&gt;
&lt;li&gt;Adopting Fog owned data into other libraries - Very easy if other library allows to use custom pointers. It's possible to use for example Fog::Image in Cairo or GdiPlus, and vice-versa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article covers adopting other data (pixel buffers) into the Fog-Framework.&lt;/p&gt;

&lt;h2&gt;The Code&lt;/h2&gt;

&lt;p&gt;Here is working, heavily commented application that will setup SDL and use Fog::Painter and other classes / functions to paint into the buffer managed by the SDL library. The Fog::ImageBits structure was used to pass raw-data buffer into Fog::Painter.&lt;/p&gt;

&lt;pre class="lang-c"&gt;
// ============================================================================
// [Include Section]
// ============================================================================

#include &amp;lt;Fog/Core.h&amp;gt;
#include &amp;lt;Fog/G2d.h&amp;gt;

#include &amp;lt;SDL.h&amp;gt;

// ============================================================================
// [Tools]
// ============================================================================

static Fog::TransformF createRotationMatrix(Fog::PointF center, float rotation)
{
  Fog::TransformF m;
  
  m.translate(-center, Fog::MATRIX_APPEND);
  m.rotate(rotation, Fog::MATRIX_APPEND);
  m.translate(center, Fog::MATRIX_APPEND);

  return m;
}

// ============================================================================
// [SdlApplication]
// ============================================================================

// SdlApplication is nothing more than thin wrapper to SDL library. You need
// just to instantiate it and call run() to enter the SDL event loop.
struct SdlApplication
{
  SdlApplication();
  ~SdlApplication();

  // Application state (just convenience instead of 0, 1, ...).
  enum APP_STATE
  {
    APP_OK = 0,
    APP_FAILED = 1
  };

  // Initialize application, called by run(), don't call manually.
  int init(int width, int height);

  // Destroy application, called by destructor, don't call manually.
  void destroy();

  // Run application, called by your code.
  int run(int width, int height);

  // Called to process SDL event.
  void onEvent(SDL_Event* ev);

  // Called on timer event.
  static Uint32 _onTimerCb(Uint32 interval, void* param);
  void onTimer();

  // Called to render content into buffer.
  void onRender();

  // Called to render content using Fog::Painter, called by onRender().
  void onPaint(Fog::Painter&amp;amp; p);

  // SDL screen surface, the surface we will paint to.
  SDL_Surface* _screen;

  // SDL timer.
  SDL_TimerID _timer;

  // Delay between frames.
  int _interval;

  // Some stuff we work with.
  double _rotate;

  // Whether the application is in event loop.
  bool _running;
};

SdlApplication::SdlApplication() :
  _screen(NULL),
  _timer(0),
  _interval(25),
  _rotate(0.0),
  _running(false)
{
}

SdlApplication::~SdlApplication()
{
  destroy();
}

int SdlApplication::init(int width, int height)
{
  // Initialize the SDL library.
  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) &amp;lt; 0)
  {
    fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
    return APP_FAILED;
  }

  // Create main surface.
  if ((_screen = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
  {
    fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
    return APP_FAILED;
  }

  // Create timer
  _timer = SDL_AddTimer(_interval, SdlApplication::_onTimerCb, reinterpret_cast&amp;lt;void*&gt;(this));

  // Success.
  return APP_OK;
}

void SdlApplication::destroy()
{
  if (_screen)
  {
    SDL_RemoveTimer(_timer);
    SDL_FreeSurface(_screen);
    SDL_Quit();

    _screen = NULL;
  }
}

int SdlApplication::run(int width, int height)
{
  // Initialize application.
  int state = init(width, height);
  if (state != APP_OK) return state;

  // Enter to the SDL event loop.
  SDL_Event ev;
  _running = true;

  while (SDL_WaitEvent(&amp;amp;ev))
  {
    onEvent(&amp;amp;ev);
    if (_running == false) break;
  }

  return APP_OK;
}

void SdlApplication::onEvent(SDL_Event* ev)
{
  switch (ev-&amp;gt;type)
  {
    case SDL_QUIT:
      _running = false;
      break;

    case SDL_USEREVENT:
      // This is our timer event.
      onTimer();
      break;
  }
}

Uint32 SdlApplication::_onTimerCb(Uint32 interval, void* param)
{
  // On timer callback is called from different thread, we just send custom event
  // back to the main one.
  SdlApplication* app = reinterpret_cast&amp;lt;SdlApplication*&gt;(param);

  SDL_UserEvent e;
  memset(&amp;amp;e, 0, sizeof(e));
  e.type = SDL_USEREVENT;
  SDL_PushEvent(reinterpret_cast&amp;lt;SDL_Event*&amp;gt;(&amp;amp;e));

  return interval;
}

void SdlApplication::onTimer()
{
  // Do some stuff...
  _rotate += 0.01;

  // Render new frame.
  onRender();
}

void SdlApplication::onRender()
{
  // Lock surface pixels.
  SDL_LockSurface(_screen);

  // Create Fog::Painter instance mapped to the SDL surface data.
  Fog::Painter p;

  // Setup image buffer for painter.
  Fog::ImageBits buf;

  buf.setRaw(reinterpret_cast&amp;lt;uint8_t*&amp;gt;(_screen-&amp;gt;pixels),
    Fog::SizeI(_screen-&amp;gt;w, _screen-&amp;gt;h),
    Fog::IMAGE_FORMAT_XRGB32, 
    _screen-&amp;gt;pitch);

  // Call our paint handler.
  if (p.begin(buf) == Fog::ERR_OK) onPaint(p);

  // Never forget to call p.end(). Painting can be asynchronous and
  // SDL_UnlockSurface() can invalidate the surface-&amp;gt;pixels pointer.
  p.end();

  // Unlock surface pixels.
  SDL_UnlockSurface(_screen);

  // Flip buffer.
  SDL_Flip(_screen);
}

void SdlApplication::onPaint(Fog::Painter&amp;amp; p)
{
  // Just use the Fog-Framework ;-)

  // Create some variable we will work with.
  float w = float(_screen-&amp;gt;w);
  float h = float(_screen-&amp;gt;h);

  float roundw = 100.0f;
  float roundh = 100.0f;

  Fog::PointF cp(w / 2.0f, h / 2.0f);

  // Clear the entire screen.
  p.setSource(Fog::Argb(0xFF000000));
  p.fillAll();

  p.save();

  // Rotate across the screen center point.
  p.transform(createRotationMatrix(cp, _rotate));

  // And draw something...
  Fog::LinearGradientF gradient;

  gradient.setPoints(
    Fog::DoublePoint(cp.x - roundw / 2.0f, cp.y - roundh / 2.0f),
    Fog::DoublePoint(cp.x + roundw / 2.0f, cp.y + roundh / 2.0f));
  gradient.addStop(Fog::ArgbStop(0.0f, Fog::Argb32(0xFFFFFFFF)));
  gradient.addStop(Fog::ArgbStop(0.5f, Fog::Argb32(0xFFFFFF00)));
  gradient.addStop(Fog::ArgbStop(1.0f, Fog::Argb32(0xFFFF0000)));

  p.setSource(pattern);
  p.fillRound(Fog::RoundF(
    Fog::RectF(cp.x - roundw / 2.0f, cp.y - roundh / 2.0f, roundw, roundh),
    Fog::PointF(20.0f, 20.0f))
  );

  p.restore();
}

// ============================================================================
// [Entry-Point]
// ============================================================================

// SDL may redeclare main to something else, cut it.
#undef main

int main(int argc, char* argv[])
{
  SdlApplication app;
  return app.run(640, 480);
}
&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Fog-Framework isn't the only library you can use with SDL. There are many libraries that can do the job, but Fog-Framework is single library that covers various problems without extra dependencies. Another reason to use Fog is that it's one of the fastest open-source libraries available, so give it a try;-)&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_1uWuBHvqyec/S8Z-5kK7rNI/AAAAAAAAADc/ZZ9eP7Gy5cM/s1600/sdlexample.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 313px;" src="http://2.bp.blogspot.com/_1uWuBHvqyec/S8Z-5kK7rNI/AAAAAAAAADc/ZZ9eP7Gy5cM/s400/sdlexample.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5460191125660478674" /&gt;&lt;/a&gt;

&lt;p&gt;The presented example should work and will be updated to work with current Fog-trunk.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-5356529038715614037?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/5356529038715614037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/04/using-fog-in-within-sdl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5356529038715614037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5356529038715614037'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/04/using-fog-in-within-sdl.html' title='Using Fog with SDL'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1uWuBHvqyec/S8Z-5kK7rNI/AAAAAAAAADc/ZZ9eP7Gy5cM/s72-c/sdlexample.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-124349765152815695</id><published>2010-04-12T14:51:00.005+02:00</published><updated>2010-04-15T18:48:58.559+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='assembler'/><title type='text'>Using the MMX extensions without -msse (GCC)</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Yesterday I ported the Fog-Framework to the MinGW. The biggest problem was with porting current pure MMX-EXT code to GCC without using a -msse parameter (this means you can't include xmmintrin.h).&lt;/p&gt;

&lt;p&gt;Problem is that if you not enable SSE then you can't use MMX extensions in the code. Fog-Framework contains MMX, MMX+SSE, MMX+3dNow and SSE2 stack so I really needed to take advantage of one intrinsic in the MMX+3dNow code - _mm_movemask_pi8() (PMOVMSKB in assembler).&lt;/p&gt;

&lt;h2&gt;Solution&lt;/h2&gt;

&lt;p&gt;I created new IntrinMMXExt.h header file that is included only if SSE is not used. This header currently defines only the missing function I needed, but it can be extended in the future. The function is here, it's written using GCC assembly (GAS) and it should fit into your code without any changes:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
static inline int _mm_movemask_pi8(__m64 a)
{
  int result;
  __asm__(&amp;quot;pmovmskb %1, %0\n\t" : "=r"(result) : "y"(a));
  return result;
}
&lt;/pre&gt;

&lt;p&gt;The most interesting part of code is &lt;code&gt;:&amp;quot;y"(a)&lt;/code&gt; that tells GCC that &lt;code&gt;a&lt;/code&gt; must be in MMX register. If you want to use XMM register then it will be &lt;code&gt;"x"&lt;/code&gt;. I never expected that it will be so easy to write such function, enjoy:)&lt;/p&gt;

&lt;h2&gt;Letters explanation used in __asm__ block&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&amp;quot;abcd&amp;quot; - AX, BX, CX or DX register.&lt;/li&gt;
&lt;li&gt;&amp;quot;q" - AX, BX, CX or DX register, low-byte when using 8-bit register (AL, BL, CL, DL).&lt;/li&gt;
&lt;li&gt;&amp;quot;Q&amp;quot; - AX, BX, CX or DX register, high-byte when using 8-bit register (AH, BH, CH, DH).&lt;/li&gt;
&lt;li&gt;&amp;quot;SD&amp;quot; - SI or DI registers.&lt;/li&gt;
&lt;li&gt;&amp;quot;A" - EDX:EAX registers (64-bit value in two registers).&lt;/li&gt;
&lt;li&gt;&amp;quot;y&amp;quot; - MM register.&lt;/li&gt;
&lt;li&gt;&amp;quot;x" - XMM register.&lt;/li&gt;
&lt;li&gt;&amp;quot;t&amp;quot; - ST(0) register (floating point).&lt;/li&gt;
&lt;li&gt;&amp;quot;r&amp;quot; - General purpose register.&lt;/li&gt;
&lt;li&gt;&amp;quot;m&amp;quot; - Memory.&lt;/li&gt;
&lt;li&gt;&amp;quot;i&amp;quot; - Immediate.&lt;/li&gt;
&lt;li&gt;&amp;quot;g&amp;quot; - Memory, general purpose register or immediate.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-124349765152815695?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/124349765152815695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/04/using-mmx-extensions-without-msse-gcc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/124349765152815695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/124349765152815695'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/04/using-mmx-extensions-without-msse-gcc.html' title='Using the MMX extensions without -msse (GCC)'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-816210065903350394</id><published>2010-04-11T23:26:00.012+02:00</published><updated>2010-04-16T09:24:50.509+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog - Layers and clipping to paths</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;There is one rule I broke today - "never write more than one post per day". But I hope that people that's following my blog will forgive me :-). Currently I'm working on layers and clipping to paths (painter related) and I'm getting troubles to finish this stuff. I'd like to expand more about clipping, the design I'm preparing and multithreading issues, or features?&lt;/p&gt;

&lt;h2&gt;Abstract&lt;/h2&gt;

&lt;p&gt;Let's summarize the goals in a few points:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Define clipping API, clipping will be part of Fog::Painter.&lt;/li&gt;
 &lt;li&gt;Allow to clip to rectangles or a path, the API should be similar as the current painting API.&lt;/p&gt;
 &lt;li&gt;Allow these clipping operations - COPY, UNION, INTERSECT, XOR and SUBTRACT.&lt;/li&gt;
 &lt;li&gt;Allow using the actual opacity when clipping paths.&lt;/li&gt;
 &lt;li&gt;Allow save() / restore(), make it very efficient.&lt;/li&gt;
 &lt;li&gt;Clipping API inside rendering routines must be very efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;API Proposal&lt;/h2&gt;

&lt;p&gt;The API proposal (it can change, it's only what I'm working with):&lt;/p&gt;

&lt;pre class="lang-c"&gt;
struct FOG_API PaintEngine
{
  // Only additions, not the whole PaintEngine.

  // Clip parameters.
  virtual uint32_t getClipRule() const = 0;
  virtual err_t setClipRule(uint32_t clipRule) = 0;

  virtual float getClipAlpha() const = 0;
  virtual err_t setClipAlpha(float alpha) = 0;

  // Raster clipping.
  virtual err_t clipRect(
    const IntRect&amp;amp; rect,
    uint32_t clipOp) = 0;

  virtual err_t clipMask(
    const IntPoint&amp;amp; pt,
    const Image&amp; mask,
    uint32_t clipOp) = 0;

  virtual err_t clipRegion(
    const Region&amp;amp; region,
    uint32_t clipOp) = 0;

  // Vector clipping.
  virtual err_t clipRect(
    const DoubleRect&amp;amp; rect,
    uint32_t clipOp) = 0;

  virtual err_t clipMask(
    const DoublePoint&amp;amp; pt,
    const Image&amp; mask,
    uint32_t clipOp) = 0;

  virtual err_t clipRects(
    const DoubleRect* r,
    sysuint_t count,
    uint32_t clipOp) = 0;

  virtual err_t clipRound(
    const DoubleRect&amp;amp; r,
    const DoublePoint&amp; radius,
    uint32_t clipOp) = 0;

  virtual err_t clipEllipse(
    const DoublePoint&amp;amp; cp,
    const DoublePoint&amp; r,
    uint32_t clipOp) = 0;

  virtual err_t clipArc(
    const DoublePoint&amp;amp; cp, 
    const DoublePoint&amp; r, 
    double start,
    double sweep,
    uint32_t clipOp) = 0;

  virtual err_t clipPath(
    const DoublePath&amp;amp; path,
    uint32_t clipOp) = 0;

  virtual err_t resetClip() = 0;
};
&lt;/pre&gt;

&lt;p&gt;Clipping operators and flags are defined in the Fog/Graphics/Constants.h:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
enum CLIP_OP
{
  CLIP_OP_MASK = 0xFFFF,

  CLIP_OP_COPY = 0,
  CLIP_OP_UNION = 1,
  CLIP_OP_INTERSECT = 2,
  CLIP_OP_XOR = 3,
  CLIP_OP_SUBTRACT = 4,

  CLIP_OP_COUNT = 5
};

enum CLIP_FLAGS
{
  CLIP_FLAG_MASK = 0x0000FF00,

  CLIP_FLAG_STROKE = 0x00000100,
  CLIP_FLAG_INVERT = 0x00000200
};
&lt;/pre&gt;

&lt;h2&gt;Discussion&lt;/h2&gt;

&lt;p&gt;You should imagine that goals are very rich, if everything will be completed then Fog::Painter will be one of most featured painting class in 2d graphics libraries today. The biggest problem with this all stuff is to make clipping memory and performance efficient. For example examine this scenario:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
void paintSomething(Painter&amp;amp; p)
{
  // Save state.

  p.save();

  // Reset the clipping region to our rectangle. The resulting 
  // clip region will be one rectangle at:
  //
  //   [100, 100] -&gt; [200, 200].

  p.clipRect(
    IntRect(100, 100, 100, 100),
    CLIP_OP_COPY);

  // Unite the current clipping rectangle with a new rectangle,
  // using Fog::Region API, the resulting clipping region will
  // be three rectangles at: 
  //
  //   [100, 100, 200, 150]
  //   [100, 150, 250, 200]
  //   [150, 200, 250, 250]
  //
  // Good is that painter can clip to more than one rectangle and
  // it's well optimized already.

  p.clipRect(
    IntRect(150, 150, 100, 100),
    CLIP_OP_UNION);

  // We should do something more exacting, we will intersect current
  // clipping region with circle. Generally this will result to making
  // clip-mask from current clipping region, rasterizing ellipse, and
  // doing intersect operation with the clip-mask.

  p.clipEllipse(
    DoublePoint(125.0, 125.0),
    DoublePoint(100.0, 80.0),
    CLIP_OP_INTERSECT);

  // Now I'm sure that we have clipping-mask created, so each painter
  // command will be blit using this clip-mask. This is also optimized,
  // but generally slower than using simple clip region.
  //
  // If we can fill everything we should see the region we created.
  // The ellipse corners must be anti-aliased.

  p.setSource(Argb(0xFFFFFFFF));
  p.fillAll();

  // And the now we enter to the interesting problem. We want to save
  // state and intersect our region with something else. The painter
  // engine must be able to optimize such thing, because we don't want
  // to copy data to new clip mask that will be never rewritten.

  p.save();

  // So clip to smaller ellipse using XOR operator.

  p.clipEllipse(
    DoublePoint(125.0, 125.0),
    DoublePoint(50.0, 50.0),
    CLIP_OP_XOR);

  // And fill all using 50% opacity to see what happened.

  p.setSource(Argb(0x7F0000FF));
  p.fillAll();

  // Restore the saved state (including clipping).

  p.restore();

  // Restore the master state (to the state used before 
  // this function was called).
  p.restore();
}
&lt;/pre&gt;

&lt;p&gt;The example should be very explanatory how the paint engine works. If clipping area can be described by one or more rectangles aligned to pixel grid, then Fog::Region is used. This is the most optimized clipping and I expect that it will be the most used one. If it's needed to clip to text, shape or to set another image as a clip-mask then paint engine must create temporary buffer where the clipping bits will be set. We are talking about mask, but this mask must be smarter than common image container. I solved clip-mask inside painter using these techniques:&lt;/p&gt;

&lt;ul&gt;

 &lt;li&gt;Clip-mask state ID - Each painter state has ID that is incremented or decremented calling the Painter::save() or Painter::restore() methods, respectively. This state is also saved to clip-mask. This all prevents against modification clip-mask that has lower clip-state than the current state is. Note that when used multithreaded renderer the context states can be totally different at some time (for example thread-#1 can work with clip-mask-#4 and thread-#2 can work with clip-mask-#8).&lt;/li&gt;

 &lt;li&gt;Clip spans - Each paint context (main or worker one) contains special memory allocator that is responsible for allocating data used by the clipping engine. Each row contains pointer to the header. If the pointer is NULL then this row is fully clipped, otherwise it's pointer to small data structure that contains linked list of clip-spans. Clip span can be mask or single-value container (so handling semi-transparent clip spans is as fast as handling full opaque ones). The last problem were to solve data ownership. I solved it by using one bit in pointer (which is never used by pointer itself, hackery, mostly used by scripting languages and VMs) that is ORed with the pointer to header. If the bit is set then you can't modify the clip-spans, copy must be made instead. Although the design seems to be complicated it's not too much complicated as it may be looking.&lt;/li&gt;

 &lt;li&gt;Multithreaded design using existing concepts in RasterPaintEngine - Using delta and offset to work on raster buffer and clip-buffer too. Simple clip operations (rectangles based) are performed by main-thread, but mask-clip operations are performed by workers (if multithreading is used) asynchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;You can see that it's not simple so expect some weeks until this all will be ready, but when finished I'm expecting really great API and performance.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-816210065903350394?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/816210065903350394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-layers-and-clipping-to-paths.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/816210065903350394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/816210065903350394'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-layers-and-clipping-to-paths.html' title='Fog - Layers and clipping to paths'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-7238908075853620004</id><published>2010-04-11T17:56:00.009+02:00</published><updated>2010-04-15T18:52:04.329+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><title type='text'>Fog and MinGW</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;It's few days I wanted to measure performance using GCC 4.4 compiler under Windows (MinGW project) and MS compiler that comes with Visual Studio 2005. I know that GCC 3.X that comes with classic MinGW distribution is not usable, because the SSE2 code will crash (variables that must be aligned to 16-bytes aren't actually aligned). But I found TDM's builds &lt;a href="http://www.tdragon.net/recentgcc/"&gt;here&lt;/a&gt; that comes with GCC 4.4 so I wanted to try it. It's classic MinGW distribution that contains everything you need to compile Fog under Windows.&lt;/p&gt;

&lt;h2&gt;Problems&lt;/h2&gt;

&lt;p&gt;Porting to different compilers can be sometimes problem, but Fog-Framework can be already compiled under Linux by GCC so this should not be issue there, but it was! See next list for summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SEH (Structured Exception Handling) support (currently the support is half or none). I disabled setting thread name which required SEH under Windows.&lt;/li&gt;
&lt;li&gt;__uuidof keyword is not supported. I added the declaration to Fog/Core/WinCom_p.h file.&lt;/li&gt;
&lt;li&gt;SSE2 aligned variables (GCC 3.X is unsupported by Fog-Framework).&lt;/li&gt;
&lt;li&gt;Some MMX issues (for example _mm_movemask_pi8() isn't declared by mmintrin, but only by xmmintrin.h). This is ugly, because you can't use this instruction in 3dNow code (or code that is not using SSE and xmmintrin.h header at all).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Status&lt;/h2&gt;

&lt;p&gt;Currently I &lt;s&gt;failed&lt;/s&gt;, but there is only little work getting it working. The MMX issue killed my efforts and I haven't more time to port Fog-Framework to MinGW. I think that MSVC builds will be always preferred so MinGW support is not too important at this stage.&lt;/p&gt;

&lt;p&gt;Tried it again, solved all remaining issues and get Fog-Framework working with MinGW. The SSE2 code seems to work.&lt;/p&gt;

&lt;h2&gt;Benchmarks&lt;/h2&gt;

&lt;p&gt;Fog compiled by MSVC from Visual Studio 2005:&lt;/p&gt;

&lt;pre&gt;
Fog-st                |Size      |Time
----------------------+----------+---------------
Create-Destroy        |          |     8.556 [ms]
FillRect              |8x8       |   114.737 [ms]
FillRectAffine        |8x8       |   661.535 [ms]
FillRound             |8x8       |  1255.336 [ms]
FillPolygon           |8x8       |   849.288 [ms]
LinearGradient        |8x8       |   123.087 [ms]
Image                 |8x8       |    73.623 [ms]
ImageAffine           |8x8       |   690.516 [ms]
FillRect              |16x16     |   147.333 [ms]
FillRectAffine        |16x16     |  1206.372 [ms]
FillRound             |16x16     |  1762.231 [ms]
FillPolygon           |16x16     |  1605.876 [ms]
LinearGradient        |16x16     |   348.908 [ms]
Image                 |16x16     |   192.550 [ms]
ImageAffine           |16x16     |  1605.280 [ms]
FillRect              |32x32     |   426.969 [ms]
FillRectAffine        |32x32     |  2390.545 [ms]
FillRound             |32x32     |  2384.321 [ms]
FillPolygon           |32x32     |  3225.605 [ms]
LinearGradient        |32x32     |  1142.196 [ms]
Image                 |32x32     |   605.737 [ms]
ImageAffine           |32x32     |  4589.409 [ms]
FillRect              |64x64     |  1442.734 [ms]
FillRectAffine        |64x64     |  5319.678 [ms]
FillRound             |64x64     |  4051.782 [ms]
FillPolygon           |64x64     |  6466.598 [ms]
LinearGradient        |64x64     |  4109.335 [ms]
Image                 |64x64     |  2114.683 [ms]
ImageAffine           |64x64     | 15363.219 [ms]
FillRect              |128x128   |  5248.772 [ms]
FillRectAffine        |128x128   | 13056.322 [ms]
FillRound             |128x128   |  8969.170 [ms]
FillPolygon           |128x128   | 13303.179 [ms]
LinearGradient        |128x128   | 15219.043 [ms]
Image                 |128x128   |  6686.566 [ms]
ImageAffine           |128x128   | 57204.439 [ms]
---------------------------------+---------------
Summary                          |183965.512 [ms]
&lt;/pre&gt;

&lt;p&gt;Fog compiled by MinGW, GCC 4.4:&lt;/p&gt;

&lt;pre&gt;
Fog-st                |Size      |Time
----------------------+----------+---------------
Create-Destroy        |          |     9.704 [ms]
FillRect              |8x8       |   177.904 [ms]
FillRectAffine        |8x8       |   783.850 [ms]
FillRound             |8x8       |  1648.189 [ms]
FillPolygon           |8x8       |  1000.516 [ms]
LinearGradient        |8x8       |   147.183 [ms]
Image                 |8x8       |    78.658 [ms]
ImageAffine           |8x8       |   802.412 [ms]
FillRect              |16x16     |   151.563 [ms]
FillRectAffine        |16x16     |  1358.739 [ms]
FillRound             |16x16     |  2178.581 [ms]
FillPolygon           |16x16     |  1832.505 [ms]
LinearGradient        |16x16     |   379.035 [ms]
Image                 |16x16     |   201.049 [ms]
ImageAffine           |16x16     |  1670.730 [ms]
FillRect              |32x32     |   432.374 [ms]
FillRectAffine        |32x32     |  2622.023 [ms]
FillRound             |32x32     |  2822.627 [ms]
FillPolygon           |32x32     |  3563.021 [ms]
LinearGradient        |32x32     |  1142.975 [ms]
Image                 |32x32     |   620.877 [ms]
ImageAffine           |32x32     |  4416.297 [ms]
FillRect              |64x64     |  1430.939 [ms]
FillRectAffine        |64x64     |  5707.836 [ms]
FillRound             |64x64     |  4540.674 [ms]
FillPolygon           |64x64     |  7114.262 [ms]
LinearGradient        |64x64     |  3832.149 [ms]
Image                 |64x64     |  2167.543 [ms]
ImageAffine           |64x64     | 14033.499 [ms]
FillRect              |128x128   |  5177.839 [ms]
FillRectAffine        |128x128   | 13816.561 [ms]
FillRound             |128x128   |  9868.423 [ms]
FillPolygon           |128x128   | 14507.163 [ms]
LinearGradient        |128x128   | 13908.575 [ms]
Image                 |128x128   |  6668.388 [ms]
ImageAffine           |128x128   | 50864.119 [ms]
---------------------------------+---------------
Summary                          |181678.674 [ms]
&lt;/pre&gt;

&lt;p&gt;The results are pretty interesting, the LinearGradient and ImageAffine tests are significantly better compiled by GCC.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-7238908075853620004?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/7238908075853620004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-and-mingw.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/7238908075853620004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/7238908075853620004'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/04/fog-and-mingw.html' title='Fog and MinGW'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-712984771083183338</id><published>2010-03-06T18:17:00.013+01:00</published><updated>2011-10-08T16:22:20.168+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog and C++ exceptions</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Last few weeks I'm thinking about something I rejected a many years ago - C++ exceptions and RTTI. The reason I rejected these features is that it makes resulting binary code bigger and writing exception safe code is a bit different. I think that the major part of Fog code is exception safe, but I can't assure that all the code really is.&lt;/p&gt;

&lt;p&gt;The most interesting question is why? I'm asking yourself, why? Fog-Framework contains error codes for almost everything. It's quite simple to add new ones, it's simple to use operating system ones and it's simple to propagate error codes to the caller (just return them). &lt;/p&gt;

&lt;h2&gt;Code bloat&lt;/h2&gt;

&lt;p&gt;Fog is currently always compiled without exceptions and RTTI, because it makes resulting binary compiled by GCC smaller (about 10-15%, more for 64-bit). The most interesting thing is that MSVC can compile code with exceptions much better (resulting code grows only by few kilobytes). Personally I'm calling this as a true code-bloat and it's sometimes a very good argument from hardcore-C lovers against C++. Unfortunately for them - it can be turned off!&lt;/p&gt;

&lt;p&gt;Let me show the pros and cons of current Fog-Framework code base.&lt;/p&gt;

&lt;h2&gt;Pros (code without exceptions)&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;Exceptions, STL and RTTI features are not used/needed.&lt;/li&gt;
 &lt;li&gt;Resulting binary code is smaller (15% is very good).&lt;/li&gt;
 &lt;li&gt;It's not needed to write exception-safe code.&lt;/li&gt;
 &lt;li&gt;Error codes are lightweight and enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Cons (code without exceptions)&lt;/h2&gt;

&lt;ul&gt;
 &lt;li&gt;Exception enabled code can be more readable.&lt;/li&gt;
 &lt;li&gt;Checking for errors is sometimes annoying, because in most cases there are checks for memory allocation failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Model cases&lt;/h2&gt;

&lt;p&gt;I'd like to show some model cases where I think that exceptions are good and where don't. The first example demonstrates Fog::StringW and checking for error codes. I think that here the exception enabled code could be more readable (Here only memory allocation failure can happen).&lt;/p&gt;

&lt;pre class="lang-c"&gt;
err_t test(Fog::StringW&amp;amp; result)
{
  // Error can be only be returned in case that there is not enough
  // memory to allocate the array of characters needed for the string.
  err_t err;

  err = result.set(Fog::Ascii8("Hello World"));
  if (FOG_IS_ERROR(err)) return err;

  err = result.append(Fog::CharW('!'));
  if (FOG_IS_ERROR(err)) return err;

  return Fog::ERR_OK;
}
&lt;/pre&gt;

&lt;p&gt;In next example I think that error codes make sense and I like them very much:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
err_t test(const Fog::StringW&amp;amp; fileName)
{
  Fog::Stream stream;
  err_t err;

  // Here I think that error code is better. It must be processed by caller 
  // in all cases (opening a file seems to be an important task). The most
  // expected error should be related to a filesystem (file not found) or to 
  // user permissions (can't read).
  err = stream.openFile(fileName, Fog::STREAM_OPEN_READ);
  if (FOG_IS_ERROR(err)) return err;

  // And history repeats itself :)
  err = stream.truncate(0);
  if (FOG_IS_ERROR(err)) return err;

  // ...

  return Fog::ERR_OK;
}
&lt;/pre&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I'm staying with exception-free code (no exceptions, RTTI and STL) and I will probably never use them in my libraries in the future. I forget to mention one important reason in the PROS section - any application or library can use Fog-Framework as a third-party product without switching to exceptions or RTTI. If you like exceptions, just use them;)&lt;/p&gt;

&lt;h2&gt;Suggestions&lt;/h2&gt;

&lt;p&gt;Error codes can be simply turned to exceptions by using macros. For example following macro will test result of the expression inside and throw an Exception on error condition:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
// Define our macro.
#define FOG_THROW_ON_ERROR(expression) \
  do { \
    err_t __err_inside = (expression); \
    if (FOG_IS_ERROR(__err_inside)) \
      throw new Exception(__err_inside); \
  } while (0)

// Use our macro.
Fog::Stream stream;
FOG_THROW_ON_ERROR( stream.openFile(fileName, Fog::STREAM_OPEN_WRITE) );
&lt;/pre&gt;

&lt;p&gt;Our macro can be rewritten to the more robust form allowing you to do more than only throw exception (for example you can log it):&lt;/p&gt;

&lt;pre class="lang-c"&gt;
void error_handler(err_t err)
{
  throw new Exception(err);
}

#define FOG_THROW_ON_ERROR(expression) \
  do { \
    err_t __err_inside = (expression); \
    if (FOG_IS_ERROR(__err_inside)) \
      error_handler(__err_inside); \
  } while (0)
&lt;/pre&gt;

&lt;p&gt;Also the similar macro can be written for current code-base. I added following macro to help with readability of the code:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
#define FOG_RETURN_ON_ERROR(expression) \
  do { \
    err_t __err_inside = (expression); \
    if (FOG_IS_ERROR(__err_inside)) \
      return __err_inside; \
  } while (0)
&lt;/pre&gt;

&lt;p&gt;The comparison between the first example with and without the macro is here:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
// Old (without macro).
err_t test(Fog::StringW&amp;amp; result)
{
  // Error can be only be returned in case that there is not enough
  // memory to allocate the array of characters needed for the string.
  err_t err;

  err = result.set(Fog::Ascii8("Hello World"));
  if (FOG_IS_ERROR(err)) return err;

  err = result.append(Fog::CharW('!'));
  if (FOG_IS_ERROR(err)) return err;

  return Fog::ERR_OK;
}

// New (with macro).
err_t test(Fog::StringW&amp;amp; result)
{
  FOG_RETURN_ON_ERROR( result.set(Fog::Ascii8("Hello World")) );
  FOG_RETURN_ON_ERROR( result.append(Fog::CharW('!')) );

  return Fog::ERR_OK;
}
&lt;/pre&gt;

&lt;h2&gt;Conclusion 2&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;FOG_RETURN_ON_ERROR()&lt;/code&gt; is now a standard way of how to propagate errors to the called. It's suitable in most of cases, but there are still some cases where standard &lt;code&gt;err = ...; if (err) ...&lt;/code&gt; code needs to be processed, because on error condition additional cleanup code needs to be run.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-712984771083183338?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/712984771083183338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/03/fog-and-c-exceptions.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/712984771083183338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/712984771083183338'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/03/fog-and-c-exceptions.html' title='Fog and C++ exceptions'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-166342766068219923</id><published>2010-02-27T09:09:00.004+01:00</published><updated>2010-04-15T18:53:37.823+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>ImageIO::GdiPlus work continues</title><content type='html'>&lt;h2&gt;Finally&lt;/h2&gt;

&lt;p&gt;It's weekend and I get some time to work on Fog again. Today I finished basic support for writing images through GDI+ ImageIO backend (Fog::ImageIO::GdiPlusEncoderDevice class). The idea of proxy providers (and proxy encoders / decoders) is gone (also the related constants are away), because it was too complex to implement it correctly. Instead there is provider for each supported image file type (at this time there are only three - jpeg, png and tiff).&lt;/p&gt;

&lt;p&gt;The API is fully integrated with rest of Fog-Framework, but I found that I'm not able to use progress indication (I didn't find the API in GdiPlus). Currently also properties are not supported (so for example you can't set jpeg compression), but I will fix this very soon.&lt;/p&gt;

&lt;h2&gt;What's next?&lt;/h2&gt;

&lt;p&gt;Next thing I want to improve in Fog library is raster engine. I want to implement all remaining stuff needed to make Fog fully usable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow painting to ARGB32 and A8 images, currently Fog can crash:-).&lt;/li&gt;
&lt;li&gt;Improve image filtering, allow to use filters by painter and take advantage of multithreading.&lt;/li&gt;
&lt;li&gt;Allow to set global painter opacity.&lt;/li&gt;
&lt;li&gt;Fix font backends to support kerning and hinting.&lt;/li&gt;
&lt;li&gt;Write pure MMX backend (the machine where I'm currently sitting is not SSE2 capable and Fog performance is very close to Gdi+).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't know which point I implement first, but I want to first finish raster engine stuff and then move to vectors. After all of this will be finished I'm looking forward to write widgets in Fog/Gui.&lt;/p&gt;

&lt;p&gt;That's all, enjoy my work!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-166342766068219923?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/166342766068219923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/02/imageiogdiplus-work-continues.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/166342766068219923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/166342766068219923'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/02/imageiogdiplus-work-continues.html' title='ImageIO::GdiPlus work continues'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-6302676796453075742</id><published>2010-02-14T22:41:00.001+01:00</published><updated>2010-02-28T06:37:33.994+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>ImageIO::GdiPlus Support</title><content type='html'>&lt;p&gt;Recently I haven't time to write status of Fog library. Of course there are some news, but I thing that everything is moving so slow. This weekend I worked on windows-only machine so I tried to make Gdi+ support in &lt;code class="lang-c"&gt;Fog::ImageIO&lt;/code&gt;. The reason is that this is native library under Windows (like libpng and libjpeg under unix). It wasn't easy.&lt;/p&gt;

&lt;h2&gt;IStream&lt;/h2&gt;

&lt;p&gt;Firstly I needed to create &lt;code class="lang-c"&gt;IStream&lt;/code&gt; &amp;lt;-&amp;gt; &lt;code class="lang-c"&gt;Fog::Stream&lt;/code&gt; bridge. The default &lt;a href="http://msdn.microsoft.com/en-us/library/ms752876%28VS.85%29.aspx"&gt;IStream implementation from MSDN&lt;/a&gt; helped me a lot to complete &lt;code class="lang-c"&gt;Fog::WinIStream&lt;/code&gt; class that implements some methods from &lt;code class="lang-c"&gt;IStream&lt;/code&gt; and &lt;code class="lang-c"&gt;ISequentalStream&lt;/code&gt; interface. &lt;code class="lang-c"&gt;Fog::WinIStream&lt;/code&gt; is used internally and it's not exported.&lt;/p&gt;

&lt;h2&gt;GdiPlusProvider&lt;/h2&gt;

&lt;p&gt;Secondly the &lt;code class="lang-c"&gt;Fog::ImageIO::GdiPlusProvider&lt;/code&gt; was needed. The design goal was to create provider that will be able to use &lt;code class="lang-c"&gt;Fog::Stream&lt;/code&gt; API (like all other providers do). The &lt;code class="lang-c"&gt;Fog::Stream&lt;/code&gt; is used to create &lt;code class="lang-c"&gt;Fog::WinIStream&lt;/code&gt; instance that implements &lt;code class="lang-c"&gt;IStream&lt;/code&gt; interface. GdiPlus supports &lt;code class="lang-c"&gt;IStream&lt;/code&gt; interface for Input/Output so image reading and writing using native &lt;code class="lang-c"&gt;Fog::Stream&lt;/code&gt; is now supported.&lt;/p&gt;

&lt;h2&gt;Dependencies&lt;/h2&gt;

&lt;p&gt;GdiPlus provider is runtime loading dependency and I wrote it in way that no GdiPlus header files are needed to compile Fog with GdiPlus support. Fog is using runtime loaded &lt;a href="http://msdn.microsoft.com/en-us/library/ms533969%28VS.85%29.aspx"&gt;GdiPlus Flat API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Status&lt;/h2&gt;

&lt;p&gt;Currently only a &lt;code class="lang-c"&gt;Fog::ImageIO::GdiPlusDecoderDevice&lt;/code&gt; is functional, encoder needs still some work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-6302676796453075742?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/6302676796453075742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2010/02/imageiogdiplus-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6302676796453075742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6302676796453075742'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2010/02/imageiogdiplus-support.html' title='ImageIO::GdiPlus Support'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-6042175700754698187</id><published>2009-10-19T03:09:00.001+02:00</published><updated>2010-03-31T17:59:27.242+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='blitjit'/><title type='text'>Fog vs BlitJit - Benchmarking SrcOver</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;It's some time ago I wanted to know &lt;a href="http://code.google.com/p/blitjit/"&gt;BlitJit&lt;/a&gt; library possibilities. BlitJit library is library that allows to jit compile graphics functions so they can be called from C/C++ code. But question is how good is the code this library produces compared to SSE2 code in Fog? The SSE2 code in Fog library is written using inline SSE2 intrinsics, BlitJit code generator can generate code only using SSE2 intrinsics, so we are talking about comparing SSE2 code generated by different code generators - gcc vs BlitJit that's using &lt;a href="http://code.google.com/p/asmjit/"&gt;AsmJit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Static vs Dynamic code&lt;/h2&gt;

&lt;p&gt;Before I show code generator example I'd like to explain differences in static and dynamic assembler. Static assembler is used by Fog library (through C++ intrinsics) and it's compiled by C++ compiler into shared library (machine code). After the shared library is loaded the code can run (this means that code is interpreted by host processor). Dynamic code generation is concept used to dynamically compile code (usually on-the-fly). This is usually done for performance (compiling inner loops, graphics, sound effects) or as a cross-platform solution for some programming languages (Java, LLVM, etc).&lt;/p&gt;

&lt;p&gt;Summary of basic differences:&lt;/p&gt;

&lt;table class="table"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Static code&lt;/td&gt;&lt;td&gt;Dynamic code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;CPU:&lt;/td&gt;&lt;td&gt;Compiled for host compatible CPU&lt;/td&gt;&lt;td&gt;Dynamic compiler can compile to any supported CPU on-the-fly&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Code storage:&lt;/td&gt;&lt;td&gt;Shared libraries, executables&lt;/td&gt;&lt;td&gt;Process virtual memory&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Optimizations:&lt;/td&gt;&lt;td&gt;Compiler (C/C++/...) or hand written (Asm), architecture and CPU features must be set before compilation&lt;/td&gt;&lt;td&gt;Hand written, JIT compiler can optimize better for current CPU (SSE2, SSE3) and take adventage of embedding constants, drastically expanding inner loops, etc...&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Code sharing:&lt;/td&gt;&lt;td&gt;Static code is usually shared between processes (shared libraries)&lt;/td&gt;&lt;td&gt;Dynamic code is normally not shared between processes, but can be (Java, .NET)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Complexity:&lt;/td&gt;&lt;td&gt;Normal&lt;/td&gt;&lt;td&gt;Very complex, need time to study asm and to write good code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Performance:&lt;/td&gt;&lt;td&gt;Very good&lt;/td&gt;&lt;td&gt;Best (you can recompile loops, embed constants, etc...)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2&gt;Benchmark suite&lt;/h2&gt;

&lt;p&gt;So you should now know basic differences in theory, let's look into practice. The function that was benchmarked is SrcOver for 32-bit premultiplied ARGB source and destination. I'm benchmarked span blitter (one row per time) in Fog library and two span blitters generated by BlitJit (JITed). First generated function is using four pixels in inner loop, second eight pixels in inner loop. My machine contains Core Quad Q6600@2.4GHz and I'm running Gentoo Linux (64-bit), kernel 2.6.30, gcc 4.4.1. I think that other information are not important, because we are talking all the time about software rendering.&lt;/p&gt;

&lt;p&gt;Benchmarking function makes 500x blit of source image (128x128) into destination image (400x400) using provided blitter. Main function and helper are here:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
static void _blitImage(Fog::Image&amp;amp; dst, int x, int y, const Fog::Image&amp;amp; src, BlitterFn blitter)
{
  sysint_t i;

  sysint_t w = src.getWidth();
  sysint_t h = src.getHeight();

  sysint_t dstStride = dst.getStride();
  sysint_t srcStride = src.getStride();

  uint8_t* dstData = const_cast&amp;lt;uint8_t*&amp;gt;(dst.cFirst()) + y * dstStride + (x &amp;lt;&amp;lt; 2);
  const uint8_t* srcData = src.cFirst();

  for (i = h; i; i--, dstData += dstStride, srcData += srcStride)
  {
    blitter(dstData, srcData, w, NULL);
  }
}

static double _blitBench(Fog::Image&amp;amp; dst, const Fog::Image* images, BlitterFn blitter)
{
  // Move images to the cache.
  dst.drawImage(Fog::IntPoint(0, 0), images[0], Fog::CompositeSrcOver);
  dst.drawImage(Fog::IntPoint(0, 0), images[1], Fog::CompositeSrcOver);
  dst.drawImage(Fog::IntPoint(0, 0), images[2], Fog::CompositeSrcOver);
  dst.drawImage(Fog::IntPoint(0, 0), images[3], Fog::CompositeSrcOver);
  dst.clear(0x00000000);

  srand(10);

  Fog::TimeTicks time = Fog::TimeTicks::highResNow();

  for (int i = 0; i &amp;lt; 500; i++)
  {
    int x = rand() % (400 - 128);
    int y = rand() % (400 - 128);
    int z = rand() % 4;

    _blitImage(dst, x, y, images[z], blitter);
  }

  return (Fog::TimeTicks::highResNow() - time).inMillisecondsF();
}
&lt;/pre&gt;

&lt;p&gt;Blitters were generated by this initializer:&lt;/p&gt;

&lt;pre class="lang-c"&gt;
typedef void (FOG_FASTCALL *BlitterFn)(uint8_t* dst, const uint8_t* src, sysint_t w, const void* closure);

static BlitterFn blitterFog;
static BlitterFn blitterExperimental;

static void _blitInit()
{
  // Get Fog blitter from Fog::Raster module.
  blitterFog = (BlitterFn)(
    Fog::Raster::functionMap-&gt;raster
      [Fog::CompositeSrcOver]
      [Fog::Image::FormatPRGB32]
        .span_composite[Fog::Image::FormatPRGB32]);

  // Generate blitter using BlitJit library
  BlitJit::Generator gen;

  AsmJit::FileLogger logger(stderr);
  gen.c-&amp;gt;setLogger(&amp;amp;logger);

  gen.setPrefetch(true);
  gen.setClosure(true);

  gen.experimentalBlitSpan(
    &amp;amp;BlitJit::Api::pixelFormats[BlitJit::PixelFormat::PRGB32],
    &amp;amp;BlitJit::Api::pixelFormats[BlitJit::PixelFormat::PRGB32],
    &amp;amp;BlitJit::Api::operators[BlitJit::Operator::CompositeOver]);
  blitterExperimental = AsmJit::function_cast&amp;lt;BlitterFn&amp;gt;(gen.c-&gt;make());
}
&lt;/pre&gt;

&lt;p&gt;Destination buffer and source images were prepared using this code:&lt;/p&gt;
&lt;pre class="lang-c"&gt;
  Image dst;
  Image src[4];

  dst.create(400, 400, Fog::Image::FormatPRGB32);

  src[0].readFile(Fog::Ascii8(&amp;quot;babelfish.png&amp;quot;));
  src[0].convert(Fog::Image::FormatPRGB32);
  src[1].readFile(Fog::Ascii8(&amp;quot;blockdevice.png&amp;quot;));
  src[1].convert(Fog::Image::FormatPRGB32);
  src[2].readFile(Fog::Ascii8(&amp;quot;drop.png&amp;quot;));
  src[2].convert(Fog::Image::FormatPRGB32);
  src[3].readFile(Fog::Ascii8(&amp;quot;kweather.png&amp;quot;));
  src[3].convert(Fog::Image::FormatPRGB32);
&lt;/pre&gt;

&lt;h2&gt;Results&lt;/h2&gt;

&lt;p&gt;Here are benchmarked results:&lt;p&gt;

&lt;table class="table"&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Function&lt;/td&gt;&lt;td&gt;Best time [ms]&lt;/td&gt;&lt;td&gt;Average time [ms]&lt;/td&gt;&lt;td&gt;Average [FPS]&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Fog (SSE2, GCC 4.4.1)&lt;/td&gt;&lt;td&gt;20.200&lt;/td&gt;&lt;td&gt;22.800&lt;/td&gt;&lt;td&gt;43.85&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;BlitJit (SSE2, 4 pixels at time)&lt;/td&gt;&lt;td&gt;17.500&lt;/td&gt;&lt;td&gt;18.400&lt;/td&gt;&lt;td&gt;54.35&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;BlitJit (SSE2, 8 pixels at time)&lt;/td&gt;&lt;td&gt;&lt;b&gt;15.000&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;15.800&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;63.30&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Screenshot of the benchmarking application:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_1uWuBHvqyec/Stu8iiNC1zI/AAAAAAAAACc/QlSZlysJdkw/s1600-h/screen.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 169px;" src="http://2.bp.blogspot.com/_1uWuBHvqyec/Stu8iiNC1zI/AAAAAAAAACc/QlSZlysJdkw/s320/screen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5394112280189392690" /&gt;&lt;/a&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;You can see that nearly equal Fog and BlitJit code (Fog uses 4 pixels at a time in inner loops) needs only 86% of CPU time to run. When using 8 pixels per loop BlitJit needs only 75% CPU time to run compared to Fog. I think that results are promising, you probably never beat BlitJit using C/C++ code and when using assembler you probably never write faster code than BlitJit is able to generate.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-6042175700754698187?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/6042175700754698187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2009/10/fog-vs-blitjit-benchmarking-srcover.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6042175700754698187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/6042175700754698187'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2009/10/fog-vs-blitjit-benchmarking-srcover.html' title='Fog vs BlitJit - Benchmarking SrcOver'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1uWuBHvqyec/Stu8iiNC1zI/AAAAAAAAACc/QlSZlysJdkw/s72-c/screen.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-2743774624443973990</id><published>2009-08-16T00:53:00.003+02:00</published><updated>2011-10-08T16:06:35.963+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='fog-svg'/><title type='text'>Fog - First Multithreaded SVG Renderer?</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Last two weeks there are few things that happen in Fog library. The first one is that Fog/Xml library was improved, it's now better and it should be also faster. The second, most interesting thing is new Fog/Svg library that is able to render basic SVG documents. Currently there are many things that's not supported, but API is written to be extensible (classes and virtual methods). Main problems are CSS selectors (that's not supported) and style attributes (currently only style=&amp;quot;something=value;..." is supported).&lt;/p&gt;

&lt;h2&gt;Status&lt;/h2&gt;

&lt;p&gt;The SVG format is quite complicated and I think that it's impossible to make full support of this format based on the official specification (I used &lt;a href="http://www.w3.org/TR/SVG/REC-SVG11-20030114.pdf"&gt;official specification&lt;/a&gt;). But on the other side, there are many tools that exports SVG documents only by using limited set of features, and I want to support these documents.&lt;/p&gt;

&lt;p&gt;What is working:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;All SVG painting commands - circle, ellipse, g, line, path, polygon, polyline, rect.&lt;/li&gt;
 &lt;li&gt;Affine transformations - transform attribute.&lt;/li&gt;
 &lt;li&gt;Definitions - linearGradient and radialGradient, link attribute xlink:href is also supported.&lt;/li&gt;
 &lt;li&gt;Fill rule and pattern (color or url to gradient), Stroke width, stroke styles and pattern (color or url).&lt;/li&gt;
 &lt;li&gt;DPI conversion (currently not for all elements, added yesterday).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is not working:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Filter effects - not supported.&lt;/li&gt;
 &lt;li&gt;Text - there is basic support but it's broken at the moment.&lt;/li&gt;
 &lt;li&gt;Scripting and animations are not supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the implementation in Fog library is currently very basic, it's first open-source (MIT) SVG rendering engine that is able to use multithreading (through Fog painting engine).&lt;/p&gt;

&lt;p&gt;And here is popular SVG tiger rendered by Fog/Svg:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_1uWuBHvqyec/SodNfRlECOI/AAAAAAAAAB0/Pr4_tNd57AQ/s1600-h/tiger.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 312px; height: 320px;" src="http://3.bp.blogspot.com/_1uWuBHvqyec/SodNfRlECOI/AAAAAAAAAB0/Pr4_tNd57AQ/s320/tiger.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5370346280352745698" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-2743774624443973990?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/2743774624443973990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2009/08/fog-first-multithreaded-svg-renderer.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2743774624443973990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/2743774624443973990'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2009/08/fog-first-multithreaded-svg-renderer.html' title='Fog - First Multithreaded SVG Renderer?'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_1uWuBHvqyec/SodNfRlECOI/AAAAAAAAAB0/Pr4_tNd57AQ/s72-c/tiger.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7596298501677777346.post-5853837945831105136</id><published>2009-06-25T04:42:00.008+02:00</published><updated>2011-10-08T16:07:16.110+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fog-graphics'/><category scheme='http://www.blogger.com/atom/ns#' term='fog'/><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Fog - Introduction</title><content type='html'>&lt;p&gt;Some time ago I started writing new graphics library that I want to use as a drawing backend for my windowing system and GUI toolkit. Its name is Fog, which stands for 'Fair Object Graphics'. Currently Fog library contains many classes and like other libraries it's divided into sections. My intention when I started writing the Fog library was performance and easy-to-use API. I think that I have succeed except that the library is not finished yet (like many others).&lt;/p&gt;

&lt;p&gt;Fog library is currently pure software based library (so no GPU, only CPU is used for rasterization and rendering), but main advantage is that architecture of the library allows to replace blitters and renderers. Currently there is quite efficient SSE2 backend, your CPU will like it;). Optimized are also gradient fills and benchmarks show that Fog library can fill gradients or tile images in unbelivable time compared to others.&lt;/p&gt;

&lt;p&gt;So why I'm talking about Fog? The Fog library is getting better day by day and I think that next year the library will be able to compete with others in number of features and speed. There are graphic libraries used in both Windows and Linux/BSD world, but each library has advantages and disadvantages. For example, GDI+ is quite fast and full-featured (you can find really interesting graphics effects and possibilities in it), but it's closed-source and it can't be ported to other operating systems. There is also Cairo, which is really mature library, but compared to GDI+ it's slower and doesn't contain as many features as GDI+ (I think that Mono developers have really hard times getting Cairo to work as Graphics2d API). So for cross-platform development is Cairo the only choice, except you are a more experienced developer that can wrap for example AntiGrain.&lt;/p&gt;

&lt;p&gt;So I think it's time to introduce a new library - Fog, that can be used as a solution for cross-platform development for applications with graphic output. Fog library also comes with platform layer, so you can use for example &lt;code&gt;Fog::StringW&lt;/code&gt; to work with unicode strings, &lt;code&gt;Fog::DirIterator&lt;/code&gt; to iterate over objects in a directory, and various other classes.&lt;/p&gt;

&lt;p&gt;Small example on how to render something with Fog-Framework:&lt;/p&gt;
&lt;pre class="lang-c"&gt;
  using namespace Fog;

  Image image(SizeI(320, 320), IMAGE_FORMAT_PRGB32);
  Painter p(image);

  p.setSource(Argb(0xFFFFFFFF));
  p.fillAll();

  float x = 10.5f;
  float y = 10.5f;
  float w = 300.0f;
  float h = 300.0f;

  PathF path;
  path.addRound(RectF(x, y, w, h), PointF(50.0f, 50.0f));

  LinearGradient gradient(PointF(x, y), PointF(x + w, y + h));
  gradient.addStop(0.0f, Argb32(0xFFFFFF00));
  gradient.addStop(1.0f, Argb32(0xFFFF0000));

  p.setSource(gradient);
  p.fillPath(path);

  p.setSource(Argb32(0xFF000000));
  p.drawPath(path);
  p.end();

  image.writeToFile(StringW::fromAscii8("./output.png"));
&lt;/pre&gt;

&lt;p&gt;And here is the resulting image 'output.png':&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_1uWuBHvqyec/SkLu2aBQrkI/AAAAAAAAAAM/9s1mXDgXTpY/s1600-h/output.png"&gt;&lt;img style="margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 320px;" src="http://2.bp.blogspot.com/_1uWuBHvqyec/SkLu2aBQrkI/AAAAAAAAAAM/9s1mXDgXTpY/s320/output.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5351101925734526530" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I thing that this example is self-explanatory. Fog-Framework is strongly object-oriented and there are classes with related members and methods for everything. You can also see that Fog painting engine is state based, so it's closer to Cairo than to GDI+, but on the other hand, Fog also contains very strong raster manipulation methods, so it's not pure vector graphics library, it's just yet another graphics library where design and preformance are important properties.&lt;/p&gt;

&lt;p&gt;For more info about Fog-Framework please visit &lt;a href="http://code.google.com/p/fog/"&gt;Fog project page&lt;/a&gt;. The library is MIT licensed, so you can use it for what you want without restrictions.&lt;/p&gt;

&lt;p&gt;List of other graphics libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cairographics.org/"&gt;Cairo&lt;/a&gt; - Cross-platform 2d vector graphics library.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://qt.nokia.com/products"&gt;Qt&lt;/a&gt; - If you are Qt developer, just use built-in Qt painting, it's well integrated with rest of Qt API.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/skia/"&gt;Skia&lt;/a&gt; - Interesting library, the design is very friendly for embedded systems, possibility to use only fixed point math.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to Kralik for corrections!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7596298501677777346-5853837945831105136?l=fog-framework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://fog-framework.blogspot.com/feeds/5853837945831105136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://fog-framework.blogspot.com/2009/06/fog-graphics-library.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5853837945831105136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7596298501677777346/posts/default/5853837945831105136'/><link rel='alternate' type='text/html' href='http://fog-framework.blogspot.com/2009/06/fog-graphics-library.html' title='Fog - Introduction'/><author><name>Petr Kobalíček</name><uri>http://www.blogger.com/profile/15634384573845850706</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1uWuBHvqyec/SkLu2aBQrkI/AAAAAAAAAAM/9s1mXDgXTpY/s72-c/output.png' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
