graphics-libart.html
来自「linux下gnome编程」· HTML 代码 · 共 806 行 · 第 1/2 页
HTML
806 行
<HTML><HEAD><TITLE>Libart</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.61"><LINKREL="HOME"TITLE="Writing GNOME Applications"HREF="index.html"><LINKREL="UP"TITLE="Graphics"HREF="graphics.html"><LINKREL="PREVIOUS"TITLE="GdkRGB"HREF="graphics-gdkrgb.html"><LINKREL="NEXT"TITLE="Gdk-pixbuf"HREF="graphics-gdk-pixbuf.html"></HEAD><BODYCLASS="SECT1"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Writing GNOME Applications</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="graphics-gdkrgb.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 10. Graphics</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="graphics-gdk-pixbuf.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="GRAPHICS-LIBART">Libart</A></H1><P> Libart brings a very important feature to GNOME: high-quality anti-aliased, vector-based image manipulation. Libart's assortment of paths, points, and regions gives you very fine-grained control over important tasks, such as image rotation, scaling, and shearing. Libart is optimized for quick, efficient rendering, making it a prime candidate for graphic-intensive applications. </P><P> A full presentation of the libart API could easily take up an entire chapter or two, so to keep things short we will focus on the basic concepts and data structures, with the hope that you can use this knowledge to explore and learn the finer details of this library more quickly on your own. </P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN811">Vector Paths</A></H2><P> A vector path in libart is an array of coordinates that form a consecutive series of line segments, connected end to end. A path can be open, as with a line graph, or it can be closed, as with a polygon or figure eight. A path can cross over itself any number of times. The structure that libart uses to keep track of each point in a vector path looks like this: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct _ArtVpath ArtVpath;struct _ArtVpath{ ArtPathcode code; double x; double y;}; </PRE></TD></TR></TABLE><P> Figure 10.5 shows an array of five ArtVpath elements tracing the four sides of a diamond shape. </P><DIVCLASS="FIGURE"><ANAME="AEN816"></A><P><B>Figure 10-5. Array of ArtVpath Elements</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f5.png"></IMG></P></DIV></DIV><P> Each element consists of a single coordinate point and one property, the ArtPathcode enumeration, which tells libart how this point connects to the previous point, if any: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef enum{ ART_MOVETO, ART_MOVETO_OPEN, ART_CURVETO, ART_LINETO, ART_END} ArtPathcode; </PRE></TD></TR></TABLE><P> The first point in a path array must be ART_MOVETO if the path is a closed path or ART_MOVETO_OPEN for an open path. The final point is always ART_END. All other points in a vector path array must be ART_LINETO. In a closed path, libart will implicitly connect the ART_END point to the initial ART_MOVETO point. </P><P> By definition, a vector path consists of all straight lines. For this reason, ART_CURVETO is not permitted in vector paths. As we will see in the next section, the more complex Bezier paths can handle curves. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN825">Bezier Paths</A></H2><P> When you can get away with only straight lines, use vector paths. The calculations are simple and fast, and the paths are easy to build. However, if you are trying to draw anything natural-looking, straight lines will make it look blocky and clumsy. At some point you will probably want to render a real curve. This is where Bezier paths come into play. </P><P> Each element of a Bezier path requires three coordinate points rather than the single point used by a vector path element. In a nutshell, the Bezier curve is defined by its starting and ending points, as well as a middle point, usually off to the side. The curve will trace a path from the first coordinate to the final coordinate, pulled away from a straight line by the middle coordinate in a pre- dictable, mathematical curve. This path is defined by the following cubic equations, where t goes from 0 to 1: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">x = x0(1 - t)3 + x1(1 - t)2t + x2(1 - t)t2 + x3t3y = y0(1 - t)3 + y1(1 - t)2t + y2(1 - t)t2 + y3t3 </PRE></TD></TR></TABLE><P> Libart uses the following data structure to hold the data for each Bezier line segment; a Bezier path is an array of one or more of these segments. It can be open or closed, and it can be a mixture of straight lines (where only the x3 and y3 coordinates are used) and curved lines. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct _ArtBpath ArtBpath;struct _ArtBpath{ ArtPathcode code; double x1; double y1; double x2; double y2; double x3; double y3;}; </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN832">Sorted Vector Paths</A></H2><P> As part of its suite of optimizations, libart defines a sorted vector path (SVP) to organize a normal vector path into groups of similar segments. Each SVP element consists of two or more points (i.e., a vector path) tracing a path of coordinates that steadily increases or decreases along the y-axis. This rule helps optimize algorithms that render in a vertical direction, in particular those used to display image buffers on the screen. </P><P> Consider a path shaped like the letter V. A vector path would describe it with a downward (increasing y-axis) stroke, followed by an upward (decreasing y-axis) stroke. A sorted vector path would break it up into two downward strokes converging on the same point, thus making it easier to render the V from the top down. Figure 10.6 shows the letters V and R broken down into vector paths and sorted vector paths. </P><DIVCLASS="FIGURE"><ANAME="AEN836"></A><P><B>Figure 10-6. Vector Paths of the Letters V and R</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f6.png"></IMG></P></DIV></DIV><P> Another important feature of SVPs that helps optimize their rendering code is the bounding box assigned to each SVP segment. This bounding box defines the minimum rectangular area that can contain that SVP segment (which, remember, can contain more than two points, like the second segment in the "R" example). When part or all of a sorted vector path needs to be redrawn, the area that must be "dirtied" can be clipped and reduced quite a bit, so that only the areas covered by those bounding boxes are repainted rather than a single, huge rectangle that covers the entire path. This clipping can save a lot of needless work. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN842">Microtile Arrays</A></H2><P> Libart's microtile arrays make it easier to optimize image redrawing, by breaking the "dirty" areas down into smaller rectangles. The microtile array (affectionately abbreviated uta, with the "u" standing for the Greek letter m, or micron) represents a grid of 32 32 pixel squares overlaid on an area of coordinate space. For example, a 96 64 pixel buffer would have six microtiles, arranged in a 3 2 grid. </P><P> Figure 10.7 shows a path drawn in the shape of a guitar case. Rather than having to rerender the bounding box of the entire path, indicated by the dotted line, the microtile array breaks the dirty regions into smaller components. The gray rectangles show the areas that need to be refreshed when using the uta. </P><DIVCLASS="FIGURE"><ANAME="AEN846"></A><P><B>Figure 10-7. Microtile Arrays</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/10f7.png"></IMG></P></DIV></DIV><P> Each microtile has a single bounding box within its 32 32 area, to mark the entire area of interest-the "dirty" area in the case of repainting algorithms-within its grid square. When an application attempts to refresh its microtiled drawing areas, it can roll through the uta and redraw only the area contents of each bounding box. It can ignore all microtiles with zero-area bounding boxes. The fewer unnecessary pixels the application has to redraw, the faster the refresh will take place each time. In practice, the microtiles are usually merged and decomposed into an array of rectangles, optimized for efficient redraws. </P><P> A significant advantage to utas is that you can add to them dynamically, as the dirty area changes. The microtiles will adjust their bounding boxes to include the new areas or ignore the areas they already cover. This makes it much easier to implement deferred painting updates, in which redraws happen during idle times. Between updates, the microtiles accumulate "dirt," but they always remain in a ready-to-use state, whenever the next repaint event happens to occur. </P><P> Another advantage of microtile arrays is their stable memory footprint. No matter how many times a drawing area is damaged, the number of microtiles never increases. Only the coordinates of the existing bounding boxes change. Utas are also very efficient, especially because of their 32-pixel grid size. The 32-pixel boundaries result in convenient 4-byte-aligned chunks of the pixel buffer. Also, the fact that each bounding box is constrained to a coordinate range of 0 to 32 pixels makes it possible to fit all four coordinate values into a single 32-bit integer. Technically, each coordinate fits into 5 bits, but to maintain the optimization, each coordinate is padded to 8 bits. Thus our earlier 96 64 pixel example requires only 24 bytes (6 microtiles 4 bytes) to express its bounding-box data. </P></DIV><DIVCLASS="SECT2"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?