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 + -
显示快捷键?