1544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/************************************************************************** 2544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 3544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Copyright 2009 VMware, Inc. All Rights Reserved. 4544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 5544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * Permission is hereby granted, free of charge, to any person obtaining a 6544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * copy of this software and associated documentation files (the 7544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * "Software"), to deal in the Software without restriction, including 8544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * without limitation the rights to use, copy, modify, merge, publish, 9544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * distribute, sub license, and/or sell copies of the Software, and to 10544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * permit persons to whom the Software is furnished to do so, subject to 11544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * the following conditions: 12544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 13544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * The above copyright notice and this permission notice (including the 14544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * next paragraph) shall be included in all copies or substantial portions 15544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * of the Software. 16544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 17544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 25544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin **************************************************************************/ 26544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 27544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "path.h" 28544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 29544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "stroker.h" 30544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "polygon.h" 31544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "bezier.h" 32544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "matrix.h" 33544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "vg_context.h" 34544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "util_array.h" 35544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "arc.h" 36544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "path_utils.h" 37544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "paint.h" 38544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "shader.h" 39544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 40544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "util/u_memory.h" 41544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 42544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include <assert.h> 43544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 44544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define DEBUG_PATH 0 45544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 46544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct path { 47544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_object base; 48544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGbitfield caps; 49544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean dirty; 50544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean dirty_stroke; 51544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 52544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathDatatype datatype; 53544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 54544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat scale; 55544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat bias; 56544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 57544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_segments; 58544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 59544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array * segments; 60544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array * control_points; 61544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 62544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct { 63544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon_array polygon_array; 64544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix matrix; 65544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } fill_polys; 66544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 67544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct { 68544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path; 69544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix matrix; 70544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat stroke_width; 71544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat miter_limit; 72544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGCapStyle cap_style; 73544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGJoinStyle join_style; 74544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } stroked; 75544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 76544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 77544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 78544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void data_at(void **data, 79544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *p, 80544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint start, VGint count, 81544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *out) 82544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 83544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathDatatype dt = p->datatype; 84544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 85544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint end = start + count; 86544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *itr = out; 87544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 88544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(dt) { 89544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_8: { 90544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGbyte **bdata = (VGbyte **)data; 91544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = start; i < end; ++i) { 92544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *itr = (*bdata)[i]; 93544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr; 94544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 95544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *bdata += count; 96544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 97544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 98544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_16: { 99544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGshort **bdata = (VGshort **)data; 100544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = start; i < end; ++i) { 101544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *itr = (*bdata)[i]; 102544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr; 103544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 104544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *bdata += count; 105544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 106544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 107544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_32: { 108544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint **bdata = (VGint **)data; 109544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = start; i < end; ++i) { 110544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *itr = (*bdata)[i]; 111544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr; 112544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 113544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *bdata += count; 114544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 115544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 116544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_F: { 117544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat **fdata = (VGfloat **)data; 118544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = start; i < end; ++i) { 119544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *itr = (*fdata)[i]; 120544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr; 121544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 122544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *fdata += count; 123544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 124544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 125544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 126544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"Unknown path datatype!"); 127544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 128544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 129544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 130544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 131544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid vg_float_to_datatype(VGPathDatatype datatype, 132544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte *common_data, 133544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *data, 134544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords) 135544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 136544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 137544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(datatype) { 138544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_8: { 139544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < num_coords; ++i) { 140544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin common_data[i] = (VGubyte)data[i]; 141544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 142544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 143544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 144544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_16: { 145544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGshort *buf = (VGshort*)common_data; 146544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < num_coords; ++i) { 147544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin buf[i] = (VGshort)data[i]; 148544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 149544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 150544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 151544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_S_32: { 152544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint *buf = (VGint*)common_data; 153544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < num_coords; ++i) { 154544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin buf[i] = (VGint)data[i]; 155544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 156544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 157544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 158544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_PATH_DATATYPE_F: { 159544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memcpy(common_data, data, sizeof(VGfloat) * num_coords); 160544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 161544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 162544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 163544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"Unknown path datatype!"); 164544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 165544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 166544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 167544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void coords_adjust_by_scale_bias(struct path *p, 168544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *pdata, VGint num_coords, 169544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat scale, VGfloat bias, 170544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathDatatype datatype) 171544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 172544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 173544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords = (VGfloat *)pdata; 174544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte *common_data = (VGubyte *)pdata; 175544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint size_dst = size_for_datatype(datatype); 176544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 177544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 178544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < num_coords; ++i) { 179544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 180544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = data[0] * scale + bias; 181544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(datatype, common_data, data, 1); 182544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin common_data += size_dst; 183544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 184544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 185544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 186544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct path * path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias, 187544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint segmentCapacityHint, 188544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint coordCapacityHint, 189544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGbitfield capabilities) 190544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 191544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = CALLOC_STRUCT(path); 192544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 193544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_init_object(&path->base, vg_current_context(), VG_OBJECT_PATH); 194544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->caps = capabilities & VG_PATH_CAPABILITY_ALL; 195ceb6d34906c7c03c102c7e78dd02f5b0ebab4ca9Chia-I Wu vg_context_add_object(vg_current_context(), &path->base); 196544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 197544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->datatype = dt; 198544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->scale = scale; 199544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->bias = bias; 200544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 201544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8)); 202544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->control_points = array_create(size_for_datatype(dt)); 203544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 204544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->dirty = VG_TRUE; 205544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->dirty_stroke = VG_TRUE; 206544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 207544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return path; 208544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 209544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 210cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wustatic void polygon_array_cleanup(struct polygon_array *polyarray) 211cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu{ 212cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu if (polyarray->array) { 213cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu VGint i; 214cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu 215cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu for (i = 0; i < polyarray->array->num_elements; i++) { 216cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu struct polygon *p = ((struct polygon **) polyarray->array->data)[i]; 217cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu polygon_destroy(p); 218cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu } 219cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu 220cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu array_destroy(polyarray->array); 221cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu polyarray->array = NULL; 222cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu } 223cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu} 224cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu 225544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_destroy(struct path *p) 226544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 227ceb6d34906c7c03c102c7e78dd02f5b0ebab4ca9Chia-I Wu vg_context_remove_object(vg_current_context(), &p->base); 228544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 229544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(p->segments); 230544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(p->control_points); 231cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu 232cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu polygon_array_cleanup(&p->fill_polys.polygon_array); 233544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 234544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (p->stroked.path) 235544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(p->stroked.path); 236544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 237f914cd1796845164109c837a111c39ba64852ad4nobled FREE(p); 238544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 239544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 240544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGbitfield path_capabilities(struct path *p) 241544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 242544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->caps; 243544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 244544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 245544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_set_capabilities(struct path *p, VGbitfield bf) 246544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 247544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->caps = (bf & VG_PATH_CAPABILITY_ALL); 248544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 249544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 250544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_append_data(struct path *p, 251544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint numSegments, 252544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGubyte * pathSegments, 253544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const void * pathData) 254544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 255544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint old_segments = p->num_segments; 256544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_new_coords = num_elements_for_segments(pathSegments, numSegments); 257544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(p->segments, pathSegments, numSegments); 258544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(p->control_points, pathData, num_new_coords); 259544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 260544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->num_segments += numSegments; 261544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!floatsEqual(p->scale, 1.f) || !floatsEqual(p->bias, 0.f)) { 262544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte *coords = (VGubyte*)p->control_points->data; 263544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords_adjust_by_scale_bias(p, 264544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords + old_segments * p->control_points->datatype_size, 265544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin num_new_coords, 266544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->scale, p->bias, p->datatype); 267544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 268544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty = VG_TRUE; 269544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty_stroke = VG_TRUE; 270544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 271544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 272544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGint path_num_segments(struct path *p) 273544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 274544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->num_segments; 275544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 276544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 277544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void map_if_relative(VGfloat ox, VGfloat oy, 278544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean relative, 279544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *x, VGfloat *y) 280544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 281544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (relative) { 282544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (x) 283544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *x += ox; 284544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (y) 285544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *y += oy; 286544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 287544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 288544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 289544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void close_polygon(struct polygon *current, 290544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat sx, VGfloat sy, 291544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat ox, VGfloat oy, 292544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 293544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 294544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!floatsEqual(sx, ox) || 295544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin !floatsEqual(sy, oy)) { 296544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0 = sx; 297544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat y0 = sy; 298544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 299544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(current, x0, y0); 300544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 301544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 302544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 303544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void convert_path(struct path *p, 304544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathDatatype to, 305544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *dst, 306544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords) 307544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 308544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 309544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords = (VGfloat *)p->control_points->data; 310544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte *common_data = (VGubyte *)dst; 311544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint size_dst = size_for_datatype(to); 312544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 313544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 314544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < num_coords; ++i) { 315544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 316544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(to, common_data, data, 1); 317544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin common_data += size_dst; 318544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 319544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 320544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 321544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void polygon_array_calculate_bounds( struct polygon_array *polyarray ) 322544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 323544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *polys = polyarray->array; 324544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat min_x, max_x; 325544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat min_y, max_y; 326544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat bounds[4]; 327544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin unsigned i; 328544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 329544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(polys); 3309ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu 3319ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu if (!polys->num_elements) { 3329ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu polyarray->min_x = 0.0f; 3339ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu polyarray->min_y = 0.0f; 3349ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu polyarray->max_x = 0.0f; 3359ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu polyarray->max_y = 0.0f; 3369ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu return; 3379ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu } 3389ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu 339544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds); 340544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin min_x = bounds[0]; 341544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin min_y = bounds[1]; 342544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin max_x = bounds[0] + bounds[2]; 343544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin max_y = bounds[1] + bounds[3]; 344544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 1; i < polys->num_elements; ++i) { 345544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *p = (((struct polygon**)polys->data)[i]); 346544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_bounding_rect(p, bounds); 347544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin min_x = MIN2(min_x, bounds[0]); 348544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin min_y = MIN2(min_y, bounds[1]); 349544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin max_x = MAX2(max_x, bounds[0] + bounds[2]); 350544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin max_y = MAX2(max_y, bounds[1] + bounds[3]); 351544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 352544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 353544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polyarray->min_x = min_x; 354544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polyarray->min_y = min_y; 355544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polyarray->max_x = max_x; 356544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polyarray->max_y = max_y; 357544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 358544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 359544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 360544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic struct polygon_array * path_get_fill_polygons(struct path *p, struct matrix *matrix) 361544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 362544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 363544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *current = 0; 364544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat sx, sy, px, py, ox, oy; 365544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0, y0, x1, y1, x2, y2, x3, y3; 366544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 367544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords = (VGfloat *)p->control_points->data; 368544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *array; 369544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 3706386f80dbd6f1230abf16fa5ac65dc0dca70033aBrian Paul memset(data, 0, sizeof(data)); 3716386f80dbd6f1230abf16fa5ac65dc0dca70033aBrian Paul 372544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (p->fill_polys.polygon_array.array) 373544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 374544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (memcmp( &p->fill_polys.matrix, 375544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix, 376544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sizeof *matrix ) == 0 && p->dirty == VG_FALSE) 377544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 378544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return &p->fill_polys.polygon_array; 379544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 380544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else { 381cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu polygon_array_cleanup(&p->fill_polys.polygon_array); 382544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 383544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 384544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 385cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu /* an array of pointers to polygons */ 386cb2791213a660dc39c22872ea9095bdfaa61aae4Chia-I Wu array = array_create(sizeof(struct polygon *)); 387544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 388544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sx = sy = px = py = ox = oy = 0.f; 389544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 3909ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu if (p->num_segments) 3919ea4936a36f5011695a3996c63cfad6b480b3e49Chia-I Wu current = polygon_create(32); 392544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 393544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < p->num_segments; ++i) { 394544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = ((VGubyte*)(p->segments->data))[i]; 395544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint command = SEGMENT_COMMAND(segment); 396544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean relative = SEGMENT_ABS_REL(segment); 397544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 398544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(command) { 399544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: 400544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin close_polygon(current, sx, sy, ox, oy, matrix); 401544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = sx; 402544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = sy; 403544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 404544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO: 405544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (current && polygon_vertex_count(current) > 0) { 406544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* add polygon */ 407544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin close_polygon(current, sx, sy, ox, oy, matrix); 408544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(array, ¤t, 1); 409544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin current = polygon_create(32); 410544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 411544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 412544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 413544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[1]; 414544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, &y0); 415544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sx = x0; 416544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sy = y0; 417544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 418544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 419544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 420544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 421544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 422544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(current, x0, y0); 423544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 424544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO: 425544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 426544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 427544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[1]; 428544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, &y0); 429544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 430544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 431544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 432544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 433544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 434544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(current, x0, y0); 435544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 436544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_HLINE_TO: 437544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 438544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 439544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 440544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, 0); 441544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 442544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 443544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 444544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 445544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(current, x0, y0); 446544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 447544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_VLINE_TO: 448544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 449544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 450544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[0]; 451544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, 0, &y0); 452544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 453544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 454544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 455544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 456544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex_append(current, x0, y0); 457544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 458544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO: { 459544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 460544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 6, data); 461544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 462544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 463544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[0]; 464544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[1]; 465544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = data[2]; 466544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = data[3]; 467544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[4]; 468544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[5]; 469544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 470544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x2, &y2); 471544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 472544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 473544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 474544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x2; 475544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y2; 476544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 477544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 478544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 479544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 480544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 481544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, x0, y0, x1, y1, 482544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2, y2, x3, y3); 483544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_add_to_polygon(&bezier, current); 484544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 485544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 486544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_QUAD_TO: { 487544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 488544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 4, data); 489544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 490544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 491544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[0]; 492544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[1]; 493544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 494544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 495544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 496544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 497544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 498544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 499544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 500544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 501544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 502544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 503544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 504544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 505544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 506544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 507544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 508544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 509544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 510544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 511544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 512544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, x0, y0, x1, y1, 513544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2, y2, x3, y3); 514544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_add_to_polygon(&bezier, current); 515544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 516544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 517544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SQUAD_TO: { 518544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 519544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 520544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 521544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 522544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2*ox-px; 523544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2*oy-py; 524544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[0]; 525544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[1]; 526544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 527544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 528544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 529544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 530544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 531544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 532544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 533544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 534544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 535544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 536544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 537544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 538544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 539544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 540544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 541544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 542544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, x0, y0, x1, y1, 543544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2, y2, x3, y3); 544544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_add_to_polygon(&bezier, current); 545544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 546544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 547544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCUBIC_TO: { 548544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 549544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 4, data); 550544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 551544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 552544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2*ox-px; 553544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2*oy-py; 554544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = data[0]; 555544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = data[1]; 556544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 557544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 558544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x2, &y2); 559544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 560544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 561544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 562544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x2; 563544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y2; 564544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 565544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 566544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 567544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 568544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 569544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, x0, y0, x1, y1, 570544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2, y2, x3, y3); 571544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_add_to_polygon(&bezier, current); 572544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 573544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 574544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 575544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 576544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 577544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 578544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat rh, rv, rot; 579544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 580544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 581544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 5, data); 582544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 583544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 584544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rh = data[0]; 585544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rv = data[1]; 586544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rot = data[2]; 587544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[3]; 588544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[4]; 589544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 590544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 591544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n", 592544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0, y0, x1, y1, rh, rv, rot); 593544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 594544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, command, x0, y0, x1, y1, 595544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rh, rv, rot); 596544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_add_to_polygon(&arc, current, 597544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix); 598544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x1; 599544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y1; 600544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 601544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 602544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 603544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 604544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 605544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin abort(); 606544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(!"Unknown segment!"); 607544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 608544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 609544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (current) { 610544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (polygon_vertex_count(current) > 0) { 611544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin close_polygon(current, sx, sy, ox, oy, matrix); 612544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(array, ¤t, 1); 613544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else 614544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_destroy(current); 615544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 616544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 617544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->fill_polys.polygon_array.array = array; 618544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->fill_polys.matrix = *matrix; 619544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 620544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_array_calculate_bounds( &p->fill_polys.polygon_array ); 621544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 622544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty = VG_FALSE; 623544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 624544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return &p->fill_polys.polygon_array; 625544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 626544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 627544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGbyte path_datatype_size(struct path *p) 628544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 629544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return size_for_datatype(p->datatype); 630544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 631544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 632544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGPathDatatype path_datatype(struct path *p) 633544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 634544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->datatype; 635544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 636544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 637544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGfloat path_scale(struct path *p) 638544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 639544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->scale; 640544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 641544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 642544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGfloat path_bias(struct path *p) 643544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 644544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->bias; 645544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 646544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 647544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGint path_num_coords(struct path *p) 648544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 649544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return num_elements_for_segments((VGubyte*)p->segments->data, 650544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->num_segments); 651544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 652544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 653544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_modify_coords(struct path *p, 654544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint startIndex, 655544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint numSegments, 656544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const void * pathData) 657544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 658544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte *segments = (VGubyte*)(p->segments->data); 659544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint count = num_elements_for_segments(&segments[startIndex], numSegments); 660544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint start_cp = num_elements_for_segments(segments, startIndex); 661544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 662544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_change_data(p->control_points, pathData, start_cp, count); 663544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords_adjust_by_scale_bias(p, 664544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ((VGubyte*)p->control_points->data) + 665544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (startIndex * p->control_points->datatype_size), 666544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_num_coords(p), 667544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->scale, p->bias, p->datatype); 668544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty = VG_TRUE; 669544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty_stroke = VG_TRUE; 670544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 671544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 672544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_for_each_segment(struct path *path, 673544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_for_each_cb cb, 674544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *user_data) 675544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 676544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 677544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_for_each_data p; 678544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 679544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords = (VGfloat *)path->control_points->data; 680544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 681544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.coords = data; 682544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.sx = p.sy = p.px = p.py = p.ox = p.oy = 0.f; 683544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.user_data = user_data; 684544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 685544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < path->num_segments; ++i) { 686544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint command; 687544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean relative; 688544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 689544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.segment = ((VGubyte*)(path->segments->data))[i]; 690544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin command = SEGMENT_COMMAND(p.segment); 691544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin relative = SEGMENT_ABS_REL(p.segment); 692544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 693544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(command) { 694544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: 695544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 696544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 697544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO: 698544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 2, data); 699544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 700544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 701544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.sx = data[0]; 702544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.sy = data[1]; 703544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[0]; 704544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[1]; 705544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 706544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 707544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 708544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO: 709544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 2, data); 710544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 711544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 712544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[0]; 713544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[1]; 714544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 715544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 716544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 717544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_HLINE_TO: 718544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 1, data); 719544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], 0); 720544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.segment = VG_LINE_TO; 721544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = p.oy; 722544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 723544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[0]; 724544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[1]; 725544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 726544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 727544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 728544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_VLINE_TO: 729544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 1, data); 730544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, 0, &data[0]); 731544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.segment = VG_LINE_TO; 732544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = data[0]; 733544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = p.ox; 734544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 735544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[0]; 736544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[1]; 737544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 738544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 739544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 740544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO: { 741544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 6, data); 742544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 743544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); 744544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[4], &data[5]); 745544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 746544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[2]; 747544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[3]; 748544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[4]; 749544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[5]; 750544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 751544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 752544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_QUAD_TO: { 753544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 4, data); 754544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 755544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); 756544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 757544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 758544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 759544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[2]; 760544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[3]; 761544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 762544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 763544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SQUAD_TO: { 764544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 2, data); 765544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 766544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 767544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = 2*p.ox-p.px; 768544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = 2*p.oy-p.py; 769544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[2]; 770544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[3]; 771544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 772544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 773544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCUBIC_TO: { 774544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 4, data); 775544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); 776544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); 777544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 778544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[0]; 779544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[1]; 780544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[2]; 781544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[3]; 782544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 783544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 784544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 785544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 786544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 787544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 788544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, path, 0, 5, data); 789544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(p.ox, p.oy, relative, &data[3], &data[4]); 790544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 791544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n", 792544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox, p.oy, data[3], data[4], data[0], data[1], data[2]); 793544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 794544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cb(path, &p); 795544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.ox = data[3]; 796544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.oy = data[4]; 797544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.px = data[3]; 798544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p.py = data[4]; 799544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 800544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 801544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 802544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin abort(); 803544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(!"Unknown segment!"); 804544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 805544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 806544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 807544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 808544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct transform_data { 809544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *segments; 810544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *coords; 811544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 812544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix; 813544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 814544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathDatatype datatype; 815544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 816544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 817544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean transform_cb(struct path *p, 818544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_for_each_data *pd) 819544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 820544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct transform_data *td = (struct transform_data *)pd->user_data; 821544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords = num_elements_for_segments(&pd->segment, 1); 822544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = SEGMENT_COMMAND(pd->segment);/* abs bit is 0 */ 823544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 824544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte common_data[sizeof(VGfloat)*8]; 825544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 826544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memcpy(data, pd->coords, sizeof(VGfloat) * num_coords); 827544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 828544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(segment) { 829544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: 830544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 831544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO: 832544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 833544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 834544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 835544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO: 836544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 837544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 838544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 839544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_HLINE_TO: 840544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_VLINE_TO: 841544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 842544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 843544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_QUAD_TO: 844544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 845544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 846544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 847544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2], data[3], &data[2], &data[3]); 848544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 849544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO: 850544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 851544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 852544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 853544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2], data[3], &data[2], &data[3]); 854544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 855544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[4], data[5], &data[4], &data[5]); 856544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 857544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SQUAD_TO: 858544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 859544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 860544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 861544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCUBIC_TO: 862544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 863544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], &data[0], &data[1]); 864544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(td->matrix, 865544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2], data[3], &data[2], &data[3]); 866544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 867544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 868544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 869544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 870544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 871544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 872544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = path_create(td->datatype, 873544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); 874544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, segment, 875544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox, pd->oy, data[3], data[4], 876544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0], data[1], data[2]); 877544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 878544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_path(&arc, path, td->matrix); 879544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 880544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin num_coords = path_num_coords(path); 881544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 882544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(td->segments, path->segments->data, 883544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path->num_segments); 884544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(td->coords, path->control_points->data, 885544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin num_coords); 886544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(path); 887544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 888544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 889544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 890544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 891544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 892544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 893544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 894544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 895544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(td->datatype, common_data, data, num_coords); 896544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 897534c13302291c07a44afd528f4c758ced4296db5Zack Rusin array_append_data(td->segments, &pd->segment, 1); 898544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(td->coords, common_data, num_coords); 899544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 900544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 901544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 902544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_transform(struct path *dst, struct path *src) 903544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 904544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct transform_data data; 905544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_context *ctx = dst->base.ctx; 906544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 907544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data.segments = dst->segments; 908544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data.coords = dst->control_points; 909544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data.matrix = &ctx->state.vg.path_user_to_surface_matrix; 910544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data.datatype = dst->datatype; 911544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 912544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_for_each_segment(src, transform_cb, (void*)&data); 913544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 914544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->num_segments = dst->segments->num_elements; 915544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty = VG_TRUE; 916544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty_stroke = VG_TRUE; 917544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 918544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 919544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_append_path(struct path *dst, 920544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *src) 921544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 922544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords = path_num_coords(src); 923544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *dst_data = malloc(size_for_datatype(dst->datatype) * num_coords); 924544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(dst->segments, 925544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin src->segments->data, 926544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin src->num_segments); 927544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin convert_path(src, dst->datatype, 928544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst_data, num_coords); 929544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(dst->control_points, 930544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst_data, 931544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin num_coords); 932544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin free(dst_data); 933544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 934544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->num_segments += src->num_segments; 935544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty = VG_TRUE; 936544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty_stroke = VG_TRUE; 937544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 938544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 939544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGboolean is_segment_arc(VGubyte segment) 940544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 941544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte scommand = SEGMENT_COMMAND(segment); 942544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return (scommand == VG_SCCWARC_TO || 943544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin scommand == VG_SCWARC_TO || 944544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin scommand == VG_LCCWARC_TO || 945544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin scommand == VG_LCWARC_TO); 946544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 947544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 948544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct path_iter_data { 949544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path; 950544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment; 951544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords; 952544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat px, py, ox, oy, sx, sy; 953544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 954544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGubyte normalize_coords(struct path_iter_data *pd, 955544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint *num_coords, 956544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *data) 957544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 958544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint command = SEGMENT_COMMAND(pd->segment); 959544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean relative = SEGMENT_ABS_REL(pd->segment); 960544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 961544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(command) { 962544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: 963544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 0; 964544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = pd->sx; 965544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = pd->sy; 966544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_CLOSE_PATH; 967544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 968544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO: 969544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 2, data); 970544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); 971544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->sx = data[0]; 972544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->sy = data[1]; 973544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[0]; 974544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[1]; 975544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[0]; 976544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[1]; 977544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 2; 978544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_MOVE_TO_ABS; 979544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 980544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO: 981544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 2, data); 982544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); 983544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[0]; 984544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[1]; 985544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[0]; 986544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[1]; 987544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 2; 988544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_LINE_TO_ABS; 989544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 990544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_HLINE_TO: 991544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 1, data); 992544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[0], 0); 993544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = pd->oy; 994544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[0]; 995544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[1]; 996544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[0]; 997544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[1]; 998544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 2; 999544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_LINE_TO_ABS; 1000544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1001544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_VLINE_TO: 1002544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 1, data); 1003544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, 0, &data[0]); 1004544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = data[0]; 1005544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = pd->ox; 1006544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[0]; 1007544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[1]; 1008544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[0]; 1009544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[1]; 1010544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 2; 1011544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_LINE_TO_ABS; 1012544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1013544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO: { 1014544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 6, data); 1015544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); 1016544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[2], &data[3]); 1017544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[4], &data[5]); 1018544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[2]; 1019544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[3]; 1020544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[4]; 1021544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[5]; 1022544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 6; 1023544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_CUBIC_TO_ABS; 1024544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1025544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1026544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_QUAD_TO: { 1027544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0, y0, x1, y1, x2, y2, x3, y3; 1028544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 4, data); 1029544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = pd->ox; 1030544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = pd->oy; 1031544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[0]; 1032544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[1]; 1033544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 1034544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 1035544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &x1, &y1); 1036544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); 1037544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = x1; 1038544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = y1; 1039544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 1040544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 1041544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 1042544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 1043544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 1044544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1045544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = x3; 1046544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = y3; 1047544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = x1; 1048544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = y1; 1049544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2] = x2; 1050544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[3] = y2; 1051544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[4] = x3; 1052544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[5] = y3; 1053544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 6; 1054544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_CUBIC_TO_ABS; 1055544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1056544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1057544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SQUAD_TO: { 1058544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0, y0, x1, y1, x2, y2, x3, y3; 1059544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 2, data); 1060544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = pd->ox; 1061544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = pd->oy; 1062544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2 * pd->ox - pd->px; 1063544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2 * pd->oy - pd->py; 1064544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[0]; 1065544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[1]; 1066544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); 1067544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = x1; 1068544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = y1; 1069544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 1070544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 1071544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 1072544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 1073544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 1074544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1075544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = x3; 1076544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = y3; 1077544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = x1; 1078544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = y1; 1079544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2] = x2; 1080544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[3] = y2; 1081544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[4] = x3; 1082544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[5] = y3; 1083544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 6; 1084544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_CUBIC_TO_ABS; 1085544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1086544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1087544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCUBIC_TO: { 1088544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0, y0, x1, y1, x2, y2, x3, y3; 1089544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 4, data); 1090544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = pd->ox; 1091544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = pd->oy; 1092544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2*pd->ox-pd->px; 1093544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2*pd->oy-pd->py; 1094544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = data[0]; 1095544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = data[1]; 1096544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 1097544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 1098544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &x2, &y2); 1099544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); 1100544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = x3; 1101544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = y3; 1102544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = x2; 1103544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = y2; 1104544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = x1; 1105544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = y1; 1106544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2] = x2; 1107544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[3] = y2; 1108544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[4] = x3; 1109544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[5] = y3; 1110544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 6; 1111544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_CUBIC_TO_ABS; 1112544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1113544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1114544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 1115544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 1116544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 1117544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 1118544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&pd->coords, pd->path, 0, 5, data); 1119544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(pd->ox, pd->oy, relative, &data[3], &data[4]); 1120544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->ox = data[3]; 1121544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->oy = data[4]; 1122544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->px = data[3]; 1123544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pd->py = data[4]; 1124544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *num_coords = 5; 1125544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return command | VG_ABSOLUTE; 1126544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1127544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1128544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 1129544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin abort(); 1130544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(!"Unknown segment!"); 1131544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1132544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1133544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1134544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void linearly_interpolate(VGfloat *result, 1135544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *start, 1136544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *end, 1137544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat amount, 1138544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint number) 1139544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1140544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1141544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < number; ++i) { 1142544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin result[i] = start[i] + (end[i] - start[i]) * amount; 1143544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1144544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1145544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1146544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGboolean path_interpolate(struct path *dst, 1147544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *start, struct path *end, 1148544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat amount) 1149544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1150544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* temporary path that we can discard if it will turn 1151544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * out that start is not compatible with end */ 1152544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *res_path = path_create(dst->datatype, 1153544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1.0, 0.0, 1154544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 0, 0, dst->caps); 1155544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1156544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat start_coords[8]; 1157544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat end_coords[8]; 1158544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat results[8]; 1159544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte common_data[sizeof(VGfloat)*8]; 1160544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_iter_data start_iter, end_iter; 1161544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1162544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&start_iter, 0, sizeof(struct path_iter_data)); 1163544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&end_iter, 0, sizeof(struct path_iter_data)); 1164544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1165544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_iter.path = start; 1166544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_iter.coords = start->control_points->data; 1167544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin end_iter.path = end; 1168544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin end_iter.coords = end->control_points->data; 1169544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1170544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < start->num_segments; ++i) { 1171544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment; 1172544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte ssegment, esegment; 1173544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint snum_coords, enum_coords; 1174544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_iter.segment = ((VGubyte*)(start->segments->data))[i]; 1175544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin end_iter.segment = ((VGubyte*)(end->segments->data))[i]; 1176544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1177544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ssegment = normalize_coords(&start_iter, &snum_coords, 1178544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_coords); 1179544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin esegment = normalize_coords(&end_iter, &enum_coords, 1180544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin end_coords); 1181544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1182544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (is_segment_arc(ssegment)) { 1183544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!is_segment_arc(esegment)) { 1184544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(res_path); 1185544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 1186544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1187544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (amount > 0.5) 1188544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin segment = esegment; 1189544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 1190544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin segment = ssegment; 1191544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (is_segment_arc(esegment)) { 1192544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(res_path); 1193544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 1194544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1195544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else if (ssegment != esegment) { 1196544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(res_path); 1197544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 1198544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1199544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 1200544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin segment = ssegment; 1201544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1202544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin linearly_interpolate(results, start_coords, end_coords, 1203544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin amount, snum_coords); 1204544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(dst->datatype, common_data, results, snum_coords); 1205544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(res_path, 1, &segment, common_data); 1206544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1207544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1208544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_path(dst, res_path); 1209544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(res_path); 1210544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1211544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty = VG_TRUE; 1212544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dst->dirty_stroke = VG_TRUE; 1213544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1214544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1215544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1216544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1217544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_clear(struct path *p, VGbitfield capabilities) 1218544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1219544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_set_capabilities(p, capabilities); 1220544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(p->segments); 1221544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(p->control_points); 1222544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8)); 1223544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->control_points = array_create(size_for_datatype(p->datatype)); 1224544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->num_segments = 0; 1225544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty = VG_TRUE; 1226544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty_stroke = VG_TRUE; 1227544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1228544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1229544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct path * path_create_stroke(struct path *p, 1230544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix *matrix) 1231544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1232544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1233544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat sx, sy, px, py, ox, oy; 1234544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0, y0, x1, y1, x2, y2, x3, y3; 1235544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8]; 1236544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void *coords = (VGfloat *)p->control_points->data; 1237544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int dashed = (p->base.ctx->state.vg.stroke.dash_pattern_num ? 1 : 0); 1238544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct dash_stroker stroker; 1239544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_state *vg_state = &p->base.ctx->state.vg; 1240544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1241544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (p->stroked.path) 1242544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 1243544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* ### compare the dash patterns to see if we can cache them. 1244544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * for now we simply always bail out if the path is dashed. 1245544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin */ 1246544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (memcmp( &p->stroked.matrix, 1247544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix, 1248544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sizeof *matrix ) == 0 && 1249544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin !dashed && !p->dirty_stroke && 1250544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(p->stroked.stroke_width, vg_state->stroke.line_width.f) && 1251544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(p->stroked.miter_limit, vg_state->stroke.miter_limit.f) && 1252544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.cap_style == vg_state->stroke.cap_style && 1253544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.join_style == vg_state->stroke.join_style) 1254544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 1255544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->stroked.path; 1256544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1257544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else { 1258544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy( p->stroked.path ); 1259544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.path = NULL; 1260544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1261544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1262544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1263544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1264544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sx = sy = px = py = ox = oy = 0.f; 1265544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1266544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dashed) 1267544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dash_stroker_init((struct stroker *)&stroker, vg_state); 1268544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 1269544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_init((struct stroker *)&stroker, vg_state); 1270544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1271544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_begin((struct stroker *)&stroker); 1272544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1273544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < p->num_segments; ++i) { 1274544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = ((VGubyte*)(p->segments->data))[i]; 1275544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint command = SEGMENT_COMMAND(segment); 1276544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean relative = SEGMENT_ABS_REL(segment); 1277544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1278544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(command) { 1279544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: { 1280544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x0 = sx; 1281544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat y0 = sy; 1282544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1283544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x0, y0); 1284544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1285544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1286544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO: 1287544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 1288544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 1289544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[1]; 1290544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, &y0); 1291544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sx = x0; 1292544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sy = y0; 1293544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 1294544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 1295544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 1296544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 1297544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1298544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_move_to((struct stroker *)&stroker, x0, y0); 1299544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1300544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO: 1301544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 1302544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 1303544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[1]; 1304544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, &y0); 1305544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 1306544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 1307544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 1308544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 1309544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1310544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x0, y0); 1311544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1312544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_HLINE_TO: 1313544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 1314544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = data[0]; 1315544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1316544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x0, 0); 1317544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x0; 1318544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 1319544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 1320544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1321544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x0, y0); 1322544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1323544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_VLINE_TO: 1324544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 1, data); 1325544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1326544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = data[0]; 1327544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, 0, &y0); 1328544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y0; 1329544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x0; 1330544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y0; 1331544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1332544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x0, y0); 1333544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1334544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO: { 1335544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 6, data); 1336544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1337544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1338544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[0]; 1339544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[1]; 1340544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = data[2]; 1341544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = data[3]; 1342544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[4]; 1343544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[5]; 1344544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 1345544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x2, &y2); 1346544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 1347544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && 1348544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x1, x2) && floatsEqual(y1, y2) && 1349544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x2, x3) && floatsEqual(y2, y3)) { 1350544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /*ignore the empty segment */ 1351544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1352544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { 1353544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if dup vertex, emit a line */ 1354544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1355544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1356544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1357544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x3, y3); 1358544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1359544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1360544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1361544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1362544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x2; 1363544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y2; 1364544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 1365544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1366544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 1367544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 1368544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1369544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); 1370544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1371544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1372544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_QUAD_TO: { 1373544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 4, data); 1374544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1375544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1376544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[0]; 1377544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[1]; 1378544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 1379544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 1380544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 1381544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 1382544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 1383544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 1384544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 1385544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 1386544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 1387544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 1388544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 1389544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1390544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && 1391544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x1, x2) && floatsEqual(y1, y2) && 1392544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x2, x3) && floatsEqual(y2, y3)) { 1393544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /*ignore the empty segment */ 1394544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1395544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { 1396544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if dup vertex, emit a line */ 1397544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1398544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1399544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1400544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x3, y3); 1401544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1402544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1403544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1404544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1405544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 1406544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1407544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 1408544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 1409544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1410544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); 1411544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1412544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1413544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SQUAD_TO: { 1414544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 2, data); 1415544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1416544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1417544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2*ox-px; 1418544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2*oy-py; 1419544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[0]; 1420544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[1]; 1421544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 1422544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 1423544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 1424544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /* form a cubic out of it */ 1425544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = (x3 + 2*x1) / 3.f; 1426544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = (y3 + 2*y1) / 3.f; 1427544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = (x0 + 2*x1) / 3.f; 1428544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = (y0 + 2*y1) / 3.f; 1429544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1430544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && 1431544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x1, x2) && floatsEqual(y1, y2) && 1432544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x2, x3) && floatsEqual(y2, y3)) { 1433544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /*ignore the empty segment */ 1434544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1435544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { 1436544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if dup vertex, emit a line */ 1437544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1438544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1439544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1440544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x3, y3); 1441544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1442544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1443544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1444544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1445544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 1446544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1447544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 1448544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 1449544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1450544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); 1451544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1452544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1453544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCUBIC_TO: { 1454544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 4, data); 1455544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1456544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1457544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = 2*ox-px; 1458544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = 2*oy-py; 1459544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x2 = data[0]; 1460544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y2 = data[1]; 1461544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x3 = data[2]; 1462544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y3 = data[3]; 1463544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x2, &y2); 1464544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x3, &y3); 1465544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && 1466544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x1, x2) && floatsEqual(y1, y2) && 1467544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(x2, x3) && floatsEqual(y2, y3)) { 1468544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /*ignore the empty segment */ 1469544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1470544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { 1471544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if dup vertex, emit a line */ 1472544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1473544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1474544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1475544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x3, y3); 1476544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1477544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1478544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x3; 1479544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y3; 1480544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x2; 1481544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y2; 1482544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(matrix_is_affine(matrix)); 1483544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x0, y0, &x0, &y0); 1484544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 1485544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x2, y2, &x2, &y2); 1486544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x3, y3, &x3, &y3); 1487544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); 1488544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1489544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1490544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 1491544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 1492544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 1493544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 1494544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat rh, rv, rot; 1495544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 1496544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1497544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data_at(&coords, p, 0, 5, data); 1498544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x0 = ox; 1499544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y0 = oy; 1500544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rh = data[0]; 1501544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rv = data[1]; 1502544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rot = data[2]; 1503544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1 = data[3]; 1504544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin y1 = data[4]; 1505544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin map_if_relative(ox, oy, relative, &x1, &y1); 1506544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(x1, ox) && floatsEqual(y1, oy)) { 1507544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if dup vertex, emit a line */ 1508544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x1; 1509544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y1; 1510544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_map_point(matrix, x1, y1, &x1, &y1); 1511544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to((struct stroker *)&stroker, x1, y1); 1512544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1513544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1514544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, command, x0, y0, x1, y1, 1515544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rh, rv, rot); 1516544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_stroke_cb(&arc, (struct stroker *)&stroker, 1517544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix); 1518544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = x1; 1519544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = y1; 1520544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px = x1; 1521544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin py = y1; 1522544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1523544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1524544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 1525544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin abort(); 1526544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(!"Unknown segment!"); 1527544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1528544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1529544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1530544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_end((struct stroker *)&stroker); 1531544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1532544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dashed) 1533544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dash_stroker_cleanup((struct dash_stroker *)&stroker); 1534544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 1535544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cleanup((struct stroker *)&stroker); 1536544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1537544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.path = stroker.base.path; 1538544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.matrix = *matrix; 1539544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->dirty_stroke = VG_FALSE; 1540544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.stroke_width = vg_state->stroke.line_width.f; 1541544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.miter_limit = vg_state->stroke.miter_limit.f; 1542544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.cap_style = vg_state->stroke.cap_style; 1543544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p->stroked.join_style = vg_state->stroke.join_style; 1544544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1545544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return stroker.base.path; 1546544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1547544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1548165cb19abc4279839b0f5f53eb2feac60c2f415eChia-I Wuvoid path_render(struct path *p, VGbitfield paintModes, 1549165cb19abc4279839b0f5f53eb2feac60c2f415eChia-I Wu struct matrix *mat) 1550544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1551544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_context *ctx = vg_current_context(); 1552b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu struct matrix paint_matrix; 1553544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1554544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_validate_state(ctx); 1555544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1556544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_set_drawing_image(ctx->shader, VG_FALSE); 1557544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_set_image(ctx->shader, 0); 1558544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if 0 1559544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin fprintf(stderr, "Matrix(11=%f 12=%f 13=%f 21=%f 22=%f 23=%f 31=%f 32=%f 33=%f)\n", 1560544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin mat->m[0], mat->m[1], mat->m[2], 1561544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin mat->m[3], mat->m[4], mat->m[5], 1562544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin mat->m[6], mat->m[7], mat->m[8]); 1563544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 1564b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu if ((paintModes & VG_FILL_PATH) && 1565b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu vg_get_paint_matrix(ctx, 1566b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu &ctx->state.vg.fill_paint_to_user_matrix, 1567b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu mat, 1568b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu &paint_matrix)) { 1569544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* First the fill */ 1570a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu shader_set_surface_matrix(ctx->shader, mat); 1571544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); 1572b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu shader_set_paint_matrix(ctx->shader, &paint_matrix); 1573544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_bind(ctx->shader); 1574a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu path_fill(p); 1575544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1576544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1577b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu if ((paintModes & VG_STROKE_PATH) && 1578b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu vg_get_paint_matrix(ctx, 1579b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu &ctx->state.vg.stroke_paint_to_user_matrix, 1580b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu mat, 1581b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu &paint_matrix)) { 1582544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* 8.7.5: "line width less than or equal to 0 prevents stroking from 1583544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * taking place."*/ 1584544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (ctx->state.vg.stroke.line_width.f <= 0) 1585544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 1586a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu shader_set_surface_matrix(ctx->shader, mat); 1587544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint); 1588b06de80843e7d096bed4ae03ddc5e2842f1876afChia-I Wu shader_set_paint_matrix(ctx->shader, &paint_matrix); 1589544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin shader_bind(ctx->shader); 1590a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu path_stroke(p); 1591544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1592544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1593544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1594a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wuvoid path_fill(struct path *p) 1595544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1596544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_context *ctx = vg_current_context(); 1597a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu struct matrix identity; 1598a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu 1599a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu matrix_load_identity(&identity); 1600a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu 1601544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 1602a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu struct polygon_array *polygon_array = path_get_fill_polygons(p, &identity); 1603544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *polys = polygon_array->array; 1604544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1605544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!polygon_array || !polys || !polys->num_elements) { 1606544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 1607544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1608544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_array_fill(polygon_array, ctx); 1609544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1610544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1611544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1612a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wuvoid path_stroke(struct path *p) 1613544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1614544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_context *ctx = vg_current_context(); 1615544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGFillRule old_fill = ctx->state.vg.fill_rule; 1616544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix identity; 1617544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *stroke; 1618544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1619544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&identity); 1620544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke = path_create_stroke(p, &identity); 1621544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroke && !path_is_empty(stroke)) { 1622544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ctx->state.vg.fill_rule = VG_NON_ZERO; 1623544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1624a84a1e344f544ec4da61809d4f09853a94d93e07Chia-I Wu path_fill(stroke); 1625544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1626544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ctx->state.vg.fill_rule = old_fill; 1627544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1628544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1629544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1630544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_move_to(struct path *p, float x, float y) 1631544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1632544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = VG_MOVE_TO_ABS; 1633544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte common_data[sizeof(VGfloat) * 2]; 1634544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[2] = {x, y}; 1635544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1636544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(p->datatype, common_data, data, 2); 1637544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(p, 1, &segment, common_data); 1638544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1639544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1640544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_line_to(struct path *p, float x, float y) 1641544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1642544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = VG_LINE_TO_ABS; 1643544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte common_data[sizeof(VGfloat) * 2]; 1644544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[2] = {x, y}; 1645544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1646544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(p->datatype, common_data, data, 2); 1647544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1648544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(p, 1, &segment, common_data); 1649544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1650544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1651544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_cubic_to(struct path *p, float px1, float py1, 1652544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin float px2, float py2, 1653544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin float x, float y) 1654544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1655544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment = VG_CUBIC_TO_ABS; 1656544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte common_data[sizeof(VGfloat) * 6]; 1657544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[6]; 1658544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1659544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = px1; data[1] = py1; 1660544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[2] = px2; data[3] = py2; 1661544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[4] = x; data[5] = y; 1662544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1663544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin vg_float_to_datatype(p->datatype, common_data, data, 6); 1664544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1665544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(p, 1, &segment, common_data); 1666544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1667544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1668544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void line_bounds(VGfloat *line /*x1,y1,x2,y2*/, 1669544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *bounds) 1670544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1671544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[0] = MIN2(line[0], line[2]); 1672544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[1] = MIN2(line[1], line[3]); 1673544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[2] = MAX2(line[0], line[2]) - bounds[0]; 1674544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[3] = MAX2(line[1], line[3]) - bounds[1]; 1675544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1676544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1677544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void unite_bounds(VGfloat *bounds, 1678544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *el) 1679544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1680544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat cx1, cy1, cx2, cy2; 1681544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat nx1, ny1, nx2, ny2; 1682544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1683544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx1 = bounds[0]; 1684544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cy1 = bounds[1]; 1685544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx2 = bounds[0] + bounds[2]; 1686544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cy2 = bounds[1] + bounds[3]; 1687544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1688544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin nx1 = el[0]; 1689544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ny1 = el[1]; 1690544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin nx2 = el[0] + el[2]; 1691544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ny2 = el[1] + el[3]; 1692544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1693544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[0] = MIN2(cx1, nx1); 1694544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[1] = MIN2(cy1, ny1); 1695544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[2] = MAX2(cx2, nx2) - bounds[0]; 1696544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[3] = MAX2(cy2, ny2) - bounds[1]; 1697544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1698544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1699544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void set_bounds(VGfloat *bounds, 1700544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *element_bounds, 1701544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean *initialized) 1702544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1703544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!(*initialized)) { 1704544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memcpy(bounds, element_bounds, 4 * sizeof(VGfloat)); 1705544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *initialized = VG_TRUE; 1706544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else 1707544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin unite_bounds(bounds, element_bounds); 1708544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1709544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1710544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_bounding_rect(struct path *p, float *x, float *y, 1711544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin float *w, float *h) 1712544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1713544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1714544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8]; 1715544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_iter_data iter; 1716544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords; 1717544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat bounds[4]; 1718544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat element_bounds[4]; 1719544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat ox, oy; 1720544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean bounds_inited = VG_FALSE; 1721544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1722544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&iter, 0, sizeof(struct path_iter_data)); 1723544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&bounds, 0, sizeof(bounds)); 1724544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1725544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!p->num_segments) { 1726544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[2] = -1; 1727544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bounds[3] = -1; 1728544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1729544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1730544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1731544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.path = p; 1732544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.coords = p->control_points->data; 1733544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1734544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < p->num_segments; ++i) { 1735544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment; 1736544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.segment = ((VGubyte*)(p->segments->data))[i]; 1737544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1738544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = iter.ox; 1739544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = iter.oy; 1740544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1741544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin segment = normalize_coords(&iter, &num_coords, coords); 1742544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1743544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(segment) { 1744544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: 1745544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 1746544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1747544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: { 1748544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {ox, oy, coords[0], coords[1]}; 1749544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_bounds(line, element_bounds); 1750544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin set_bounds(bounds, element_bounds, &bounds_inited); 1751544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1752544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1753544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: { 1754544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 1755544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, ox, oy, 1756544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], 1757544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2], coords[3], 1758544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4], coords[5]); 1759544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_exact_bounds(&bezier, element_bounds); 1760544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin set_bounds(bounds, element_bounds, &bounds_inited); 1761544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1762544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1763544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 1764544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 1765544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 1766544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 1767544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 1768544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix identity; 1769544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = path_create(VG_PATH_DATATYPE_F, 1770544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); 1771544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1772544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&identity); 1773544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, segment, 1774544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox, oy, coords[3], coords[4], 1775544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], coords[2]); 1776544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1777544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_path(&arc, path, &identity); 1778544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1779544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_bounding_rect(path, element_bounds + 0, element_bounds + 1, 1780544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin element_bounds + 2, element_bounds + 3); 1781544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin set_bounds(bounds, element_bounds, &bounds_inited); 1782544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1783544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1784544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 1785544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 1786544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1787544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1788544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1789544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *x = bounds[0]; 1790544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *y = bounds[1]; 1791544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *w = bounds[2]; 1792544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *h = bounds[3]; 1793544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1794544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1795544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinfloat path_length(struct path *p, int start_segment, int num_segments) 1796544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1797544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1798544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8]; 1799544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_iter_data iter; 1800544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords; 1801544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat length = 0; 1802544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat ox, oy; 1803544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean in_range = VG_FALSE; 1804544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1805544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&iter, 0, sizeof(struct path_iter_data)); 1806544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1807544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.path = p; 1808544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.coords = p->control_points->data; 1809544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1810544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < (start_segment + num_segments); ++i) { 1811544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte segment; 1812544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1813544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.segment = ((VGubyte*)(p->segments->data))[i]; 1814544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1815544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox = iter.ox; 1816544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin oy = iter.oy; 1817544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1818544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin segment = normalize_coords(&iter, &num_coords, coords); 1819544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1820544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin in_range = (i >= start_segment) && i <= (start_segment + num_segments); 1821544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!in_range) 1822544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 1823544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1824544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(segment) { 1825544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 1826544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1827544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: { 1828544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {ox, oy, iter.sx, iter.sy}; 1829544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length += line_lengthv(line); 1830544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1831544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1832544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: { 1833544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {ox, oy, coords[0], coords[1]}; 1834544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length += line_lengthv(line); 1835544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1836544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1837544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: { 1838544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 1839544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, ox, oy, 1840544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], 1841544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2], coords[3], 1842544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4], coords[5]); 1843544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length += bezier_length(&bezier, BEZIER_DEFAULT_ERROR); 1844544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1845544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1846544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 1847544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 1848544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 1849544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 1850544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 1851544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix identity; 1852544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = path_create(VG_PATH_DATATYPE_F, 1853544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); 1854544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1855544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&identity); 1856544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, segment, 1857544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ox, oy, coords[3], coords[4], 1858544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], coords[2]); 1859544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1860544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_path(&arc, path, &identity); 1861544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1862544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length += path_length(path, 0, path_num_segments(path)); 1863544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1864544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1865544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 1866544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 1867544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1868544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1869544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1870544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return length; 1871544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1872544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1873544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGboolean point_on_current_segment(VGfloat distance, 1874544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat length, 1875544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat segment_length) 1876544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1877544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 1878544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (((floatIsZero(distance) || distance < 0) && floatIsZero(length)) || 1879544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ((distance > length || floatsEqual(distance, length)) && 1880544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (floatsEqual(distance, length + segment_length) || 1881544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin distance < (length + segment_length)))); 1882544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1883544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1884544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean path_point_segment(struct path_iter_data iter, 1885544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_iter_data prev_iter, 1886544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8], 1887544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat distance, 1888544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat length, VGfloat *current_length, 1889544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *point, VGfloat *normal) 1890544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1891544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (iter.segment) { 1892544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 1893544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1894544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: { 1895544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy}; 1896544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean on_current_segment = VG_FALSE; 1897544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length = line_lengthv(line); 1898544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin on_current_segment = point_on_current_segment(distance, 1899544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length, 1900544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length); 1901544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (on_current_segment) { 1902544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat at = (distance - length) / line_lengthv(line); 1903544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normal_vector(line, normal); 1904544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_point_at(line, at, point); 1905544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1906544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1907544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1908544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1909544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: { 1910544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]}; 1911544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean on_current_segment = VG_FALSE; 1912544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length = line_lengthv(line); 1913544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin on_current_segment = point_on_current_segment(distance, 1914544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length, 1915544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length); 1916544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (on_current_segment) { 1917544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat at = (distance - length) / line_lengthv(line); 1918544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normal_vector(line, normal); 1919544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_point_at(line, at, point); 1920544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1921544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1922544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1923544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1924544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: { 1925544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 1926544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, prev_iter.ox, prev_iter.oy, 1927544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], 1928544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2], coords[3], 1929544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4], coords[5]); 1930544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length = bezier_length(&bezier, BEZIER_DEFAULT_ERROR); 1931544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (point_on_current_segment(distance, length, *current_length)) { 1932544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_point_at_length(&bezier, distance - length, 1933544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin point, normal); 1934544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1935544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1936544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1937544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1938544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 1939544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 1940544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 1941544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 1942544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 1943544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix identity; 1944544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = path_create(VG_PATH_DATATYPE_F, 1945544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); 1946544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1947544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&identity); 1948544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, iter.segment, 1949544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_iter.ox, prev_iter.oy, coords[3], coords[4], 1950544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], coords[2]); 1951544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1952544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_path(&arc, path, &identity); 1953544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1954544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *current_length = path_length(path, 0, path_num_segments(path)); 1955544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (point_on_current_segment(distance, length, *current_length)) { 1956544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_point(path, 0, path_num_segments(path), 1957544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin distance - length, point, normal); 1958544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1959544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1960544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1961544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 1962544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 1963544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 1964544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1965544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 1966544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1967544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1968544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid path_point(struct path *p, VGint start_segment, VGint num_segments, 1969544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat distance, VGfloat *point, VGfloat *normal) 1970544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1971544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1972544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8]; 1973544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path_iter_data iter, prev_iter; 1974544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords; 1975544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat length = 0; 1976544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat current_length = 0; 1977544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1978544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&iter, 0, sizeof(struct path_iter_data)); 1979544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(&prev_iter, 0, sizeof(struct path_iter_data)); 1980544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1981544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin point[0] = 0; 1982544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin point[1] = 0; 1983544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1984544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin normal[0] = 0; 1985544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin normal[1] = -1; 1986544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1987544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.path = p; 1988544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.coords = p->control_points->data; 1989544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (distance < 0) 1990544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin distance = 0; 1991544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1992544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < (start_segment + num_segments); ++i) { 1993544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean outside_range = (i < start_segment || 1994544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin i >= (start_segment + num_segments)); 1995544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1996544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_iter = iter; 1997544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1998544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.segment = ((VGubyte*)(p->segments->data))[i]; 1999544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin iter.segment = normalize_coords(&iter, &num_coords, coords); 2000544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2001544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (outside_range) 2002544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin continue; 2003544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2004544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (path_point_segment(iter, prev_iter, coords, 2005544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin distance, length, ¤t_length, 2006544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin point, normal)) 2007544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 2008544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2009544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin length += current_length; 2010544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2011544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2012544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* 2013544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *OpenVG 1.0 - 8.6.11 vgPointAlongPath 2014544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * 2015544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * If distance is greater than or equal to the path length 2016544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *(i.e., the value returned by vgPathLength when called with the same 2017544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *startSegment and numSegments parameters), the visual ending point of 2018544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin *the path is used. 2019544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin */ 2020544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 2021544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (iter.segment) { 2022544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 2023544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 2024544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CLOSE_PATH: { 2025544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy}; 2026544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normal_vector(line, normal); 2027544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_point_at(line, 1.f, point); 2028544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2029544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 2030544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: { 2031544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]}; 2032544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normal_vector(line, normal); 2033544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_point_at(line, 1.f, point); 2034544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2035544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 2036544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: { 2037544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 2038544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, prev_iter.ox, prev_iter.oy, 2039544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], 2040544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2], coords[3], 2041544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4], coords[5]); 2042544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_point_at_t(&bezier, 1.f, point, normal); 2043544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2044544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 2045544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCCWARC_TO: 2046544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_SCWARC_TO: 2047544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCCWARC_TO: 2048544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LCWARC_TO: { 2049544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 2050544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix identity; 2051544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct path *path = path_create(VG_PATH_DATATYPE_F, 2052544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); 2053544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2054544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&identity); 2055544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_init(&arc, iter.segment, 2056544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_iter.ox, prev_iter.oy, coords[3], coords[4], 2057544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0], coords[1], coords[2]); 2058544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2059544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_to_path(&arc, path, &identity); 2060544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2061544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_point(path, 0, path_num_segments(path), 2062544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* to make sure we're bigger than len * 2 it */ 2063544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2 * path_length(path, 0, path_num_segments(path)), 2064544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin point, normal); 2065544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2066544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 2067544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 2068544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 2069544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2070544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 2071544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 2072544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 2073544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack RusinVGboolean path_is_empty(struct path *p) 2074544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 2075544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return p->segments->num_elements == 0; 2076544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 2077