27 |
#include <libart/libart.h> |
#include <libart/libart.h> |
28 |
#include <libart/art_affine.h> |
#include <libart/art_affine.h> |
29 |
#include <libart/art_render.h> |
#include <libart/art_render.h> |
30 |
|
#include <libart/art_bpath.h> |
31 |
#include <libart/art_render_svp.h> |
#include <libart/art_render_svp.h> |
32 |
|
|
33 |
#include "GFContext.h" |
#include "GFContext.h" |
114 |
{ |
{ |
115 |
/* We just truncate the number of vectors. */ |
/* We just truncate the number of vectors. */ |
116 |
context->vpath_n = 0; |
context->vpath_n = 0; |
117 |
|
context->bpath_n = 0; |
118 |
} |
} |
119 |
|
|
120 |
/* Close current subpath. */ |
/* Close current subpath. */ |
179 |
context->gstate->alpha_value = value; |
context->gstate->alpha_value = value; |
180 |
} |
} |
181 |
|
|
|
/* Set fill color to VALUE. Number of components in VALUE is |
|
|
specified by current fill color space. */ |
|
|
void |
|
|
GFContextSetFillColor (GFContextRef context, float value[]) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
for (i = 0; i < context->gstate->fill_space->n_components; i++) |
|
|
context->gstate->fill_color [i] = value [i]; |
|
|
} |
|
|
|
|
182 |
/* Set CONTEXT's fill color space to COLORSPACE. */ |
/* Set CONTEXT's fill color space to COLORSPACE. */ |
183 |
void |
void |
184 |
GFContextSetFillColorSpace (GFContextRef context, |
GFContextSetFillColorSpace (GFContextRef context, |
188 |
context->gstate->fill_space = colorspace; |
context->gstate->fill_space = colorspace; |
189 |
} |
} |
190 |
|
|
|
|
|
|
/* Set stoke color to VALUE. Number of components in VALUE is |
|
|
specified by current stroke color space. */ |
|
|
void |
|
|
GFContextSetStrokeColor (GFContextRef context, float value[]) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
for (i = 0; i < context->gstate->stroke_space->n_components; i++) |
|
|
context->gstate->stroke_color [i] = value [i]; |
|
|
} |
|
|
|
|
191 |
/* Set CONTEXT's stroke color space to COLORSPACE. */ |
/* Set CONTEXT's stroke color space to COLORSPACE. */ |
192 |
void |
void |
193 |
GFContextSetStrokeColorSpace (GFContextRef context, |
GFContextSetStrokeColorSpace (GFContextRef context, |
204 |
GFContextSetRGBFillColor (GFContextRef context, float r, float |
GFContextSetRGBFillColor (GFContextRef context, float r, float |
205 |
g, float b, float alpha) |
g, float b, float alpha) |
206 |
{ |
{ |
207 |
float value_array [3] = { r, g, b }; |
float value_array [4] = { r, g, b, alpha }; |
208 |
|
|
209 |
GFContextSetFillColorSpace (context, GFColorSpaceCreateDeviceRGB ()); |
GFContextSetFillColorSpace (context, GFColorSpaceCreateDeviceRGB ()); |
210 |
GFContextSetFillColor (context, value_array); |
GFContextSetFillColor (context, value_array); |
|
GFContextSetAlpha (context, alpha); |
|
211 |
} |
} |
212 |
|
|
213 |
/* Convenience function to set stroke color space to DeviceRGB |
/* Convenience function to set stroke color space to DeviceRGB |
216 |
GFContextSetRGBStrokeColor (GFContextRef context, float r, float |
GFContextSetRGBStrokeColor (GFContextRef context, float r, float |
217 |
g, float b, float alpha) |
g, float b, float alpha) |
218 |
{ |
{ |
219 |
float value_array [3] = { r, g, b }; |
float value_array [4] = { r, g, b, alpha }; |
220 |
|
|
221 |
GFContextSetStrokeColorSpace (context, GFColorSpaceCreateDeviceRGB ()); |
GFContextSetStrokeColorSpace (context, GFColorSpaceCreateDeviceRGB ()); |
222 |
GFContextSetStrokeColor (context, value_array); |
GFContextSetStrokeColor (context, value_array); |
|
GFContextSetAlpha (context, alpha); |
|
223 |
} |
} |
224 |
|
|
225 |
/* Set line width in current graphic state to LINE_WIDTH. */ |
/* Set line width in current graphic state to LINE_WIDTH. */ |
249 |
gstate->line_join = line_join; |
gstate->line_join = line_join; |
250 |
} |
} |
251 |
|
|
252 |
|
static void |
253 |
|
path_arc_segment (GFContextRef context, |
254 |
|
double xc, double yc, |
255 |
|
double th0, double th1, |
256 |
|
double rx, double ry, double x_axis_rotation) |
257 |
|
{ |
258 |
|
ArtBpath bez; |
259 |
|
double sin_th, cos_th; |
260 |
|
double a00, a01, a10, a11; |
261 |
|
double x1, y1, x2, y2, x3, y3; |
262 |
|
double t; |
263 |
|
double th_half; |
264 |
|
|
265 |
|
sin_th = sin (x_axis_rotation); |
266 |
|
cos_th = cos (x_axis_rotation); |
267 |
|
|
268 |
|
/* inverse transform compared with rsvg_path_arc */ |
269 |
|
a00 = cos_th * rx; |
270 |
|
a01 = -sin_th * ry; |
271 |
|
a10 = sin_th * rx; |
272 |
|
a11 = cos_th * ry; |
273 |
|
|
274 |
|
th_half = 0.5 * (th1 - th0); |
275 |
|
t = (8.0 / 3.0) * sin (th_half * 0.5) * sin (th_half * 0.5) / sin (th_half); |
276 |
|
x1 = xc + cos (th0) - t * sin (th0); |
277 |
|
y1 = yc + sin (th0) + t * cos (th0); |
278 |
|
x3 = xc + cos (th1); |
279 |
|
y3 = yc + sin (th1); |
280 |
|
x2 = x3 + t * sin (th1); |
281 |
|
y2 = y3 - t * cos (th1); |
282 |
|
|
283 |
|
bez.code = ART_CURVETO; |
284 |
|
bez.x1 = a00 * x1 + a01 * y1; |
285 |
|
bez.y1 = a10 * x1 + a11 * y1; |
286 |
|
bez.x2 = a00 * x2 + a01 * y2; |
287 |
|
bez.y2 = a10 * x2 + a11 * y2; |
288 |
|
bez.x3 = a00 * x3 + a01 * y3; |
289 |
|
bez.y3 = a10 * x3 + a11 * y3; |
290 |
|
|
291 |
|
context->bpath [context->bpath_n++] = bez; |
292 |
|
|
293 |
|
art_vpath_add_point (&context->vpath, &context->vpath_n, |
294 |
|
&context->vpath_n_max, ART_CURVETO, bez.x3, bez.y3); |
295 |
|
} |
296 |
|
|
297 |
|
/* Draws an elliptical arc from the current point to (X, Y). |
298 |
|
The size and orientation of the ellipse are defined by |
299 |
|
two radii (RX, RY) and an X_AXIS_ROTATION, which indicates |
300 |
|
how the ellipse as a whole is rotated relative to the current |
301 |
|
coordinate system. LARGE_ARC_FLAG and SWEEP_FLAG contribute |
302 |
|
to the automatic calculations and help determine how the arc |
303 |
|
is drawn. |
304 |
|
|
305 |
|
LARGE_ARC_FLAG: 0 for arc length <= 180, 1 for arc >= 180. |
306 |
|
SWEEP_FLAG: 0 for "negative angle", 1 for "positive angle". */ |
307 |
|
void |
308 |
|
GFContextAddArcToPoint (GFContextRef context, float rx, float ry, |
309 |
|
float x_axis_rotation, int large_arc_flag, |
310 |
|
int sweep_flag, float x, float y) |
311 |
|
{ |
312 |
|
double sin_th, cos_th; |
313 |
|
double a00, a01, a10, a11, cpx, cpy; |
314 |
|
double x0, y0, x1, y1, xc, yc; |
315 |
|
double d, sfactor, sfactor_sq; |
316 |
|
double th0, th1, th_arc; |
317 |
|
int i, n_segs; |
318 |
|
|
319 |
|
sin_th = sin (x_axis_rotation); |
320 |
|
cos_th = cos (x_axis_rotation); |
321 |
|
a00 = cos_th / rx; |
322 |
|
a01 = sin_th / rx; |
323 |
|
a10 = -sin_th / ry; |
324 |
|
a11 = cos_th / ry; |
325 |
|
|
326 |
|
cpx = context->vpath[context->vpath_n - 1].x; |
327 |
|
cpy = context->vpath[context->vpath_n - 1].y; |
328 |
|
|
329 |
|
x0 = a00 * cpx + a01 * cpy; |
330 |
|
y0 = a10 * cpx + a11 * cpy; |
331 |
|
x1 = a00 * x + a01 * y; |
332 |
|
y1 = a10 * x + a11 * y; |
333 |
|
|
334 |
|
/* (x0, y0) is current point in transformed coordinate space. |
335 |
|
(x1, y1) is new point in transformed coordinate space. |
336 |
|
|
337 |
|
The arc fits a unit-radius circle in this space. */ |
338 |
|
d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); |
339 |
|
sfactor_sq = 1.0 / d - 0.25; |
340 |
|
if (sfactor_sq < 0) |
341 |
|
sfactor_sq = 0; |
342 |
|
sfactor = sqrt (sfactor_sq); |
343 |
|
|
344 |
|
if (sweep_flag == large_arc_flag) |
345 |
|
sfactor = -sfactor; |
346 |
|
|
347 |
|
xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); |
348 |
|
yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); |
349 |
|
/* (xc, yc) is center of the circle. */ |
350 |
|
|
351 |
|
th0 = atan2 (y0 - yc, x0 - xc); |
352 |
|
th1 = atan2 (y1 - yc, x1 - xc); |
353 |
|
|
354 |
|
th_arc = th1 - th0; |
355 |
|
if (th_arc < 0 && sweep_flag) |
356 |
|
th_arc += 2 * M_PI; |
357 |
|
else if (th_arc > 0 && !sweep_flag) |
358 |
|
th_arc -= 2 * M_PI; |
359 |
|
|
360 |
|
n_segs = ceil (fabs (th_arc / (M_PI * 0.5 + 0.001))); |
361 |
|
|
362 |
|
for (i = 0; i < n_segs; i++) |
363 |
|
path_arc_segment (context, xc, yc, |
364 |
|
th0 + i * th_arc / n_segs, |
365 |
|
th0 + (i + 1) * th_arc / n_segs, |
366 |
|
rx, ry, x_axis_rotation); |
367 |
|
} |
368 |
|
|
369 |
|
|
370 |
|
|
371 |
/* Add a bezier curve from current point to (X0, Y0). (X1, Y1) and |
/* Add a bezier curve from current point to (X0, Y0). (X1, Y1) and |
372 |
(X2, Y2) is the two control points. */ |
(X2, Y2) is the two control points. */ |
373 |
void |
void |
457 |
bez[0].x3 = cx; |
bez[0].x3 = cx; |
458 |
bez[0].y3 = cy; |
bez[0].y3 = cy; |
459 |
bez[1] = context->bpath [bez_index++]; |
bez[1] = context->bpath [bez_index++]; |
|
bez[1].y1 = context->size.height - bez[1].y1; |
|
|
bez[1].y2 = context->size.height - bez[1].y2; |
|
|
bez[1].y3 = context->size.height - bez[1].y3; |
|
460 |
bez[2].code = ART_END; |
bez[2].code = ART_END; |
461 |
|
|
462 |
bezpath = art_bez_path_to_vec (bez, 0.5); /* ?? from state. */ |
bezpath = art_bez_path_to_vec (bez, 0.5); /* ?? from state. */ |
471 |
else |
else |
472 |
{ |
{ |
473 |
art_vpath_add_point (&final, &final_n, &final_n_max, |
art_vpath_add_point (&final, &final_n, &final_n_max, |
474 |
vpath[i].code, vpath[i].x, |
vpath[i].code, vpath[i].x, vpath[i].y); |
|
context->size.height - vpath[i].y); |
|
475 |
} |
} |
476 |
|
|
477 |
cx = final [final_n - 1].x; |
cx = final [final_n - 1].x; |
504 |
svp = art_svp_rewind_uncrossed (uncrossed, wind_rule); |
svp = art_svp_rewind_uncrossed (uncrossed, wind_rule); |
505 |
art_free (uncrossed); |
art_free (uncrossed); |
506 |
|
|
507 |
rowstride = context->size.width * (context->n_components + 1) |
rowstride = context->size.width * (context->n_components ) |
508 |
* context->n_bits_per_component / 8; |
* context->n_bits_per_component / 8; |
509 |
|
|
510 |
alpha_info = alpha_info_to_libart_alpha_info (context->alpha_info); |
alpha_info = alpha_info_to_libart_alpha_info (context->alpha_info); |
513 |
render = art_render_new (x0, y0, x1 - x0, y1 - y0, context->dst_buffer, |
render = art_render_new (x0, y0, x1 - x0, y1 - y0, context->dst_buffer, |
514 |
rowstride, 3, 8, alpha_info, alpha_pos, NULL); |
rowstride, 3, 8, alpha_info, alpha_pos, NULL); |
515 |
art_render_svp (render, svp); |
art_render_svp (render, svp); |
516 |
(*gstate->stroke_space->render_fn) (gstate->fill_space, |
paintserver_invoke (context, gstate->fill_space, render); |
517 |
gstate->fill_color, render); |
art_render_mask_solid (render, render->opacity * gstate->alpha_value); |
|
art_render_mask_solid (render, MAX_OPACITY (gstate->alpha_value)); |
|
518 |
art_render_invoke (render); |
art_render_invoke (render); |
519 |
|
paintserver_free (context, gstate->fill_space); |
520 |
art_free (svp); |
art_free (svp); |
521 |
} |
} |
522 |
|
|
533 |
svp = art_svp_uncross (tmp_svp); |
svp = art_svp_uncross (tmp_svp); |
534 |
art_free (tmp_svp); |
art_free (tmp_svp); |
535 |
|
|
536 |
rowstride = context->size.width * (context->n_components + 1) |
rowstride = context->size.width * (context->n_components) |
537 |
* context->n_bits_per_component / 8; |
* context->n_bits_per_component / 8; |
538 |
|
|
539 |
alpha_info = alpha_info_to_libart_alpha_info (context->alpha_info); |
alpha_info = alpha_info_to_libart_alpha_info (context->alpha_info); |
542 |
render = art_render_new (x0, y0, x1 - x0, y1 - y0, context->dst_buffer, |
render = art_render_new (x0, y0, x1 - x0, y1 - y0, context->dst_buffer, |
543 |
rowstride, 3, 8, alpha_info, alpha_pos, NULL); |
rowstride, 3, 8, alpha_info, alpha_pos, NULL); |
544 |
art_render_svp (render, svp); |
art_render_svp (render, svp); |
545 |
(*gstate->stroke_space->render_fn) (gstate->stroke_space, |
paintserver_invoke (context, gstate->stroke_space, render); |
546 |
gstate->stroke_color, render); |
art_render_mask_solid (render, render->opacity * gstate->alpha_value); |
|
art_render_mask_solid (render, MAX_OPACITY (gstate->alpha_value)); |
|
547 |
art_render_invoke (render); |
art_render_invoke (render); |
548 |
|
paintserver_free (context, gstate->stroke_space); |
549 |
art_free (svp); |
art_free (svp); |
550 |
} |
} |
551 |
art_free (transformed); |
art_free (transformed); |