1 | /* |
---|
2 | * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation |
---|
3 | * All rights reserved. |
---|
4 | * |
---|
5 | * This file is part of the Gnome Library. |
---|
6 | * |
---|
7 | * The Gnome Library is free software; you can redistribute it and/or |
---|
8 | * modify it under the terms of the GNU Library General Public License as |
---|
9 | * published by the Free Software Foundation; either version 2 of the |
---|
10 | * License, or (at your option) any later version. |
---|
11 | * |
---|
12 | * The Gnome Library is distributed in the hope that it will be useful, |
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | * Library General Public License for more details. |
---|
16 | * |
---|
17 | * You should have received a copy of the GNU Library General Public |
---|
18 | * License along with the Gnome Library; see the file COPYING.LIB. If not, |
---|
19 | * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
20 | * Boston, MA 02111-1307, USA. |
---|
21 | */ |
---|
22 | /* |
---|
23 | @NOTATION@ |
---|
24 | */ |
---|
25 | /* Miscellaneous utility functions for the GnomeCanvas widget |
---|
26 | * |
---|
27 | * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is |
---|
28 | * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. |
---|
29 | * |
---|
30 | * |
---|
31 | * Author: Federico Mena <federico@nuclecu.unam.mx> |
---|
32 | */ |
---|
33 | |
---|
34 | #include <config.h> |
---|
35 | |
---|
36 | /* needed for M_PI_2 under 'gcc -ansi -predantic' on GNU/Linux */ |
---|
37 | #ifndef _BSD_SOURCE |
---|
38 | # define _BSD_SOURCE 1 |
---|
39 | #endif |
---|
40 | #include <sys/types.h> |
---|
41 | |
---|
42 | #include <glib.h> |
---|
43 | #include <math.h> |
---|
44 | #include "gnome-canvas.h" |
---|
45 | #include "gnome-canvas-util.h" |
---|
46 | #include <libart_lgpl/art_uta.h> |
---|
47 | #include <libart_lgpl/art_svp.h> |
---|
48 | #include <libart_lgpl/art_svp_ops.h> |
---|
49 | #include <libart_lgpl/art_rgb.h> |
---|
50 | #include <libart_lgpl/art_rgb_svp.h> |
---|
51 | #include <libart_lgpl/art_uta_svp.h> |
---|
52 | #include <libart_lgpl/art_rect_svp.h> |
---|
53 | |
---|
54 | /** |
---|
55 | * gnome_canvas_points_new: |
---|
56 | * @num_points: The number of points to allocate space for in the array. |
---|
57 | * |
---|
58 | * Creates a structure that should be used to pass an array of points to |
---|
59 | * items. |
---|
60 | * |
---|
61 | * Return value: A newly-created array of points. It should be filled in |
---|
62 | * by the user. |
---|
63 | **/ |
---|
64 | GnomeCanvasPoints * |
---|
65 | gnome_canvas_points_new (int num_points) |
---|
66 | { |
---|
67 | GnomeCanvasPoints *points; |
---|
68 | |
---|
69 | g_return_val_if_fail (num_points > 1, NULL); |
---|
70 | |
---|
71 | points = g_new (GnomeCanvasPoints, 1); |
---|
72 | points->num_points = num_points; |
---|
73 | points->coords = g_new (double, 2 * num_points); |
---|
74 | points->ref_count = 1; |
---|
75 | |
---|
76 | return points; |
---|
77 | } |
---|
78 | |
---|
79 | /** |
---|
80 | * gnome_canvas_points_ref: |
---|
81 | * @points: A canvas points structure. |
---|
82 | * |
---|
83 | * Increases the reference count of the specified points structure. |
---|
84 | * |
---|
85 | * Return value: The canvas points structure itself. |
---|
86 | **/ |
---|
87 | GnomeCanvasPoints * |
---|
88 | gnome_canvas_points_ref (GnomeCanvasPoints *points) |
---|
89 | { |
---|
90 | g_return_val_if_fail (points != NULL, NULL); |
---|
91 | |
---|
92 | points->ref_count += 1; |
---|
93 | return points; |
---|
94 | } |
---|
95 | |
---|
96 | /** |
---|
97 | * gnome_canvas_points_free: |
---|
98 | * @points: A canvas points structure. |
---|
99 | * |
---|
100 | * Decreases the reference count of the specified points structure. If it |
---|
101 | * reaches zero, then the structure is freed. |
---|
102 | **/ |
---|
103 | void |
---|
104 | gnome_canvas_points_free (GnomeCanvasPoints *points) |
---|
105 | { |
---|
106 | g_return_if_fail (points != NULL); |
---|
107 | |
---|
108 | points->ref_count -= 1; |
---|
109 | if (points->ref_count == 0) { |
---|
110 | g_free (points->coords); |
---|
111 | g_free (points); |
---|
112 | } |
---|
113 | } |
---|
114 | |
---|
115 | /** |
---|
116 | * gnome_canvas_get_miter_points: |
---|
117 | * @x1: X coordinate of the first point |
---|
118 | * @y1: Y coordinate of the first point |
---|
119 | * @x2: X coordinate of the second (angle) point |
---|
120 | * @y2: Y coordinate of the second (angle) point |
---|
121 | * @x3: X coordinate of the third point |
---|
122 | * @y3: Y coordinate of the third point |
---|
123 | * @width: Width of the line |
---|
124 | * @mx1: The X coordinate of the first miter point is returned here. |
---|
125 | * @my1: The Y coordinate of the first miter point is returned here. |
---|
126 | * @mx2: The X coordinate of the second miter point is returned here. |
---|
127 | * @my2: The Y coordinate of the second miter point is returned here. |
---|
128 | * |
---|
129 | * Given three points forming an angle, computes the coordinates of the inside |
---|
130 | * and outside points of the mitered corner formed by a line of a given width at |
---|
131 | * that angle. |
---|
132 | * |
---|
133 | * Return value: FALSE if the angle is less than 11 degrees (this is the same |
---|
134 | * threshold as X uses. If this occurs, the return points are not modified. |
---|
135 | * Otherwise, returns TRUE. |
---|
136 | **/ |
---|
137 | int |
---|
138 | gnome_canvas_get_miter_points (double x1, double y1, double x2, double y2, double x3, double y3, |
---|
139 | double width, |
---|
140 | double *mx1, double *my1, double *mx2, double *my2) |
---|
141 | { |
---|
142 | double theta1; /* angle of segment p2-p1 */ |
---|
143 | double theta2; /* angle of segment p2-p3 */ |
---|
144 | double theta; /* angle between line segments */ |
---|
145 | double theta3; /* angle that bisects theta1 and theta2 and points to p1 */ |
---|
146 | double dist; /* distance of miter points from p2 */ |
---|
147 | double dx, dy; /* x and y offsets corresponding to dist */ |
---|
148 | |
---|
149 | #define ELEVEN_DEGREES (11.0 * G_PI / 180.0) |
---|
150 | |
---|
151 | if (y2 == y1) |
---|
152 | theta1 = (x2 < x1) ? 0.0 : G_PI; |
---|
153 | else if (x2 == x1) |
---|
154 | theta1 = (y2 < y1) ? G_PI_2 : -G_PI_2; |
---|
155 | else |
---|
156 | theta1 = atan2 (y1 - y2, x1 - x2); |
---|
157 | |
---|
158 | if (y3 == y2) |
---|
159 | theta2 = (x3 > x2) ? 0 : G_PI; |
---|
160 | else if (x3 == x2) |
---|
161 | theta2 = (y3 > y2) ? G_PI_2 : -G_PI_2; |
---|
162 | else |
---|
163 | theta2 = atan2 (y3 - y2, x3 - x2); |
---|
164 | |
---|
165 | theta = theta1 - theta2; |
---|
166 | |
---|
167 | if (theta > G_PI) |
---|
168 | theta -= 2.0 * G_PI; |
---|
169 | else if (theta < -G_PI) |
---|
170 | theta += 2.0 * G_PI; |
---|
171 | |
---|
172 | if ((theta < ELEVEN_DEGREES) && (theta > -ELEVEN_DEGREES)) |
---|
173 | return FALSE; |
---|
174 | |
---|
175 | dist = 0.5 * width / sin (0.5 * theta); |
---|
176 | if (dist < 0.0) |
---|
177 | dist = -dist; |
---|
178 | |
---|
179 | theta3 = (theta1 + theta2) / 2.0; |
---|
180 | if (sin (theta3 - (theta1 + G_PI)) < 0.0) |
---|
181 | theta3 += G_PI; |
---|
182 | |
---|
183 | dx = dist * cos (theta3); |
---|
184 | dy = dist * sin (theta3); |
---|
185 | |
---|
186 | *mx1 = x2 + dx; |
---|
187 | *mx2 = x2 - dx; |
---|
188 | *my1 = y2 + dy; |
---|
189 | *my2 = y2 - dy; |
---|
190 | |
---|
191 | return TRUE; |
---|
192 | } |
---|
193 | |
---|
194 | /** |
---|
195 | * gnome_canvas_get_butt_points: |
---|
196 | * @x1: X coordinate of first point in the line |
---|
197 | * @y1: Y cooordinate of first point in the line |
---|
198 | * @x2: X coordinate of second point (endpoint) of the line |
---|
199 | * @y2: Y coordinate of second point (endpoint) of the line |
---|
200 | * @width: Width of the line |
---|
201 | * @project: Whether the butt points should project out by width/2 distance |
---|
202 | * @bx1: X coordinate of first butt point is returned here |
---|
203 | * @by1: Y coordinate of first butt point is returned here |
---|
204 | * @bx2: X coordinate of second butt point is returned here |
---|
205 | * @by2: Y coordinate of second butt point is returned here |
---|
206 | * |
---|
207 | * Computes the butt points of a line segment. |
---|
208 | **/ |
---|
209 | void |
---|
210 | gnome_canvas_get_butt_points (double x1, double y1, double x2, double y2, |
---|
211 | double width, int project, |
---|
212 | double *bx1, double *by1, double *bx2, double *by2) |
---|
213 | { |
---|
214 | double length; |
---|
215 | double dx, dy; |
---|
216 | |
---|
217 | width *= 0.5; |
---|
218 | dx = x2 - x1; |
---|
219 | dy = y2 - y1; |
---|
220 | length = sqrt (dx * dx + dy * dy); |
---|
221 | |
---|
222 | if (length < GNOME_CANVAS_EPSILON) { |
---|
223 | *bx1 = *bx2 = x2; |
---|
224 | *by1 = *by2 = y2; |
---|
225 | } else { |
---|
226 | dx = -width * (y2 - y1) / length; |
---|
227 | dy = width * (x2 - x1) / length; |
---|
228 | |
---|
229 | *bx1 = x2 + dx; |
---|
230 | *bx2 = x2 - dx; |
---|
231 | *by1 = y2 + dy; |
---|
232 | *by2 = y2 - dy; |
---|
233 | |
---|
234 | if (project) { |
---|
235 | *bx1 += dy; |
---|
236 | *bx2 += dy; |
---|
237 | *by1 -= dx; |
---|
238 | *by2 -= dx; |
---|
239 | } |
---|
240 | } |
---|
241 | } |
---|
242 | |
---|
243 | /** |
---|
244 | * gnome_canvas_polygon_to_point: |
---|
245 | * @poly: Vertices of the polygon. X coordinates are in the even indices, and Y |
---|
246 | * coordinates are in the odd indices |
---|
247 | * @num_points: Number of points in the polygon |
---|
248 | * @x: X coordinate of the point |
---|
249 | * @y: Y coordinate of the point |
---|
250 | * |
---|
251 | * Computes the distance between a point and a polygon. |
---|
252 | * |
---|
253 | * Return value: The distance from the point to the polygon, or zero if the |
---|
254 | * point is inside the polygon. |
---|
255 | **/ |
---|
256 | double |
---|
257 | gnome_canvas_polygon_to_point (double *poly, int num_points, double x, double y) |
---|
258 | { |
---|
259 | double best; |
---|
260 | int intersections; |
---|
261 | int i; |
---|
262 | double *p; |
---|
263 | double dx, dy; |
---|
264 | |
---|
265 | /* Iterate through all the edges in the polygon, updating best and intersections. |
---|
266 | * |
---|
267 | * When computing intersections, include left X coordinate of line within its range, but not |
---|
268 | * Y coordinate. Otherwise if the point lies exactly below a vertex we'll count it as two |
---|
269 | * intersections. |
---|
270 | */ |
---|
271 | |
---|
272 | best = 1.0e36; |
---|
273 | intersections = 0; |
---|
274 | |
---|
275 | for (i = num_points, p = poly; i > 1; i--, p += 2) { |
---|
276 | double px, py, dist; |
---|
277 | |
---|
278 | /* Compute the point on the current edge closest to the point and update the |
---|
279 | * intersection count. This must be done separately for vertical edges, horizontal |
---|
280 | * edges, and others. |
---|
281 | */ |
---|
282 | |
---|
283 | if (p[2] == p[0]) { |
---|
284 | /* Vertical edge */ |
---|
285 | |
---|
286 | px = p[0]; |
---|
287 | |
---|
288 | if (p[1] >= p[3]) { |
---|
289 | py = MIN (p[1], y); |
---|
290 | py = MAX (py, p[3]); |
---|
291 | } else { |
---|
292 | py = MIN (p[3], y); |
---|
293 | py = MAX (py, p[1]); |
---|
294 | } |
---|
295 | } else if (p[3] == p[1]) { |
---|
296 | /* Horizontal edge */ |
---|
297 | |
---|
298 | py = p[1]; |
---|
299 | |
---|
300 | if (p[0] >= p[2]) { |
---|
301 | px = MIN (p[0], x); |
---|
302 | px = MAX (px, p[2]); |
---|
303 | |
---|
304 | if ((y < py) && (x < p[0]) && (x >= p[2])) |
---|
305 | intersections++; |
---|
306 | } else { |
---|
307 | px = MIN (p[2], x); |
---|
308 | px = MAX (px, p[0]); |
---|
309 | |
---|
310 | if ((y < py) && (x < p[2]) && (x >= p[0])) |
---|
311 | intersections++; |
---|
312 | } |
---|
313 | } else { |
---|
314 | double m1, b1, m2, b2; |
---|
315 | int lower; |
---|
316 | |
---|
317 | /* Diagonal edge. Convert the edge to a line equation (y = m1*x + b1), then |
---|
318 | * compute a line perpendicular to this edge but passing through the point, |
---|
319 | * (y = m2*x + b2). |
---|
320 | */ |
---|
321 | |
---|
322 | m1 = (p[3] - p[1]) / (p[2] - p[0]); |
---|
323 | b1 = p[1] - m1 * p[0]; |
---|
324 | |
---|
325 | m2 = -1.0 / m1; |
---|
326 | b2 = y - m2 * x; |
---|
327 | |
---|
328 | px = (b2 - b1) / (m1 - m2); |
---|
329 | py = m1 * px + b1; |
---|
330 | |
---|
331 | if (p[0] > p[2]) { |
---|
332 | if (px > p[0]) { |
---|
333 | px = p[0]; |
---|
334 | py = p[1]; |
---|
335 | } else if (px < p[2]) { |
---|
336 | px = p[2]; |
---|
337 | py = p[3]; |
---|
338 | } |
---|
339 | } else { |
---|
340 | if (px > p[2]) { |
---|
341 | px = p[2]; |
---|
342 | py = p[3]; |
---|
343 | } else if (px < p[0]) { |
---|
344 | px = p[0]; |
---|
345 | py = p[1]; |
---|
346 | } |
---|
347 | } |
---|
348 | |
---|
349 | lower = (m1 * x + b1) > y; |
---|
350 | |
---|
351 | if (lower && (x >= MIN (p[0], p[2])) && (x < MAX (p[0], p[2]))) |
---|
352 | intersections++; |
---|
353 | } |
---|
354 | |
---|
355 | /* Compute the distance to the closest point, and see if that is the best so far */ |
---|
356 | |
---|
357 | dx = x - px; |
---|
358 | dy = y - py; |
---|
359 | dist = sqrt (dx * dx + dy * dy); |
---|
360 | if (dist < best) |
---|
361 | best = dist; |
---|
362 | } |
---|
363 | |
---|
364 | /* We've processed all the points. If the number of intersections is odd, the point is |
---|
365 | * inside the polygon. |
---|
366 | */ |
---|
367 | |
---|
368 | if (intersections & 0x1) |
---|
369 | return 0.0; |
---|
370 | else |
---|
371 | return best; |
---|
372 | } |
---|
373 | |
---|
374 | /* Here are some helper functions for aa rendering: */ |
---|
375 | |
---|
376 | /** |
---|
377 | * gnome_canvas_render_svp: |
---|
378 | * @buf: the canvas buffer to render over |
---|
379 | * @svp: the vector path to render |
---|
380 | * @rgba: the rgba color to render |
---|
381 | * |
---|
382 | * Render the svp over the buf. |
---|
383 | **/ |
---|
384 | void |
---|
385 | gnome_canvas_render_svp (GnomeCanvasBuf *buf, ArtSVP *svp, guint32 rgba) |
---|
386 | { |
---|
387 | guint32 fg_color, bg_color; |
---|
388 | int alpha; |
---|
389 | |
---|
390 | if (buf->is_bg) { |
---|
391 | bg_color = buf->bg_color; |
---|
392 | alpha = rgba & 0xff; |
---|
393 | if (alpha == 0xff) |
---|
394 | fg_color = rgba >> 8; |
---|
395 | else { |
---|
396 | /* composite over background color */ |
---|
397 | int bg_r, bg_g, bg_b; |
---|
398 | int fg_r, fg_g, fg_b; |
---|
399 | int tmp; |
---|
400 | |
---|
401 | bg_r = (bg_color >> 16) & 0xff; |
---|
402 | fg_r = (rgba >> 24) & 0xff; |
---|
403 | tmp = (fg_r - bg_r) * alpha; |
---|
404 | fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8); |
---|
405 | |
---|
406 | bg_g = (bg_color >> 8) & 0xff; |
---|
407 | fg_g = (rgba >> 16) & 0xff; |
---|
408 | tmp = (fg_g - bg_g) * alpha; |
---|
409 | fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8); |
---|
410 | |
---|
411 | bg_b = bg_color & 0xff; |
---|
412 | fg_b = (rgba >> 8) & 0xff; |
---|
413 | tmp = (fg_b - bg_b) * alpha; |
---|
414 | fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8); |
---|
415 | |
---|
416 | fg_color = (fg_r << 16) | (fg_g << 8) | fg_b; |
---|
417 | } |
---|
418 | art_rgb_svp_aa (svp, |
---|
419 | buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1, |
---|
420 | fg_color, bg_color, |
---|
421 | buf->buf, buf->buf_rowstride, |
---|
422 | NULL); |
---|
423 | buf->is_bg = 0; |
---|
424 | buf->is_buf = 1; |
---|
425 | } else { |
---|
426 | art_rgb_svp_alpha (svp, |
---|
427 | buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1, |
---|
428 | rgba, |
---|
429 | buf->buf, buf->buf_rowstride, |
---|
430 | NULL); |
---|
431 | } |
---|
432 | } |
---|
433 | |
---|
434 | /** |
---|
435 | * gnome_canvas_update_svp: |
---|
436 | * @canvas: the canvas containing the svp that needs updating. |
---|
437 | * @p_svp: a pointer to the existing svp |
---|
438 | * @new_svp: the new svp |
---|
439 | * |
---|
440 | * Sets the svp to the new value, requesting repaint on what's changed. This |
---|
441 | * function takes responsibility for freeing new_svp. |
---|
442 | **/ |
---|
443 | void |
---|
444 | gnome_canvas_update_svp (GnomeCanvas *canvas, ArtSVP **p_svp, ArtSVP *new_svp) |
---|
445 | { |
---|
446 | ArtSVP *old_svp; |
---|
447 | ArtSVP *diff G_GNUC_UNUSED; |
---|
448 | ArtUta *repaint_uta; |
---|
449 | |
---|
450 | old_svp = *p_svp; |
---|
451 | |
---|
452 | if (old_svp != NULL) { |
---|
453 | ArtDRect bb; |
---|
454 | art_drect_svp (&bb, old_svp); |
---|
455 | if ((bb.x1 - bb.x0) * (bb.y1 - bb.y0) > (64 * 64)) { |
---|
456 | repaint_uta = art_uta_from_svp (old_svp); |
---|
457 | gnome_canvas_request_redraw_uta (canvas, repaint_uta); |
---|
458 | } else { |
---|
459 | ArtIRect ib; |
---|
460 | art_drect_to_irect (&ib, &bb); |
---|
461 | gnome_canvas_request_redraw (canvas, ib.x0, ib.y0, ib.x1, ib.y1); |
---|
462 | } |
---|
463 | art_svp_free (old_svp); |
---|
464 | } |
---|
465 | |
---|
466 | if (new_svp != NULL) { |
---|
467 | ArtDRect bb; |
---|
468 | art_drect_svp (&bb, new_svp); |
---|
469 | if ((bb.x1 - bb.x0) * (bb.y1 - bb.y0) > (64 * 64)) { |
---|
470 | repaint_uta = art_uta_from_svp (new_svp); |
---|
471 | gnome_canvas_request_redraw_uta (canvas, repaint_uta); |
---|
472 | } else { |
---|
473 | ArtIRect ib; |
---|
474 | art_drect_to_irect (&ib, &bb); |
---|
475 | gnome_canvas_request_redraw (canvas, ib.x0, ib.y0, ib.x1, ib.y1); |
---|
476 | } |
---|
477 | } |
---|
478 | |
---|
479 | *p_svp = new_svp; |
---|
480 | } |
---|
481 | |
---|
482 | /** |
---|
483 | * gnome_canvas_update_svp_clip: |
---|
484 | * @canvas: the canvas containing the svp that needs updating. |
---|
485 | * @p_svp: a pointer to the existing svp |
---|
486 | * @new_svp: the new svp |
---|
487 | * @clip_svp: a clip path, if non-null |
---|
488 | * |
---|
489 | * Sets the svp to the new value, clipping if necessary, and requesting repaint |
---|
490 | * on what's changed. This function takes responsibility for freeing new_svp. |
---|
491 | **/ |
---|
492 | void |
---|
493 | gnome_canvas_update_svp_clip (GnomeCanvas *canvas, ArtSVP **p_svp, ArtSVP *new_svp, ArtSVP *clip_svp) |
---|
494 | { |
---|
495 | ArtSVP *clipped_svp; |
---|
496 | |
---|
497 | if (clip_svp != NULL) { |
---|
498 | clipped_svp = art_svp_intersect (new_svp, clip_svp); |
---|
499 | art_svp_free (new_svp); |
---|
500 | } else { |
---|
501 | clipped_svp = new_svp; |
---|
502 | } |
---|
503 | gnome_canvas_update_svp (canvas, p_svp, clipped_svp); |
---|
504 | } |
---|
505 | |
---|
506 | /** |
---|
507 | * gnome_canvas_item_reset_bounds: |
---|
508 | * @item: A canvas item |
---|
509 | * |
---|
510 | * Resets the bounding box of a canvas item to an empty rectangle. |
---|
511 | **/ |
---|
512 | void |
---|
513 | gnome_canvas_item_reset_bounds (GnomeCanvasItem *item) |
---|
514 | { |
---|
515 | item->x1 = 0.0; |
---|
516 | item->y1 = 0.0; |
---|
517 | item->x2 = 0.0; |
---|
518 | item->y2 = 0.0; |
---|
519 | } |
---|
520 | |
---|
521 | /** |
---|
522 | * gnome_canvas_item_update_svp: |
---|
523 | * @item: the canvas item containing the svp that needs updating. |
---|
524 | * @p_svp: a pointer to the existing svp |
---|
525 | * @new_svp: the new svp |
---|
526 | * |
---|
527 | * Sets the svp to the new value, requesting repaint on what's changed. This |
---|
528 | * function takes responsibility for freeing new_svp. This routine also adds the |
---|
529 | * svp's bbox to the item's. |
---|
530 | **/ |
---|
531 | void |
---|
532 | gnome_canvas_item_update_svp (GnomeCanvasItem *item, ArtSVP **p_svp, ArtSVP *new_svp) |
---|
533 | { |
---|
534 | ArtDRect bbox; |
---|
535 | |
---|
536 | gnome_canvas_update_svp (item->canvas, p_svp, new_svp); |
---|
537 | if (new_svp) { |
---|
538 | bbox.x0 = item->x1; |
---|
539 | bbox.y0 = item->y1; |
---|
540 | bbox.x1 = item->x2; |
---|
541 | bbox.y1 = item->y2; |
---|
542 | art_drect_svp_union (&bbox, new_svp); |
---|
543 | item->x1 = bbox.x0; |
---|
544 | item->y1 = bbox.y0; |
---|
545 | item->x2 = bbox.x1; |
---|
546 | item->y2 = bbox.y1; |
---|
547 | } |
---|
548 | } |
---|
549 | |
---|
550 | /** |
---|
551 | * gnome_canvas_item_update_svp_clip: |
---|
552 | * @item: the canvas item containing the svp that needs updating. |
---|
553 | * @p_svp: a pointer to the existing svp |
---|
554 | * @new_svp: the new svp |
---|
555 | * @clip_svp: a clip path, if non-null |
---|
556 | * |
---|
557 | * Sets the svp to the new value, clipping if necessary, and requesting repaint |
---|
558 | * on what's changed. This function takes responsibility for freeing new_svp. |
---|
559 | **/ |
---|
560 | void |
---|
561 | gnome_canvas_item_update_svp_clip (GnomeCanvasItem *item, ArtSVP **p_svp, ArtSVP *new_svp, |
---|
562 | ArtSVP *clip_svp) |
---|
563 | { |
---|
564 | ArtSVP *clipped_svp; |
---|
565 | |
---|
566 | if (clip_svp != NULL) { |
---|
567 | clipped_svp = art_svp_intersect (new_svp, clip_svp); |
---|
568 | art_svp_free (new_svp); |
---|
569 | } else { |
---|
570 | clipped_svp = new_svp; |
---|
571 | } |
---|
572 | |
---|
573 | gnome_canvas_item_update_svp (item, p_svp, clipped_svp); |
---|
574 | } |
---|
575 | |
---|
576 | /** |
---|
577 | * gnome_canvas_item_request_redraw_svp |
---|
578 | * @item: the item containing the svp |
---|
579 | * @svp: the svp that needs to be redrawn |
---|
580 | * |
---|
581 | * Request redraw of the svp if in aa mode, or the entire item in in xlib mode. |
---|
582 | **/ |
---|
583 | void |
---|
584 | gnome_canvas_item_request_redraw_svp (GnomeCanvasItem *item, const ArtSVP *svp) |
---|
585 | { |
---|
586 | GnomeCanvas *canvas; |
---|
587 | ArtUta *uta; |
---|
588 | |
---|
589 | canvas = item->canvas; |
---|
590 | if (canvas->aa) { |
---|
591 | if (svp != NULL) { |
---|
592 | uta = art_uta_from_svp (svp); |
---|
593 | gnome_canvas_request_redraw_uta (canvas, uta); |
---|
594 | } |
---|
595 | } else { |
---|
596 | gnome_canvas_request_redraw (canvas, item->x1, item->y1, item->x2, item->y2); |
---|
597 | } |
---|
598 | } |
---|
599 | |
---|
600 | /** |
---|
601 | * gnome_canvas_update_bbox: |
---|
602 | * @item: the canvas item needing update |
---|
603 | * @x1: Left coordinate of the new bounding box |
---|
604 | * @y1: Top coordinate of the new bounding box |
---|
605 | * @x2: Right coordinate of the new bounding box |
---|
606 | * @y2: Bottom coordinate of the new bounding box |
---|
607 | * |
---|
608 | * Sets the bbox to the new value, requesting full repaint. |
---|
609 | **/ |
---|
610 | void |
---|
611 | gnome_canvas_update_bbox (GnomeCanvasItem *item, int x1, int y1, int x2, int y2) |
---|
612 | { |
---|
613 | gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); |
---|
614 | item->x1 = x1; |
---|
615 | item->y1 = y1; |
---|
616 | item->x2 = x2; |
---|
617 | item->y2 = y2; |
---|
618 | gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); |
---|
619 | } |
---|
620 | |
---|
621 | /** |
---|
622 | * gnome_canvas_buf_ensure_buf: |
---|
623 | * @buf: the buf that needs to be represened in RGB format |
---|
624 | * |
---|
625 | * Ensure that the buffer is in RGB format, suitable for compositing. |
---|
626 | **/ |
---|
627 | void |
---|
628 | gnome_canvas_buf_ensure_buf (GnomeCanvasBuf *buf) |
---|
629 | { |
---|
630 | guchar *bufptr; |
---|
631 | int y; |
---|
632 | |
---|
633 | if (!buf->is_buf) { |
---|
634 | bufptr = buf->buf; |
---|
635 | for (y = buf->rect.y0; y < buf->rect.y1; y++) { |
---|
636 | art_rgb_fill_run (bufptr, |
---|
637 | buf->bg_color >> 16, |
---|
638 | (buf->bg_color >> 8) & 0xff, |
---|
639 | buf->bg_color & 0xff, |
---|
640 | buf->rect.x1 - buf->rect.x0); |
---|
641 | bufptr += buf->buf_rowstride; |
---|
642 | } |
---|
643 | buf->is_buf = 1; |
---|
644 | } |
---|
645 | } |
---|
646 | |
---|
647 | /** |
---|
648 | * gnome_canvas_join_gdk_to_art |
---|
649 | * @gdk_join: a join type, represented in GDK format |
---|
650 | * |
---|
651 | * Convert from GDK line join specifier to libart. |
---|
652 | * |
---|
653 | * Return value: The line join specifier in libart format. |
---|
654 | **/ |
---|
655 | ArtPathStrokeJoinType |
---|
656 | gnome_canvas_join_gdk_to_art (GdkJoinStyle gdk_join) |
---|
657 | { |
---|
658 | switch (gdk_join) { |
---|
659 | case GDK_JOIN_MITER: |
---|
660 | return ART_PATH_STROKE_JOIN_MITER; |
---|
661 | |
---|
662 | case GDK_JOIN_ROUND: |
---|
663 | return ART_PATH_STROKE_JOIN_ROUND; |
---|
664 | |
---|
665 | case GDK_JOIN_BEVEL: |
---|
666 | return ART_PATH_STROKE_JOIN_BEVEL; |
---|
667 | |
---|
668 | default: |
---|
669 | g_assert_not_reached (); |
---|
670 | return ART_PATH_STROKE_JOIN_MITER; /* shut up the compiler */ |
---|
671 | } |
---|
672 | } |
---|
673 | |
---|
674 | /** |
---|
675 | * gnome_canvas_cap_gdk_to_art |
---|
676 | * @gdk_cap: a cap type, represented in GDK format |
---|
677 | * |
---|
678 | * Convert from GDK line cap specifier to libart. |
---|
679 | * |
---|
680 | * Return value: The line cap specifier in libart format. |
---|
681 | **/ |
---|
682 | ArtPathStrokeCapType |
---|
683 | gnome_canvas_cap_gdk_to_art (GdkCapStyle gdk_cap) |
---|
684 | { |
---|
685 | switch (gdk_cap) { |
---|
686 | case GDK_CAP_BUTT: |
---|
687 | case GDK_CAP_NOT_LAST: |
---|
688 | return ART_PATH_STROKE_CAP_BUTT; |
---|
689 | |
---|
690 | case GDK_CAP_ROUND: |
---|
691 | return ART_PATH_STROKE_CAP_ROUND; |
---|
692 | |
---|
693 | case GDK_CAP_PROJECTING: |
---|
694 | return ART_PATH_STROKE_CAP_SQUARE; |
---|
695 | |
---|
696 | default: |
---|
697 | g_assert_not_reached (); |
---|
698 | return ART_PATH_STROKE_CAP_BUTT; /* shut up the compiler */ |
---|
699 | } |
---|
700 | } |
---|