pixman-utils.c revision 317c648b
1/*
2 * Copyright © 2000 SuSE, Inc.
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 SuSE not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  SuSE makes no representations about the
11 * suitability of this software for any purpose.  It is provided "as is"
12 * without express or implied warranty.
13 *
14 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
16 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Author:  Keith Packard, SuSE, Inc.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <stdlib.h>
29
30#include "pixman-private.h"
31
32/*
33 * Compute the smallest value no less than y which is on a
34 * grid row
35 */
36
37PIXMAN_EXPORT pixman_fixed_t
38pixman_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 = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
44    if (f > Y_FRAC_LAST(n))
45    {
46	if (pixman_fixed_to_int(i) == 0x7fff)
47	{
48	    f = 0xffff; /* saturate */
49	} else {
50	    f = Y_FRAC_FIRST(n);
51	    i += pixman_fixed_1;
52	}
53    }
54    return (i | f);
55}
56
57#define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
58
59/*
60 * Compute the largest value no greater than y which is on a
61 * grid row
62 */
63PIXMAN_EXPORT pixman_fixed_t
64pixman_sample_floor_y (pixman_fixed_t y, int n)
65{
66    pixman_fixed_t   f = pixman_fixed_frac(y);
67    pixman_fixed_t   i = pixman_fixed_floor (y);
68
69    f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
70    if (f < Y_FRAC_FIRST(n))
71    {
72	if (pixman_fixed_to_int(i) == 0x8000)
73	{
74	    f = 0; /* saturate */
75	} else {
76	    f = Y_FRAC_LAST(n);
77	    i -= pixman_fixed_1;
78	}
79    }
80    return (i | f);
81}
82
83/*
84 * Step an edge by any amount (including negative values)
85 */
86PIXMAN_EXPORT void
87pixman_edge_step (pixman_edge_t *e, int n)
88{
89    pixman_fixed_48_16_t	ne;
90
91    e->x += n * e->stepx;
92
93    ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
94
95    if (n >= 0)
96    {
97	if (ne > 0)
98	{
99	    int nx = (ne + e->dy - 1) / e->dy;
100	    e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
101	    e->x += nx * e->signdx;
102	}
103    }
104    else
105    {
106	if (ne <= -e->dy)
107	{
108	    int nx = (-ne) / e->dy;
109	    e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
110	    e->x -= nx * e->signdx;
111	}
112    }
113}
114
115/*
116 * A private routine to initialize the multi-step
117 * elements of an edge structure
118 */
119static void
120_pixman_edge_multi_init (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
121{
122    pixman_fixed_t	stepx;
123    pixman_fixed_48_16_t	ne;
124
125    ne = n * (pixman_fixed_48_16_t) e->dx;
126    stepx = n * e->stepx;
127    if (ne > 0)
128    {
129	int nx = ne / e->dy;
130	ne -= nx * e->dy;
131	stepx += nx * e->signdx;
132    }
133    *dx_p = ne;
134    *stepx_p = stepx;
135}
136
137/*
138 * Initialize one edge structure given the line endpoints and a
139 * starting y value
140 */
141PIXMAN_EXPORT void
142pixman_edge_init (pixman_edge_t	*e,
143		  int		n,
144		  pixman_fixed_t		y_start,
145		  pixman_fixed_t		x_top,
146		  pixman_fixed_t		y_top,
147		  pixman_fixed_t		x_bot,
148		  pixman_fixed_t		y_bot)
149{
150    pixman_fixed_t	dx, dy;
151
152    e->x = x_top;
153    e->e = 0;
154    dx = x_bot - x_top;
155    dy = y_bot - y_top;
156    e->dy = dy;
157    e->dx = 0;
158    if (dy)
159    {
160	if (dx >= 0)
161	{
162	    e->signdx = 1;
163	    e->stepx = dx / dy;
164	    e->dx = dx % dy;
165	    e->e = -dy;
166	}
167	else
168	{
169	    e->signdx = -1;
170	    e->stepx = -(-dx / dy);
171	    e->dx = -dx % dy;
172	    e->e = 0;
173	}
174
175	_pixman_edge_multi_init (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
176	_pixman_edge_multi_init (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
177    }
178    pixman_edge_step (e, y_start - y_top);
179}
180
181/*
182 * Initialize one edge structure given a line, starting y value
183 * and a pixel offset for the line
184 */
185PIXMAN_EXPORT void
186pixman_line_fixed_edge_init (pixman_edge_t *e,
187			     int	    n,
188			     pixman_fixed_t	    y,
189			     const pixman_line_fixed_t *line,
190			     int	    x_off,
191			     int	    y_off)
192{
193    pixman_fixed_t	x_off_fixed = pixman_int_to_fixed(x_off);
194    pixman_fixed_t	y_off_fixed = pixman_int_to_fixed(y_off);
195    const pixman_point_fixed_t *top, *bot;
196
197    if (line->p1.y <= line->p2.y)
198    {
199	top = &line->p1;
200	bot = &line->p2;
201    }
202    else
203    {
204	top = &line->p2;
205	bot = &line->p1;
206    }
207    pixman_edge_init (e, n, y,
208		    top->x + x_off_fixed,
209		    top->y + y_off_fixed,
210		    bot->x + x_off_fixed,
211		    bot->y + y_off_fixed);
212}
213
214pixman_bool_t
215pixman_multiply_overflows_int (unsigned int a,
216		               unsigned int b)
217{
218    return a >= INT32_MAX / b;
219}
220
221pixman_bool_t
222pixman_addition_overflows_int (unsigned int a,
223		               unsigned int b)
224{
225    return a > INT32_MAX - b;
226}
227
228void *
229pixman_malloc_ab(unsigned int a,
230		 unsigned int b)
231{
232    if (a >= INT32_MAX / b)
233	return NULL;
234
235    return malloc (a * b);
236}
237
238void *
239pixman_malloc_abc (unsigned int a,
240		   unsigned int b,
241		   unsigned int c)
242{
243    if (a >= INT32_MAX / b)
244	return NULL;
245    else if (a * b >= INT32_MAX / c)
246	return NULL;
247    else
248	return malloc (a * b * c);
249}
250
251
252/**
253 * pixman_version:
254 *
255 * Returns the version of the pixman library encoded in a single
256 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
257 * later versions compare greater than earlier versions.
258 *
259 * A run-time comparison to check that pixman's version is greater than
260 * or equal to version X.Y.Z could be performed as follows:
261 *
262 * <informalexample><programlisting>
263 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
264 * </programlisting></informalexample>
265 *
266 * See also pixman_version_string() as well as the compile-time
267 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
268 *
269 * Return value: the encoded version.
270 **/
271PIXMAN_EXPORT int
272pixman_version (void)
273{
274    return PIXMAN_VERSION;
275}
276
277/*
278 * Helper routine to expand a color component from 0 < n <= 8 bits to 16 bits by
279 * replication.
280 */
281static inline uint64_t
282expand16(const uint8_t val, int nbits)
283{
284    // Start out with the high bit of val in the high bit of result.
285    uint16_t result = (uint16_t)val << (16 - nbits);
286
287    if (nbits == 0)
288        return 0;
289
290    // Copy the bits in result, doubling the number of bits each time, until we
291    // fill all 16 bits.
292    while (nbits < 16) {
293        result |= result >> nbits;
294        nbits *= 2;
295    }
296
297    return result;
298}
299
300/*
301 * This function expands images from ARGB8 format to ARGB16.  To preserve
302 * precision, it needs to know the original source format.  For example, if the
303 * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
304 * the expanded value is 12345123.  To correctly expand this to 16 bits, it
305 * should be 1234512345123451 and not 1234512312345123.
306 */
307void
308pixman_expand(uint64_t *dst, const uint32_t *src,
309	      pixman_format_code_t format, int width)
310{
311    /*
312     * Determine the sizes of each component and the masks and shifts required
313     * to extract them from the source pixel.
314     */
315    const int a_size = PIXMAN_FORMAT_A(format),
316              r_size = PIXMAN_FORMAT_R(format),
317              g_size = PIXMAN_FORMAT_G(format),
318              b_size = PIXMAN_FORMAT_B(format);
319    const int a_shift = 32 - a_size,
320              r_shift = 24 - r_size,
321              g_shift = 16 - g_size,
322              b_shift =  8 - b_size;
323    const uint8_t a_mask = ~(~0 << a_size),
324                  r_mask = ~(~0 << r_size),
325                  g_mask = ~(~0 << g_size),
326                  b_mask = ~(~0 << b_size);
327    int i;
328
329    /* Start at the end so that we can do the expansion in place when src == dst */
330    for (i = width - 1; i >= 0; i--)
331    {
332        const uint32_t pixel = src[i];
333        // Extract the components.
334        const uint8_t a = (pixel >> a_shift) & a_mask,
335                      r = (pixel >> r_shift) & r_mask,
336                      g = (pixel >> g_shift) & g_mask,
337                      b = (pixel >> b_shift) & b_mask;
338        const uint64_t a16 = a_size ? expand16(a, a_size) : 0xffff,
339                       r16 = expand16(r, r_size),
340                       g16 = expand16(g, g_size),
341                       b16 = expand16(b, b_size);
342
343        dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
344    }
345}
346
347/*
348 * Contracting is easier than expanding.  We just need to truncate the
349 * components.
350 */
351void
352pixman_contract(uint32_t *dst, const uint64_t *src, int width)
353{
354    int i;
355
356    /* Start at the beginning so that we can do the contraction in place when
357     * src == dst */
358    for (i = 0; i < width; i++)
359    {
360        const uint8_t a = src[i] >> 56,
361                      r = src[i] >> 40,
362                      g = src[i] >> 24,
363                      b = src[i] >> 8;
364        dst[i] = a << 24 | r << 16 | g << 8 | b;
365    }
366}
367
368/**
369 * pixman_version_string:
370 *
371 * Returns the version of the pixman library as a human-readable string
372 * of the form "X.Y.Z".
373 *
374 * See also pixman_version() as well as the compile-time equivalents
375 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
376 *
377 * Return value: a string containing the version.
378 **/
379PIXMAN_EXPORT const char*
380pixman_version_string (void)
381{
382    return PIXMAN_VERSION_STRING;
383}
384
385/**
386 * pixman_format_supported_destination:
387 * @format: A pixman_format_code_t format
388 *
389 * Return value: whether the provided format code is a supported
390 * format for a pixman surface used as a destination in
391 * rendering.
392 *
393 * Currently, all pixman_format_code_t values are supported
394 * except for the YUV formats.
395 **/
396PIXMAN_EXPORT pixman_bool_t
397pixman_format_supported_destination (pixman_format_code_t format)
398{
399    switch (format) {
400    /* 32 bpp formats */
401    case PIXMAN_a2b10g10r10:
402    case PIXMAN_x2b10g10r10:
403    case PIXMAN_a8r8g8b8:
404    case PIXMAN_x8r8g8b8:
405    case PIXMAN_a8b8g8r8:
406    case PIXMAN_x8b8g8r8:
407    case PIXMAN_b8g8r8a8:
408    case PIXMAN_b8g8r8x8:
409    case PIXMAN_r8g8b8:
410    case PIXMAN_b8g8r8:
411    case PIXMAN_r5g6b5:
412    case PIXMAN_b5g6r5:
413    /* 16 bpp formats */
414    case PIXMAN_a1r5g5b5:
415    case PIXMAN_x1r5g5b5:
416    case PIXMAN_a1b5g5r5:
417    case PIXMAN_x1b5g5r5:
418    case PIXMAN_a4r4g4b4:
419    case PIXMAN_x4r4g4b4:
420    case PIXMAN_a4b4g4r4:
421    case PIXMAN_x4b4g4r4:
422    /* 8bpp formats */
423    case PIXMAN_a8:
424    case PIXMAN_r3g3b2:
425    case PIXMAN_b2g3r3:
426    case PIXMAN_a2r2g2b2:
427    case PIXMAN_a2b2g2r2:
428    case PIXMAN_c8:
429    case PIXMAN_g8:
430    case PIXMAN_x4a4:
431    /* Collides with PIXMAN_c8
432    case PIXMAN_x4c4:
433    */
434    /* Collides with PIXMAN_g8
435    case PIXMAN_x4g4:
436    */
437    /* 4bpp formats */
438    case PIXMAN_a4:
439    case PIXMAN_r1g2b1:
440    case PIXMAN_b1g2r1:
441    case PIXMAN_a1r1g1b1:
442    case PIXMAN_a1b1g1r1:
443    case PIXMAN_c4:
444    case PIXMAN_g4:
445    /* 1bpp formats */
446    case PIXMAN_a1:
447    case PIXMAN_g1:
448	return TRUE;
449
450    /* YUV formats */
451    case PIXMAN_yuy2:
452    case PIXMAN_yv12:
453    default:
454	return FALSE;
455    }
456}
457
458/**
459 * pixman_format_supported_source:
460 * @format: A pixman_format_code_t format
461 *
462 * Return value: whether the provided format code is a supported
463 * format for a pixman surface used as a source in
464 * rendering.
465 *
466 * Currently, all pixman_format_code_t values are supported.
467 **/
468PIXMAN_EXPORT pixman_bool_t
469pixman_format_supported_source (pixman_format_code_t format)
470{
471    switch (format) {
472    /* 32 bpp formats */
473    case PIXMAN_a2b10g10r10:
474    case PIXMAN_x2b10g10r10:
475    case PIXMAN_a8r8g8b8:
476    case PIXMAN_x8r8g8b8:
477    case PIXMAN_a8b8g8r8:
478    case PIXMAN_x8b8g8r8:
479    case PIXMAN_b8g8r8a8:
480    case PIXMAN_b8g8r8x8:
481    case PIXMAN_r8g8b8:
482    case PIXMAN_b8g8r8:
483    case PIXMAN_r5g6b5:
484    case PIXMAN_b5g6r5:
485    /* 16 bpp formats */
486    case PIXMAN_a1r5g5b5:
487    case PIXMAN_x1r5g5b5:
488    case PIXMAN_a1b5g5r5:
489    case PIXMAN_x1b5g5r5:
490    case PIXMAN_a4r4g4b4:
491    case PIXMAN_x4r4g4b4:
492    case PIXMAN_a4b4g4r4:
493    case PIXMAN_x4b4g4r4:
494    /* 8bpp formats */
495    case PIXMAN_a8:
496    case PIXMAN_r3g3b2:
497    case PIXMAN_b2g3r3:
498    case PIXMAN_a2r2g2b2:
499    case PIXMAN_a2b2g2r2:
500    case PIXMAN_c8:
501    case PIXMAN_g8:
502    case PIXMAN_x4a4:
503    /* Collides with PIXMAN_c8
504    case PIXMAN_x4c4:
505    */
506    /* Collides with PIXMAN_g8
507    case PIXMAN_x4g4:
508    */
509    /* 4bpp formats */
510    case PIXMAN_a4:
511    case PIXMAN_r1g2b1:
512    case PIXMAN_b1g2r1:
513    case PIXMAN_a1r1g1b1:
514    case PIXMAN_a1b1g1r1:
515    case PIXMAN_c4:
516    case PIXMAN_g4:
517    /* 1bpp formats */
518    case PIXMAN_a1:
519    case PIXMAN_g1:
520    /* YUV formats */
521    case PIXMAN_yuy2:
522    case PIXMAN_yv12:
523	return TRUE;
524
525    default:
526	return FALSE;
527    }
528}
529
530void
531_pixman_walk_composite_region (pixman_implementation_t *imp,
532			      pixman_op_t op,
533			      pixman_image_t * pSrc,
534			      pixman_image_t * pMask,
535			      pixman_image_t * pDst,
536			      int16_t xSrc,
537			      int16_t ySrc,
538			      int16_t xMask,
539			      int16_t yMask,
540			      int16_t xDst,
541			      int16_t yDst,
542			      uint16_t width,
543			      uint16_t height,
544			      pixman_bool_t srcRepeat,
545			      pixman_bool_t maskRepeat,
546			      pixman_composite_func_t compositeRect)
547{
548    int		    n;
549    const pixman_box32_t *pbox;
550    int		    w, h, w_this, h_this;
551    int		    x_msk, y_msk, x_src, y_src, x_dst, y_dst;
552    pixman_region32_t reg;
553    pixman_region32_t *region;
554
555    pixman_region32_init (&reg);
556    if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
557					    xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
558    {
559	return;
560    }
561
562    region = &reg;
563
564    pbox = pixman_region32_rectangles (region, &n);
565    while (n--)
566    {
567	h = pbox->y2 - pbox->y1;
568	y_src = pbox->y1 - yDst + ySrc;
569	y_msk = pbox->y1 - yDst + yMask;
570	y_dst = pbox->y1;
571	while (h)
572	{
573	    h_this = h;
574	    w = pbox->x2 - pbox->x1;
575	    x_src = pbox->x1 - xDst + xSrc;
576	    x_msk = pbox->x1 - xDst + xMask;
577	    x_dst = pbox->x1;
578	    if (maskRepeat)
579	    {
580		y_msk = MOD (y_msk, pMask->bits.height);
581		if (h_this > pMask->bits.height - y_msk)
582		    h_this = pMask->bits.height - y_msk;
583	    }
584	    if (srcRepeat)
585	    {
586		y_src = MOD (y_src, pSrc->bits.height);
587		if (h_this > pSrc->bits.height - y_src)
588		    h_this = pSrc->bits.height - y_src;
589	    }
590	    while (w)
591	    {
592		w_this = w;
593		if (maskRepeat)
594		{
595		    x_msk = MOD (x_msk, pMask->bits.width);
596		    if (w_this > pMask->bits.width - x_msk)
597			w_this = pMask->bits.width - x_msk;
598		}
599		if (srcRepeat)
600		{
601		    x_src = MOD (x_src, pSrc->bits.width);
602		    if (w_this > pSrc->bits.width - x_src)
603			w_this = pSrc->bits.width - x_src;
604		}
605		(*compositeRect) (imp,
606				  op, pSrc, pMask, pDst,
607				  x_src, y_src, x_msk, y_msk, x_dst, y_dst,
608				  w_this, h_this);
609		w -= w_this;
610		x_src += w_this;
611		x_msk += w_this;
612		x_dst += w_this;
613	    }
614	    h -= h_this;
615	    y_src += h_this;
616	    y_msk += h_this;
617	    y_dst += h_this;
618	}
619	pbox++;
620    }
621    pixman_region32_fini (&reg);
622}
623
624static pixman_bool_t
625mask_is_solid (pixman_image_t *mask)
626{
627    if (mask->type == SOLID)
628	return TRUE;
629
630    if (mask->type == BITS &&
631	mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
632	mask->bits.width == 1 &&
633	mask->bits.height == 1)
634    {
635	return TRUE;
636    }
637
638    return FALSE;
639}
640
641static const FastPathInfo *
642get_fast_path (const FastPathInfo *fast_paths,
643	       pixman_op_t         op,
644	       pixman_image_t     *pSrc,
645	       pixman_image_t     *pMask,
646	       pixman_image_t     *pDst,
647	       pixman_bool_t       is_pixbuf)
648{
649    const FastPathInfo *info;
650
651    for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
652    {
653	pixman_bool_t valid_src		= FALSE;
654	pixman_bool_t valid_mask	= FALSE;
655
656	if (info->op != op)
657	    continue;
658
659	if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))		||
660	    (pSrc->type == BITS && info->src_format == pSrc->bits.format))
661	{
662	    valid_src = TRUE;
663	}
664
665	if (!valid_src)
666	    continue;
667
668	if ((info->mask_format == PIXMAN_null && !pMask)			||
669	    (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
670	{
671	    valid_mask = TRUE;
672
673	    if (info->flags & NEED_SOLID_MASK)
674	    {
675		if (!pMask || !mask_is_solid (pMask))
676		    valid_mask = FALSE;
677	    }
678
679	    if (info->flags & NEED_COMPONENT_ALPHA)
680	    {
681		if (!pMask || !pMask->common.component_alpha)
682		    valid_mask = FALSE;
683	    }
684	}
685
686	if (!valid_mask)
687	    continue;
688
689	if (info->dest_format != pDst->bits.format)
690	    continue;
691
692	if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
693	    continue;
694
695	return info;
696    }
697
698    return NULL;
699}
700
701pixman_bool_t
702_pixman_run_fast_path (const FastPathInfo *paths,
703		       pixman_implementation_t *imp,
704		       pixman_op_t op,
705		       pixman_image_t *src,
706		       pixman_image_t *mask,
707		       pixman_image_t *dest,
708		       int32_t src_x,
709		       int32_t src_y,
710		       int32_t mask_x,
711		       int32_t mask_y,
712		       int32_t dest_x,
713		       int32_t dest_y,
714		       int32_t width,
715		       int32_t height)
716{
717    pixman_composite_func_t func = NULL;
718    pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL;
719    pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
720
721    if ((src->type == BITS || pixman_image_can_get_solid (src)) &&
722	(!mask || mask->type == BITS)
723        && !src->common.transform && !(mask && mask->common.transform)
724        && !(mask && mask->common.alpha_map) && !src->common.alpha_map && !dest->common.alpha_map
725        && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
726        && (src->common.repeat != PIXMAN_REPEAT_PAD)
727        && (src->common.repeat != PIXMAN_REPEAT_REFLECT)
728        && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
729		      mask->common.repeat != PIXMAN_REPEAT_PAD &&
730		      mask->common.repeat != PIXMAN_REPEAT_REFLECT))
731	&& !src->common.read_func && !src->common.write_func
732	&& !(mask && mask->common.read_func)
733	&& !(mask && mask->common.write_func)
734	&& !dest->common.read_func
735	&& !dest->common.write_func)
736    {
737	const FastPathInfo *info;
738	pixman_bool_t pixbuf;
739
740	pixbuf =
741	    src && src->type == BITS		&&
742	    mask && mask->type == BITS		&&
743	    src->bits.bits == mask->bits.bits	&&
744	    src_x == mask_x			&&
745	    src_y == mask_y			&&
746	    !mask->common.component_alpha	&&
747	    !mask_repeat;
748
749	info = get_fast_path (paths, op, src, mask, dest, pixbuf);
750
751	if (info)
752	{
753	    func = info->func;
754
755	    if (info->src_format == PIXMAN_solid)
756		src_repeat = FALSE;
757
758	    if (info->mask_format == PIXMAN_solid || info->flags & NEED_SOLID_MASK)
759		mask_repeat = FALSE;
760
761	    if ((src_repeat			&&
762		 src->bits.width == 1		&&
763		 src->bits.height == 1)	||
764		(mask_repeat			&&
765		 mask->bits.width == 1		&&
766		 mask->bits.height == 1))
767	    {
768		/* If src or mask are repeating 1x1 images and src_repeat or
769		 * mask_repeat are still TRUE, it means the fast path we
770		 * selected does not actually handle repeating images.
771		 *
772		 * So rather than call the "fast path" with a zillion
773		 * 1x1 requests, we just fall back to the general code (which
774		 * does do something sensible with 1x1 repeating images).
775		 */
776		func = NULL;
777	    }
778	}
779    }
780
781    if (func)
782    {
783	_pixman_walk_composite_region (imp, op,
784				       src, mask, dest,
785				       src_x, src_y, mask_x, mask_y,
786				       dest_x, dest_y,
787				       width, height,
788				       src_repeat, mask_repeat,
789				       func);
790	return TRUE;
791    }
792
793    return FALSE;
794}
795