[CPML] Merged line and close implementation
[adg.git] / cpml / cpml-primitive.c
blob7720a7df3af68feae4fdec319e5c76b496d30522
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008, 2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:cpml-primitive
23 * @Section_Id:CpmlPrimitive
24 * @title: CpmlPrimitive
25 * @short_description: Basic component of segments
27 * A primitive is an atomic geometric element found inside #CpmlSegment.
28 * The available primitives are the same defined by #cairo_path_data_type_t
29 * with the additional %CAIRO_PATH_ARC_TO type (check #CpmlPrimitiveType
30 * for further information) and without %CAIRO_PATH_MOVE_TO as it is not
31 * considered a primitive and it is managed in different way: the move-to
32 * primitives are only used to define the origin of a segment.
33 **/
35 /**
36 * CpmlPrimitiveType:
38 * This is another name for #cairo_path_data_type_t type. Although
39 * phisically they are the same struct, #CpmlPrimitiveType conceptually
40 * embodies an important difference: it can be used to specify the
41 * special %CAIRO_PATH_ARC_TO primitive. This is not a native cairo
42 * primitive and having two different types is a good way to make clear
43 * when a function expect or not embedded arc-to primitives.
44 **/
46 /**
47 * CpmlPrimitive:
48 * @segment: the source #CpmlSegment
49 * @org: a pointer to the first point of the primitive
50 * @data: the array of the path data, prepended by the header
52 * As for #CpmlSegment, also the primitive is unobtrusive. This
53 * means CpmlPrimitive does not include any coordinates but instead
54 * keeps pointers to the original segment (and, by transition, to
55 * the underlying #CpmlPath struct).
56 **/
59 #include "cpml-internal.h"
60 #include "cpml-extents.h"
61 #include "cpml-segment.h"
62 #include "cpml-primitive.h"
63 #include "cpml-primitive-private.h"
64 #include "cpml-line.h"
65 #include "cpml-arc.h"
66 #include "cpml-curve.h"
67 #include "cpml-close.h"
68 #include <stdlib.h>
69 #include <string.h>
70 #include <stdio.h>
73 static const _CpmlPrimitiveClass *
74 get_class (CpmlPrimitiveType type);
75 static void dump_cairo_point (const cairo_path_data_t *path_data);
78 /**
79 * cpml_primitive_copy:
80 * @primitive: the destination #CpmlPrimitive
81 * @src: the source #CpmlPrimitive
83 * Copies @src in @primitive. This is a shallow copy: the internal fields
84 * of @primitive refer to the same memory as the original @src primitive.
86 * Returns: @primitive
87 **/
88 CpmlPrimitive *
89 cpml_primitive_copy(CpmlPrimitive *primitive, const CpmlPrimitive *src)
91 return memcpy(primitive, src, sizeof(CpmlPrimitive));
94 /**
95 * cpml_primitive_from_segment:
96 * @primitive: the destination #CpmlPrimitive struct
97 * @segment: the source segment
99 * Initializes @primitive to the first primitive of @segment.
101 * Returns: @primitive
103 CpmlPrimitive *
104 cpml_primitive_from_segment(CpmlPrimitive *primitive, CpmlSegment *segment)
106 primitive->segment = segment;
108 /* The first element of a CpmlSegment is always a CAIRO_PATH_MOVE_TO,
109 * as ensured by cpml_segment_from_cairo() and by the browsing APIs,
110 * so the origin is in the second data item */
111 primitive->org = &segment->data[1];
113 /* Also, the segment APIs ensure that @segment is prepended by
114 * only one CAIRO_PATH_MOVE_TO */
115 primitive->data = segment->data + segment->data[0].header.length;
117 return primitive;
121 * cpml_primitive_reset:
122 * @primitive: a #CpmlPrimitive
124 * Resets @primitive so it refers to the first primitive of the
125 * source segment.
127 void
128 cpml_primitive_reset(CpmlPrimitive *primitive)
130 cpml_primitive_from_segment(primitive, primitive->segment);
134 * cpml_primitive_next:
135 * @primitive: a #CpmlPrimitive
138 * Changes @primitive so it refers to the next primitive on the
139 * source segment. If there are no more primitives, @primitive is
140 * not changed and 0 is returned.
142 * Returns: 1 on success, 0 if no next primitive found or errors
144 cairo_bool_t
145 cpml_primitive_next(CpmlPrimitive *primitive)
147 cairo_path_data_t *new_data;
149 new_data = primitive->data + primitive->data->header.length;
150 if (new_data - primitive->segment->data >= primitive->segment->num_data)
151 return 0;
153 /* TODO: this is a temporary workaround to be removed as soon as
154 * the issue #21 will be resolved */
155 if (new_data->header.type == CAIRO_PATH_MOVE_TO)
156 return 0;
158 primitive->org = cpml_primitive_get_point(primitive, -1);
159 primitive->data = new_data;
161 return 1;
165 * cpml_primitive_get_npoints:
166 * @primitive: a #CpmlPrimitive
168 * Gets the number of points required to identify @primitive.
169 * It is similar to cpml_primitive_type_get_npoints() but using
170 * a @primitive instance instead of a type.
172 * Returns: the number of points or -1 on errors
175 cpml_primitive_get_npoints(const CpmlPrimitive *primitive)
177 return cpml_primitive_type_get_npoints(primitive->data->header.type);
181 * cpml_primitive_get_point:
182 * @primitive: a #CpmlPrimitive
183 * @npoint: the index of the point to retrieve
185 * Gets the specified @npoint from @primitive. The index starts
186 * at 0: if @npoint is 0, the start point (the origin) is
187 * returned, 1 for the second point and so on. If @npoint is
188 * negative, it is considered as a negative index from the end,
189 * so that -1 is the end point, -2 the point before the end point
190 * and so on.
192 * %CAIRO_PATH_CLOSE_PATH is managed in a special way: if @npoint
193 * is -1 or 1 and @primitive is a close-path, this function cycles
194 * the source #CpmlSegment and returns the first point. This is
195 * needed because requesting the end point (or the second point)
196 * of a close path is a valid operation and must returns the start
197 * of the segment.
199 * Returns: a pointer to the requested point (in cairo format)
200 * or %NULL if the point is outside the valid range
202 cairo_path_data_t *
203 cpml_primitive_get_point(const CpmlPrimitive *primitive, int npoint)
205 int npoints;
207 /* For a start point request, simply return the origin
208 * without further checking */
209 if (npoint == 0)
210 return primitive->org;
212 /* The CAIRO_PATH_CLOSE_PATH special case */
213 if (primitive->data->header.type == CAIRO_PATH_CLOSE_PATH &&
214 (npoint == 1 || npoint == -1))
215 return &primitive->segment->data[1];
217 npoints = cpml_primitive_get_npoints(primitive);
218 if (npoints < 0)
219 return NULL;
221 /* If npoint is negative, consider it as a negative index from the end */
222 if (npoint < 0)
223 npoint = npoints + npoint;
225 /* Out of range condition */
226 if (npoint < 0 || npoint >= npoints)
227 return NULL;
229 return npoint == 0 ? primitive->org : &primitive->data[npoint];
233 * cpml_primitive_to_cairo:
234 * @primitive: a #CpmlPrimitive
235 * @cr: the destination cairo context
237 * Renders a single @primitive to the @cr cairo context.
238 * As a special case, if the primitive is a #CAIRO_PATH_CLOSE_PATH,
239 * an equivalent line is rendered, because a close path left alone
240 * is not renderable.
242 * Also a #CAIRO_PATH_ARC_TO primitive is treated specially, as it
243 * is not natively supported by cairo and has its own rendering API.
245 void
246 cpml_primitive_to_cairo(const CpmlPrimitive *primitive, cairo_t *cr)
248 cairo_path_t path;
249 cairo_path_data_t *path_data;
251 cairo_move_to(cr, primitive->org->point.x, primitive->org->point.y);
253 switch (primitive->data->header.type) {
255 case CAIRO_PATH_CLOSE_PATH:
256 path_data = cpml_primitive_get_point(primitive, -1);
257 cairo_line_to(cr, path_data->point.x, path_data->point.y);
258 break;
260 case CAIRO_PATH_ARC_TO:
261 cpml_arc_to_cairo(primitive, cr);
262 break;
264 default:
265 path.status = CAIRO_STATUS_SUCCESS;
266 path.data = primitive->data;
267 path.num_data = primitive->data->header.length;
268 cairo_append_path(cr, &path);
269 break;
274 * cpml_primitive_dump:
275 * @primitive: a #CpmlPrimitive
276 * @org_also: whether to output also the origin coordinates
278 * Dumps info on the specified @primitive to stdout: useful for
279 * debugging purposes. If @org_also is 1, a %CAIRO_PATH_MOVE_TO
280 * to the origin is prepended to the data otherwise the
281 * <structfield>org</structfield> field is not used.
283 void
284 cpml_primitive_dump(const CpmlPrimitive *primitive, cairo_bool_t org_also)
286 const cairo_path_data_t *data;
287 int type, n, npoints;
289 data = primitive->data;
290 type = data->header.type;
291 npoints = cpml_primitive_get_npoints(primitive);
292 if (npoints < 0) {
293 printf("Unhandled primitive type (%d)\n", type);
294 return;
297 /* Dump the origin movement, if requested */
298 if (org_also) {
299 printf("Move to ");
300 dump_cairo_point(primitive->org);
301 printf("\n");
304 switch (type) {
306 case CAIRO_PATH_LINE_TO:
307 printf("Line to ");
308 break;
310 case CAIRO_PATH_ARC_TO:
311 printf("Arc to ");
312 break;
314 case CAIRO_PATH_CURVE_TO:
315 printf("Curve to ");
316 break;
318 case CAIRO_PATH_CLOSE_PATH:
319 printf("Path close");
320 break;
322 default:
323 printf("Unknown primitive (type = %d)", type);
324 break;
327 for (n = 1; n < npoints; ++n)
328 dump_cairo_point(cpml_primitive_get_point(primitive, n));
330 printf("\n");
334 * cpml_primitive_put_intersections_with_segment:
335 * @primitive: a #CpmlPrimitive
336 * @segment: a #CpmlSegment
337 * @dest: the destination vector of #CpmlPair
338 * @max: maximum number of intersections to return
340 * Computes the intersections between @segment and @primitive by
341 * sequentially scanning the primitives in @segment and looking
342 * for intersections with @primitive.
343 * If the intersections are more than @max, only the first @max pairs
344 * are stored in @dest.
346 * Returns: the number of intersections found
349 cpml_primitive_put_intersections_with_segment(const CpmlPrimitive *primitive,
350 const CpmlSegment *segment,
351 CpmlPair *dest, int max)
353 CpmlPrimitive portion;
354 int found;
356 cpml_primitive_from_segment(&portion, (CpmlSegment *) segment);
357 found = 0;
359 while (found < max) {
360 found += cpml_primitive_put_intersections(&portion, primitive,
361 max-found, dest+found);
362 if (!cpml_primitive_next(&portion))
363 break;
366 return found;
371 * cpml_primitive_type_get_npoints:
372 * @type: a primitive type
374 * Gets the number of points required to identify the @type primitive.
376 * <note><para>
377 * This function is primitive dependent, that is every primitive has
378 * its own implementation.
379 * </para></note>
381 * Returns: the number of points or -1 on errors
384 cpml_primitive_type_get_npoints(CpmlPrimitiveType type)
386 const _CpmlPrimitiveClass *class_data = get_class(type);
388 if (class_data == NULL)
389 return -1;
391 return class_data->n_points;
395 * cpml_primitive_get_length:
396 * @primitive: a #CpmlPrimitive
398 * Abstracts the length() family functions by providing a common
399 * way to access the underlying primitive-specific implementation.
400 * The function returns the length of @primitive.
402 * <note><para>
403 * This function is primitive dependent, that is every primitive has
404 * its own implementation.
405 * </para></note>
407 * Returns: the requested length or 0 on errors
409 double
410 cpml_primitive_get_length(const CpmlPrimitive *primitive)
412 switch (primitive->data->header.type) {
414 case CAIRO_PATH_LINE_TO:
415 case CAIRO_PATH_CLOSE_PATH:
416 return cpml_line_get_length(primitive);
418 case CAIRO_PATH_ARC_TO:
419 return cpml_arc_get_length(primitive);
421 case CAIRO_PATH_CURVE_TO:
422 return cpml_curve_get_length(primitive);
424 default:
425 break;
428 return 0.;
432 * cpml_primitive_put_extents:
433 * @primitive: a #CpmlPrimitive
434 * @extents: where to store the extents
436 * Abstracts the extents() family functions by providing a common
437 * way to access the underlying primitive-specific implementation.
438 * The function stores in @extents the bounding box of @primitive.
440 * <note><para>
441 * This function is primitive dependent, that is every primitive has
442 * its own implementation.
443 * </para></note>
445 void
446 cpml_primitive_put_extents(const CpmlPrimitive *primitive,
447 CpmlExtents *extents)
449 switch (primitive->data->header.type) {
451 case CAIRO_PATH_LINE_TO:
452 case CAIRO_PATH_CLOSE_PATH:
453 return cpml_line_put_extents(primitive, extents);
455 case CAIRO_PATH_ARC_TO:
456 return cpml_arc_put_extents(primitive, extents);
458 case CAIRO_PATH_CURVE_TO:
459 return cpml_curve_put_extents(primitive, extents);
461 default:
462 extents->is_defined = 0;
463 break;
468 * cpml_primitive_put_pair_at:
469 * @primitive: a #CpmlPrimitive
470 * @pos: the position value
471 * @pair: the destination #CpmlPair
473 * Abstracts the put_pair_at() family functions by providing a common
474 * way to access the underlying primitive-specific implementation.
476 * It gets the coordinates of the point lying on @primitive
477 * at position @pos. @pos is an homogeneous factor where 0 is the
478 * start point, 1 the end point, 0.5 the mid point and so on.
479 * The relation 0 < @pos < 1 should be satisfied, although some
480 * primitives accept value outside this range.
482 * <note><para>
483 * This function is primitive dependent, that is every primitive has
484 * its own implementation.
485 * </para></note>
487 void
488 cpml_primitive_put_pair_at(const CpmlPrimitive *primitive, double pos,
489 CpmlPair *pair)
491 switch (primitive->data->header.type) {
493 case CAIRO_PATH_LINE_TO:
494 cpml_line_put_pair_at(primitive, pos, pair);
495 break;
497 case CAIRO_PATH_ARC_TO:
498 cpml_arc_put_pair_at(primitive, pos, pair);
499 break;
501 case CAIRO_PATH_CURVE_TO:
502 cpml_curve_put_pair_at(primitive, pos, pair);
503 break;
505 case CAIRO_PATH_CLOSE_PATH:
506 cpml_close_put_pair_at(primitive, pos, pair);
507 break;
509 default:
510 break;
515 * cpml_primitive_put_vector_at:
516 * @primitive: a #CpmlPrimitive
517 * @pos: the position value
518 * @vector: the destination #CpmlVector
520 * Abstracts the put_vector_at() family functions by providing a common
521 * way to access the underlying primitive-specific implementation.
523 * It gets the steepness of the point at position @pos on @primitive.
524 * @pos is an homogeneous factor where 0 is the start point, 1 the
525 * end point, 0.5 the mid point and so on.
526 * The relation 0 < @pos < 1 should be satisfied, although some
527 * primitives accept value outside this range.
529 * <note><para>
530 * This function is primitive dependent, that is every primitive has
531 * its own implementation.
532 * </para></note>
534 void
535 cpml_primitive_put_vector_at(const CpmlPrimitive *primitive, double pos,
536 CpmlVector *vector)
538 switch (primitive->data->header.type) {
540 case CAIRO_PATH_LINE_TO:
541 cpml_line_put_vector_at(primitive, pos, vector);
542 break;
544 case CAIRO_PATH_ARC_TO:
545 cpml_arc_put_vector_at(primitive, pos, vector);
546 break;
548 case CAIRO_PATH_CURVE_TO:
549 cpml_curve_put_vector_at(primitive, pos, vector);
550 break;
552 case CAIRO_PATH_CLOSE_PATH:
553 cpml_close_put_vector_at(primitive, pos, vector);
554 break;
556 default:
557 break;
562 * cpml_primitive_get_closest_pos:
563 * @primitive: a #CpmlPrimitive
564 * @pair: the coordinates of the subject point
566 * Returns the pos value of the point on @primitive nearest to @pair.
567 * The returned value is always between 0 and 1 or -1 in case of errors.
569 * <note><para>
570 * This function is primitive dependent, that is every primitive has
571 * its own implementation.
572 * </para></note>
574 * Returns: the requested pos value between 0 and 1 or -1 on errors
576 double
577 cpml_primitive_get_closest_pos(const CpmlPrimitive *primitive,
578 const CpmlPair *pair)
580 switch (primitive->data->header.type) {
582 case CAIRO_PATH_LINE_TO:
583 return cpml_line_get_closest_pos(primitive, pair);
585 case CAIRO_PATH_ARC_TO:
586 return cpml_arc_get_closest_pos(primitive, pair);
588 case CAIRO_PATH_CURVE_TO:
589 return cpml_curve_get_closest_pos(primitive, pair);
591 case CAIRO_PATH_CLOSE_PATH:
592 return cpml_close_get_closest_pos(primitive, pair);
594 default:
595 break;
598 return -1.;
602 * cpml_primitive_join:
603 * @primitive: the first #CpmlPrimitive
604 * @primitive2: the second #CpmlPrimitive
606 * Joins two primitive modifying the end point of @primitive and the
607 * start point of @primitive2 so that the resulting points will overlap.
609 * <important>
610 * <title>TODO</title>
611 * <itemizedlist>
612 * <listitem>Actually, the join is done by extending the end vector
613 * of @primitive and the start vector of @primitive2 and
614 * interpolating the intersection: this means no primitive
615 * dependent code is needed. Anyway, it is likely to change
616 * in the future because this approach is quite naive when
617 * curves are involved.</listitem>
618 * </itemizedlist>
619 * </important>
621 * Returns: 1 on success, 0 if the end vector of @primitive
622 * and the start vector of @primitive2 are parallel
624 cairo_bool_t
625 cpml_primitive_join(CpmlPrimitive *primitive, CpmlPrimitive *primitive2)
627 cairo_path_data_t *end1, *start2;
628 CpmlPrimitive line1, line2;
629 cairo_path_data_t data1[2], data2[2];
630 CpmlPair joint;
632 end1 = cpml_primitive_get_point(primitive, -1);
633 start2 = cpml_primitive_get_point(primitive2, 0);
635 /* Check if the primitives are yet connected */
636 if (end1->point.x == start2->point.x && end1->point.y == start2->point.y)
637 return 1;
639 line1.org = cpml_primitive_get_point(primitive, -2);
640 line1.data = data1;
641 data1[0].header.type = CAIRO_PATH_LINE_TO;
642 data1[1] = *end1;
644 line2.org = start2;
645 line2.data = data2;
646 data2[0].header.type = CAIRO_PATH_LINE_TO;
647 data2[1] = *cpml_primitive_get_point(primitive2, 1);
649 if (!cpml_line_put_intersections(&line1, &line2, 1, &joint))
650 return 0;
652 cpml_pair_to_cairo(&joint, end1);
653 cpml_pair_to_cairo(&joint, start2);
655 return 1;
659 * cpml_primitive_put_intersections:
660 * @primitive: the first #CpmlPrimitive
661 * @primitive2: the second #CpmlPrimitive
662 * @max: maximum number of intersections to return
663 * @dest: the destination buffer that can contain @max #CpmlPair
665 * Finds the intersection points between the given primitives and
666 * returns the result in @dest. The size of @dest should be enough
667 * to store @max #CpmlPair. The absoulte max number of intersections
668 * is dependent from the type of the primitive involved in the
669 * operation. If there are at least one Bézier curve involved, up to
670 * 4 intersections could be returned. Otherwise, if there is an arc
671 * the intersections will be 2 at maximum. For line line primitives,
672 * there is only 1 point (or obviously 0 if the lines do not intersect).
674 * <note><para>
675 * This function is primitive dependent: every new primitive must
676 * expose API to get intersections with any other primitive type
677 * (excluding %CAIRO_PATH_CLOSE_PATH, as it is converted to a line
678 * primitive).</para>
679 * <para>The convention used by CPML is that a primitive should
680 * expose only intersection APIs dealing with lower complexity
681 * primitives. This is required to avoid double functions:
682 * you will have only a cpml_curve_put_intersections_with_line()
683 * function, not a cpml_line_put_intersections_with_curve(), as
684 * the latter is easily reproduced by calling the former with
685 * @primitive2 and @primitive swapped.
686 * </para></note>
688 * Returns: the number of intersection points found or 0 if the
689 * primitives do not intersect
692 cpml_primitive_put_intersections(const CpmlPrimitive *primitive,
693 const CpmlPrimitive *primitive2,
694 int max, CpmlPair *dest)
696 CpmlPrimitiveType type1, type2;
698 type1 = primitive->data->header.type;
699 type2 = primitive->data->header.type;
701 /* Close path primitives are treated as line-to */
702 if (type1 == CAIRO_PATH_CLOSE_PATH)
703 type1 = CAIRO_PATH_LINE_TO;
704 if (type2 == CAIRO_PATH_CLOSE_PATH)
705 type2 = CAIRO_PATH_LINE_TO;
707 /* Order the two primitives in ascending complexity, to facilitate
708 * the dispatcher logic */
709 if (cpml_primitive_type_get_npoints(type1) > cpml_primitive_type_get_npoints(type2)) {
710 const CpmlPrimitive *tmp_primitive;
711 CpmlPrimitiveType tmp_type;
713 tmp_type = type1;
714 tmp_primitive = primitive;
716 type1 = type2;
717 primitive = primitive2;
719 type2 = tmp_type;
720 primitive2 = tmp_primitive;
723 /* Dispatcher: probably there's a smarter way to do this */
724 switch (type1) {
726 case CAIRO_PATH_LINE_TO:
727 if (type2 == CAIRO_PATH_LINE_TO)
728 return cpml_line_put_intersections(primitive2, primitive,
729 max, dest);
730 else if (type2 == CAIRO_PATH_ARC_TO)
731 return cpml_arc_put_intersections_with_line(primitive2, primitive,
732 max, dest);
733 else if (type2 == CAIRO_PATH_CURVE_TO)
734 return cpml_curve_put_intersections_with_line(primitive2, primitive,
735 max, dest);
736 break;
738 case CAIRO_PATH_ARC_TO:
739 if (type2 == CAIRO_PATH_ARC_TO)
740 return cpml_arc_put_intersections(primitive2, primitive,
741 max, dest);
742 else if (type2 == CAIRO_PATH_CURVE_TO)
743 return cpml_curve_put_intersections_with_arc(primitive2, primitive,
744 max, dest);
745 break;
747 case CAIRO_PATH_CURVE_TO:
748 if (type2 == CAIRO_PATH_CURVE_TO)
749 return cpml_curve_put_intersections(primitive2, primitive,
750 max, dest);
751 break;
753 default:
754 break;
757 /* Primitive combination not found */
758 return 0;
762 * cpml_primitive_offset:
763 * @primitive: a #CpmlPrimitive
764 * @offset: distance for the computed offset primitive
766 * Given a primitive, computes the same (or approximated) parallel
767 * primitive distant @offset from the original one and returns
768 * the result by changing @primitive.
770 * <note><para>
771 * This function is primitive dependent, that is every primitive has
772 * its own implementation.
773 * </para></note>
775 void
776 cpml_primitive_offset(CpmlPrimitive *primitive, double offset)
778 switch (primitive->data->header.type) {
780 case CAIRO_PATH_LINE_TO:
781 cpml_line_offset(primitive, offset);
782 break;
784 case CAIRO_PATH_ARC_TO:
785 cpml_arc_offset(primitive, offset);
786 break;
788 case CAIRO_PATH_CURVE_TO:
789 cpml_curve_offset(primitive, offset);
790 break;
792 case CAIRO_PATH_CLOSE_PATH:
793 cpml_close_offset(primitive, offset);
794 break;
796 default:
797 break;
802 static const _CpmlPrimitiveClass *
803 get_class(CpmlPrimitiveType type)
805 switch (type) {
806 case CAIRO_PATH_LINE_TO:
807 return _cpml_line_get_class();
808 case CAIRO_PATH_ARC_TO:
809 return _cpml_arc_get_class();
810 case CAIRO_PATH_CURVE_TO:
811 return _cpml_curve_get_class();
812 case CAIRO_PATH_CLOSE_PATH:
813 return _cpml_close_get_class();
814 default:
815 break;
818 return NULL;
821 static void
822 dump_cairo_point(const cairo_path_data_t *path_data)
824 printf("(%g %g) ", path_data->point.x, path_data->point.y);