Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1891 serge 1
/*
2
 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
3
 *             2005 Lars Knoll & Zack Rusin, Trolltech
4
 *             2008 Aaron Plattner, NVIDIA Corporation
5
 * Copyright © 2000 SuSE, Inc.
6
 * Copyright © 2007, 2009 Red Hat, Inc.
7
 * Copyright © 2008 André Tupinambá 
8
 *
9
 * Permission to use, copy, modify, distribute, and sell this software and its
10
 * documentation for any purpose is hereby granted without fee, provided that
11
 * the above copyright notice appear in all copies and that both that
12
 * copyright notice and this permission notice appear in supporting
13
 * documentation, and that the name of Keith Packard not be used in
14
 * advertising or publicity pertaining to distribution of the software without
15
 * specific, written prior permission.  Keith Packard makes no
16
 * representations about the suitability of this software for any purpose.  It
17
 * is provided "as is" without express or implied warranty.
18
 *
19
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26
 * SOFTWARE.
27
 */
28
 
29
#ifdef HAVE_CONFIG_H
30
#include 
31
#endif
32
#include 
33
#include 
34
#include 
35
#include "pixman-private.h"
36
#include "pixman-combine32.h"
37
 
38
/* Store functions */
39
void
40
_pixman_image_store_scanline_32 (bits_image_t *  image,
41
                                 int             x,
42
                                 int             y,
43
                                 int             width,
44
                                 const uint32_t *buffer)
45
{
46
    image->store_scanline_32 (image, x, y, width, buffer);
47
 
48
    if (image->common.alpha_map)
49
    {
50
	x -= image->common.alpha_origin_x;
51
	y -= image->common.alpha_origin_y;
52
 
53
	image->common.alpha_map->store_scanline_32 (
54
	    image->common.alpha_map, x, y, width, buffer);
55
    }
56
}
57
 
58
void
59
_pixman_image_store_scanline_64 (bits_image_t *  image,
60
                                 int             x,
61
                                 int             y,
62
                                 int             width,
63
                                 const uint32_t *buffer)
64
{
65
    image->store_scanline_64 (image, x, y, width, buffer);
66
 
67
    if (image->common.alpha_map)
68
    {
69
	x -= image->common.alpha_origin_x;
70
	y -= image->common.alpha_origin_y;
71
 
72
	image->common.alpha_map->store_scanline_64 (
73
	    image->common.alpha_map, x, y, width, buffer);
74
    }
75
}
76
 
77
/* Fetch functions */
78
 
79
static force_inline uint32_t
80
fetch_pixel_no_alpha (bits_image_t *image,
81
		      int x, int y, pixman_bool_t check_bounds)
82
{
83
    if (check_bounds &&
84
	(x < 0 || x >= image->width || y < 0 || y >= image->height))
85
    {
86
	return 0;
87
    }
88
 
89
    return image->fetch_pixel_32 (image, x, y);
90
}
91
 
92
typedef uint32_t (* get_pixel_t) (bits_image_t *image,
93
				  int x, int y, pixman_bool_t check_bounds);
94
 
95
static force_inline void
96
repeat (pixman_repeat_t repeat, int size, int *coord)
97
{
98
    switch (repeat)
99
    {
100
    case PIXMAN_REPEAT_NORMAL:
101
	*coord = MOD (*coord, size);
102
	break;
103
 
104
    case PIXMAN_REPEAT_PAD:
105
	*coord = CLIP (*coord, 0, size - 1);
106
	break;
107
 
108
    case PIXMAN_REPEAT_REFLECT:
109
	*coord = MOD (*coord, size * 2);
110
 
111
	if (*coord >= size)
112
	    *coord = size * 2 - *coord - 1;
113
	break;
114
 
115
    case PIXMAN_REPEAT_NONE:
116
	break;
117
 
118
    default:
119
        break;
120
    }
121
}
122
 
123
static force_inline uint32_t
124
bits_image_fetch_pixel_nearest (bits_image_t   *image,
125
				pixman_fixed_t  x,
126
				pixman_fixed_t  y,
127
				get_pixel_t	get_pixel)
128
{
129
    int x0 = pixman_fixed_to_int (x - pixman_fixed_e);
130
    int y0 = pixman_fixed_to_int (y - pixman_fixed_e);
131
 
132
    if (image->common.repeat != PIXMAN_REPEAT_NONE)
133
    {
134
	repeat (image->common.repeat, image->width, &x0);
135
	repeat (image->common.repeat, image->height, &y0);
136
 
137
	return get_pixel (image, x0, y0, FALSE);
138
    }
139
    else
140
    {
141
	return get_pixel (image, x0, y0, TRUE);
142
    }
143
}
144
 
145
#if SIZEOF_LONG > 4
146
 
147
static force_inline uint32_t
148
bilinear_interpolation (uint32_t tl, uint32_t tr,
149
			uint32_t bl, uint32_t br,
150
			int distx, int disty)
151
{
152
    uint64_t distxy, distxiy, distixy, distixiy;
153
    uint64_t tl64, tr64, bl64, br64;
154
    uint64_t f, r;
155
 
156
    distxy = distx * disty;
157
    distxiy = distx * (256 - disty);
158
    distixy = (256 - distx) * disty;
159
    distixiy = (256 - distx) * (256 - disty);
160
 
161
    /* Alpha and Blue */
162
    tl64 = tl & 0xff0000ff;
163
    tr64 = tr & 0xff0000ff;
164
    bl64 = bl & 0xff0000ff;
165
    br64 = br & 0xff0000ff;
166
 
167
    f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
168
    r = f & 0x0000ff0000ff0000ull;
169
 
170
    /* Red and Green */
171
    tl64 = tl;
172
    tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
173
 
174
    tr64 = tr;
175
    tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
176
 
177
    bl64 = bl;
178
    bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
179
 
180
    br64 = br;
181
    br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
182
 
183
    f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
184
    r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
185
 
186
    return (uint32_t)(r >> 16);
187
}
188
 
189
#else
190
 
191
static force_inline uint32_t
192
bilinear_interpolation (uint32_t tl, uint32_t tr,
193
			uint32_t bl, uint32_t br,
194
			int distx, int disty)
195
{
196
    int distxy, distxiy, distixy, distixiy;
197
    uint32_t f, r;
198
 
199
    distxy = distx * disty;
200
    distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
201
    distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
202
    distixiy =
203
	256 * 256 - (disty << 8) -
204
	(distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */
205
 
206
    /* Blue */
207
    r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
208
      + (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy;
209
 
210
    /* Green */
211
    f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
212
      + (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy;
213
    r |= f & 0xff000000;
214
 
215
    tl >>= 16;
216
    tr >>= 16;
217
    bl >>= 16;
218
    br >>= 16;
219
    r >>= 16;
220
 
221
    /* Red */
222
    f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy
223
      + (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy;
224
    r |= f & 0x00ff0000;
225
 
226
    /* Alpha */
227
    f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy
228
      + (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy;
229
    r |= f & 0xff000000;
230
 
231
    return r;
232
}
233
 
234
#endif
235
 
236
static force_inline uint32_t
237
bits_image_fetch_pixel_bilinear (bits_image_t   *image,
238
				 pixman_fixed_t  x,
239
				 pixman_fixed_t  y,
240
				 get_pixel_t	 get_pixel)
241
{
242
    pixman_repeat_t repeat_mode = image->common.repeat;
243
    int width = image->width;
244
    int height = image->height;
245
    int x1, y1, x2, y2;
246
    uint32_t tl, tr, bl, br;
247
    int32_t distx, disty;
248
 
249
    x1 = x - pixman_fixed_1 / 2;
250
    y1 = y - pixman_fixed_1 / 2;
251
 
252
    distx = (x1 >> 8) & 0xff;
253
    disty = (y1 >> 8) & 0xff;
254
 
255
    x1 = pixman_fixed_to_int (x1);
256
    y1 = pixman_fixed_to_int (y1);
257
    x2 = x1 + 1;
258
    y2 = y1 + 1;
259
 
260
    if (repeat_mode != PIXMAN_REPEAT_NONE)
261
    {
262
	repeat (repeat_mode, width, &x1);
263
	repeat (repeat_mode, height, &y1);
264
	repeat (repeat_mode, width, &x2);
265
	repeat (repeat_mode, height, &y2);
266
 
267
	tl = get_pixel (image, x1, y1, FALSE);
268
	bl = get_pixel (image, x1, y2, FALSE);
269
	tr = get_pixel (image, x2, y1, FALSE);
270
	br = get_pixel (image, x2, y2, FALSE);
271
    }
272
    else
273
    {
274
	tl = get_pixel (image, x1, y1, TRUE);
275
	tr = get_pixel (image, x2, y1, TRUE);
276
	bl = get_pixel (image, x1, y2, TRUE);
277
	br = get_pixel (image, x2, y2, TRUE);
278
    }
279
 
280
    return bilinear_interpolation (tl, tr, bl, br, distx, disty);
281
}
282
 
283
static void
284
bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima,
285
					  int              offset,
286
					  int              line,
287
					  int              width,
288
					  uint32_t *       buffer,
289
					  const uint32_t * mask)
290
{
291
    bits_image_t *bits = &ima->bits;
292
    pixman_fixed_t x_top, x_bottom, x;
293
    pixman_fixed_t ux_top, ux_bottom, ux;
294
    pixman_vector_t v;
295
    uint32_t top_mask, bottom_mask;
296
    uint32_t *top_row;
297
    uint32_t *bottom_row;
298
    uint32_t *end;
299
    uint32_t zero[2] = { 0, 0 };
300
    uint32_t one = 1;
301
    int y, y1, y2;
302
    int disty;
303
    int mask_inc;
304
    int w;
305
 
306
    /* reference point is the center of the pixel */
307
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
308
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
309
    v.vector[2] = pixman_fixed_1;
310
 
311
    if (!pixman_transform_point_3d (bits->common.transform, &v))
312
	return;
313
 
314
    ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
315
    x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;
316
 
317
    y = v.vector[1] - pixman_fixed_1/2;
318
    disty = (y >> 8) & 0xff;
319
 
320
    /* Load the pointers to the first and second lines from the source
321
     * image that bilinear code must read.
322
     *
323
     * The main trick in this code is about the check if any line are
324
     * outside of the image;
325
     *
326
     * When I realize that a line (any one) is outside, I change
327
     * the pointer to a dummy area with zeros. Once I change this, I
328
     * must be sure the pointer will not change, so I set the
329
     * variables to each pointer increments inside the loop.
330
     */
331
    y1 = pixman_fixed_to_int (y);
332
    y2 = y1 + 1;
333
 
334
    if (y1 < 0 || y1 >= bits->height)
335
    {
336
	top_row = zero;
337
	x_top = 0;
338
	ux_top = 0;
339
    }
340
    else
341
    {
342
	top_row = bits->bits + y1 * bits->rowstride;
343
	x_top = x;
344
	ux_top = ux;
345
    }
346
 
347
    if (y2 < 0 || y2 >= bits->height)
348
    {
349
	bottom_row = zero;
350
	x_bottom = 0;
351
	ux_bottom = 0;
352
    }
353
    else
354
    {
355
	bottom_row = bits->bits + y2 * bits->rowstride;
356
	x_bottom = x;
357
	ux_bottom = ux;
358
    }
359
 
360
    /* Instead of checking whether the operation uses the mast in
361
     * each loop iteration, verify this only once and prepare the
362
     * variables to make the code smaller inside the loop.
363
     */
364
    if (!mask)
365
    {
366
        mask_inc = 0;
367
        mask = &one;
368
    }
369
    else
370
    {
371
        /* If have a mask, prepare the variables to check it */
372
        mask_inc = 1;
373
    }
374
 
375
    /* If both are zero, then the whole thing is zero */
376
    if (top_row == zero && bottom_row == zero)
377
    {
378
	memset (buffer, 0, width * sizeof (uint32_t));
379
	return;
380
    }
381
    else if (bits->format == PIXMAN_x8r8g8b8)
382
    {
383
	if (top_row == zero)
384
	{
385
	    top_mask = 0;
386
	    bottom_mask = 0xff000000;
387
	}
388
	else if (bottom_row == zero)
389
	{
390
	    top_mask = 0xff000000;
391
	    bottom_mask = 0;
392
	}
393
	else
394
	{
395
	    top_mask = 0xff000000;
396
	    bottom_mask = 0xff000000;
397
	}
398
    }
399
    else
400
    {
401
	top_mask = 0;
402
	bottom_mask = 0;
403
    }
404
 
405
    end = buffer + width;
406
 
407
    /* Zero fill to the left of the image */
408
    while (buffer < end && x < pixman_fixed_minus_1)
409
    {
410
	*buffer++ = 0;
411
	x += ux;
412
	x_top += ux_top;
413
	x_bottom += ux_bottom;
414
	mask += mask_inc;
415
    }
416
 
417
    /* Left edge
418
     */
419
    while (buffer < end && x < 0)
420
    {
421
	uint32_t tr, br;
422
	int32_t distx;
423
 
424
	tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
425
	br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
426
 
427
	distx = (x >> 8) & 0xff;
428
 
429
	*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);
430
 
431
	x += ux;
432
	x_top += ux_top;
433
	x_bottom += ux_bottom;
434
	mask += mask_inc;
435
    }
436
 
437
    /* Main part */
438
    w = pixman_int_to_fixed (bits->width - 1);
439
 
440
    while (buffer < end  &&  x < w)
441
    {
442
	if (*mask)
443
	{
444
	    uint32_t tl, tr, bl, br;
445
	    int32_t distx;
446
 
447
	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
448
	    tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
449
	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
450
	    br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;
451
 
452
	    distx = (x >> 8) & 0xff;
453
 
454
	    *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
455
	}
456
 
457
	buffer++;
458
	x += ux;
459
	x_top += ux_top;
460
	x_bottom += ux_bottom;
461
	mask += mask_inc;
462
    }
463
 
464
    /* Right Edge */
465
    w = pixman_int_to_fixed (bits->width);
466
    while (buffer < end  &&  x < w)
467
    {
468
	if (*mask)
469
	{
470
	    uint32_t tl, bl;
471
	    int32_t distx;
472
 
473
	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
474
	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
475
 
476
	    distx = (x >> 8) & 0xff;
477
 
478
	    *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
479
	}
480
 
481
	buffer++;
482
	x += ux;
483
	x_top += ux_top;
484
	x_bottom += ux_bottom;
485
	mask += mask_inc;
486
    }
487
 
488
    /* Zero fill to the left of the image */
489
    while (buffer < end)
490
	*buffer++ = 0;
491
}
492
 
493
static force_inline uint32_t
494
bits_image_fetch_pixel_convolution (bits_image_t   *image,
495
				    pixman_fixed_t  x,
496
				    pixman_fixed_t  y,
497
				    get_pixel_t     get_pixel)
498
{
499
    pixman_fixed_t *params = image->common.filter_params;
500
    int x_off = (params[0] - pixman_fixed_1) >> 1;
501
    int y_off = (params[1] - pixman_fixed_1) >> 1;
502
    int32_t cwidth = pixman_fixed_to_int (params[0]);
503
    int32_t cheight = pixman_fixed_to_int (params[1]);
504
    int32_t srtot, sgtot, sbtot, satot;
505
    int32_t i, j, x1, x2, y1, y2;
506
    pixman_repeat_t repeat_mode = image->common.repeat;
507
    int width = image->width;
508
    int height = image->height;
509
 
510
    params += 2;
511
 
512
    x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off);
513
    y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off);
514
    x2 = x1 + cwidth;
515
    y2 = y1 + cheight;
516
 
517
    srtot = sgtot = sbtot = satot = 0;
518
 
519
    for (i = y1; i < y2; ++i)
520
    {
521
	for (j = x1; j < x2; ++j)
522
	{
523
	    int rx = j;
524
	    int ry = i;
525
 
526
	    pixman_fixed_t f = *params;
527
 
528
	    if (f)
529
	    {
530
		uint32_t pixel;
531
 
532
		if (repeat_mode != PIXMAN_REPEAT_NONE)
533
		{
534
		    repeat (repeat_mode, width, &rx);
535
		    repeat (repeat_mode, height, &ry);
536
 
537
		    pixel = get_pixel (image, rx, ry, FALSE);
538
		}
539
		else
540
		{
541
		    pixel = get_pixel (image, rx, ry, TRUE);
542
		}
543
 
544
		srtot += RED_8 (pixel) * f;
545
		sgtot += GREEN_8 (pixel) * f;
546
		sbtot += BLUE_8 (pixel) * f;
547
		satot += ALPHA_8 (pixel) * f;
548
	    }
549
 
550
	    params++;
551
	}
552
    }
553
 
554
    satot >>= 16;
555
    srtot >>= 16;
556
    sgtot >>= 16;
557
    sbtot >>= 16;
558
 
559
    satot = CLIP (satot, 0, 0xff);
560
    srtot = CLIP (srtot, 0, 0xff);
561
    sgtot = CLIP (sgtot, 0, 0xff);
562
    sbtot = CLIP (sbtot, 0, 0xff);
563
 
564
    return ((satot << 24) | (srtot << 16) | (sgtot <<  8) | (sbtot));
565
}
566
 
567
static force_inline uint32_t
568
bits_image_fetch_pixel_filtered (bits_image_t *image,
569
				 pixman_fixed_t x,
570
				 pixman_fixed_t y,
571
				 get_pixel_t    get_pixel)
572
{
573
    switch (image->common.filter)
574
    {
575
    case PIXMAN_FILTER_NEAREST:
576
    case PIXMAN_FILTER_FAST:
577
	return bits_image_fetch_pixel_nearest (image, x, y, get_pixel);
578
	break;
579
 
580
    case PIXMAN_FILTER_BILINEAR:
581
    case PIXMAN_FILTER_GOOD:
582
    case PIXMAN_FILTER_BEST:
583
	return bits_image_fetch_pixel_bilinear (image, x, y, get_pixel);
584
	break;
585
 
586
    case PIXMAN_FILTER_CONVOLUTION:
587
	return bits_image_fetch_pixel_convolution (image, x, y, get_pixel);
588
	break;
589
 
590
    default:
591
        break;
592
    }
593
 
594
    return 0;
595
}
596
 
597
static void
598
bits_image_fetch_affine_no_alpha (pixman_image_t * image,
599
				  int              offset,
600
				  int              line,
601
				  int              width,
602
				  uint32_t *       buffer,
603
				  const uint32_t * mask)
604
{
605
    pixman_fixed_t x, y;
606
    pixman_fixed_t ux, uy;
607
    pixman_vector_t v;
608
    int i;
609
 
610
    /* reference point is the center of the pixel */
611
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
612
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
613
    v.vector[2] = pixman_fixed_1;
614
 
615
    if (image->common.transform)
616
    {
617
	if (!pixman_transform_point_3d (image->common.transform, &v))
618
	    return;
619
 
620
	ux = image->common.transform->matrix[0][0];
621
	uy = image->common.transform->matrix[1][0];
622
    }
623
    else
624
    {
625
	ux = pixman_fixed_1;
626
	uy = 0;
627
    }
628
 
629
    x = v.vector[0];
630
    y = v.vector[1];
631
 
632
    for (i = 0; i < width; ++i)
633
    {
634
	if (!mask || mask[i])
635
	{
636
	    buffer[i] = bits_image_fetch_pixel_filtered (
637
		&image->bits, x, y, fetch_pixel_no_alpha);
638
	}
639
 
640
	x += ux;
641
	y += uy;
642
    }
643
}
644
 
645
/* General fetcher */
646
static force_inline uint32_t
647
fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_bounds)
648
{
649
    uint32_t pixel;
650
 
651
    if (check_bounds &&
652
	(x < 0 || x >= image->width || y < 0 || y >= image->height))
653
    {
654
	return 0;
655
    }
656
 
657
    pixel = image->fetch_pixel_32 (image, x, y);
658
 
659
    if (image->common.alpha_map)
660
    {
661
	uint32_t pixel_a;
662
 
663
	x -= image->common.alpha_origin_x;
664
	y -= image->common.alpha_origin_y;
665
 
666
	if (x < 0 || x >= image->common.alpha_map->width ||
667
	    y < 0 || y >= image->common.alpha_map->height)
668
	{
669
	    pixel_a = 0;
670
	}
671
	else
672
	{
673
	    pixel_a = image->common.alpha_map->fetch_pixel_32 (
674
		image->common.alpha_map, x, y);
675
 
676
	    pixel_a = ALPHA_8 (pixel_a);
677
	}
678
 
679
	pixel &= 0x00ffffff;
680
	pixel |= (pixel_a << 24);
681
    }
682
 
683
    return pixel;
684
}
685
 
686
static void
687
bits_image_fetch_general (pixman_image_t * image,
688
			  int              offset,
689
			  int              line,
690
			  int              width,
691
			  uint32_t *       buffer,
692
			  const uint32_t * mask)
693
{
694
    pixman_fixed_t x, y, w;
695
    pixman_fixed_t ux, uy, uw;
696
    pixman_vector_t v;
697
    int i;
698
 
699
    /* reference point is the center of the pixel */
700
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
701
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
702
    v.vector[2] = pixman_fixed_1;
703
 
704
    if (image->common.transform)
705
    {
706
	if (!pixman_transform_point_3d (image->common.transform, &v))
707
	    return;
708
 
709
	ux = image->common.transform->matrix[0][0];
710
	uy = image->common.transform->matrix[1][0];
711
	uw = image->common.transform->matrix[2][0];
712
    }
713
    else
714
    {
715
	ux = pixman_fixed_1;
716
	uy = 0;
717
	uw = 0;
718
    }
719
 
720
    x = v.vector[0];
721
    y = v.vector[1];
722
    w = v.vector[2];
723
 
724
    for (i = 0; i < width; ++i)
725
    {
726
	pixman_fixed_t x0, y0;
727
 
728
	if (!mask || mask[i])
729
	{
730
	    if (w != 0)
731
	    {
732
		x0 = ((pixman_fixed_48_16_t)x << 16) / w;
733
		y0 = ((pixman_fixed_48_16_t)y << 16) / w;
734
	    }
735
	    else
736
	    {
737
		x0 = 0;
738
		y0 = 0;
739
	    }
740
 
741
	    buffer[i] = bits_image_fetch_pixel_filtered (
742
		&image->bits, x0, y0, fetch_pixel_general);
743
	}
744
 
745
	x += ux;
746
	y += uy;
747
	w += uw;
748
    }
749
}
750
 
751
static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
752
 
753
typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x);
754
 
755
static force_inline void
756
bits_image_fetch_bilinear_affine (pixman_image_t * image,
757
				  int              offset,
758
				  int              line,
759
				  int              width,
760
				  uint32_t *       buffer,
761
				  const uint32_t * mask,
762
 
763
				  convert_pixel_t	convert_pixel,
764
				  pixman_format_code_t	format,
765
				  pixman_repeat_t	repeat_mode)
766
{
767
    pixman_fixed_t x, y;
768
    pixman_fixed_t ux, uy;
769
    pixman_vector_t v;
770
    bits_image_t *bits = &image->bits;
771
    int i;
772
 
773
    /* reference point is the center of the pixel */
774
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
775
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
776
    v.vector[2] = pixman_fixed_1;
777
 
778
    if (!pixman_transform_point_3d (image->common.transform, &v))
779
	return;
780
 
781
    ux = image->common.transform->matrix[0][0];
782
    uy = image->common.transform->matrix[1][0];
783
 
784
    x = v.vector[0];
785
    y = v.vector[1];
786
 
787
    for (i = 0; i < width; ++i)
788
    {
789
	int x1, y1, x2, y2;
790
	uint32_t tl, tr, bl, br;
791
	int32_t distx, disty;
792
	int width = image->bits.width;
793
	int height = image->bits.height;
794
	const uint8_t *row1;
795
	const uint8_t *row2;
796
 
797
	if (mask && !mask[i])
798
	    goto next;
799
 
800
	x1 = x - pixman_fixed_1 / 2;
801
	y1 = y - pixman_fixed_1 / 2;
802
 
803
	distx = (x1 >> 8) & 0xff;
804
	disty = (y1 >> 8) & 0xff;
805
 
806
	y1 = pixman_fixed_to_int (y1);
807
	y2 = y1 + 1;
808
	x1 = pixman_fixed_to_int (x1);
809
	x2 = x1 + 1;
810
 
811
	if (repeat_mode != PIXMAN_REPEAT_NONE)
812
	{
813
	    uint32_t mask;
814
 
815
	    mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
816
 
817
	    repeat (repeat_mode, width, &x1);
818
	    repeat (repeat_mode, height, &y1);
819
	    repeat (repeat_mode, width, &x2);
820
	    repeat (repeat_mode, height, &y2);
821
 
822
	    row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
823
	    row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
824
 
825
	    tl = convert_pixel (row1, x1) | mask;
826
	    tr = convert_pixel (row1, x2) | mask;
827
	    bl = convert_pixel (row2, x1) | mask;
828
	    br = convert_pixel (row2, x2) | mask;
829
	}
830
	else
831
	{
832
	    uint32_t mask1, mask2;
833
	    int bpp;
834
 
835
	    /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
836
	     * which means if you use it in expressions, those
837
	     * expressions become unsigned themselves. Since
838
	     * the variables below can be negative in some cases,
839
	     * that will lead to crashes on 64 bit architectures.
840
	     *
841
	     * So this line makes sure bpp is signed
842
	     */
843
	    bpp = PIXMAN_FORMAT_BPP (format);
844
 
845
	    if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
846
	    {
847
		buffer[i] = 0;
848
		goto next;
849
	    }
850
 
851
	    if (y2 == 0)
852
	    {
853
		row1 = zero;
854
		mask1 = 0;
855
	    }
856
	    else
857
	    {
858
		row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
859
		row1 += bpp / 8 * x1;
860
 
861
		mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
862
	    }
863
 
864
	    if (y1 == height - 1)
865
	    {
866
		row2 = zero;
867
		mask2 = 0;
868
	    }
869
	    else
870
	    {
871
		row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
872
		row2 += bpp / 8 * x1;
873
 
874
		mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
875
	    }
876
 
877
	    if (x2 == 0)
878
	    {
879
		tl = 0;
880
		bl = 0;
881
	    }
882
	    else
883
	    {
884
		tl = convert_pixel (row1, 0) | mask1;
885
		bl = convert_pixel (row2, 0) | mask2;
886
	    }
887
 
888
	    if (x1 == width - 1)
889
	    {
890
		tr = 0;
891
		br = 0;
892
	    }
893
	    else
894
	    {
895
		tr = convert_pixel (row1, 1) | mask1;
896
		br = convert_pixel (row2, 1) | mask2;
897
	    }
898
	}
899
 
900
	buffer[i] = bilinear_interpolation (
901
	    tl, tr, bl, br, distx, disty);
902
 
903
    next:
904
	x += ux;
905
	y += uy;
906
    }
907
}
908
 
909
static force_inline uint32_t
910
convert_a8r8g8b8 (const uint8_t *row, int x)
911
{
912
    return *(((uint32_t *)row) + x);
913
}
914
 
915
static force_inline uint32_t
916
convert_x8r8g8b8 (const uint8_t *row, int x)
917
{
918
    return *(((uint32_t *)row) + x);
919
}
920
 
921
static force_inline uint32_t
922
convert_a8 (const uint8_t *row, int x)
923
{
924
    return *(row + x) << 24;
925
}
926
 
927
static force_inline uint32_t
928
convert_r5g6b5 (const uint8_t *row, int x)
929
{
930
    return CONVERT_0565_TO_0888 (*((uint16_t *)row + x));
931
}
932
 
933
#define MAKE_BILINEAR_FETCHER(name, format, repeat_mode)		\
934
    static void								\
935
    bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image,	\
936
					       int              offset,	\
937
					       int              line,	\
938
					       int              width,	\
939
					       uint32_t *       buffer,	\
940
					       const uint32_t * mask)	\
941
    {									\
942
	bits_image_fetch_bilinear_affine (image, offset, line, width, buffer, mask, \
943
					  convert_ ## format,		\
944
					  PIXMAN_ ## format,		\
945
					  repeat_mode);			\
946
    }									\
947
    extern int no_such_variable
948
 
949
MAKE_BILINEAR_FETCHER (pad_a8r8g8b8,     a8r8g8b8, PIXMAN_REPEAT_PAD);
950
MAKE_BILINEAR_FETCHER (none_a8r8g8b8,    a8r8g8b8, PIXMAN_REPEAT_NONE);
951
MAKE_BILINEAR_FETCHER (reflect_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_REFLECT);
952
MAKE_BILINEAR_FETCHER (normal_a8r8g8b8,  a8r8g8b8, PIXMAN_REPEAT_NORMAL);
953
MAKE_BILINEAR_FETCHER (pad_x8r8g8b8,     x8r8g8b8, PIXMAN_REPEAT_PAD);
954
MAKE_BILINEAR_FETCHER (none_x8r8g8b8,    x8r8g8b8, PIXMAN_REPEAT_NONE);
955
MAKE_BILINEAR_FETCHER (reflect_x8r8g8b8, x8r8g8b8, PIXMAN_REPEAT_REFLECT);
956
MAKE_BILINEAR_FETCHER (normal_x8r8g8b8,  x8r8g8b8, PIXMAN_REPEAT_NORMAL);
957
MAKE_BILINEAR_FETCHER (pad_a8,           a8,       PIXMAN_REPEAT_PAD);
958
MAKE_BILINEAR_FETCHER (none_a8,          a8,       PIXMAN_REPEAT_NONE);
959
MAKE_BILINEAR_FETCHER (reflect_a8,	 a8,       PIXMAN_REPEAT_REFLECT);
960
MAKE_BILINEAR_FETCHER (normal_a8,	 a8,       PIXMAN_REPEAT_NORMAL);
961
MAKE_BILINEAR_FETCHER (pad_r5g6b5,       r5g6b5,   PIXMAN_REPEAT_PAD);
962
MAKE_BILINEAR_FETCHER (none_r5g6b5,      r5g6b5,   PIXMAN_REPEAT_NONE);
963
MAKE_BILINEAR_FETCHER (reflect_r5g6b5,   r5g6b5,   PIXMAN_REPEAT_REFLECT);
964
MAKE_BILINEAR_FETCHER (normal_r5g6b5,    r5g6b5,   PIXMAN_REPEAT_NORMAL);
965
 
966
static void
967
bits_image_fetch_solid_32 (pixman_image_t * image,
968
                           int              x,
969
                           int              y,
970
                           int              width,
971
                           uint32_t *       buffer,
972
                           const uint32_t * mask)
973
{
974
    uint32_t color;
975
    uint32_t *end;
976
 
977
    color = image->bits.fetch_pixel_32 (&image->bits, 0, 0);
978
 
979
    end = buffer + width;
980
    while (buffer < end)
981
	*(buffer++) = color;
982
}
983
 
984
static void
985
bits_image_fetch_solid_64 (pixman_image_t * image,
986
                           int              x,
987
                           int              y,
988
                           int              width,
989
                           uint32_t *       b,
990
                           const uint32_t * unused)
991
{
992
    uint64_t color;
993
    uint64_t *buffer = (uint64_t *)b;
994
    uint64_t *end;
995
 
996
    color = image->bits.fetch_pixel_64 (&image->bits, 0, 0);
997
 
998
    end = buffer + width;
999
    while (buffer < end)
1000
	*(buffer++) = color;
1001
}
1002
 
1003
static void
1004
bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
1005
                                            pixman_bool_t wide,
1006
                                            int           x,
1007
                                            int           y,
1008
                                            int           width,
1009
                                            uint32_t *    buffer)
1010
{
1011
    uint32_t w;
1012
 
1013
    if (y < 0 || y >= image->height)
1014
    {
1015
	memset (buffer, 0, width * (wide? 8 : 4));
1016
	return;
1017
    }
1018
 
1019
    if (x < 0)
1020
    {
1021
	w = MIN (width, -x);
1022
 
1023
	memset (buffer, 0, w * (wide ? 8 : 4));
1024
 
1025
	width -= w;
1026
	buffer += w * (wide? 2 : 1);
1027
	x += w;
1028
    }
1029
 
1030
    if (x < image->width)
1031
    {
1032
	w = MIN (width, image->width - x);
1033
 
1034
	if (wide)
1035
	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1036
	else
1037
	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1038
 
1039
	width -= w;
1040
	buffer += w * (wide? 2 : 1);
1041
	x += w;
1042
    }
1043
 
1044
    memset (buffer, 0, width * (wide ? 8 : 4));
1045
}
1046
 
1047
static void
1048
bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
1049
                                              pixman_bool_t wide,
1050
                                              int           x,
1051
                                              int           y,
1052
                                              int           width,
1053
                                              uint32_t *    buffer)
1054
{
1055
    uint32_t w;
1056
 
1057
    while (y < 0)
1058
	y += image->height;
1059
 
1060
    while (y >= image->height)
1061
	y -= image->height;
1062
 
1063
    while (width)
1064
    {
1065
	while (x < 0)
1066
	    x += image->width;
1067
	while (x >= image->width)
1068
	    x -= image->width;
1069
 
1070
	w = MIN (width, image->width - x);
1071
 
1072
	if (wide)
1073
	    image->fetch_scanline_64 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1074
	else
1075
	    image->fetch_scanline_32 ((pixman_image_t *)image, x, y, w, buffer, NULL);
1076
 
1077
	buffer += w * (wide? 2 : 1);
1078
	x += w;
1079
	width -= w;
1080
    }
1081
}
1082
 
1083
static void
1084
bits_image_fetch_untransformed_32 (pixman_image_t * image,
1085
                                   int              x,
1086
                                   int              y,
1087
                                   int              width,
1088
                                   uint32_t *       buffer,
1089
                                   const uint32_t * mask)
1090
{
1091
    if (image->common.repeat == PIXMAN_REPEAT_NONE)
1092
    {
1093
	bits_image_fetch_untransformed_repeat_none (
1094
	    &image->bits, FALSE, x, y, width, buffer);
1095
    }
1096
    else
1097
    {
1098
	bits_image_fetch_untransformed_repeat_normal (
1099
	    &image->bits, FALSE, x, y, width, buffer);
1100
    }
1101
}
1102
 
1103
static void
1104
bits_image_fetch_untransformed_64 (pixman_image_t * image,
1105
                                   int              x,
1106
                                   int              y,
1107
                                   int              width,
1108
                                   uint32_t *       buffer,
1109
                                   const uint32_t * unused)
1110
{
1111
    if (image->common.repeat == PIXMAN_REPEAT_NONE)
1112
    {
1113
	bits_image_fetch_untransformed_repeat_none (
1114
	    &image->bits, TRUE, x, y, width, buffer);
1115
    }
1116
    else
1117
    {
1118
	bits_image_fetch_untransformed_repeat_normal (
1119
	    &image->bits, TRUE, x, y, width, buffer);
1120
    }
1121
}
1122
 
1123
typedef struct
1124
{
1125
    pixman_format_code_t	format;
1126
    uint32_t			flags;
1127
    fetch_scanline_t		fetch_32;
1128
    fetch_scanline_t		fetch_64;
1129
} fetcher_info_t;
1130
 
1131
static const fetcher_info_t fetcher_info[] =
1132
{
1133
    { PIXMAN_solid,
1134
      FAST_PATH_NO_ALPHA_MAP,
1135
      bits_image_fetch_solid_32,
1136
      bits_image_fetch_solid_64
1137
    },
1138
 
1139
    { PIXMAN_any,
1140
      (FAST_PATH_NO_ALPHA_MAP			|
1141
       FAST_PATH_ID_TRANSFORM			|
1142
       FAST_PATH_NO_CONVOLUTION_FILTER		|
1143
       FAST_PATH_NO_PAD_REPEAT			|
1144
       FAST_PATH_NO_REFLECT_REPEAT),
1145
      bits_image_fetch_untransformed_32,
1146
      bits_image_fetch_untransformed_64
1147
    },
1148
 
1149
#define FAST_BILINEAR_FLAGS						\
1150
    (FAST_PATH_NO_ALPHA_MAP		|				\
1151
     FAST_PATH_NO_ACCESSORS		|				\
1152
     FAST_PATH_HAS_TRANSFORM		|				\
1153
     FAST_PATH_AFFINE_TRANSFORM		|				\
1154
     FAST_PATH_X_UNIT_POSITIVE		|				\
1155
     FAST_PATH_Y_UNIT_ZERO		|				\
1156
     FAST_PATH_NONE_REPEAT		|				\
1157
     FAST_PATH_BILINEAR_FILTER)
1158
 
1159
    { PIXMAN_a8r8g8b8,
1160
      FAST_BILINEAR_FLAGS,
1161
      bits_image_fetch_bilinear_no_repeat_8888,
1162
      _pixman_image_get_scanline_generic_64
1163
    },
1164
 
1165
    { PIXMAN_x8r8g8b8,
1166
      FAST_BILINEAR_FLAGS,
1167
      bits_image_fetch_bilinear_no_repeat_8888,
1168
      _pixman_image_get_scanline_generic_64
1169
    },
1170
 
1171
#define GENERAL_BILINEAR_FLAGS						\
1172
    (FAST_PATH_NO_ALPHA_MAP		|				\
1173
     FAST_PATH_NO_ACCESSORS		|				\
1174
     FAST_PATH_HAS_TRANSFORM		|				\
1175
     FAST_PATH_AFFINE_TRANSFORM		|				\
1176
     FAST_PATH_BILINEAR_FILTER)
1177
 
1178
#define BILINEAR_AFFINE_FAST_PATH(name, format, repeat)			\
1179
    { PIXMAN_ ## format,						\
1180
      GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT,		\
1181
      bits_image_fetch_bilinear_affine_ ## name,			\
1182
      _pixman_image_get_scanline_generic_64				\
1183
    },
1184
 
1185
    BILINEAR_AFFINE_FAST_PATH (pad_a8r8g8b8, a8r8g8b8, PAD)
1186
    BILINEAR_AFFINE_FAST_PATH (none_a8r8g8b8, a8r8g8b8, NONE)
1187
    BILINEAR_AFFINE_FAST_PATH (reflect_a8r8g8b8, a8r8g8b8, REFLECT)
1188
    BILINEAR_AFFINE_FAST_PATH (normal_a8r8g8b8, a8r8g8b8, NORMAL)
1189
    BILINEAR_AFFINE_FAST_PATH (pad_x8r8g8b8, x8r8g8b8, PAD)
1190
    BILINEAR_AFFINE_FAST_PATH (none_x8r8g8b8, x8r8g8b8, NONE)
1191
    BILINEAR_AFFINE_FAST_PATH (reflect_x8r8g8b8, x8r8g8b8, REFLECT)
1192
    BILINEAR_AFFINE_FAST_PATH (normal_x8r8g8b8, x8r8g8b8, NORMAL)
1193
    BILINEAR_AFFINE_FAST_PATH (pad_a8, a8, PAD)
1194
    BILINEAR_AFFINE_FAST_PATH (none_a8, a8, NONE)
1195
    BILINEAR_AFFINE_FAST_PATH (reflect_a8, a8, REFLECT)
1196
    BILINEAR_AFFINE_FAST_PATH (normal_a8, a8, NORMAL)
1197
    BILINEAR_AFFINE_FAST_PATH (pad_r5g6b5, r5g6b5, PAD)
1198
    BILINEAR_AFFINE_FAST_PATH (none_r5g6b5, r5g6b5, NONE)
1199
    BILINEAR_AFFINE_FAST_PATH (reflect_r5g6b5, r5g6b5, REFLECT)
1200
    BILINEAR_AFFINE_FAST_PATH (normal_r5g6b5, r5g6b5, NORMAL)
1201
 
1202
    /* Affine, no alpha */
1203
    { PIXMAN_any,
1204
      (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM),
1205
      bits_image_fetch_affine_no_alpha,
1206
      _pixman_image_get_scanline_generic_64
1207
    },
1208
 
1209
    /* General */
1210
    { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 },
1211
 
1212
    { PIXMAN_null },
1213
};
1214
 
1215
static void
1216
bits_image_property_changed (pixman_image_t *image)
1217
{
1218
    uint32_t flags = image->common.flags;
1219
    pixman_format_code_t format = image->common.extended_format_code;
1220
    const fetcher_info_t *info;
1221
 
1222
    _pixman_bits_image_setup_accessors (&image->bits);
1223
 
1224
    info = fetcher_info;
1225
    while (info->format != PIXMAN_null)
1226
    {
1227
	if ((info->format == format || info->format == PIXMAN_any)	&&
1228
	    (info->flags & flags) == info->flags)
1229
	{
1230
	    image->common.get_scanline_32 = info->fetch_32;
1231
	    image->common.get_scanline_64 = info->fetch_64;
1232
	    break;
1233
	}
1234
 
1235
	info++;
1236
    }
1237
}
1238
 
1239
static uint32_t *
1240
create_bits (pixman_format_code_t format,
1241
             int                  width,
1242
             int                  height,
1243
             int *                rowstride_bytes)
1244
{
1245
    int stride;
1246
    int buf_size;
1247
    int bpp;
1248
 
1249
    /* what follows is a long-winded way, avoiding any possibility of integer
1250
     * overflows, of saying:
1251
     * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
1252
     */
1253
 
1254
    bpp = PIXMAN_FORMAT_BPP (format);
1255
    if (pixman_multiply_overflows_int (width, bpp))
1256
	return NULL;
1257
 
1258
    stride = width * bpp;
1259
    if (pixman_addition_overflows_int (stride, 0x1f))
1260
	return NULL;
1261
 
1262
    stride += 0x1f;
1263
    stride >>= 5;
1264
 
1265
    stride *= sizeof (uint32_t);
1266
 
1267
    if (pixman_multiply_overflows_int (height, stride))
1268
	return NULL;
1269
 
1270
    buf_size = height * stride;
1271
 
1272
    if (rowstride_bytes)
1273
	*rowstride_bytes = stride;
1274
 
1275
    return calloc (buf_size, 1);
1276
}
1277
 
1278
PIXMAN_EXPORT pixman_image_t *
1279
pixman_image_create_bits (pixman_format_code_t format,
1280
                          int                  width,
1281
                          int                  height,
1282
                          uint32_t *           bits,
1283
                          int                  rowstride_bytes)
1284
{
1285
    pixman_image_t *image;
1286
    uint32_t *free_me = NULL;
1287
 
1288
    /* must be a whole number of uint32_t's
1289
     */
1290
    return_val_if_fail (
1291
	bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
1292
 
1293
    return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL);
1294
 
1295
    if (!bits && width && height)
1296
    {
1297
	free_me = bits = create_bits (format, width, height, &rowstride_bytes);
1298
	if (!bits)
1299
	    return NULL;
1300
    }
1301
 
1302
    image = _pixman_image_allocate ();
1303
 
1304
    if (!image)
1305
    {
1306
	if (free_me)
1307
	    free (free_me);
1308
 
1309
	return NULL;
1310
    }
1311
 
1312
    image->type = BITS;
1313
    image->bits.format = format;
1314
    image->bits.width = width;
1315
    image->bits.height = height;
1316
    image->bits.bits = bits;
1317
    image->bits.free_me = free_me;
1318
    image->bits.read_func = NULL;
1319
    image->bits.write_func = NULL;
1320
 
1321
    /* The rowstride is stored in number of uint32_t */
1322
    image->bits.rowstride = rowstride_bytes / (int) sizeof (uint32_t);
1323
 
1324
    image->bits.indexed = NULL;
1325
 
1326
    image->common.property_changed = bits_image_property_changed;
1327
 
1328
    _pixman_image_reset_clip_region (image);
1329
 
1330
    return image;
1331
}