Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3959 | Serge | 1 | /* |
2 | * Copyright © 2012 Intel Corporation |
||
3 | * |
||
4 | * This library is free software; you can redistribute it and/or |
||
5 | * modify it either under the terms of the GNU Lesser General Public |
||
6 | * License version 2.1 as published by the Free Software Foundation |
||
7 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
||
8 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
||
9 | * notice, a recipient may use your version of this file under either |
||
10 | * the MPL or the LGPL. |
||
11 | * |
||
12 | * You should have received a copy of the LGPL along with this library |
||
13 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
||
14 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
||
15 | * You should have received a copy of the MPL along with this library |
||
16 | * in the file COPYING-MPL-1.1 |
||
17 | * |
||
18 | * The contents of this file are subject to the Mozilla Public License |
||
19 | * Version 1.1 (the "License"); you may not use this file except in |
||
20 | * compliance with the License. You may obtain a copy of the License at |
||
21 | * http://www.mozilla.org/MPL/ |
||
22 | * |
||
23 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
||
24 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
||
25 | * the specific language governing rights and limitations. |
||
26 | * |
||
27 | * The Original Code is the cairo graphics library. |
||
28 | * |
||
29 | * The Initial Developer of the Original Code is Chris Wilson |
||
30 | * |
||
31 | * Contributor(s): |
||
32 | * Chris Wilson |
||
33 | */ |
||
34 | |||
35 | #include "cairoint.h" |
||
36 | |||
37 | #include "cairo-damage-private.h" |
||
38 | #include "cairo-region-private.h" |
||
39 | |||
40 | static const cairo_damage_t __cairo_damage__nil = { CAIRO_STATUS_NO_MEMORY }; |
||
41 | |||
42 | cairo_damage_t * |
||
43 | _cairo_damage_create_in_error (cairo_status_t status) |
||
44 | { |
||
45 | _cairo_error_throw (status); |
||
46 | return (cairo_damage_t *) &__cairo_damage__nil; |
||
47 | } |
||
48 | |||
49 | cairo_damage_t * |
||
50 | _cairo_damage_create (void) |
||
51 | { |
||
52 | cairo_damage_t *damage; |
||
53 | |||
54 | damage = malloc (sizeof (*damage)); |
||
55 | if (unlikely (damage == NULL)) { |
||
56 | _cairo_error_throw(CAIRO_STATUS_NO_MEMORY); |
||
57 | return (cairo_damage_t *) &__cairo_damage__nil; |
||
58 | } |
||
59 | |||
60 | damage->status = CAIRO_STATUS_SUCCESS; |
||
61 | damage->region = NULL; |
||
62 | damage->dirty = 0; |
||
63 | damage->tail = &damage->chunks; |
||
64 | damage->chunks.base = damage->boxes; |
||
65 | damage->chunks.size = ARRAY_LENGTH(damage->boxes); |
||
66 | damage->chunks.count = 0; |
||
67 | damage->chunks.next = NULL; |
||
68 | |||
69 | damage->remain = damage->chunks.size; |
||
70 | |||
71 | return damage; |
||
72 | } |
||
73 | |||
74 | void |
||
75 | _cairo_damage_destroy (cairo_damage_t *damage) |
||
76 | { |
||
77 | struct _cairo_damage_chunk *chunk, *next; |
||
78 | |||
79 | if (damage == (cairo_damage_t *) &__cairo_damage__nil) |
||
80 | return; |
||
81 | |||
82 | for (chunk = damage->chunks.next; chunk != NULL; chunk = next) { |
||
83 | next = chunk->next; |
||
84 | free (chunk); |
||
85 | } |
||
86 | cairo_region_destroy (damage->region); |
||
87 | free (damage); |
||
88 | } |
||
89 | |||
90 | static cairo_damage_t * |
||
91 | _cairo_damage_add_boxes(cairo_damage_t *damage, |
||
92 | const cairo_box_t *boxes, |
||
93 | int count) |
||
94 | { |
||
95 | struct _cairo_damage_chunk *chunk; |
||
96 | int n, size; |
||
97 | |||
98 | TRACE ((stderr, "%s x%d\n", __FUNCTION__, count)); |
||
99 | |||
100 | if (damage == NULL) |
||
101 | damage = _cairo_damage_create (); |
||
102 | if (damage->status) |
||
103 | return damage; |
||
104 | |||
105 | damage->dirty += count; |
||
106 | |||
107 | n = count; |
||
108 | if (n > damage->remain) |
||
109 | n = damage->remain; |
||
110 | |||
111 | memcpy (damage->tail->base + damage->tail->count, boxes, |
||
112 | n * sizeof (cairo_box_t)); |
||
113 | |||
114 | count -= n; |
||
115 | damage->tail->count += n; |
||
116 | damage->remain -= n; |
||
117 | |||
118 | if (count == 0) |
||
119 | return damage; |
||
120 | |||
121 | size = 2 * damage->tail->size; |
||
122 | if (size < count) |
||
123 | size = (count + 64) & ~63; |
||
124 | |||
125 | chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size); |
||
126 | if (unlikely (chunk == NULL)) { |
||
127 | _cairo_damage_destroy (damage); |
||
128 | return (cairo_damage_t *) &__cairo_damage__nil; |
||
129 | } |
||
130 | |||
131 | chunk->next = NULL; |
||
132 | chunk->base = (cairo_box_t *) (chunk + 1); |
||
133 | chunk->size = size; |
||
134 | chunk->count = count; |
||
135 | |||
136 | damage->tail->next = chunk; |
||
137 | damage->tail = chunk; |
||
138 | |||
139 | memcpy (damage->tail->base, boxes + n, |
||
140 | count * sizeof (cairo_box_t)); |
||
141 | damage->remain = size - count; |
||
142 | |||
143 | return damage; |
||
144 | } |
||
145 | |||
146 | cairo_damage_t * |
||
147 | _cairo_damage_add_box(cairo_damage_t *damage, |
||
148 | const cairo_box_t *box) |
||
149 | { |
||
150 | TRACE ((stderr, "%s: (%d, %d),(%d, %d)\n", __FUNCTION__, |
||
151 | box->p1.x, box->p1.y, box->p2.x, box->p2.y)); |
||
152 | |||
153 | return _cairo_damage_add_boxes(damage, box, 1); |
||
154 | } |
||
155 | |||
156 | cairo_damage_t * |
||
157 | _cairo_damage_add_rectangle(cairo_damage_t *damage, |
||
158 | const cairo_rectangle_int_t *r) |
||
159 | { |
||
160 | cairo_box_t box; |
||
161 | |||
162 | TRACE ((stderr, "%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, |
||
163 | r->x, r->y, r->width, r->height)); |
||
164 | |||
165 | box.p1.x = r->x; |
||
166 | box.p1.y = r->y; |
||
167 | box.p2.x = r->x + r->width; |
||
168 | box.p2.y = r->y + r->height; |
||
169 | |||
170 | return _cairo_damage_add_boxes(damage, &box, 1); |
||
171 | } |
||
172 | |||
173 | cairo_damage_t * |
||
174 | _cairo_damage_add_region (cairo_damage_t *damage, |
||
175 | const cairo_region_t *region) |
||
176 | { |
||
177 | cairo_box_t *boxes; |
||
178 | int nbox; |
||
179 | |||
180 | TRACE ((stderr, "%s\n", __FUNCTION__)); |
||
181 | |||
182 | boxes = _cairo_region_get_boxes (region, &nbox); |
||
183 | return _cairo_damage_add_boxes(damage, boxes, nbox); |
||
184 | } |
||
185 | |||
186 | cairo_damage_t * |
||
187 | _cairo_damage_reduce (cairo_damage_t *damage) |
||
188 | { |
||
189 | cairo_box_t *free_boxes = NULL; |
||
190 | cairo_box_t *boxes, *b; |
||
191 | struct _cairo_damage_chunk *chunk, *last; |
||
192 | |||
193 | TRACE ((stderr, "%s: dirty=%d\n", __FUNCTION__, |
||
194 | damage ? damage->dirty : -1)); |
||
195 | if (damage == NULL || damage->status || !damage->dirty) |
||
196 | return damage; |
||
197 | |||
198 | if (damage->region) { |
||
199 | cairo_region_t *region; |
||
200 | |||
201 | region = damage->region; |
||
202 | damage->region = NULL; |
||
203 | |||
204 | damage = _cairo_damage_add_region (damage, region); |
||
205 | cairo_region_destroy (region); |
||
206 | |||
207 | if (unlikely (damage->status)) |
||
208 | return damage; |
||
209 | } |
||
210 | |||
211 | boxes = damage->tail->base; |
||
212 | if (damage->dirty > damage->tail->size) { |
||
213 | boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t)); |
||
214 | if (unlikely (boxes == NULL)) { |
||
215 | _cairo_damage_destroy (damage); |
||
216 | return (cairo_damage_t *) &__cairo_damage__nil; |
||
217 | } |
||
218 | |||
219 | b = boxes; |
||
220 | last = NULL; |
||
221 | } else { |
||
222 | b = boxes + damage->tail->count; |
||
223 | last = damage->tail; |
||
224 | } |
||
225 | |||
226 | for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) { |
||
227 | memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t)); |
||
228 | b += chunk->count; |
||
229 | } |
||
230 | |||
231 | damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty); |
||
232 | free (free_boxes); |
||
233 | |||
234 | if (unlikely (damage->region->status)) { |
||
235 | _cairo_damage_destroy (damage); |
||
236 | return (cairo_damage_t *) &__cairo_damage__nil; |
||
237 | } |
||
238 | |||
239 | damage->dirty = 0; |
||
240 | return damage; |
||
241 | }> |