Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1891 serge 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 
25
#endif
26
 
27
#include 
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
}