Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2004 Keith Packard
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Keith Packard not be used in
  9.  * advertising or publicity pertaining to distribution of the software without
  10.  * specific, written prior permission.  Keith Packard makes no
  11.  * representations about the suitability of this software for any purpose.  It
  12.  * is provided "as is" without express or implied warranty.
  13.  *
  14.  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <stdio.h>
  28. #include "pixman-private.h"
  29.  
  30. /*
  31.  * Compute the smallest value greater than or equal to y which is on a
  32.  * grid row.
  33.  */
  34.  
  35. PIXMAN_EXPORT pixman_fixed_t
  36. pixman_sample_ceil_y (pixman_fixed_t y, int n)
  37. {
  38.     pixman_fixed_t f = pixman_fixed_frac (y);
  39.     pixman_fixed_t i = pixman_fixed_floor (y);
  40.  
  41.     f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
  42.         Y_FRAC_FIRST (n);
  43.    
  44.     if (f > Y_FRAC_LAST (n))
  45.     {
  46.         if (pixman_fixed_to_int (i) == 0x7fff)
  47.         {
  48.             f = 0xffff; /* saturate */
  49.         }
  50.         else
  51.         {
  52.             f = Y_FRAC_FIRST (n);
  53.             i += pixman_fixed_1;
  54.         }
  55.     }
  56.     return (i | f);
  57. }
  58.  
  59. /*
  60.  * Compute the largest value strictly less than y which is on a
  61.  * grid row.
  62.  */
  63. PIXMAN_EXPORT pixman_fixed_t
  64. pixman_sample_floor_y (pixman_fixed_t y,
  65.                        int            n)
  66. {
  67.     pixman_fixed_t f = pixman_fixed_frac (y);
  68.     pixman_fixed_t i = pixman_fixed_floor (y);
  69.  
  70.     f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
  71.         Y_FRAC_FIRST (n);
  72.  
  73.     if (f < Y_FRAC_FIRST (n))
  74.     {
  75.         if (pixman_fixed_to_int (i) == 0x8000)
  76.         {
  77.             f = 0; /* saturate */
  78.         }
  79.         else
  80.         {
  81.             f = Y_FRAC_LAST (n);
  82.             i -= pixman_fixed_1;
  83.         }
  84.     }
  85.     return (i | f);
  86. }
  87.  
  88. /*
  89.  * Step an edge by any amount (including negative values)
  90.  */
  91. PIXMAN_EXPORT void
  92. pixman_edge_step (pixman_edge_t *e,
  93.                   int            n)
  94. {
  95.     pixman_fixed_48_16_t ne;
  96.  
  97.     e->x += n * e->stepx;
  98.  
  99.     ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
  100.  
  101.     if (n >= 0)
  102.     {
  103.         if (ne > 0)
  104.         {
  105.             int nx = (ne + e->dy - 1) / e->dy;
  106.             e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
  107.             e->x += nx * e->signdx;
  108.         }
  109.     }
  110.     else
  111.     {
  112.         if (ne <= -e->dy)
  113.         {
  114.             int nx = (-ne) / e->dy;
  115.             e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
  116.             e->x -= nx * e->signdx;
  117.         }
  118.     }
  119. }
  120.  
  121. /*
  122.  * A private routine to initialize the multi-step
  123.  * elements of an edge structure
  124.  */
  125. static void
  126. _pixman_edge_multi_init (pixman_edge_t * e,
  127.                          int             n,
  128.                          pixman_fixed_t *stepx_p,
  129.                          pixman_fixed_t *dx_p)
  130. {
  131.     pixman_fixed_t stepx;
  132.     pixman_fixed_48_16_t ne;
  133.  
  134.     ne = n * (pixman_fixed_48_16_t) e->dx;
  135.     stepx = n * e->stepx;
  136.  
  137.     if (ne > 0)
  138.     {
  139.         int nx = ne / e->dy;
  140.         ne -= nx * e->dy;
  141.         stepx += nx * e->signdx;
  142.     }
  143.  
  144.     *dx_p = ne;
  145.     *stepx_p = stepx;
  146. }
  147.  
  148. /*
  149.  * Initialize one edge structure given the line endpoints and a
  150.  * starting y value
  151.  */
  152. PIXMAN_EXPORT void
  153. pixman_edge_init (pixman_edge_t *e,
  154.                   int            n,
  155.                   pixman_fixed_t y_start,
  156.                   pixman_fixed_t x_top,
  157.                   pixman_fixed_t y_top,
  158.                   pixman_fixed_t x_bot,
  159.                   pixman_fixed_t y_bot)
  160. {
  161.     pixman_fixed_t dx, dy;
  162.  
  163.     e->x = x_top;
  164.     e->e = 0;
  165.     dx = x_bot - x_top;
  166.     dy = y_bot - y_top;
  167.     e->dy = dy;
  168.     e->dx = 0;
  169.  
  170.     if (dy)
  171.     {
  172.         if (dx >= 0)
  173.         {
  174.             e->signdx = 1;
  175.             e->stepx = dx / dy;
  176.             e->dx = dx % dy;
  177.             e->e = -dy;
  178.         }
  179.         else
  180.         {
  181.             e->signdx = -1;
  182.             e->stepx = -(-dx / dy);
  183.             e->dx = -dx % dy;
  184.             e->e = 0;
  185.         }
  186.  
  187.         _pixman_edge_multi_init (e, STEP_Y_SMALL (n),
  188.                                  &e->stepx_small, &e->dx_small);
  189.  
  190.         _pixman_edge_multi_init (e, STEP_Y_BIG (n),
  191.                                  &e->stepx_big, &e->dx_big);
  192.     }
  193.     pixman_edge_step (e, y_start - y_top);
  194. }
  195.  
  196. /*
  197.  * Initialize one edge structure given a line, starting y value
  198.  * and a pixel offset for the line
  199.  */
  200. PIXMAN_EXPORT void
  201. pixman_line_fixed_edge_init (pixman_edge_t *            e,
  202.                              int                        n,
  203.                              pixman_fixed_t             y,
  204.                              const pixman_line_fixed_t *line,
  205.                              int                        x_off,
  206.                              int                        y_off)
  207. {
  208.     pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
  209.     pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
  210.     const pixman_point_fixed_t *top, *bot;
  211.  
  212.     if (line->p1.y <= line->p2.y)
  213.     {
  214.         top = &line->p1;
  215.         bot = &line->p2;
  216.     }
  217.     else
  218.     {
  219.         top = &line->p2;
  220.         bot = &line->p1;
  221.     }
  222.    
  223.     pixman_edge_init (e, n, y,
  224.                       top->x + x_off_fixed,
  225.                       top->y + y_off_fixed,
  226.                       bot->x + x_off_fixed,
  227.                       bot->y + y_off_fixed);
  228. }
  229.  
  230. PIXMAN_EXPORT void
  231. pixman_add_traps (pixman_image_t * image,
  232.                   int16_t          x_off,
  233.                   int16_t          y_off,
  234.                   int              ntrap,
  235.                   pixman_trap_t *  traps)
  236. {
  237.     int bpp;
  238.     int width;
  239.     int height;
  240.  
  241.     pixman_fixed_t x_off_fixed;
  242.     pixman_fixed_t y_off_fixed;
  243.     pixman_edge_t l, r;
  244.     pixman_fixed_t t, b;
  245.  
  246.     _pixman_image_validate (image);
  247.    
  248.     width = image->bits.width;
  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 width;
  353.     int height;
  354.  
  355.     pixman_fixed_t x_off_fixed;
  356.     pixman_fixed_t y_off_fixed;
  357.     pixman_edge_t l, r;
  358.     pixman_fixed_t t, b;
  359.  
  360.     return_if_fail (image->type == BITS);
  361.  
  362.     _pixman_image_validate (image);
  363.    
  364.     if (!pixman_trapezoid_valid (trap))
  365.         return;
  366.  
  367.     width = image->bits.width;
  368.     height = image->bits.height;
  369.     bpp = PIXMAN_FORMAT_BPP (image->bits.format);
  370.  
  371.     x_off_fixed = pixman_int_to_fixed (x_off);
  372.     y_off_fixed = pixman_int_to_fixed (y_off);
  373.  
  374.     t = trap->top + y_off_fixed;
  375.     if (t < 0)
  376.         t = 0;
  377.     t = pixman_sample_ceil_y (t, bpp);
  378.  
  379.     b = trap->bottom + y_off_fixed;
  380.     if (pixman_fixed_to_int (b) >= height)
  381.         b = pixman_int_to_fixed (height) - 1;
  382.     b = pixman_sample_floor_y (b, bpp);
  383.    
  384.     if (b >= t)
  385.     {
  386.         /* initialize edge walkers */
  387.         pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
  388.         pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
  389.  
  390.         pixman_rasterize_edges (image, &l, &r, t, b);
  391.     }
  392. }
  393.