gfx/cairo/libpixman/src/pixman-edge.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    23 #ifdef HAVE_CONFIG_H
    24 #include <config.h>
    25 #endif
    27 #include <string.h>
    29 #include "pixman-private.h"
    30 #include "pixman-accessor.h"
    32 /*
    33  * Step across a small sample grid gap
    34  */
    35 #define RENDER_EDGE_STEP_SMALL(edge)					\
    36     {									\
    37 	edge->x += edge->stepx_small;					\
    38 	edge->e += edge->dx_small;					\
    39 	if (edge->e > 0)						\
    40 	{								\
    41 	    edge->e -= edge->dy;					\
    42 	    edge->x += edge->signdx;					\
    43 	}								\
    44     }
    46 /*
    47  * Step across a large sample grid gap
    48  */
    49 #define RENDER_EDGE_STEP_BIG(edge)					\
    50     {									\
    51 	edge->x += edge->stepx_big;					\
    52 	edge->e += edge->dx_big;					\
    53 	if (edge->e > 0)						\
    54 	{								\
    55 	    edge->e -= edge->dy;					\
    56 	    edge->x += edge->signdx;					\
    57 	}								\
    58     }
    60 #ifdef PIXMAN_FB_ACCESSORS
    61 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
    62 #else
    63 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
    64 #endif
    66 /*
    67  * 4 bit alpha
    68  */
    70 #define N_BITS  4
    71 #define RASTERIZE_EDGES rasterize_edges_4
    73 #ifndef WORDS_BIGENDIAN
    74 #define SHIFT_4(o)      ((o) << 2)
    75 #else
    76 #define SHIFT_4(o)      ((1 - (o)) << 2)
    77 #endif
    79 #define GET_4(x, o)      (((x) >> SHIFT_4 (o)) & 0xf)
    80 #define PUT_4(x, o, v)							\
    81     (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
    83 #define DEFINE_ALPHA(line, x)						\
    84     uint8_t   *__ap = (uint8_t *) line + ((x) >> 1);			\
    85     int __ao = (x) & 1
    87 #define STEP_ALPHA      ((__ap += __ao), (__ao ^= 1))
    89 #define ADD_ALPHA(a)							\
    90     {									\
    91         uint8_t __o = READ (image, __ap);				\
    92         uint8_t __a = (a) + GET_4 (__o, __ao);				\
    93         WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
    94     }
    96 #include "pixman-edge-imp.h"
    98 #undef ADD_ALPHA
    99 #undef STEP_ALPHA
   100 #undef DEFINE_ALPHA
   101 #undef RASTERIZE_EDGES
   102 #undef N_BITS
   105 /*
   106  * 1 bit alpha
   107  */
   109 #define N_BITS 1
   110 #define RASTERIZE_EDGES rasterize_edges_1
   112 #include "pixman-edge-imp.h"
   114 #undef RASTERIZE_EDGES
   115 #undef N_BITS
   117 /*
   118  * 8 bit alpha
   119  */
   121 static force_inline uint8_t
   122 clip255 (int x)
   123 {
   124     if (x > 255)
   125 	return 255;
   127     return x;
   128 }
   130 #define ADD_SATURATE_8(buf, val, length)				\
   131     do									\
   132     {									\
   133         int i__ = (length);						\
   134         uint8_t *buf__ = (buf);						\
   135         int val__ = (val);						\
   136 									\
   137         while (i__--)							\
   138         {								\
   139             WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
   140             (buf__)++;							\
   141 	}								\
   142     } while (0)
   144 /*
   145  * We want to detect the case where we add the same value to a long
   146  * span of pixels.  The triangles on the end are filled in while we
   147  * count how many sub-pixel scanlines contribute to the middle section.
   148  *
   149  *                 +--------------------------+
   150  *  fill_height =|   \                      /
   151  *                     +------------------+
   152  *                      |================|
   153  *                   fill_start       fill_end
   154  */
   155 static void
   156 rasterize_edges_8 (pixman_image_t *image,
   157                    pixman_edge_t * l,
   158                    pixman_edge_t * r,
   159                    pixman_fixed_t  t,
   160                    pixman_fixed_t  b)
   161 {
   162     pixman_fixed_t y = t;
   163     uint32_t  *line;
   164     int fill_start = -1, fill_end = -1;
   165     int fill_size = 0;
   166     uint32_t *buf = (image)->bits.bits;
   167     int stride = (image)->bits.rowstride;
   168     int width = (image)->bits.width;
   170     line = buf + pixman_fixed_to_int (y) * stride;
   172     for (;;)
   173     {
   174         uint8_t *ap = (uint8_t *) line;
   175         pixman_fixed_t lx, rx;
   176         int lxi, rxi;
   178         /* clip X */
   179         lx = l->x;
   180         if (lx < 0)
   181 	    lx = 0;
   183         rx = r->x;
   185         if (pixman_fixed_to_int (rx) >= width)
   186 	{
   187 	    /* Use the last pixel of the scanline, covered 100%.
   188 	     * We can't use the first pixel following the scanline,
   189 	     * because accessing it could result in a buffer overrun.
   190 	     */
   191 	    rx = pixman_int_to_fixed (width) - 1;
   192 	}
   194         /* Skip empty (or backwards) sections */
   195         if (rx > lx)
   196         {
   197             int lxs, rxs;
   199             /* Find pixel bounds for span. */
   200             lxi = pixman_fixed_to_int (lx);
   201             rxi = pixman_fixed_to_int (rx);
   203             /* Sample coverage for edge pixels */
   204             lxs = RENDER_SAMPLES_X (lx, 8);
   205             rxs = RENDER_SAMPLES_X (rx, 8);
   207             /* Add coverage across row */
   208             if (lxi == rxi)
   209             {
   210                 WRITE (image, ap + lxi,
   211 		       clip255 (READ (image, ap + lxi) + rxs - lxs));
   212 	    }
   213             else
   214             {
   215                 WRITE (image, ap + lxi,
   216 		       clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
   218                 /* Move forward so that lxi/rxi is the pixel span */
   219                 lxi++;
   221                 /* Don't bother trying to optimize the fill unless
   222 		 * the span is longer than 4 pixels. */
   223                 if (rxi - lxi > 4)
   224                 {
   225                     if (fill_start < 0)
   226                     {
   227                         fill_start = lxi;
   228                         fill_end = rxi;
   229                         fill_size++;
   230 		    }
   231                     else
   232                     {
   233                         if (lxi >= fill_end || rxi < fill_start)
   234                         {
   235                             /* We're beyond what we saved, just fill it */
   236                             ADD_SATURATE_8 (ap + fill_start,
   237                                             fill_size * N_X_FRAC (8),
   238                                             fill_end - fill_start);
   239                             fill_start = lxi;
   240                             fill_end = rxi;
   241                             fill_size = 1;
   242 			}
   243                         else
   244                         {
   245                             /* Update fill_start */
   246                             if (lxi > fill_start)
   247                             {
   248                                 ADD_SATURATE_8 (ap + fill_start,
   249                                                 fill_size * N_X_FRAC (8),
   250                                                 lxi - fill_start);
   251                                 fill_start = lxi;
   252 			    }
   253                             else if (lxi < fill_start)
   254                             {
   255                                 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
   256                                                 fill_start - lxi);
   257 			    }
   259                             /* Update fill_end */
   260                             if (rxi < fill_end)
   261                             {
   262                                 ADD_SATURATE_8 (ap + rxi,
   263                                                 fill_size * N_X_FRAC (8),
   264                                                 fill_end - rxi);
   265                                 fill_end = rxi;
   266 			    }
   267                             else if (fill_end < rxi)
   268                             {
   269                                 ADD_SATURATE_8 (ap + fill_end,
   270                                                 N_X_FRAC (8),
   271                                                 rxi - fill_end);
   272 			    }
   273                             fill_size++;
   274 			}
   275 		    }
   276 		}
   277                 else
   278                 {
   279                     ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
   280 		}
   282                 WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
   283 	    }
   284 	}
   286         if (y == b)
   287         {
   288             /* We're done, make sure we clean up any remaining fill. */
   289             if (fill_start != fill_end)
   290             {
   291                 if (fill_size == N_Y_FRAC (8))
   292                 {
   293                     MEMSET_WRAPPED (image, ap + fill_start,
   294 				    0xff, fill_end - fill_start);
   295 		}
   296                 else
   297                 {
   298                     ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
   299                                     fill_end - fill_start);
   300 		}
   301 	    }
   302             break;
   303 	}
   305         if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
   306         {
   307             RENDER_EDGE_STEP_SMALL (l);
   308             RENDER_EDGE_STEP_SMALL (r);
   309             y += STEP_Y_SMALL (8);
   310 	}
   311         else
   312         {
   313             RENDER_EDGE_STEP_BIG (l);
   314             RENDER_EDGE_STEP_BIG (r);
   315             y += STEP_Y_BIG (8);
   316             if (fill_start != fill_end)
   317             {
   318                 if (fill_size == N_Y_FRAC (8))
   319                 {
   320                     MEMSET_WRAPPED (image, ap + fill_start,
   321 				    0xff, fill_end - fill_start);
   322 		}
   323                 else
   324                 {
   325                     ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
   326                                     fill_end - fill_start);
   327 		}
   329                 fill_start = fill_end = -1;
   330                 fill_size = 0;
   331 	    }
   333             line += stride;
   334 	}
   335     }
   336 }
   338 #ifndef PIXMAN_FB_ACCESSORS
   339 static
   340 #endif
   341 void
   342 PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
   343                         pixman_edge_t * l,
   344                         pixman_edge_t * r,
   345                         pixman_fixed_t  t,
   346                         pixman_fixed_t  b)
   347 {
   348     switch (PIXMAN_FORMAT_BPP (image->bits.format))
   349     {
   350     case 1:
   351 	rasterize_edges_1 (image, l, r, t, b);
   352 	break;
   354     case 4:
   355 	rasterize_edges_4 (image, l, r, t, b);
   356 	break;
   358     case 8:
   359 	rasterize_edges_8 (image, l, r, t, b);
   360 	break;
   362     default:
   363         break;
   364     }
   365 }
   367 #ifndef PIXMAN_FB_ACCESSORS
   369 PIXMAN_EXPORT void
   370 pixman_rasterize_edges (pixman_image_t *image,
   371                         pixman_edge_t * l,
   372                         pixman_edge_t * r,
   373                         pixman_fixed_t  t,
   374                         pixman_fixed_t  b)
   375 {
   376     return_if_fail (image->type == BITS);
   377     return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
   379     if (image->bits.read_func || image->bits.write_func)
   380 	pixman_rasterize_edges_accessors (image, l, r, t, b);
   381     else
   382 	pixman_rasterize_edges_no_accessors (image, l, r, t, b);
   383 }
   385 #endif

mercurial