Subversion Repositories Kolibri OS

Rev

Rev 1891 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
  3.  * Copyright © 2004 Keith Packard
  4.  *
  5.  * Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both that
  8.  * copyright notice and this permission notice appear in supporting
  9.  * documentation, and that the name of Keith Packard not be used in
  10.  * advertising or publicity pertaining to distribution of the software without
  11.  * specific, written prior permission.  Keith Packard makes no
  12.  * representations about the suitability of this software for any purpose.  It
  13.  * is provided "as is" without express or implied warranty.
  14.  *
  15.  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17.  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  20.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21.  * PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include <config.h>
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include "pixman-private.h"
  31.  
  32. /*
  33.  * Compute the smallest value greater than or equal to y which is on a
  34.  * grid row.
  35.  */
  36.  
  37. PIXMAN_EXPORT pixman_fixed_t
  38. pixman_sample_ceil_y (pixman_fixed_t y, int n)
  39. {
  40.     pixman_fixed_t f = pixman_fixed_frac (y);
  41.     pixman_fixed_t i = pixman_fixed_floor (y);
  42.  
  43.     f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
  44.         Y_FRAC_FIRST (n);
  45.    
  46.     if (f > Y_FRAC_LAST (n))
  47.     {
  48.         if (pixman_fixed_to_int (i) == 0x7fff)
  49.         {
  50.             f = 0xffff; /* saturate */
  51.         }
  52.         else
  53.         {
  54.             f = Y_FRAC_FIRST (n);
  55.             i += pixman_fixed_1;
  56.         }
  57.     }
  58.     return (i | f);
  59. }
  60.  
  61. /*
  62.  * Compute the largest value strictly less than y which is on a
  63.  * grid row.
  64.  */
  65. PIXMAN_EXPORT pixman_fixed_t
  66. pixman_sample_floor_y (pixman_fixed_t y,
  67.                        int            n)
  68. {
  69.     pixman_fixed_t f = pixman_fixed_frac (y);
  70.     pixman_fixed_t i = pixman_fixed_floor (y);
  71.  
  72.     f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
  73.         Y_FRAC_FIRST (n);
  74.  
  75.     if (f < Y_FRAC_FIRST (n))
  76.     {
  77.         if (pixman_fixed_to_int (i) == 0x8000)
  78.         {
  79.             f = 0; /* saturate */
  80.         }
  81.         else
  82.         {
  83.             f = Y_FRAC_LAST (n);
  84.             i -= pixman_fixed_1;
  85.         }
  86.     }
  87.     return (i | f);
  88. }
  89.  
  90. /*
  91.  * Step an edge by any amount (including negative values)
  92.  */
  93. PIXMAN_EXPORT void
  94. pixman_edge_step (pixman_edge_t *e,
  95.                   int            n)
  96. {
  97.     pixman_fixed_48_16_t ne;
  98.  
  99.     e->x += n * e->stepx;
  100.  
  101.     ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
  102.  
  103.     if (n >= 0)
  104.     {
  105.         if (ne > 0)
  106.         {
  107.             int nx = (ne + e->dy - 1) / e->dy;
  108.             e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
  109.             e->x += nx * e->signdx;
  110.         }
  111.     }
  112.     else
  113.     {
  114.         if (ne <= -e->dy)
  115.         {
  116.             int nx = (-ne) / e->dy;
  117.             e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
  118.             e->x -= nx * e->signdx;
  119.         }
  120.     }
  121. }
  122.  
  123. /*
  124.  * A private routine to initialize the multi-step
  125.  * elements of an edge structure
  126.  */
  127. static void
  128. _pixman_edge_multi_init (pixman_edge_t * e,
  129.                          int             n,
  130.                          pixman_fixed_t *stepx_p,
  131.                          pixman_fixed_t *dx_p)
  132. {
  133.     pixman_fixed_t stepx;
  134.     pixman_fixed_48_16_t ne;
  135.  
  136.     ne = n * (pixman_fixed_48_16_t) e->dx;
  137.     stepx = n * e->stepx;
  138.  
  139.     if (ne > 0)
  140.     {
  141.         int nx = ne / e->dy;
  142.         ne -= nx * (pixman_fixed_48_16_t)e->dy;
  143.         stepx += nx * e->signdx;
  144.     }
  145.  
  146.     *dx_p = ne;
  147.     *stepx_p = stepx;
  148. }
  149.  
  150. /*
  151.  * Initialize one edge structure given the line endpoints and a
  152.  * starting y value
  153.  */
  154. PIXMAN_EXPORT void
  155. pixman_edge_init (pixman_edge_t *e,
  156.                   int            n,
  157.                   pixman_fixed_t y_start,
  158.                   pixman_fixed_t x_top,
  159.                   pixman_fixed_t y_top,
  160.                   pixman_fixed_t x_bot,
  161.                   pixman_fixed_t y_bot)
  162. {
  163.     pixman_fixed_t dx, dy;
  164.  
  165.     e->x = x_top;
  166.     e->e = 0;
  167.     dx = x_bot - x_top;
  168.     dy = y_bot - y_top;
  169.     e->dy = dy;
  170.     e->dx = 0;
  171.  
  172.     if (dy)
  173.     {
  174.         if (dx >= 0)
  175.         {
  176.             e->signdx = 1;
  177.             e->stepx = dx / dy;
  178.             e->dx = dx % dy;
  179.             e->e = -dy;
  180.         }
  181.         else
  182.         {
  183.             e->signdx = -1;
  184.             e->stepx = -(-dx / dy);
  185.             e->dx = -dx % dy;
  186.             e->e = 0;
  187.         }
  188.  
  189.         _pixman_edge_multi_init (e, STEP_Y_SMALL (n),
  190.                                  &e->stepx_small, &e->dx_small);
  191.  
  192.         _pixman_edge_multi_init (e, STEP_Y_BIG (n),
  193.                                  &e->stepx_big, &e->dx_big);
  194.     }
  195.     pixman_edge_step (e, y_start - y_top);
  196. }
  197.  
  198. /*
  199.  * Initialize one edge structure given a line, starting y value
  200.  * and a pixel offset for the line
  201.  */
  202. PIXMAN_EXPORT void
  203. pixman_line_fixed_edge_init (pixman_edge_t *            e,
  204.                              int                        n,
  205.                              pixman_fixed_t             y,
  206.                              const pixman_line_fixed_t *line,
  207.                              int                        x_off,
  208.                              int                        y_off)
  209. {
  210.     pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
  211.     pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
  212.     const pixman_point_fixed_t *top, *bot;
  213.  
  214.     if (line->p1.y <= line->p2.y)
  215.     {
  216.         top = &line->p1;
  217.         bot = &line->p2;
  218.     }
  219.     else
  220.     {
  221.         top = &line->p2;
  222.         bot = &line->p1;
  223.     }
  224.    
  225.     pixman_edge_init (e, n, y,
  226.                       top->x + x_off_fixed,
  227.                       top->y + y_off_fixed,
  228.                       bot->x + x_off_fixed,
  229.                       bot->y + y_off_fixed);
  230. }
  231.  
  232. PIXMAN_EXPORT void
  233. pixman_add_traps (pixman_image_t *     image,
  234.                   int16_t              x_off,
  235.                   int16_t              y_off,
  236.                   int                  ntrap,
  237.                   const pixman_trap_t *traps)
  238. {
  239.     int bpp;
  240.     int height;
  241.  
  242.     pixman_fixed_t x_off_fixed;
  243.     pixman_fixed_t y_off_fixed;
  244.     pixman_edge_t l, r;
  245.     pixman_fixed_t t, b;
  246.  
  247.     _pixman_image_validate (image);
  248.    
  249.     height = image->bits.height;
  250.     bpp = PIXMAN_FORMAT_BPP (image->bits.format);
  251.  
  252.     x_off_fixed = pixman_int_to_fixed (x_off);
  253.     y_off_fixed = pixman_int_to_fixed (y_off);
  254.  
  255.     while (ntrap--)
  256.     {
  257.         t = traps->top.y + y_off_fixed;
  258.         if (t < 0)
  259.             t = 0;
  260.         t = pixman_sample_ceil_y (t, bpp);
  261.  
  262.         b = traps->bot.y + y_off_fixed;
  263.         if (pixman_fixed_to_int (b) >= height)
  264.             b = pixman_int_to_fixed (height) - 1;
  265.         b = pixman_sample_floor_y (b, bpp);
  266.  
  267.         if (b >= t)
  268.         {
  269.             /* initialize edge walkers */
  270.             pixman_edge_init (&l, bpp, t,
  271.                               traps->top.l + x_off_fixed,
  272.                               traps->top.y + y_off_fixed,
  273.                               traps->bot.l + x_off_fixed,
  274.                               traps->bot.y + y_off_fixed);
  275.  
  276.             pixman_edge_init (&r, bpp, t,
  277.                               traps->top.r + x_off_fixed,
  278.                               traps->top.y + y_off_fixed,
  279.                               traps->bot.r + x_off_fixed,
  280.                               traps->bot.y + y_off_fixed);
  281.  
  282.             pixman_rasterize_edges (image, &l, &r, t, b);
  283.         }
  284.  
  285.         traps++;
  286.     }
  287. }
  288.  
  289. #if 0
  290. static void
  291. dump_image (pixman_image_t *image,
  292.             const char *    title)
  293. {
  294.     int i, j;
  295.  
  296.     if (!image->type == BITS)
  297.         printf ("%s is not a regular image\n", title);
  298.  
  299.     if (!image->bits.format == PIXMAN_a8)
  300.         printf ("%s is not an alpha mask\n", title);
  301.  
  302.     printf ("\n\n\n%s: \n", title);
  303.  
  304.     for (i = 0; i < image->bits.height; ++i)
  305.     {
  306.         uint8_t *line =
  307.             (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
  308.  
  309.         for (j = 0; j < image->bits.width; ++j)
  310.             printf ("%c", line[j] ? '#' : ' ');
  311.  
  312.         printf ("\n");
  313.     }
  314. }
  315. #endif
  316.  
  317. PIXMAN_EXPORT void
  318. pixman_add_trapezoids (pixman_image_t *          image,
  319.                        int16_t                   x_off,
  320.                        int                       y_off,
  321.                        int                       ntraps,
  322.                        const pixman_trapezoid_t *traps)
  323. {
  324.     int i;
  325.  
  326. #if 0
  327.     dump_image (image, "before");
  328. #endif
  329.  
  330.     for (i = 0; i < ntraps; ++i)
  331.     {
  332.         const pixman_trapezoid_t *trap = &(traps[i]);
  333.  
  334.         if (!pixman_trapezoid_valid (trap))
  335.             continue;
  336.  
  337.         pixman_rasterize_trapezoid (image, trap, x_off, y_off);
  338.     }
  339.  
  340. #if 0
  341.     dump_image (image, "after");
  342. #endif
  343. }
  344.  
  345. PIXMAN_EXPORT void
  346. pixman_rasterize_trapezoid (pixman_image_t *          image,
  347.                             const pixman_trapezoid_t *trap,
  348.                             int                       x_off,
  349.                             int                       y_off)
  350. {
  351.     int bpp;
  352.     int height;
  353.  
  354.     pixman_fixed_t y_off_fixed;
  355.     pixman_edge_t l, r;
  356.     pixman_fixed_t t, b;
  357.  
  358.     return_if_fail (image->type == BITS);
  359.  
  360.     _pixman_image_validate (image);
  361.    
  362.     if (!pixman_trapezoid_valid (trap))
  363.         return;
  364.  
  365.     height = image->bits.height;
  366.     bpp = PIXMAN_FORMAT_BPP (image->bits.format);
  367.  
  368.     y_off_fixed = pixman_int_to_fixed (y_off);
  369.  
  370.     t = trap->top + y_off_fixed;
  371.     if (t < 0)
  372.         t = 0;
  373.     t = pixman_sample_ceil_y (t, bpp);
  374.  
  375.     b = trap->bottom + y_off_fixed;
  376.     if (pixman_fixed_to_int (b) >= height)
  377.         b = pixman_int_to_fixed (height) - 1;
  378.     b = pixman_sample_floor_y (b, bpp);
  379.    
  380.     if (b >= t)
  381.     {
  382.         /* initialize edge walkers */
  383.         pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
  384.         pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
  385.  
  386.         pixman_rasterize_edges (image, &l, &r, t, b);
  387.     }
  388. }
  389.  
  390. static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
  391. {
  392.     FALSE,      /* Clear                0                       0    */
  393.     FALSE,      /* Src                  1                       0    */
  394.     TRUE,       /* Dst                  0                       1    */
  395.     TRUE,       /* Over                 1                       1-Aa */
  396.     TRUE,       /* OverReverse          1-Ab                    1    */
  397.     FALSE,      /* In                   Ab                      0    */
  398.     FALSE,      /* InReverse            0                       Aa   */
  399.     FALSE,      /* Out                  1-Ab                    0    */
  400.     TRUE,       /* OutReverse           0                       1-Aa */
  401.     TRUE,       /* Atop                 Ab                      1-Aa */
  402.     FALSE,      /* AtopReverse          1-Ab                    Aa   */
  403.     TRUE,       /* Xor                  1-Ab                    1-Aa */
  404.     TRUE,       /* Add                  1                       1    */
  405. };
  406.  
  407. static pixman_bool_t
  408. get_trap_extents (pixman_op_t op, pixman_image_t *dest,
  409.                   const pixman_trapezoid_t *traps, int n_traps,
  410.                   pixman_box32_t *box)
  411. {
  412.     int i;
  413.  
  414.     /* When the operator is such that a zero source has an
  415.      * effect on the underlying image, we have to
  416.      * composite across the entire destination
  417.      */
  418.     if (!zero_src_has_no_effect [op])
  419.     {
  420.         box->x1 = 0;
  421.         box->y1 = 0;
  422.         box->x2 = dest->bits.width;
  423.         box->y2 = dest->bits.height;
  424.         return TRUE;
  425.     }
  426.    
  427.     box->x1 = INT32_MAX;
  428.     box->y1 = INT32_MAX;
  429.     box->x2 = INT32_MIN;
  430.     box->y2 = INT32_MIN;
  431.        
  432.     for (i = 0; i < n_traps; ++i)
  433.     {
  434.         const pixman_trapezoid_t *trap = &(traps[i]);
  435.         int y1, y2;
  436.            
  437.         if (!pixman_trapezoid_valid (trap))
  438.             continue;
  439.            
  440.         y1 = pixman_fixed_to_int (trap->top);
  441.         if (y1 < box->y1)
  442.             box->y1 = y1;
  443.            
  444.         y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
  445.         if (y2 > box->y2)
  446.             box->y2 = y2;
  447.            
  448. #define EXTEND_MIN(x)                                                   \
  449.         if (pixman_fixed_to_int ((x)) < box->x1)                        \
  450.             box->x1 = pixman_fixed_to_int ((x));
  451. #define EXTEND_MAX(x)                                                   \
  452.         if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)    \
  453.             box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
  454.            
  455. #define EXTEND(x)                                                       \
  456.         EXTEND_MIN(x);                                                  \
  457.         EXTEND_MAX(x);
  458.            
  459.         EXTEND(trap->left.p1.x);
  460.         EXTEND(trap->left.p2.x);
  461.         EXTEND(trap->right.p1.x);
  462.         EXTEND(trap->right.p2.x);
  463.     }
  464.        
  465.     if (box->x1 >= box->x2 || box->y1 >= box->y2)
  466.         return FALSE;
  467.  
  468.     return TRUE;
  469. }
  470.  
  471. /*
  472.  * pixman_composite_trapezoids()
  473.  *
  474.  * All the trapezoids are conceptually rendered to an infinitely big image.
  475.  * The (0, 0) coordinates of this image are then aligned with the (x, y)
  476.  * coordinates of the source image, and then both images are aligned with
  477.  * the (x, y) coordinates of the destination. Then these three images are
  478.  * composited across the entire destination.
  479.  */
  480. PIXMAN_EXPORT void
  481. pixman_composite_trapezoids (pixman_op_t                op,
  482.                              pixman_image_t *           src,
  483.                              pixman_image_t *           dst,
  484.                              pixman_format_code_t       mask_format,
  485.                              int                        x_src,
  486.                              int                        y_src,
  487.                              int                        x_dst,
  488.                              int                        y_dst,
  489.                              int                        n_traps,
  490.                              const pixman_trapezoid_t * traps)
  491. {
  492.     int i;
  493.  
  494.     return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A);
  495.    
  496.     if (n_traps <= 0)
  497.         return;
  498.  
  499.     _pixman_image_validate (src);
  500.     _pixman_image_validate (dst);
  501.  
  502.     if (op == PIXMAN_OP_ADD &&
  503.         (src->common.flags & FAST_PATH_IS_OPAQUE)               &&
  504.         (mask_format == dst->common.extended_format_code)       &&
  505.         !(dst->common.have_clip_region))
  506.     {
  507.         for (i = 0; i < n_traps; ++i)
  508.         {
  509.             const pixman_trapezoid_t *trap = &(traps[i]);
  510.            
  511.             if (!pixman_trapezoid_valid (trap))
  512.                 continue;
  513.            
  514.             pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
  515.         }
  516.     }
  517.     else
  518.     {
  519.         pixman_image_t *tmp;
  520.         pixman_box32_t box;
  521.         int i;
  522.  
  523.         if (!get_trap_extents (op, dst, traps, n_traps, &box))
  524.             return;
  525.        
  526.         if (!(tmp = pixman_image_create_bits (
  527.                   mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1)))
  528.             return;
  529.        
  530.         for (i = 0; i < n_traps; ++i)
  531.         {
  532.             const pixman_trapezoid_t *trap = &(traps[i]);
  533.            
  534.             if (!pixman_trapezoid_valid (trap))
  535.                 continue;
  536.            
  537.             pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
  538.         }
  539.        
  540.         pixman_image_composite (op, src, tmp, dst,
  541.                                 x_src + box.x1, y_src + box.y1,
  542.                                 0, 0,
  543.                                 x_dst + box.x1, y_dst + box.y1,
  544.                                 box.x2 - box.x1, box.y2 - box.y1);
  545.        
  546.         pixman_image_unref (tmp);
  547.     }
  548. }
  549.  
  550. static int
  551. greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b)
  552. {
  553.     if (a->y == b->y)
  554.         return a->x > b->x;
  555.     return a->y > b->y;
  556. }
  557.  
  558. /*
  559.  * Note that the definition of this function is a bit odd because
  560.  * of the X coordinate space (y increasing downwards).
  561.  */
  562. static int
  563. clockwise (const pixman_point_fixed_t *ref,
  564.            const pixman_point_fixed_t *a,
  565.            const pixman_point_fixed_t *b)
  566. {
  567.     pixman_point_fixed_t        ad, bd;
  568.  
  569.     ad.x = a->x - ref->x;
  570.     ad.y = a->y - ref->y;
  571.     bd.x = b->x - ref->x;
  572.     bd.y = b->y - ref->y;
  573.  
  574.     return ((pixman_fixed_32_32_t) bd.y * ad.x -
  575.             (pixman_fixed_32_32_t) ad.y * bd.x) < 0;
  576. }
  577.  
  578. static void
  579. triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps)
  580. {
  581.     const pixman_point_fixed_t *top, *left, *right, *tmp;
  582.  
  583.     top = &tri->p1;
  584.     left = &tri->p2;
  585.     right = &tri->p3;
  586.  
  587.     if (greater_y (top, left))
  588.     {
  589.         tmp = left;
  590.         left = top;
  591.         top = tmp;
  592.     }
  593.  
  594.     if (greater_y (top, right))
  595.     {
  596.         tmp = right;
  597.         right = top;
  598.         top = tmp;
  599.     }
  600.  
  601.     if (clockwise (top, right, left))
  602.     {
  603.         tmp = right;
  604.         right = left;
  605.         left = tmp;
  606.     }
  607.    
  608.     /*
  609.      * Two cases:
  610.      *
  611.      *          +               +
  612.      *         / \             / \
  613.      *        /   \           /   \
  614.      *       /     +         +     \
  615.      *      /    --           --    \
  616.      *     /   --               --   \
  617.      *    / ---                   --- \
  618.      *   +--                         --+
  619.      */
  620.  
  621.     traps->top = top->y;
  622.     traps->left.p1 = *top;
  623.     traps->left.p2 = *left;
  624.     traps->right.p1 = *top;
  625.     traps->right.p2 = *right;
  626.  
  627.     if (right->y < left->y)
  628.         traps->bottom = right->y;
  629.     else
  630.         traps->bottom = left->y;
  631.  
  632.     traps++;
  633.  
  634.     *traps = *(traps - 1);
  635.    
  636.     if (right->y < left->y)
  637.     {
  638.         traps->top = right->y;
  639.         traps->bottom = left->y;
  640.         traps->right.p1 = *right;
  641.         traps->right.p2 = *left;
  642.     }
  643.     else
  644.     {
  645.         traps->top = left->y;
  646.         traps->bottom = right->y;
  647.         traps->left.p1 = *left;
  648.         traps->left.p2 = *right;
  649.     }
  650. }
  651.  
  652. static pixman_trapezoid_t *
  653. convert_triangles (int n_tris, const pixman_triangle_t *tris)
  654. {
  655.     pixman_trapezoid_t *traps;
  656.     int i;
  657.  
  658.     if (n_tris <= 0)
  659.         return NULL;
  660.    
  661.     traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
  662.     if (!traps)
  663.         return NULL;
  664.  
  665.     for (i = 0; i < n_tris; ++i)
  666.         triangle_to_trapezoids (&(tris[i]), traps + 2 * i);
  667.  
  668.     return traps;
  669. }
  670.  
  671. PIXMAN_EXPORT void
  672. pixman_composite_triangles (pixman_op_t                 op,
  673.                             pixman_image_t *            src,
  674.                             pixman_image_t *            dst,
  675.                             pixman_format_code_t        mask_format,
  676.                             int                         x_src,
  677.                             int                         y_src,
  678.                             int                         x_dst,
  679.                             int                         y_dst,
  680.                             int                         n_tris,
  681.                             const pixman_triangle_t *   tris)
  682. {
  683.     pixman_trapezoid_t *traps;
  684.  
  685.     if ((traps = convert_triangles (n_tris, tris)))
  686.     {
  687.         pixman_composite_trapezoids (op, src, dst, mask_format,
  688.                                      x_src, y_src, x_dst, y_dst,
  689.                                      n_tris * 2, traps);
  690.        
  691.         free (traps);
  692.     }
  693. }
  694.  
  695. PIXMAN_EXPORT void
  696. pixman_add_triangles (pixman_image_t          *image,
  697.                       int32_t                  x_off,
  698.                       int32_t                  y_off,
  699.                       int                      n_tris,
  700.                       const pixman_triangle_t *tris)
  701. {
  702.     pixman_trapezoid_t *traps;
  703.  
  704.     if ((traps = convert_triangles (n_tris, tris)))
  705.     {
  706.         pixman_add_trapezoids (image, x_off, y_off,
  707.                                n_tris * 2, traps);
  708.  
  709.         free (traps);
  710.     }
  711. }
  712.