1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**************************************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2009 VMware, Inc.  All Rights Reserved.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sub license, and/or sell copies of the Software, and to
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial portions
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **************************************************************************/
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "path.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "stroker.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "polygon.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "bezier.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "matrix.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "vg_context.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util_array.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "arc.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "path_utils.h"
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "paint.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "shader.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <assert.h>
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define DEBUG_PATH 0
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct path {
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_object base;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGbitfield caps;
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGboolean dirty;
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGboolean dirty_stroke;
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGPathDatatype datatype;
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat scale;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat bias;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_segments;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array * segments;
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array * control_points;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct {
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct polygon_array polygon_array;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct matrix matrix;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } fill_polys;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct {
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct path *path;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct matrix matrix;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat stroke_width;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat miter_limit;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGCapStyle cap_style;
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGJoinStyle join_style;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } stroked;
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void data_at(void **data,
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           struct path *p,
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           VGint start, VGint count,
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           VGfloat *out)
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGPathDatatype dt = p->datatype;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint end = start + count;
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat *itr = out;
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch(dt) {
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_8: {
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGbyte **bdata = (VGbyte **)data;
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = start; i < end; ++i) {
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *itr = (*bdata)[i];
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ++itr;
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *bdata += count;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_16: {
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGshort **bdata = (VGshort **)data;
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = start; i < end; ++i) {
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *itr = (*bdata)[i];
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ++itr;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *bdata += count;
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_32: {
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint **bdata = (VGint **)data;
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = start; i < end; ++i) {
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *itr = (*bdata)[i];
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ++itr;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *bdata += count;
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_F: {
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat **fdata = (VGfloat **)data;
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = start; i < end; ++i) {
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *itr = (*fdata)[i];
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ++itr;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *fdata += count;
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_assert(!"Unknown path datatype!");
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid vg_float_to_datatype(VGPathDatatype datatype,
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGubyte *common_data,
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          const VGfloat *data,
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGint num_coords)
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch(datatype) {
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_8: {
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < num_coords; ++i) {
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         common_data[i] = (VGubyte)data[i];
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_16: {
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGshort *buf = (VGshort*)common_data;
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < num_coords; ++i) {
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         buf[i] = (VGshort)data[i];
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_S_32: {
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint *buf = (VGint*)common_data;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < num_coords; ++i) {
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         buf[i] = (VGint)data[i];
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_PATH_DATATYPE_F: {
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memcpy(common_data, data, sizeof(VGfloat) * num_coords);
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_assert(!"Unknown path datatype!");
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void coords_adjust_by_scale_bias(struct path *p,
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                        void *pdata, VGint num_coords,
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                        VGfloat scale, VGfloat bias,
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                        VGPathDatatype datatype)
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords = (VGfloat *)pdata;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte *common_data = (VGubyte *)pdata;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint size_dst = size_for_datatype(datatype);
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < num_coords; ++i) {
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&coords, p, 0, 1, data);
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[0] = data[0] * scale + bias;
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vg_float_to_datatype(datatype, common_data, data, 1);
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      common_data += size_dst;
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct path * path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias,
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGint segmentCapacityHint,
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGint coordCapacityHint,
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGbitfield capabilities)
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path *path = CALLOC_STRUCT(path);
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_init_object(&path->base, vg_current_context(), VG_OBJECT_PATH);
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->caps = capabilities & VG_PATH_CAPABILITY_ALL;
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_context_add_object(vg_current_context(), &path->base);
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->datatype = dt;
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->scale = scale;
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->bias = bias;
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8));
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->control_points = array_create(size_for_datatype(dt));
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->dirty = VG_TRUE;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path->dirty_stroke = VG_TRUE;
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return path;
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void polygon_array_cleanup(struct polygon_array *polyarray)
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (polyarray->array) {
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint i;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < polyarray->array->num_elements; i++) {
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct polygon *p = ((struct polygon **) polyarray->array->data)[i];
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_destroy(p);
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      array_destroy(polyarray->array);
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polyarray->array = NULL;
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_destroy(struct path *p)
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_context_remove_object(vg_current_context(), &p->base);
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_destroy(p->segments);
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_destroy(p->control_points);
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polygon_array_cleanup(&p->fill_polys.polygon_array);
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (p->stroked.path)
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_destroy(p->stroked.path);
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(p);
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGbitfield path_capabilities(struct path *p)
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->caps;
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_set_capabilities(struct path *p, VGbitfield bf)
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->caps = (bf & VG_PATH_CAPABILITY_ALL);
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_append_data(struct path *p,
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      VGint numSegments,
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      const VGubyte * pathSegments,
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      const void * pathData)
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint old_segments = p->num_segments;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_new_coords = num_elements_for_segments(pathSegments, numSegments);
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(p->segments, pathSegments, numSegments);
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(p->control_points, pathData, num_new_coords);
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->num_segments += numSegments;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!floatsEqual(p->scale, 1.f) || !floatsEqual(p->bias, 0.f)) {
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte *coords = (VGubyte*)p->control_points->data;
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      coords_adjust_by_scale_bias(p,
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  coords + old_segments * p->control_points->datatype_size,
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  num_new_coords,
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  p->scale, p->bias, p->datatype);
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty = VG_TRUE;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty_stroke = VG_TRUE;
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGint path_num_segments(struct path *p)
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->num_segments;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void map_if_relative(VGfloat ox, VGfloat oy,
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   VGboolean relative,
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   VGfloat *x, VGfloat *y)
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (relative) {
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (x)
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *x += ox;
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (y)
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         *y += oy;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void close_polygon(struct polygon *current,
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 VGfloat sx, VGfloat sy,
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 VGfloat ox, VGfloat oy,
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 struct  matrix *matrix)
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!floatsEqual(sx, ox) ||
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       !floatsEqual(sy, oy)) {
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat x0 = sx;
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat y0 = sy;
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(matrix, x0, y0, &x0, &y0);
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polygon_vertex_append(current, x0, y0);
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void convert_path(struct path *p,
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGPathDatatype to,
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          void *dst,
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                          VGint num_coords)
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords = (VGfloat *)p->control_points->data;
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte *common_data = (VGubyte *)dst;
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint size_dst = size_for_datatype(to);
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < num_coords; ++i) {
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&coords, p, 0, 1, data);
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vg_float_to_datatype(to, common_data, data, 1);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      common_data += size_dst;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void polygon_array_calculate_bounds( struct polygon_array *polyarray )
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array *polys = polyarray->array;
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat min_x, max_x;
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat min_y, max_y;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat bounds[4];
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned i;
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(polys);
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!polys->num_elements) {
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polyarray->min_x = 0.0f;
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polyarray->min_y = 0.0f;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polyarray->max_x = 0.0f;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polyarray->max_y = 0.0f;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds);
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   min_x = bounds[0];
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   min_y = bounds[1];
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   max_x = bounds[0] + bounds[2];
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   max_y = bounds[1] + bounds[3];
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 1; i < polys->num_elements; ++i) {
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct polygon *p = (((struct polygon**)polys->data)[i]);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polygon_bounding_rect(p, bounds);
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      min_x = MIN2(min_x, bounds[0]);
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      min_y = MIN2(min_y, bounds[1]);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      max_x = MAX2(max_x, bounds[0] + bounds[2]);
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      max_y = MAX2(max_y, bounds[1] + bounds[3]);
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polyarray->min_x = min_x;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polyarray->min_y = min_y;
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polyarray->max_x = max_x;
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polyarray->max_y = max_y;
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct polygon_array * path_get_fill_polygons(struct path *p, struct matrix *matrix)
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct polygon *current = 0;
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat sx, sy, px, py, ox, oy;
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords = (VGfloat *)p->control_points->data;
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array *array;
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(data, 0, sizeof(data));
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (p->fill_polys.polygon_array.array)
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (memcmp( &p->fill_polys.matrix,
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  matrix,
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  sizeof *matrix ) == 0 && p->dirty == VG_FALSE)
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return &p->fill_polys.polygon_array;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_array_cleanup(&p->fill_polys.polygon_array);
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* an array of pointers to polygons */
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array = array_create(sizeof(struct polygon *));
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sx = sy = px = py = ox = oy = 0.f;
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (p->num_segments)
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      current = polygon_create(32);
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < p->num_segments; ++i) {
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte segment = ((VGubyte*)(p->segments->data))[i];
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint command = SEGMENT_COMMAND(segment);
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean relative = SEGMENT_ABS_REL(segment);
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(command) {
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH:
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         close_polygon(current, sx, sy, ox, oy, matrix);
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = sx;
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = sy;
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO:
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (current && polygon_vertex_count(current) > 0) {
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* add polygon */
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            close_polygon(current, sx, sy, ox, oy, matrix);
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            array_append_data(array, &current, 1);
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            current = polygon_create(32);
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[1];
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, &y0);
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         sx = x0;
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         sy = y0;
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_vertex_append(current, x0, y0);
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO:
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[1];
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, &y0);
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_vertex_append(current, x0, y0);
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_HLINE_TO:
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 1, data);
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, 0);
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_vertex_append(current, x0, y0);
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_VLINE_TO:
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 1, data);
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[0];
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, 0, &y0);
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_vertex_append(current, x0, y0);
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO: {
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 6, data);
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = data[0];
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = data[1];
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = data[2];
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = data[3];
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[4];
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[5];
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x2, &y2);
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x2;
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y2;
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, x0, y0, x1, y1,
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       x2, y2, x3, y3);
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_add_to_polygon(&bezier, current);
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_QUAD_TO: {
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 4, data);
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = data[0];
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = data[1];
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[2];
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[3];
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         { /* form a cubic out of it */
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x2 = (x3 + 2*x1) / 3.f;
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y2 = (y3 + 2*y1) / 3.f;
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x1 = (x0 + 2*x1) / 3.f;
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y1 = (y0 + 2*y1) / 3.f;
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, x0, y0, x1, y1,
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       x2, y2, x3, y3);
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_add_to_polygon(&bezier, current);
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SQUAD_TO: {
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = 2*ox-px;
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = 2*oy-py;
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[0];
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[1];
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         { /* form a cubic out of it */
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x2 = (x3 + 2*x1) / 3.f;
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y2 = (y3 + 2*y1) / 3.f;
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x1 = (x0 + 2*x1) / 3.f;
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y1 = (y0 + 2*y1) / 3.f;
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, x0, y0, x1, y1,
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     x2, y2, x3, y3);
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_add_to_polygon(&bezier, current);
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCUBIC_TO: {
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 4, data);
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = 2*ox-px;
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = 2*oy-py;
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = data[0];
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = data[1];
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[2];
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[3];
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x2, &y2);
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x2;
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y2;
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, x0, y0, x1, y1,
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              x2, y2, x3, y3);
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_add_to_polygon(&bezier, current);
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat rh, rv, rot;
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct arc arc;
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 5, data);
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0  = ox;
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0  = oy;
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rh  = data[0];
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rv  = data[1];
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rot = data[2];
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1  = data[3];
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1  = data[4];
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n",
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      x0, y0, x1, y1, rh, rv, rot);
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_init(&arc, command, x0, y0, x1, y1,
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  rh, rv, rot);
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_add_to_polygon(&arc, current,
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            matrix);
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x1;
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y1;
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         abort();
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(!"Unknown segment!");
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (current) {
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (polygon_vertex_count(current) > 0) {
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         close_polygon(current, sx, sy, ox, oy, matrix);
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         array_append_data(array, &current, 1);
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         polygon_destroy(current);
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->fill_polys.polygon_array.array = array;
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->fill_polys.matrix = *matrix;
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   polygon_array_calculate_bounds( &p->fill_polys.polygon_array );
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty = VG_FALSE;
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return &p->fill_polys.polygon_array;
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGbyte path_datatype_size(struct path *p)
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return size_for_datatype(p->datatype);
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGPathDatatype path_datatype(struct path *p)
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->datatype;
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGfloat path_scale(struct path *p)
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->scale;
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGfloat path_bias(struct path *p)
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->bias;
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGint path_num_coords(struct path *p)
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return num_elements_for_segments((VGubyte*)p->segments->data,
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    p->num_segments);
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_modify_coords(struct path *p,
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        VGint startIndex,
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        VGint numSegments,
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        const void * pathData)
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte *segments = (VGubyte*)(p->segments->data);
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint count = num_elements_for_segments(&segments[startIndex], numSegments);
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint start_cp = num_elements_for_segments(segments, startIndex);
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_change_data(p->control_points, pathData, start_cp, count);
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   coords_adjust_by_scale_bias(p,
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               ((VGubyte*)p->control_points->data) +
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               (startIndex * p->control_points->datatype_size),
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               path_num_coords(p),
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               p->scale, p->bias, p->datatype);
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty = VG_TRUE;
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty_stroke = VG_TRUE;
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_for_each_segment(struct path *path,
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           path_for_each_cb cb,
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           void *user_data)
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path_for_each_data p;
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords = (VGfloat *)path->control_points->data;
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p.coords = data;
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p.sx = p.sy = p.px = p.py = p.ox = p.oy = 0.f;
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p.user_data = user_data;
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < path->num_segments; ++i) {
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint command;
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean relative;
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      p.segment = ((VGubyte*)(path->segments->data))[i];
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      command = SEGMENT_COMMAND(p.segment);
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      relative = SEGMENT_ABS_REL(p.segment);
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(command) {
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH:
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO:
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 2, data);
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.sx = data[0];
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.sy = data[1];
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[0];
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[1];
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO:
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 2, data);
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[0];
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[1];
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_HLINE_TO:
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 1, data);
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], 0);
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.segment = VG_LINE_TO;
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data[1] = p.oy;
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[0];
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[1];
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_VLINE_TO:
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 1, data);
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, 0, &data[0]);
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.segment = VG_LINE_TO;
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data[1] = data[0];
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data[0] = p.ox;
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[0];
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[1];
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO: {
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 6, data);
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[4], &data[5]);
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[2];
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[3];
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[4];
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[5];
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_QUAD_TO: {
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 4, data);
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[2];
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[3];
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SQUAD_TO: {
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 2, data);
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = 2*p.ox-p.px;
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = 2*p.oy-p.py;
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[2];
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[3];
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCUBIC_TO: {
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 4, data);
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]);
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]);
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[0];
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[1];
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[2];
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[3];
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, path, 0, 5, data);
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(p.ox, p.oy, relative, &data[3], &data[4]);
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n",
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      p.ox, p.oy, data[3], data[4], data[0], data[1], data[2]);
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         cb(path, &p);
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.ox = data[3];
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.oy = data[4];
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.px = data[3];
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p.py = data[4];
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         abort();
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(!"Unknown segment!");
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct transform_data {
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array *segments;
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct array *coords;
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct matrix *matrix;
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGPathDatatype datatype;
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic VGboolean transform_cb(struct path *p,
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              struct path_for_each_data *pd)
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct transform_data *td = (struct transform_data *)pd->user_data;
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_coords = num_elements_for_segments(&pd->segment, 1);
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte segment = SEGMENT_COMMAND(pd->segment);/* abs bit is 0 */
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte common_data[sizeof(VGfloat)*8];
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(data, pd->coords, sizeof(VGfloat) * num_coords);
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch(segment) {
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CLOSE_PATH:
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_MOVE_TO:
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LINE_TO:
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_HLINE_TO:
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_VLINE_TO:
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_QUAD_TO:
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[2], data[3], &data[2], &data[3]);
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CUBIC_TO:
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[2], data[3], &data[2], &data[3]);
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[4], data[5], &data[4], &data[5]);
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SQUAD_TO:
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCUBIC_TO:
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[0], data[1], &data[0], &data[1]);
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_map_point(td->matrix,
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       data[2], data[3], &data[2], &data[3]);
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCCWARC_TO:
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCWARC_TO:
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCCWARC_TO:
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCWARC_TO: {
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct arc arc;
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct path *path = path_create(td->datatype,
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                      1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      arc_init(&arc, segment,
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               pd->ox, pd->oy, data[3], data[4],
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               data[0], data[1], data[2]);
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      arc_to_path(&arc, path, td->matrix);
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      num_coords = path_num_coords(path);
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      array_append_data(td->segments, path->segments->data,
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        path->num_segments);
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      array_append_data(td->coords, path->control_points->data,
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        num_coords);
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_destroy(path);
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_TRUE;
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_float_to_datatype(td->datatype, common_data, data, num_coords);
896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(td->segments, &pd->segment, 1);
898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(td->coords, common_data, num_coords);
899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return VG_TRUE;
900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_transform(struct path *dst, struct path *src)
903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct transform_data data;
905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_context *ctx = dst->base.ctx;
906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data.segments =  dst->segments;
908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data.coords   =  dst->control_points;
909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data.matrix   = &ctx->state.vg.path_user_to_surface_matrix;
910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data.datatype = dst->datatype;
911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_for_each_segment(src, transform_cb, (void*)&data);
913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->num_segments = dst->segments->num_elements;
915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty = VG_TRUE;
916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty_stroke = VG_TRUE;
917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_append_path(struct path *dst,
920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      struct path *src)
921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_coords = path_num_coords(src);
923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *dst_data = malloc(size_for_datatype(dst->datatype) * num_coords);
924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(dst->segments,
925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     src->segments->data,
926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     src->num_segments);
927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   convert_path(src, dst->datatype,
928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                dst_data, num_coords);
929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_append_data(dst->control_points,
930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     dst_data,
931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     num_coords);
932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(dst_data);
933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->num_segments += src->num_segments;
935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty = VG_TRUE;
936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty_stroke = VG_TRUE;
937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE VGboolean is_segment_arc(VGubyte segment)
940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte scommand = SEGMENT_COMMAND(segment);
942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return (scommand == VG_SCCWARC_TO ||
943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           scommand == VG_SCWARC_TO ||
944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           scommand == VG_LCCWARC_TO ||
945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           scommand == VG_LCWARC_TO);
946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct path_iter_data {
949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path *path;
950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte segment;
951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords;
952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat px, py, ox, oy, sx, sy;
953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE VGubyte normalize_coords(struct path_iter_data *pd,
955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       VGint *num_coords,
956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       VGfloat *data)
957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint command = SEGMENT_COMMAND(pd->segment);
959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGboolean relative = SEGMENT_ABS_REL(pd->segment);
960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch(command) {
962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CLOSE_PATH:
963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 0;
964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = pd->sx;
965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = pd->sy;
966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_CLOSE_PATH;
967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_MOVE_TO:
969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 2, data);
970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->sx = data[0];
972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->sy = data[1];
973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[0];
974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[1];
975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[0];
976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[1];
977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 2;
978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_MOVE_TO_ABS;
979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LINE_TO:
981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 2, data);
982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[0];
984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[1];
985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[0];
986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[1];
987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 2;
988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_LINE_TO_ABS;
989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_HLINE_TO:
991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 1, data);
992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[0], 0);
993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[1] = pd->oy;
994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[0];
995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[1];
996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[0];
997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[1];
998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 2;
999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_LINE_TO_ABS;
1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_VLINE_TO:
1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 1, data);
1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, 0, &data[0]);
1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[1] = data[0];
1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[0] = pd->ox;
1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[0];
1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[1];
1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[0];
1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[1];
1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 2;
1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_LINE_TO_ABS;
1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CUBIC_TO: {
1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 6, data);
1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]);
1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[2], &data[3]);
1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[4], &data[5]);
1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[2];
1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[3];
1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[4];
1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[5];
1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 6;
1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_CUBIC_TO_ABS;
1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_QUAD_TO: {
1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 4, data);
1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x0 = pd->ox;
1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y0 = pd->oy;
1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x1 = data[0];
1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y1 = data[1];
1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x3 = data[2];
1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y3 = data[3];
1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &x1, &y1);
1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = x1;
1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = y1;
1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { /* form a cubic out of it */
1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = (x3 + 2*x1) / 3.f;
1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = (y3 + 2*y1) / 3.f;
1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = (x0 + 2*x1) / 3.f;
1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = (y0 + 2*y1) / 3.f;
1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = x3;
1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = y3;
1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[0] = x1;
1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[1] = y1;
1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[2] = x2;
1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[3] = y2;
1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[4] = x3;
1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[5] = y3;
1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 6;
1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_CUBIC_TO_ABS;
1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SQUAD_TO: {
1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 2, data);
1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x0 = pd->ox;
1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y0 = pd->oy;
1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x1 = 2 * pd->ox - pd->px;
1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y1 = 2 * pd->oy - pd->py;
1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x3 = data[0];
1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y3 = data[1];
1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = x1;
1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = y1;
1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      { /* form a cubic out of it */
1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = (x3 + 2*x1) / 3.f;
1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = (y3 + 2*y1) / 3.f;
1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = (x0 + 2*x1) / 3.f;
1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = (y0 + 2*y1) / 3.f;
1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = x3;
1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = y3;
1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[0] = x1;
1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[1] = y1;
1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[2] = x2;
1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[3] = y2;
1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[4] = x3;
1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[5] = y3;
1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 6;
1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_CUBIC_TO_ABS;
1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCUBIC_TO: {
1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 4, data);
1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x0 = pd->ox;
1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y0 = pd->oy;
1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x1 = 2*pd->ox-pd->px;
1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y1 = 2*pd->oy-pd->py;
1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x2 = data[0];
1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y2 = data[1];
1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      x3 = data[2];
1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      y3 = data[3];
1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &x2, &y2);
1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &x3, &y3);
1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = x3;
1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = y3;
1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = x2;
1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = y2;
1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[0] = x1;
1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[1] = y1;
1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[2] = x2;
1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[3] = y2;
1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[4] = x3;
1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data[5] = y3;
1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 6;
1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return VG_CUBIC_TO_ABS;
1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCCWARC_TO:
1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCWARC_TO:
1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCCWARC_TO:
1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCWARC_TO: {
1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      data_at(&pd->coords, pd->path, 0, 5, data);
1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      map_if_relative(pd->ox, pd->oy, relative, &data[3], &data[4]);
1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->ox = data[3];
1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->oy = data[4];
1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->px = data[3];
1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      pd->py = data[4];
1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *num_coords = 5;
1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return command | VG_ABSOLUTE;
1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
1129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      abort();
1130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(!"Unknown segment!");
1131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void linearly_interpolate(VGfloat *result,
1135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 const VGfloat *start,
1136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 const VGfloat *end,
1137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 VGfloat amount,
1138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 VGint number)
1139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < number; ++i) {
1142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      result[i] = start[i] + (end[i] - start[i]) * amount;
1143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGboolean path_interpolate(struct path *dst,
1147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           struct path *start, struct path *end,
1148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           VGfloat amount)
1149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* temporary path that we can discard if it will turn
1151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * out that start is not compatible with end */
1152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path *res_path = path_create(dst->datatype,
1153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       1.0, 0.0,
1154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       0, 0, dst->caps);
1155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat start_coords[8];
1157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat end_coords[8];
1158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat results[8];
1159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte common_data[sizeof(VGfloat)*8];
1160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path_iter_data start_iter, end_iter;
1161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&start_iter, 0, sizeof(struct path_iter_data));
1163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&end_iter, 0, sizeof(struct path_iter_data));
1164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   start_iter.path = start;
1166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   start_iter.coords = start->control_points->data;
1167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   end_iter.path = end;
1168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   end_iter.coords = end->control_points->data;
1169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < start->num_segments; ++i) {
1171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte segment;
1172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte ssegment, esegment;
1173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint snum_coords, enum_coords;
1174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      start_iter.segment = ((VGubyte*)(start->segments->data))[i];
1175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      end_iter.segment = ((VGubyte*)(end->segments->data))[i];
1176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ssegment = normalize_coords(&start_iter, &snum_coords,
1178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  start_coords);
1179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      esegment = normalize_coords(&end_iter, &enum_coords,
1180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  end_coords);
1181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (is_segment_arc(ssegment)) {
1183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!is_segment_arc(esegment)) {
1184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            path_destroy(res_path);
1185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return VG_FALSE;
1186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (amount > 0.5)
1188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            segment = esegment;
1189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         else
1190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            segment = ssegment;
1191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (is_segment_arc(esegment)) {
1192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_destroy(res_path);
1193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_FALSE;
1194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (ssegment != esegment) {
1196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_destroy(res_path);
1197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_FALSE;
1198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
1200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         segment = ssegment;
1201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linearly_interpolate(results, start_coords, end_coords,
1203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           amount, snum_coords);
1204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      vg_float_to_datatype(dst->datatype, common_data, results, snum_coords);
1205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_append_data(res_path, 1, &segment, common_data);
1206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_append_path(dst, res_path);
1209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_destroy(res_path);
1210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty = VG_TRUE;
1212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   dst->dirty_stroke = VG_TRUE;
1213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return VG_TRUE;
1215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_clear(struct path *p, VGbitfield capabilities)
1218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_set_capabilities(p, capabilities);
1220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_destroy(p->segments);
1221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   array_destroy(p->control_points);
1222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8));
1223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->control_points = array_create(size_for_datatype(p->datatype));
1224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->num_segments = 0;
1225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty = VG_TRUE;
1226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty_stroke = VG_TRUE;
1227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct path * path_create_stroke(struct path *p,
1230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 struct matrix *matrix)
1231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat sx, sy, px, py, ox, oy;
1234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
1235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[8];
1236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *coords = (VGfloat *)p->control_points->data;
1237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int dashed = (p->base.ctx->state.vg.stroke.dash_pattern_num ? 1 : 0);
1238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct dash_stroker stroker;
1239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_state *vg_state = &p->base.ctx->state.vg;
1240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (p->stroked.path)
1242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* ### compare the dash patterns to see if we can cache them.
1244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     for now we simply always bail out if the path is dashed.
1245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (memcmp( &p->stroked.matrix,
1247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  matrix,
1248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  sizeof *matrix ) == 0 &&
1249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          !dashed && !p->dirty_stroke &&
1250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          floatsEqual(p->stroked.stroke_width, vg_state->stroke.line_width.f) &&
1251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          floatsEqual(p->stroked.miter_limit, vg_state->stroke.miter_limit.f) &&
1252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          p->stroked.cap_style == vg_state->stroke.cap_style &&
1253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          p->stroked.join_style == vg_state->stroke.join_style)
1254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
1255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return p->stroked.path;
1256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
1258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_destroy( p->stroked.path );
1259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         p->stroked.path = NULL;
1260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sx = sy = px = py = ox = oy = 0.f;
1265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (dashed)
1267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dash_stroker_init((struct stroker *)&stroker, vg_state);
1268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
1269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stroker_init((struct stroker *)&stroker, vg_state);
1270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stroker_begin((struct stroker *)&stroker);
1272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < p->num_segments; ++i) {
1274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte segment = ((VGubyte*)(p->segments->data))[i];
1275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGint command = SEGMENT_COMMAND(segment);
1276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean relative = SEGMENT_ABS_REL(segment);
1277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(command) {
1279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH: {
1280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            VGfloat x0 = sx;
1281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            VGfloat y0 = sy;
1282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x0, y0, &x0, &y0);
1283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x0, y0);
1284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO:
1287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
1288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
1289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[1];
1290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, &y0);
1291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         sx = x0;
1292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         sy = y0;
1293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
1294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
1295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
1296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
1297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_move_to((struct stroker *)&stroker, x0, y0);
1299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO:
1301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
1302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
1303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[1];
1304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, &y0);
1305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
1306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
1307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
1308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
1309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_line_to((struct stroker *)&stroker, x0, y0);
1311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_HLINE_TO:
1313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 1, data);
1314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = data[0];
1315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
1316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x0, 0);
1317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x0;
1318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
1319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
1320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_line_to((struct stroker *)&stroker, x0, y0);
1322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_VLINE_TO:
1324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 1, data);
1325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
1326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = data[0];
1327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, 0, &y0);
1328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y0;
1329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x0;
1330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y0;
1331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_line_to((struct stroker *)&stroker, x0, y0);
1333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO: {
1335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 6, data);
1336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
1337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
1338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = data[0];
1339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = data[1];
1340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = data[2];
1341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = data[3];
1342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[4];
1343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[5];
1344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
1345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x2, &y2);
1346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
1347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
1348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
1349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
1350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /*ignore the empty segment */
1351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
1353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* if dup vertex, emit a line */
1354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ox = x3;
1355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            oy = y3;
1356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x3, y3, &x3, &y3);
1357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x3, y3);
1358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
1361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
1362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x2;
1363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y2;
1364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
1365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
1367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
1368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
1369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
1370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_QUAD_TO: {
1373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 4, data);
1374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
1375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
1376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = data[0];
1377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = data[1];
1378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[2];
1379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[3];
1380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
1381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
1382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
1383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
1384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         { /* form a cubic out of it */
1385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x2 = (x3 + 2*x1) / 3.f;
1386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y2 = (y3 + 2*y1) / 3.f;
1387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x1 = (x0 + 2*x1) / 3.f;
1388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y1 = (y0 + 2*y1) / 3.f;
1389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
1391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
1392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
1393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /*ignore the empty segment */
1394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
1396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* if dup vertex, emit a line */
1397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ox = x3;
1398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            oy = y3;
1399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x3, y3, &x3, &y3);
1400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x3, y3);
1401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
1404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
1405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
1406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
1408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
1409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
1410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
1411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SQUAD_TO: {
1414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 2, data);
1415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
1416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
1417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = 2*ox-px;
1418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = 2*oy-py;
1419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[0];
1420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[1];
1421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
1422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
1423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
1424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         { /* form a cubic out of it */
1425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x2 = (x3 + 2*x1) / 3.f;
1426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y2 = (y3 + 2*y1) / 3.f;
1427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            x1 = (x0 + 2*x1) / 3.f;
1428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            y1 = (y0 + 2*y1) / 3.f;
1429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
1431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
1432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
1433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /*ignore the empty segment */
1434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
1436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* if dup vertex, emit a line */
1437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ox = x3;
1438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            oy = y3;
1439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x3, y3, &x3, &y3);
1440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x3, y3);
1441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
1444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
1445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
1446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
1448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
1449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
1450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
1451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCUBIC_TO: {
1454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 4, data);
1455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0 = ox;
1456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0 = oy;
1457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1 = 2*ox-px;
1458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1 = 2*oy-py;
1459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x2 = data[0];
1460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y2 = data[1];
1461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x3 = data[2];
1462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y3 = data[3];
1463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x2, &y2);
1464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x3, &y3);
1465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (floatsEqual(x1, ox) && floatsEqual(y1, oy) &&
1466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x1, x2) && floatsEqual(y1, y2) &&
1467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             floatsEqual(x2, x3) && floatsEqual(y2, y3)) {
1468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /*ignore the empty segment */
1469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) {
1471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* if dup vertex, emit a line */
1472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ox = x3;
1473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            oy = y3;
1474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x3, y3, &x3, &y3);
1475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x3, y3);
1476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x3;
1479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y3;
1480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x2;
1481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y2;
1482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(matrix_is_affine(matrix));
1483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x0, y0, &x0, &y0);
1484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x1, y1, &x1, &y1);
1485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x2, y2, &x2, &y2);
1486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_map_point(matrix, x3, y3, &x3, &y3);
1487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3);
1488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
1491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
1492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
1493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
1494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat rh, rv, rot;
1495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct arc arc;
1496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         data_at(&coords, p, 0, 5, data);
1498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x0  = ox;
1499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y0  = oy;
1500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rh  = data[0];
1501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rv  = data[1];
1502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         rot = data[2];
1503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         x1  = data[3];
1504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         y1  = data[4];
1505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         map_if_relative(ox, oy, relative, &x1, &y1);
1506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (floatsEqual(x1, ox) && floatsEqual(y1, oy)) {
1507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* if dup vertex, emit a line */
1508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ox = x1;
1509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            oy = y1;
1510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            matrix_map_point(matrix, x1, y1, &x1, &y1);
1511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            stroker_line_to((struct stroker *)&stroker, x1, y1);
1512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_init(&arc, command, x0, y0, x1, y1,
1515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  rh, rv, rot);
1516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_stroke_cb(&arc, (struct stroker *)&stroker,
1517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                       matrix);
1518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ox = x1;
1519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         oy = y1;
1520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         px = x1;
1521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         py = y1;
1522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
1525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         abort();
1526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(!"Unknown segment!");
1527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stroker_end((struct stroker *)&stroker);
1531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (dashed)
1533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dash_stroker_cleanup((struct dash_stroker *)&stroker);
1534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
1535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stroker_cleanup((struct stroker *)&stroker);
1536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.path = stroker.base.path;
1538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.matrix = *matrix;
1539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->dirty_stroke = VG_FALSE;
1540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.stroke_width = vg_state->stroke.line_width.f;
1541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.miter_limit = vg_state->stroke.miter_limit.f;
1542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.cap_style = vg_state->stroke.cap_style;
1543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   p->stroked.join_style = vg_state->stroke.join_style;
1544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return stroker.base.path;
1546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_render(struct path *p, VGbitfield paintModes,
1549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 struct matrix *mat)
1550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_context *ctx = vg_current_context();
1552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct matrix paint_matrix;
1553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_validate_state(ctx);
1555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shader_set_drawing_image(ctx->shader, VG_FALSE);
1557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shader_set_image(ctx->shader, 0);
1558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
1559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   fprintf(stderr, "Matrix(11=%f 12=%f 13=%f 21=%f 22=%f 23=%f 31=%f 32=%f 33=%f)\n",
1560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           mat->m[0], mat->m[1], mat->m[2],
1561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           mat->m[3], mat->m[4], mat->m[5],
1562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           mat->m[6], mat->m[7], mat->m[8]);
1563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
1564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((paintModes & VG_FILL_PATH) &&
1565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       vg_get_paint_matrix(ctx,
1566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &ctx->state.vg.fill_paint_to_user_matrix,
1567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           mat,
1568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &paint_matrix)) {
1569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* First the fill */
1570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_surface_matrix(ctx->shader, mat);
1571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
1572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_paint_matrix(ctx->shader, &paint_matrix);
1573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_bind(ctx->shader);
1574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_fill(p);
1575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((paintModes & VG_STROKE_PATH) &&
1578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       vg_get_paint_matrix(ctx,
1579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &ctx->state.vg.stroke_paint_to_user_matrix,
1580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           mat,
1581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           &paint_matrix)) {
1582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* 8.7.5: "line width less than or equal to 0 prevents stroking from
1583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *  taking place."*/
1584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->state.vg.stroke.line_width.f <= 0)
1585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
1586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_surface_matrix(ctx->shader, mat);
1587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint);
1588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_set_paint_matrix(ctx->shader, &paint_matrix);
1589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      shader_bind(ctx->shader);
1590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_stroke(p);
1591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_fill(struct path *p)
1595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_context *ctx = vg_current_context();
1597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct matrix identity;
1598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   matrix_load_identity(&identity);
1600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct polygon_array *polygon_array = path_get_fill_polygons(p, &identity);
1603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct array *polys = polygon_array->array;
1604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!polygon_array || !polys || !polys->num_elements) {
1606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
1607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      polygon_array_fill(polygon_array, ctx);
1609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_stroke(struct path *p)
1613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vg_context *ctx = vg_current_context();
1615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGFillRule old_fill = ctx->state.vg.fill_rule;
1616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct matrix identity;
1617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path *stroke;
1618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   matrix_load_identity(&identity);
1620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stroke = path_create_stroke(p, &identity);
1621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (stroke && !path_is_empty(stroke)) {
1622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->state.vg.fill_rule = VG_NON_ZERO;
1623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      path_fill(stroke);
1625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->state.vg.fill_rule = old_fill;
1627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_move_to(struct path *p, float x, float y)
1631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte segment = VG_MOVE_TO_ABS;
1633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte common_data[sizeof(VGfloat) * 2];
1634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[2] = {x, y};
1635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_float_to_datatype(p->datatype, common_data, data, 2);
1637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_append_data(p, 1, &segment, common_data);
1638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_line_to(struct path *p, float x, float y)
1641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte segment = VG_LINE_TO_ABS;
1643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte common_data[sizeof(VGfloat) * 2];
1644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[2] = {x, y};
1645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_float_to_datatype(p->datatype, common_data, data, 2);
1647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_append_data(p, 1, &segment, common_data);
1649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_cubic_to(struct path *p, float px1, float py1,
1652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   float px2, float py2,
1653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   float x, float y)
1654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte segment = VG_CUBIC_TO_ABS;
1656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGubyte common_data[sizeof(VGfloat) * 6];
1657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat data[6];
1658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data[0] = px1; data[1] = py1;
1660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data[2] = px2; data[3] = py2;
1661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   data[4] = x;   data[5] = y;
1662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vg_float_to_datatype(p->datatype, common_data, data, 6);
1664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   path_append_data(p, 1, &segment, common_data);
1666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void line_bounds(VGfloat *line /*x1,y1,x2,y2*/,
1669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               VGfloat *bounds)
1670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[0] = MIN2(line[0], line[2]);
1672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[1] = MIN2(line[1], line[3]);
1673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[2] = MAX2(line[0], line[2]) - bounds[0];
1674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[3] = MAX2(line[1], line[3]) - bounds[1];
1675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void unite_bounds(VGfloat *bounds,
1678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                VGfloat *el)
1679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat cx1, cy1, cx2, cy2;
1681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat nx1, ny1, nx2, ny2;
1682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   cx1 = bounds[0];
1684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   cy1 = bounds[1];
1685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   cx2 = bounds[0] + bounds[2];
1686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   cy2 = bounds[1] + bounds[3];
1687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   nx1 = el[0];
1689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ny1 = el[1];
1690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   nx2 = el[0] + el[2];
1691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ny2 = el[1] + el[3];
1692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[0] = MIN2(cx1, nx1);
1694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[1] = MIN2(cy1, ny1);
1695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[2] = MAX2(cx2, nx2) - bounds[0];
1696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bounds[3] = MAX2(cy2, ny2) - bounds[1];
1697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE void set_bounds(VGfloat *bounds,
1700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              VGfloat *element_bounds,
1701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              VGboolean *initialized)
1702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!(*initialized)) {
1704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memcpy(bounds, element_bounds, 4 * sizeof(VGfloat));
1705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *initialized = VG_TRUE;
1706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else
1707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unite_bounds(bounds, element_bounds);
1708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_bounding_rect(struct path *p, float *x, float *y,
1711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        float *w, float *h)
1712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat coords[8];
1715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path_iter_data iter;
1716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_coords;
1717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat bounds[4];
1718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat element_bounds[4];
1719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat ox, oy;
1720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGboolean bounds_inited = VG_FALSE;
1721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&iter, 0, sizeof(struct path_iter_data));
1723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&bounds, 0, sizeof(bounds));
1724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!p->num_segments) {
1726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      bounds[2] = -1;
1727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      bounds[3] = -1;
1728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.path = p;
1732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.coords = p->control_points->data;
1733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < p->num_segments; ++i) {
1735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte segment;
1736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      iter.segment = ((VGubyte*)(p->segments->data))[i];
1737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ox = iter.ox;
1739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      oy = iter.oy;
1740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      segment = normalize_coords(&iter, &num_coords, coords);
1742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(segment) {
1744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH:
1745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO_ABS:
1746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO_ABS: {
1748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat line[4] = {ox, oy, coords[0], coords[1]};
1749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_bounds(line, element_bounds);
1750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         set_bounds(bounds, element_bounds, &bounds_inited);
1751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO_ABS: {
1754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
1755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, ox, oy,
1756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[0], coords[1],
1757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[2], coords[3],
1758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[4], coords[5]);
1759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_exact_bounds(&bezier, element_bounds);
1760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         set_bounds(bounds, element_bounds, &bounds_inited);
1761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
1764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
1765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
1766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
1767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct arc arc;
1768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct matrix identity;
1769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct path *path = path_create(VG_PATH_DATATYPE_F,
1770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
1771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_load_identity(&identity);
1773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_init(&arc, segment,
1774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  ox, oy, coords[3], coords[4],
1775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[0], coords[1], coords[2]);
1776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_to_path(&arc, path, &identity);
1778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_bounding_rect(path, element_bounds + 0, element_bounds + 1,
1780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            element_bounds + 2, element_bounds + 3);
1781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         set_bounds(bounds, element_bounds, &bounds_inited);
1782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
1785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(0);
1786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *x = bounds[0];
1790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *y = bounds[1];
1791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *w = bounds[2];
1792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *h = bounds[3];
1793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfloat path_length(struct path *p, int start_segment, int num_segments)
1796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat coords[8];
1799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path_iter_data iter;
1800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_coords;
1801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat length = 0;
1802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat ox, oy;
1803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGboolean in_range = VG_FALSE;
1804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&iter, 0, sizeof(struct path_iter_data));
1806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.path = p;
1808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.coords = p->control_points->data;
1809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < (start_segment + num_segments); ++i) {
1811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGubyte segment;
1812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      iter.segment = ((VGubyte*)(p->segments->data))[i];
1814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ox = iter.ox;
1816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      oy = iter.oy;
1817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      segment = normalize_coords(&iter, &num_coords, coords);
1819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      in_range = (i >= start_segment) && i <= (start_segment + num_segments);
1821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!in_range)
1822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
1823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch(segment) {
1825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO_ABS:
1826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH: {
1828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat line[4] = {ox, oy, iter.sx, iter.sy};
1829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         length += line_lengthv(line);
1830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO_ABS: {
1833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat line[4] = {ox, oy, coords[0], coords[1]};
1834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         length += line_lengthv(line);
1835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO_ABS: {
1838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
1839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, ox, oy,
1840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[0], coords[1],
1841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[2], coords[3],
1842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[4], coords[5]);
1843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         length += bezier_length(&bezier, BEZIER_DEFAULT_ERROR);
1844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
1847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
1848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
1849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
1850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct arc arc;
1851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct matrix identity;
1852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct path *path = path_create(VG_PATH_DATATYPE_F,
1853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
1854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_load_identity(&identity);
1856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_init(&arc, segment,
1857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  ox, oy, coords[3], coords[4],
1858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[0], coords[1], coords[2]);
1859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_to_path(&arc, path, &identity);
1861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         length += path_length(path, 0, path_num_segments(path));
1863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
1865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
1866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(0);
1867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return length;
1871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE VGboolean point_on_current_segment(VGfloat distance,
1874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                 VGfloat length,
1875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                 VGfloat segment_length)
1876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return
1878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      (((floatIsZero(distance) || distance < 0) && floatIsZero(length)) ||
1879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ((distance > length || floatsEqual(distance, length)) &&
1880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        (floatsEqual(distance, length + segment_length) ||
1881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         distance < (length + segment_length))));
1882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic VGboolean path_point_segment(struct path_iter_data iter,
1885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    struct path_iter_data prev_iter,
1886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    VGfloat coords[8],
1887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    VGfloat distance,
1888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    VGfloat length, VGfloat *current_length,
1889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    VGfloat *point, VGfloat *normal)
1890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (iter.segment) {
1892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_MOVE_TO_ABS:
1893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CLOSE_PATH: {
1895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy};
1896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean on_current_segment = VG_FALSE;
1897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *current_length = line_lengthv(line);
1898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      on_current_segment = point_on_current_segment(distance,
1899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    length,
1900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    *current_length);
1901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (on_current_segment) {
1902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat at = (distance - length) / line_lengthv(line);
1903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_normal_vector(line, normal);
1904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_point_at(line, at, point);
1905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_TRUE;
1906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LINE_TO_ABS: {
1910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]};
1911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean on_current_segment = VG_FALSE;
1912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *current_length = line_lengthv(line);
1913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      on_current_segment = point_on_current_segment(distance,
1914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    length,
1915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    *current_length);
1916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (on_current_segment) {
1917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat at = (distance - length) / line_lengthv(line);
1918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_normal_vector(line, normal);
1919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_point_at(line, at, point);
1920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_TRUE;
1921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_CUBIC_TO_ABS: {
1925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct bezier bezier;
1926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      bezier_init(&bezier, prev_iter.ox, prev_iter.oy,
1927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[0], coords[1],
1928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[2], coords[3],
1929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[4], coords[5]);
1930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *current_length = bezier_length(&bezier, BEZIER_DEFAULT_ERROR);
1931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (point_on_current_segment(distance, length, *current_length)) {
1932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_point_at_length(&bezier, distance - length,
1933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                point, normal);
1934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_TRUE;
1935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCCWARC_TO:
1939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_SCWARC_TO:
1940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCCWARC_TO:
1941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case VG_LCWARC_TO: {
1942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct arc arc;
1943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct matrix identity;
1944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct path *path = path_create(VG_PATH_DATATYPE_F,
1945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                      1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
1946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      matrix_load_identity(&identity);
1948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      arc_init(&arc, iter.segment,
1949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               prev_iter.ox, prev_iter.oy, coords[3], coords[4],
1950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               coords[0], coords[1], coords[2]);
1951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      arc_to_path(&arc, path, &identity);
1953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *current_length = path_length(path, 0, path_num_segments(path));
1955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (point_on_current_segment(distance, length, *current_length)) {
1956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_point(path, 0, path_num_segments(path),
1957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    distance - length, point, normal);
1958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return VG_TRUE;
1959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
1962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
1963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(0);
1964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return VG_FALSE;
1966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid path_point(struct path *p, VGint start_segment, VGint num_segments,
1969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                VGfloat distance, VGfloat *point, VGfloat *normal)
1970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint i;
1972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat coords[8];
1973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct path_iter_data iter, prev_iter;
1974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGint num_coords;
1975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat length = 0;
1976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VGfloat current_length = 0;
1977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&iter, 0, sizeof(struct path_iter_data));
1979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&prev_iter, 0, sizeof(struct path_iter_data));
1980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   point[0] = 0;
1982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   point[1] = 0;
1983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   normal[0] = 0;
1985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   normal[1] = -1;
1986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.path = p;
1988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   iter.coords = p->control_points->data;
1989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (distance < 0)
1990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      distance = 0;
1991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < (start_segment + num_segments); ++i) {
1993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      VGboolean outside_range = (i < start_segment ||
1994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 i >= (start_segment + num_segments));
1995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prev_iter = iter;
1997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      iter.segment = ((VGubyte*)(p->segments->data))[i];
1999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      iter.segment = normalize_coords(&iter, &num_coords, coords);
2000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (outside_range)
2002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
2003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (path_point_segment(iter, prev_iter, coords,
2005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             distance, length, &current_length,
2006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             point, normal))
2007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return;
2008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      length += current_length;
2010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /*
2013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *OpenVG 1.0 - 8.6.11 vgPointAlongPath
2014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
2015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * If distance is greater than or equal to the path length
2016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *(i.e., the value returned by vgPathLength when called with the same
2017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *startSegment and numSegments parameters), the visual ending point of
2018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *the path is used.
2019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
2021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (iter.segment) {
2022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_MOVE_TO_ABS:
2023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
2024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CLOSE_PATH: {
2025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy};
2026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_normal_vector(line, normal);
2027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_point_at(line, 1.f, point);
2028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
2030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LINE_TO_ABS: {
2031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]};
2032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_normal_vector(line, normal);
2033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         line_point_at(line, 1.f, point);
2034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
2036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_CUBIC_TO_ABS: {
2037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct bezier bezier;
2038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_init(&bezier, prev_iter.ox, prev_iter.oy,
2039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[0], coords[1],
2040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[2], coords[3],
2041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     coords[4], coords[5]);
2042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         bezier_point_at_t(&bezier, 1.f, point, normal);
2043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
2045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCCWARC_TO:
2046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_SCWARC_TO:
2047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCCWARC_TO:
2048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case VG_LCWARC_TO: {
2049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct arc arc;
2050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct matrix identity;
2051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         struct path *path = path_create(VG_PATH_DATATYPE_F,
2052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         1, 0, 0, 0, VG_PATH_CAPABILITY_ALL);
2053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         matrix_load_identity(&identity);
2055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_init(&arc, iter.segment,
2056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  prev_iter.ox, prev_iter.oy, coords[3], coords[4],
2057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  coords[0], coords[1], coords[2]);
2058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         arc_to_path(&arc, path, &identity);
2060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         path_point(path, 0, path_num_segments(path),
2062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    /* to make sure we're bigger than len * 2 it */
2063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    2 * path_length(path, 0, path_num_segments(path)),
2064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    point, normal);
2065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         break;
2067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
2068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(0);
2069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgVGboolean path_is_empty(struct path *p)
2074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return p->segments->num_elements == 0;
2076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2077