1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2009 Intel Corporation
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it either under the terms of the GNU Lesser General Public
7
 * License version 2.1 as published by the Free Software Foundation
8
 * (the "LGPL") or, at your option, under the terms of the Mozilla
9
 * Public License Version 1.1 (the "MPL"). If you do not alter this
10
 * notice, a recipient may use your version of this file under either
11
 * the MPL or the LGPL.
12
 *
13
 * You should have received a copy of the LGPL along with this library
14
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16
 * You should have received a copy of the MPL along with this library
17
 * in the file COPYING-MPL-1.1
18
 *
19
 * The contents of this file are subject to the Mozilla Public License
20
 * Version 1.1 (the "License"); you may not use this file except in
21
 * compliance with the License. You may obtain a copy of the License at
22
 * http://www.mozilla.org/MPL/
23
 *
24
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26
 * the specific language governing rights and limitations.
27
 *
28
 * The Original Code is the cairo graphics library.
29
 *
30
 * Contributor(s):
31
 *	Chris Wilson <chris@chris-wilson.co.uk>
32
 */
33

            
34
#include "cairoint.h"
35

            
36
#include "cairo-box-inline.h"
37
#include "cairo-boxes-private.h"
38
#include "cairo-error-private.h"
39

            
40
void
41
344681
_cairo_boxes_init (cairo_boxes_t *boxes)
42
{
43
344681
    boxes->status = CAIRO_STATUS_SUCCESS;
44
344681
    boxes->num_limits = 0;
45
344681
    boxes->num_boxes = 0;
46

            
47
344681
    boxes->tail = &boxes->chunks;
48
344681
    boxes->chunks.next = NULL;
49
344681
    boxes->chunks.base = boxes->boxes_embedded;
50
344681
    boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
51
344681
    boxes->chunks.count = 0;
52

            
53
344681
    boxes->is_pixel_aligned = TRUE;
54
344681
}
55

            
56
void
57
372
_cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes,
58
				  int x, int y, int w, int h)
59
{
60
372
    _cairo_boxes_init (boxes);
61

            
62
372
    _cairo_box_from_integers (&boxes->chunks.base[0], x, y, w, h);
63
372
    boxes->num_boxes = 1;
64
372
}
65

            
66
void
67
111
_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
68
			     cairo_clip_t *clip)
69
{
70
111
    _cairo_boxes_init (boxes);
71
111
    if (clip)
72
111
	_cairo_boxes_limit (boxes, clip->boxes, clip->num_boxes);
73
111
}
74

            
75
void
76
616931
_cairo_boxes_init_for_array (cairo_boxes_t *boxes,
77
			     cairo_box_t *array,
78
			     int num_boxes)
79
{
80
    int n;
81

            
82
616931
    boxes->status = CAIRO_STATUS_SUCCESS;
83
616931
    boxes->num_limits = 0;
84
616931
    boxes->num_boxes = num_boxes;
85

            
86
616931
    boxes->tail = &boxes->chunks;
87
616931
    boxes->chunks.next = NULL;
88
616931
    boxes->chunks.base = array;
89
616931
    boxes->chunks.size = num_boxes;
90
616931
    boxes->chunks.count = num_boxes;
91

            
92
1246471
    for (n = 0; n < num_boxes; n++) {
93
1264477
	if (! _cairo_fixed_is_integer (array[n].p1.x) ||
94
1260160
	    ! _cairo_fixed_is_integer (array[n].p1.y) ||
95
1259716
	    ! _cairo_fixed_is_integer (array[n].p2.x) ||
96
629747
	    ! _cairo_fixed_is_integer (array[n].p2.y))
97
	{
98
	    break;
99
	}
100
    }
101

            
102
616931
    boxes->is_pixel_aligned = n == num_boxes;
103
616931
}
104

            
105
/**
106
 * _cairo_boxes_limit:
107
 * @boxes:        the box set to be filled (return buffer)
108
 * @limits:       array of the limiting boxes to compute the bounding
109
 *                box from
110
 * @num_limits:   length of the limits array
111
 *
112
 * Computes the minimum bounding box of the given list of boxes and assign
113
 * it to the given boxes set. It also assigns that list as the list of
114
 * limiting boxes in the box set.
115
 */
116
void
117
18402
_cairo_boxes_limit (cairo_boxes_t	*boxes,
118
		    const cairo_box_t	*limits,
119
		    int			 num_limits)
120
{
121
    int n;
122

            
123
18402
    boxes->limits = limits;
124
18402
    boxes->num_limits = num_limits;
125

            
126
18402
    if (boxes->num_limits) {
127
18402
	boxes->limit = limits[0];
128
19206
	for (n = 1; n < num_limits; n++) {
129
804
	    if (limits[n].p1.x < boxes->limit.p1.x)
130
21
		boxes->limit.p1.x = limits[n].p1.x;
131

            
132
804
	    if (limits[n].p1.y < boxes->limit.p1.y)
133
3
		boxes->limit.p1.y = limits[n].p1.y;
134

            
135
804
	    if (limits[n].p2.x > boxes->limit.p2.x)
136
321
		boxes->limit.p2.x = limits[n].p2.x;
137

            
138
804
	    if (limits[n].p2.y > boxes->limit.p2.y)
139
771
		boxes->limit.p2.y = limits[n].p2.y;
140
	}
141
    }
142
18402
}
143

            
144
static void
145
354085
_cairo_boxes_add_internal (cairo_boxes_t *boxes,
146
			   const cairo_box_t *box)
147
{
148
    struct _cairo_boxes_chunk *chunk;
149

            
150
354085
    if (unlikely (boxes->status))
151
	return;
152

            
153
354085
    chunk = boxes->tail;
154
354085
    if (unlikely (chunk->count == chunk->size)) {
155
	int size;
156

            
157
696
	size = chunk->size * 2;
158
696
	chunk->next = _cairo_malloc_ab_plus_c (size,
159
					       sizeof (cairo_box_t),
160
					       sizeof (struct _cairo_boxes_chunk));
161

            
162
696
	if (unlikely (chunk->next == NULL)) {
163
	    boxes->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
164
	    return;
165
	}
166

            
167
696
	chunk = chunk->next;
168
696
	boxes->tail = chunk;
169

            
170
696
	chunk->next = NULL;
171
696
	chunk->count = 0;
172
696
	chunk->size = size;
173
696
	chunk->base = (cairo_box_t *) (chunk + 1);
174
    }
175

            
176
354085
    chunk->base[chunk->count++] = *box;
177
354085
    boxes->num_boxes++;
178

            
179
354085
    if (boxes->is_pixel_aligned)
180
241087
	boxes->is_pixel_aligned = _cairo_box_is_pixel_aligned (box);
181
}
182

            
183
cairo_status_t
184
590971
_cairo_boxes_add (cairo_boxes_t *boxes,
185
		  cairo_antialias_t antialias,
186
		  const cairo_box_t *box)
187
{
188
    cairo_box_t b;
189

            
190
590971
    if (antialias == CAIRO_ANTIALIAS_NONE) {
191
249252
	b.p1.x = _cairo_fixed_round_down (box->p1.x);
192
249252
	b.p1.y = _cairo_fixed_round_down (box->p1.y);
193
249252
	b.p2.x = _cairo_fixed_round_down (box->p2.x);
194
249252
	b.p2.y = _cairo_fixed_round_down (box->p2.y);
195
249252
	box = &b;
196
    }
197

            
198
590971
    if (box->p1.y == box->p2.y)
199
220638
	return CAIRO_STATUS_SUCCESS;
200

            
201
370333
    if (box->p1.x == box->p2.x)
202
13449
	return CAIRO_STATUS_SUCCESS;
203

            
204
356884
    if (boxes->num_limits) {
205
	cairo_point_t p1, p2;
206
85032
	cairo_bool_t reversed = FALSE;
207
	int n;
208

            
209
	/* support counter-clockwise winding for rectangular tessellation */
210
85032
	if (box->p1.x < box->p2.x) {
211
84360
	    p1.x = box->p1.x;
212
84360
	    p2.x = box->p2.x;
213
	} else {
214
672
	    p2.x = box->p1.x;
215
672
	    p1.x = box->p2.x;
216
672
	    reversed = ! reversed;
217
	}
218

            
219
85032
	if (p1.x >= boxes->limit.p2.x || p2.x <= boxes->limit.p1.x)
220
3660
	    return CAIRO_STATUS_SUCCESS;
221

            
222
83340
	if (box->p1.y < box->p2.y) {
223
83340
	    p1.y = box->p1.y;
224
83340
	    p2.y = box->p2.y;
225
	} else {
226
	    p2.y = box->p1.y;
227
	    p1.y = box->p2.y;
228
	    reversed = ! reversed;
229
	}
230

            
231
83340
	if (p1.y >= boxes->limit.p2.y || p2.y <= boxes->limit.p1.y)
232
1968
	    return CAIRO_STATUS_SUCCESS;
233

            
234
167433
	for (n = 0; n < boxes->num_limits; n++) {
235
86061
	    const cairo_box_t *limits = &boxes->limits[n];
236
	    cairo_box_t _box;
237
	    cairo_point_t _p1, _p2;
238

            
239
86061
	    if (p1.x >= limits->p2.x || p2.x <= limits->p1.x)
240
3828
		continue;
241
86019
	    if (p1.y >= limits->p2.y || p2.y <= limits->p1.y)
242
3786
		continue;
243

            
244
	    /* Otherwise, clip the box to the limits. */
245
82233
	    _p1 = p1;
246
82233
	    if (_p1.x < limits->p1.x)
247
16965
		_p1.x = limits->p1.x;
248
82233
	    if (_p1.y < limits->p1.y)
249
15813
		_p1.y = limits->p1.y;
250

            
251
82233
	    _p2 = p2;
252
82233
	    if (_p2.x > limits->p2.x)
253
17850
		_p2.x = limits->p2.x;
254
82233
	    if (_p2.y > limits->p2.y)
255
18594
		_p2.y = limits->p2.y;
256

            
257
82233
	    if (_p2.y <= _p1.y || _p2.x <= _p1.x)
258
		continue;
259

            
260
82233
	    _box.p1.y = _p1.y;
261
82233
	    _box.p2.y = _p2.y;
262
82233
	    if (reversed) {
263
129
		_box.p1.x = _p2.x;
264
129
		_box.p2.x = _p1.x;
265
	    } else {
266
82104
		_box.p1.x = _p1.x;
267
82104
		_box.p2.x = _p2.x;
268
	    }
269

            
270
82233
	    _cairo_boxes_add_internal (boxes, &_box);
271
	}
272
    } else {
273
271852
	_cairo_boxes_add_internal (boxes, box);
274
    }
275

            
276
353224
    return boxes->status;
277
}
278

            
279
/**
280
 * _cairo_boxes_extents:
281
 * @boxes:     The box set whose minimum bounding is computed.
282
 * @box:       Return buffer for the computed result.
283
 *
284
 * Computes the minimum bounding box of the given box set and stores
285
 * it in the given box.
286
 */
287
void
288
1133607
_cairo_boxes_extents (const cairo_boxes_t *boxes,
289
		      cairo_box_t *box)
290
{
291
    const struct _cairo_boxes_chunk *chunk;
292
    cairo_box_t b;
293
    int i;
294

            
295
1133607
    if (boxes->num_boxes == 0) {
296
197850
	box->p1.x = box->p1.y = box->p2.x = box->p2.y = 0;
297
197850
	return;
298
    }
299

            
300
935757
    b = boxes->chunks.base[0];
301
1871880
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
302
2043892
	for (i = 0; i < chunk->count; i++) {
303
1107769
	    if (chunk->base[i].p1.x < b.p1.x)
304
1614
		b.p1.x = chunk->base[i].p1.x;
305

            
306
1107769
	    if (chunk->base[i].p1.y < b.p1.y)
307
90
		b.p1.y = chunk->base[i].p1.y;
308

            
309
1107769
	    if (chunk->base[i].p2.x > b.p2.x)
310
2293
		b.p2.x = chunk->base[i].p2.x;
311

            
312
1107769
	    if (chunk->base[i].p2.y > b.p2.y)
313
60781
		b.p2.y = chunk->base[i].p2.y;
314
	}
315
    }
316
935757
    *box = b;
317
}
318

            
319
void
320
4597
_cairo_boxes_clear (cairo_boxes_t *boxes)
321
{
322
    struct _cairo_boxes_chunk *chunk, *next;
323

            
324
4759
    for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
325
162
	next = chunk->next;
326
162
	free (chunk);
327
    }
328

            
329
4597
    boxes->tail = &boxes->chunks;
330
4597
    boxes->chunks.next = 0;
331
4597
    boxes->chunks.count = 0;
332
4597
    boxes->chunks.base = boxes->boxes_embedded;
333
4597
    boxes->chunks.size = ARRAY_LENGTH (boxes->boxes_embedded);
334
4597
    boxes->num_boxes = 0;
335

            
336
4597
    boxes->is_pixel_aligned = TRUE;
337
4597
}
338

            
339
/**
340
 * _cairo_boxes_to_array:
341
 * @boxes      The box set to be converted.
342
 * @num_boxes  Return buffer for the number of boxes (array count).
343
 *
344
 * Linearize a box set of possibly multiple chunks into one big chunk
345
 * and returns an array of boxes
346
 *
347
 * Return value: Pointer to the newly allocated array of boxes (the number o
348
 * elements is given in num_boxes).
349
 */
350
cairo_box_t *
351
847
_cairo_boxes_to_array (const cairo_boxes_t *boxes,
352
		       int *num_boxes)
353
{
354
    const struct _cairo_boxes_chunk *chunk;
355
    cairo_box_t *box;
356
    int i, j;
357

            
358
847
    *num_boxes = boxes->num_boxes;
359

            
360
847
    box = _cairo_malloc_ab (boxes->num_boxes, sizeof (cairo_box_t));
361
847
    if (box == NULL) {
362
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
363
	return NULL;
364
    }
365

            
366
847
    j = 0;
367
1874
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
368
26850
	for (i = 0; i < chunk->count; i++)
369
25823
	    box[j++] = chunk->base[i];
370
    }
371

            
372
847
    return box;
373
}
374

            
375
void
376
344342
_cairo_boxes_fini (cairo_boxes_t *boxes)
377
{
378
    struct _cairo_boxes_chunk *chunk, *next;
379

            
380
344876
    for (chunk = boxes->chunks.next; chunk != NULL; chunk = next) {
381
534
	next = chunk->next;
382
534
	free (chunk);
383
    }
384
344342
}
385

            
386
cairo_bool_t
387
_cairo_boxes_for_each_box (cairo_boxes_t *boxes,
388
			   cairo_bool_t (*func) (cairo_box_t *box, void *data),
389
			   void *data)
390
{
391
    struct _cairo_boxes_chunk *chunk;
392
    int i;
393

            
394
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
395
	for (i = 0; i < chunk->count; i++)
396
	    if (! func (&chunk->base[i], data))
397
		return FALSE;
398
    }
399

            
400
    return TRUE;
401
}
402

            
403
struct cairo_box_renderer {
404
    cairo_span_renderer_t base;
405
    cairo_boxes_t *boxes;
406
};
407

            
408
static cairo_status_t
409
span_to_boxes (void *abstract_renderer, int y, int h,
410
	       const cairo_half_open_span_t *spans, unsigned num_spans)
411
{
412
    struct cairo_box_renderer *r = abstract_renderer;
413
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
414
    cairo_box_t box;
415

            
416
    if (num_spans == 0)
417
	return CAIRO_STATUS_SUCCESS;
418

            
419
    box.p1.y = _cairo_fixed_from_int (y);
420
    box.p2.y = _cairo_fixed_from_int (y + h);
421
    do {
422
	if (spans[0].coverage) {
423
	    box.p1.x = _cairo_fixed_from_int(spans[0].x);
424
	    box.p2.x = _cairo_fixed_from_int(spans[1].x);
425
	    status = _cairo_boxes_add (r->boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
426
	}
427
	spans++;
428
    } while (--num_spans > 1 && status == CAIRO_STATUS_SUCCESS);
429

            
430
    return status;
431
}
432

            
433
cairo_status_t
434
_cairo_rasterise_polygon_to_boxes (cairo_polygon_t			*polygon,
435
				   cairo_fill_rule_t			 fill_rule,
436
				   cairo_boxes_t *boxes)
437
{
438
    struct cairo_box_renderer renderer;
439
    cairo_scan_converter_t *converter;
440
    cairo_int_status_t status;
441
    cairo_rectangle_int_t r;
442

            
443
    TRACE ((stderr, "%s: fill_rule=%d\n", __FUNCTION__, fill_rule));
444

            
445
    _cairo_box_round_to_rectangle (&polygon->extents, &r);
446
    converter = _cairo_mono_scan_converter_create (r.x, r.y,
447
						   r.x + r.width,
448
						   r.y + r.height,
449
						   fill_rule);
450
    status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
451
    if (unlikely (status))
452
	goto cleanup_converter;
453

            
454
    renderer.boxes = boxes;
455
    renderer.base.render_rows = span_to_boxes;
456

            
457
    status = converter->generate (converter, &renderer.base);
458
cleanup_converter:
459
    converter->destroy (converter);
460
    return status;
461
}
462

            
463
void
464
_cairo_debug_print_boxes (FILE *stream, const cairo_boxes_t *boxes)
465
{
466
    const struct _cairo_boxes_chunk *chunk;
467
    cairo_box_t extents;
468
    int i;
469

            
470
    _cairo_boxes_extents (boxes, &extents);
471
    fprintf (stream, "boxes x %d: (%f, %f) x (%f, %f)\n",
472
	     boxes->num_boxes,
473
	     _cairo_fixed_to_double (extents.p1.x),
474
	     _cairo_fixed_to_double (extents.p1.y),
475
	     _cairo_fixed_to_double (extents.p2.x),
476
	     _cairo_fixed_to_double (extents.p2.y));
477

            
478
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
479
	for (i = 0; i < chunk->count; i++) {
480
	    fprintf (stderr, "  box[%d]: (%f, %f), (%f, %f)\n", i,
481
		     _cairo_fixed_to_double (chunk->base[i].p1.x),
482
		     _cairo_fixed_to_double (chunk->base[i].p1.y),
483
		     _cairo_fixed_to_double (chunk->base[i].p2.x),
484
		     _cairo_fixed_to_double (chunk->base[i].p2.y));
485
	}
486
    }
487
}