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 "stroker.h" 28544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 29544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "path.h" 30544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "vg_state.h" 31544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "util_array.h" 32544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "arc.h" 33544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "bezier.h" 34544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "matrix.h" 35544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "path_utils.h" 36544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#include "polygon.h" 37544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 38e5b5d84e8a87a5603a84f8c4625592a278bcf9afChia-I Wu#include "util/u_math.h" 39544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 40544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#ifndef M_2PI 41544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define M_2PI 6.28318530717958647692528676655900576 42544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 43544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 44544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define STROKE_SEGMENTS 0 45544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define STROKE_DEBUG 0 46544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define DEBUG_EMITS 0 47544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 48544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const VGfloat curve_threshold = 0.25f; 49544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 50544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic const VGfloat zero_coords[] = {0.f, 0.f}; 51544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 52544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinenum intersection_type { 53544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin NoIntersections, 54544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin BoundedIntersection, 55544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin UnboundedIntersection, 56544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 57544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 58544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinenum line_join_mode { 59544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin FlatJoin, 60544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin SquareJoin, 61544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin MiterJoin, 62544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin RoundJoin, 63544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin RoundCap 64544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 65544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 66544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstruct stroke_iterator { 67544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void (*next)(struct stroke_iterator *); 68544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean (*has_next)(struct stroke_iterator *); 69544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 70544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand (*current_command)(struct stroke_iterator *it); 71544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin void (*current_coords)(struct stroke_iterator *it, VGfloat *coords); 72544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 73544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint position; 74544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint coord_position; 75544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 76544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGubyte *cmds; 77544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *coords; 78544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_commands; 79544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords; 80544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 81544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct polygon *curve_poly; 82544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint curve_index; 83544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin}; 84544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 85544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGPathCommand stroke_itr_command(struct stroke_iterator *itr) 86544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 87544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return itr->current_command(itr); 88544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 89544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 90544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_itr_coords(struct stroke_iterator *itr, VGfloat *coords) 91544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 92544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_coords(itr, coords); 93544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 94544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 95544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_fw_itr_coords(struct stroke_iterator *itr, VGfloat *coords) 96544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 97544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->position >= itr->num_commands) 98544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 99544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (stroke_itr_command(itr)) { 100544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 101544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 102544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 103544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 104544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: 105544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 106544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 107544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 108544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: 109544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 110544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 111544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2] = itr->coords[itr->coord_position + 2]; 112544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[3] = itr->coords[itr->coord_position + 3]; 113544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4] = itr->coords[itr->coord_position + 4]; 114544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[5] = itr->coords[itr->coord_position + 5]; 115544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 116544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 117544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"invalid command!\n"); 118544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 119544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 120544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 121544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 122544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_bw_itr_coords(struct stroke_iterator *itr, VGfloat *coords) 123544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 124544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->position >= itr->num_commands) 125544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 126544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (stroke_itr_command(itr)) { 127544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 128544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 129544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 130544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 131544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: 132544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 133544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 134544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 135544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: 136544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position + 4]; 137544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 5]; 138544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2] = itr->coords[itr->coord_position + 2]; 139544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[3] = itr->coords[itr->coord_position + 3]; 140544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4] = itr->coords[itr->coord_position + 0]; 141544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[5] = itr->coords[itr->coord_position + 1]; 142544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 143544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 144544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"invalid command!\n"); 145544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 146544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 147544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 148544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 149544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGPathCommand stroke_fw_current_command(struct stroke_iterator *it) 150544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 151544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return it->cmds[it->position]; 152544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 153544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 154544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGPathCommand stroke_bw_current_command(struct stroke_iterator *it) 155544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 156544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand prev_cmd; 157544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (it->position == it->num_commands -1) 158544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_MOVE_TO_ABS; 159544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 160544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_cmd = it->cmds[it->position + 1]; 161544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return prev_cmd; 162544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 163544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 164544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean stroke_fw_has_next(struct stroke_iterator *itr) 165544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 166544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return itr->position < (itr->num_commands - 1); 167544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 168544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 169544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean stroke_bw_has_next(struct stroke_iterator *itr) 170544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 171544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return itr->position > 0; 172544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 173544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 174544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_fw_next(struct stroke_iterator *itr) 175544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 176544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmd; 177544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(stroke_fw_has_next(itr)); 178544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 179544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(itr); 180544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 181544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position += num_elements_for_segments(&cmd, 1); 182544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr->position; 183544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 184544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 185544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_bw_next(struct stroke_iterator *itr) 186544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 187544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmd; 188544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(stroke_bw_has_next(itr)); 189544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 190544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin --itr->position; 191544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(itr); 192544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 193544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position -= num_elements_for_segments(&cmd, 1); 194544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 195544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 196544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_itr_common_init(struct stroke_iterator *itr, 197544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *cmds, 198544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *coords) 199544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 200544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->cmds = (VGubyte*)cmds->data; 201544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->num_commands = cmds->num_elements; 202544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 203544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coords = (VGfloat*)coords->data; 204544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->num_coords = coords->num_elements; 205544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 206544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 207544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_forward_iterator(struct stroke_iterator *itr, 208544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *cmds, 209544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *coords) 210544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 211544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_common_init(itr, cmds, coords); 212544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->position = 0; 213544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position = 0; 214544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 215544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->next = stroke_fw_next; 216544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->has_next = stroke_fw_has_next; 217544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_command = stroke_fw_current_command; 218544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_coords = stroke_fw_itr_coords; 219544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 220544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 221544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_backward_iterator(struct stroke_iterator *itr, 222544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *cmds, 223544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *coords) 224544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 225544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmd; 226544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_common_init(itr, cmds, coords); 227544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->position = itr->num_commands - 1; 228544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 229544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_bw_current_command(itr); 230544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position = itr->num_coords - 231544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin num_elements_for_segments(&cmd, 1); 232544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 233544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->next = stroke_bw_next; 234544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->has_next = stroke_bw_has_next; 235544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_command = stroke_bw_current_command; 236544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_coords = stroke_bw_itr_coords; 237544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 238544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 239544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 240544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 241544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_flat_next(struct stroke_iterator *itr) 242544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 243544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmd; 244544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 245544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->curve_index >= 0) { 246544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr->curve_index; 247544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->curve_index >= polygon_vertex_count(itr->curve_poly)) { 248544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_index = -1; 249544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_destroy(itr->curve_poly); 250544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_poly = 0; 251544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else 252544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 253544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 254544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(stroke_fw_has_next(itr)); 255544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 256544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = itr->cmds[itr->position]; 257544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position += num_elements_for_segments(&cmd, 1); 258544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ++itr->position; 259544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 260544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = itr->cmds[itr->position]; 261544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 262544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cmd == VG_CUBIC_TO_ABS) { 263544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 264544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat bez[8]; 265544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 266544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[0] = itr->coords[itr->coord_position - 2]; 267544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[1] = itr->coords[itr->coord_position - 1]; 268544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[2] = itr->coords[itr->coord_position]; 269544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[3] = itr->coords[itr->coord_position + 1]; 270544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[4] = itr->coords[itr->coord_position + 2]; 271544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[5] = itr->coords[itr->coord_position + 3]; 272544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[6] = itr->coords[itr->coord_position + 4]; 273544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[7] = itr->coords[itr->coord_position + 5]; 274544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 275544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, 276544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[0], bez[1], 277544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[2], bez[3], 278544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[4], bez[5], 279544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez[6], bez[7]); 280544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* skip the first one, it's the same as the prev point */ 281544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_index = 1; 282544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->curve_poly) { 283544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_destroy(itr->curve_poly); 284544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_poly = 0; 285544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 286544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_poly = bezier_to_polygon(&bezier); 287544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 288544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 289544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 290544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean stroke_flat_has_next(struct stroke_iterator *itr) 291544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 292544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return (itr->curve_index >= 0 && 293544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_index < (polygon_vertex_count(itr->curve_poly)-1)) 294544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin || itr->position < (itr->num_commands - 1); 295544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 296544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 297544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGPathCommand stroke_flat_current_command(struct stroke_iterator *it) 298544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 299544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (it->cmds[it->position] == VG_CUBIC_TO_ABS) { 300544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_LINE_TO_ABS; 301544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 302544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return it->cmds[it->position]; 303544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 304544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 305544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_flat_itr_coords(struct stroke_iterator *itr, VGfloat *coords) 306544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 307544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->curve_index <= -1 && itr->position >= itr->num_commands) 308544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 309544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 310544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (itr->curve_index >= 0) { 311544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_vertex(itr->curve_poly, itr->curve_index, 312544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords); 313544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 314544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 315544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 316544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (stroke_itr_command(itr)) { 317544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 318544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 319544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 320544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 321544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: 322544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[0] = itr->coords[itr->coord_position]; 323544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[1] = itr->coords[itr->coord_position + 1]; 324544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 325544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: 326544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 327544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"invalid command!\n"); 328544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 329544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 330544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 331544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroke_flat_iterator(struct stroke_iterator *itr, 332544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *cmds, 333544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct array *coords) 334544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 335544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_common_init(itr, cmds, coords); 336544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->position = 0; 337544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->coord_position = 0; 338544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 339544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->next = stroke_flat_next; 340544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->has_next = stroke_flat_has_next; 341544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_command = stroke_flat_current_command; 342544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->current_coords = stroke_flat_itr_coords; 343544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_index = -1; 344544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin itr->curve_poly = 0; 345544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 346544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 347544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 348544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGboolean finite_coords4(const VGfloat *c) 349544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 350544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 351544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isfinite(c[0]) && isfinite(c[1]) && 352544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isfinite(c[2]) && isfinite(c[3]); 353544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 354544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 355544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin/* from Graphics Gems II */ 356544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#define SAME_SIGNS(a, b) ((a) * (b) >= 0) 357544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean do_lines_intersect(VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, 358544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4) 359544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 360544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns */ 361544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat r1, r2, r3, r4; /* 'sign' values */ 362544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 363544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a1 = y2 - y1; 364544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b1 = x1 - x2; 365544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin c1 = x2 * y1 - x1 * y2; 366544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 367544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin r3 = a1 * x3 + b1 * y3 + c1; 368544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin r4 = a1 * x4 + b1 * y4 + c1; 369544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 370544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (r3 != 0 && r4 != 0 && SAME_SIGNS(r3, r4)) 371544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 372544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 373544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a2 = y4 - y3; 374544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin b2 = x3 - x4; 375544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin c2 = x4 * y3 - x3 * y4; 376544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 377544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin r1 = a2 * x1 + b2 * y1 + c2; 378544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin r2 = a2 * x2 + b2 * y2 + c2; 379544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 380544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (r1 != 0 && r2 != 0 && SAME_SIGNS(r1, r2)) 381544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 382544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 383544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 384544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 385544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 386544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat line_dx(const VGfloat *l) 387544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 388544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return l[2] - l[0]; 389544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 390544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 391544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat line_dy(const VGfloat *l) 392544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 393544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return l[3] - l[1]; 394544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 395544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 396544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat line_angle(const VGfloat *l) 397544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 398544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat dx = line_dx(l); 399544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat dy = line_dy(l); 400544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 401544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat theta = atan2(-dy, dx) * 360.0 / M_2PI; 402544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 403544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat theta_normalized = theta < 0 ? theta + 360 : theta; 404544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 405544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(theta_normalized, 360.f)) 406544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 0; 407544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 408544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return theta_normalized; 409544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 410544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 411544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void line_set_length(VGfloat *l, VGfloat len) 412544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 413544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat uv[] = {l[0], l[1], l[2], l[3]}; 414544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (null_line(l)) 415544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 416544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normalize(uv); 417544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[2] = l[0] + line_dx(uv) * len; 418544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[3] = l[1] + line_dy(uv) * len; 419544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 420544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 421544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void line_translate(VGfloat *l, VGfloat x, VGfloat y) 422544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 423544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[0] += x; 424544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[1] += y; 425544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[2] += x; 426544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l[3] += y; 427544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 428544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 429544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat line_angle_to(const VGfloat *l1, 430544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *l2) 431544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 432544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat a1, a2, delta, delta_normalized; 433544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (null_line(l1) || null_line(l1)) 434544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 0; 435544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 436544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a1 = line_angle(l1); 437544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin a2 = line_angle(l2); 438544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 439544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin delta = a2 - a1; 440544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin delta_normalized = delta < 0 ? delta + 360 : delta; 441544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 442544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(delta, 360.f)) 443544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 0; 444544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 445544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return delta_normalized; 446544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 447544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 448544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat line_angles(const VGfloat *l1, 449544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *l2) 450544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 451544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat cos_line, rad = 0; 452544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 453544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (null_line(l1) || null_line(l2)) 454544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 0; 455544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 456544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cos_line = (line_dx(l1)*line_dx(l2) + line_dy(l1)*line_dy(l2)) / 457544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (line_lengthv(l1)*line_lengthv(l2)); 458544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rad = 0; 459544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 460544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cos_line >= -1.0 && cos_line <= 1.0) 461544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin rad = acos(cos_line); 462544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return rad * 360 / M_2PI; 463544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 464544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 465544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 466544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat adapted_angle_on_x(const VGfloat *line) 467544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 468544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat identity[] = {0, 0, 1, 0}; 469544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat angle = line_angles(line, identity); 470544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (line_dy(line) > 0) 471544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin angle = 360 - angle; 472544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return angle; 473544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 474544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 475544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic enum intersection_type line_intersect(const VGfloat *l1, 476544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *l2, 477544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin float *intersection_point) 478544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 479bf63b9d7a942bfbeef0b2b765bfc346c93de6fb7Vinson Lee VGfloat isect[2] = { 0 }; 480544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin enum intersection_type type; 481544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean dx_zero, ldx_zero; 482544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 483544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (null_line(l1) || null_line(l2) || 484544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin !finite_coords4(l1) || !finite_coords4(l2)) 485544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return NoIntersections; 486544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 487544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type = do_lines_intersect(l1[0], l1[1], l1[2], l1[3], l2[0], l2[1], l2[2], l2[3]) 488544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ? BoundedIntersection : UnboundedIntersection; 489544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 490544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin dx_zero = floatsEqual(line_dx(l1) + 1, 1); 491544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin ldx_zero = floatsEqual(line_dx(l2) + 1, 1); 492544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 493544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* one of the lines is vertical */ 494544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dx_zero && ldx_zero) { 495544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin type = NoIntersections; 496544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (dx_zero) { 497544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat la = line_dy(l2) / line_dx(l2); 498544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[0] = l1[0]; 499544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[1] = la * l1[0] + l2[1] - la * l2[0]; 500544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (ldx_zero) { 501544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat ta = line_dy(l1) / line_dx(l1); 502544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[0] = l2[0]; 503544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[1] = ta * l2[0] + l1[1] - ta*l1[0]; 504544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 505544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x; 506544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat ta = line_dy(l1) / line_dx(l1); 507544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat la = line_dy(l2) / line_dx(l2); 508544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (ta == la) 509544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return NoIntersections; 510544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 511544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x = ( - l2[1] + la * l2[0] + l1[1] - ta * l1[0] ) / (la - ta); 512544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[0] = x; 513544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[1] = ta*(x - l1[0]) + l1[1]; 514544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 515544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (intersection_point) { 516544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin intersection_point[0] = isect[0]; 517544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin intersection_point[1] = isect[1]; 518544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 519544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return type; 520544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 521544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 522544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE enum line_join_mode stroker_join_mode(struct stroker *s) 523544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 524544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(s->join_style) { 525544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_JOIN_MITER: 526544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return MiterJoin; 527544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_JOIN_ROUND: 528544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return RoundJoin; 529544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_JOIN_BEVEL: 530544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return FlatJoin; 531544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 532544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return FlatJoin; 533544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 534544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 535544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 536544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE enum line_join_mode stroker_cap_mode(struct stroker *s) 537544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 538544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(s->cap_style) { 539544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CAP_BUTT: 540544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return FlatJoin; 541544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CAP_ROUND: 542544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return RoundCap; 543544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CAP_SQUARE: 544544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return SquareJoin; 545544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 546544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return FlatJoin; 547544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 548544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 549544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 550544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y) 551544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 552544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmds = VG_MOVE_TO_ABS; 553544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[2] = {x, y}; 554544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_EMITS 555544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("emit move %f, %f\n", x, y); 556544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 557544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = stroker->back1_x; 558544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = stroker->back1_y; 559544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_x = x; 560544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_y = y; 561544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 562544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(stroker->path, 563544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 564544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &cmds, &coords); 565544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 566544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 567544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y) 568544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 569544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmds = VG_LINE_TO_ABS; 570544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[2] = {x, y}; 571544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_EMITS 572544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("emit line %f, %f\n", x, y); 573544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 574544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = stroker->back1_x; 575544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = stroker->back1_y; 576544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_x = x; 577544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_y = y; 578544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(stroker->path, 579544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 580544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &cmds, &coords); 581544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 582544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 583544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, 584544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat px2, VGfloat py2, 585544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x, VGfloat y) 586544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 587544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGubyte cmds = VG_CUBIC_TO_ABS; 588544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[6] = {px1, py1, px2, py2, x, y}; 589544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_EMITS 590544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("emit curve %f, %f, %f, %f, %f, %f\n", px1, py1, 591544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px2, py2, x, y); 592544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 593544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 594544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (px2 == x && py2 == y) { 595544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (px1 == x && py1 == y) { 596544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = stroker->back1_x; 597544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = stroker->back1_y; 598544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 599544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = px1; 600544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = py1; 601544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 602544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 603544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = px2; 604544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = py2; 605544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 606544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_x = x; 607544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_y = y; 608544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 609544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_append_data(stroker->path, 610544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1, 611544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin &cmds, &coords); 612544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 613544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 614544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE void create_round_join(struct stroker *stroker, 615544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x1, VGfloat y1, 616544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x2, VGfloat y2, 617544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat width, VGfloat height) 618544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 619544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 620544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix matrix; 621544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 622544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&matrix); 623544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 624544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /*stroker_emit_line_to(stroker, nx, ny);*/ 625544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 626e55cf4854d594eae9ac3f6abd24f4e616eea894fDylan Noblesmith arc_init(&arc, VG_SCCWARC_TO, 627544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x1, y1, x2, y2, width/2, height/2, 0); 628544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_stroker_emit(&arc, stroker, &matrix); 629544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 630544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 631544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 632544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void create_joins(struct stroker *stroker, 633544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat focal_x, VGfloat focal_y, 634544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *next_line, enum line_join_mode join) 635544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 636544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if DEBUG_EMITS 637544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("create_joins: focal=[%f, %f], next_line=[%f, %f,%f, %f]\n", 638544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin focal_x, focal_y, 639544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[0], next_line[1], next_line[2], next_line[3]); 640544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 641544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if we're alredy connected do nothing */ 642544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(stroker->back1_x, next_line[0]) && 643544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(stroker->back1_y, next_line[1])) 644544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 645544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 646544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (join == FlatJoin) { 647544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 648544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 649544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat prev_line[] = {stroker->back2_x, stroker->back2_y, 650544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_x, stroker->back1_y}; 651544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 652bf63b9d7a942bfbeef0b2b765bfc346c93de6fb7Vinson Lee VGfloat isect[2] = { 0 }; 653544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin enum intersection_type type = line_intersect(prev_line, next_line, isect); 654544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 655544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (join == SquareJoin) { 656544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset = stroker->stroke_width / 2; 657544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat l1[4] = {prev_line[0], 658544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[1], 659544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[2], 660544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[3]}; 661544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat l2[4] = {next_line[2], 662544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[3], 663544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[0], 664544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[1]}; 665544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 666544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(l1, line_dx(l1), line_dy(l1)); 667544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_set_length(l1, offset); 668544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 669544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(l2, line_dx(l2), line_dy(l2)); 670544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_set_length(l2, offset); 671544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 672544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, l1[2], l1[3]); 673544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, l2[2], l2[3]); 674544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, l2[0], l2[1]); 675544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (join == RoundJoin) { 676544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset = stroker->stroke_width / 2; 677544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat short_cut[4] = {prev_line[2], prev_line[3], 678544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[0], next_line[1]}; 679544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat angle = line_angles(prev_line, short_cut); 680544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 681544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (type == BoundedIntersection || 682544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (angle > 90 && !floatsEqual(angle, 90.f))) { 683544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 684544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 685544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 686544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_round_join(stroker, prev_line[2], prev_line[3], 687544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[0], next_line[1], 688544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset * 2, offset * 2); 689544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 690544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 691544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (join == RoundCap) { 692544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset = stroker->stroke_width / 2; 693544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat l1[4] = { prev_line[0], prev_line[1], 694544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[2], prev_line[3] }; 695544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat l2[4] = {focal_x, focal_y, 696544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[2], prev_line[3]}; 697544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 698544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(l1, line_dx(l1), line_dy(l1)); 699544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_set_length(l1, KAPPA * offset); 700544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 701544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* normal between prev_line and focal */ 702544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(l2, -line_dy(l2), line_dx(l2)); 703544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_set_length(l2, KAPPA * offset); 704544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 705544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_curve_to(stroker, l1[2], l1[3], 706544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[2], l2[3], 707544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[0], l2[1]); 708544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 709544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[0] = l2[0]; 710544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[1] = l2[1]; 711544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[2] = l2[0] - line_dx(l2); 712544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[3] = l2[1] - line_dy(l2); 713544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 714544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(l1, next_line[0] - l1[0], next_line[1] - l1[1]); 715544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 716544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_curve_to(stroker, 717544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l2[2], l2[3], 718544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l1[2], l1[3], 719544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin l1[0], l1[1]); 720544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (join == MiterJoin) { 721544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat miter_line[4] = {stroker->back1_x, stroker->back1_y, 722544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin isect[0], isect[1]}; 723544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat sl = (stroker->stroke_width * stroker->miter_limit); 724544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat inside_line[4] = {prev_line[2], prev_line[3], 725544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin next_line[0], next_line[1]}; 726544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat angle = line_angle_to(inside_line, prev_line); 727544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 728544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (type == BoundedIntersection || 729544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (angle > 90 && !floatsEqual(angle, 90.f))) { 730544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* 731544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("f = %f, nl = %f, pl = %f, is = %f\n", 732544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin focal_x, next_line[0], 733544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev_line[2], isect[0]);*/ 734544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 735544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 736544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 737544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 738544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (type == NoIntersections || line_lengthv(miter_line) > sl) { 739544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 740544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 741544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, isect[0], isect[1]); 742544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, next_line[0], next_line[1]); 743544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 744544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 745544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"create_joins bad join style"); 746544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 747544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 748544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 749544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 750544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroker_add_segment(struct stroker *stroker, 751544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand cmd, 752544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin const VGfloat *coords, 753544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint num_coords) 754544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 755544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* skip duplicated points */ 756544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->segments->num_elements && 757544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->last_cmd == cmd) { 758544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *data = stroker->control_points->data; 759544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data += stroker->control_points->num_elements; 760544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data -= num_coords; 761544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch (cmd) { 762544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 763544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(coords[0], data[0]) && 764544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], data[1])) 765544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 766544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 767544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: 768544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(coords[0], data[0]) && 769544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], data[1])) 770544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 771544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 772544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: 773544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(coords[0], data[0]) && 774544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], data[1]) && 775544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[2], data[2]) && 776544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[3], data[3]) && 777544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[4], data[4]) && 778544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[5], data[5])) 779544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 780544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 781544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 782544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(!"Invalid stroke segment"); 783544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 784544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (stroker->last_cmd == VG_CUBIC_TO_ABS && 785544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd == VG_LINE_TO_ABS) { 786544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *data = stroker->control_points->data; 787544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data += stroker->control_points->num_elements; 788544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data -= 2; 789544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(coords[0], data[0]) && 790544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], data[1])) 791544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 792544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 793544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->last_cmd = cmd; 794544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(stroker->segments, &cmd, 1); 795544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_append_data(stroker->control_points, coords, num_coords); 796544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 797544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 798544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y) 799544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 800544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[2] = {x, y}; 801544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_SEGMENTS 802544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("stroker_move_to(%f, %f)\n", x, y); 803544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 804544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 805544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->segments->num_elements > 0) 806544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->process_subpath(stroker); 807544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 808544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_reset(stroker->segments); 809544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_reset(stroker->control_points); 810544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 811544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_add_segment(stroker, VG_MOVE_TO_ABS, coords, 2); 812544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 813544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 814544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y) 815544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 816544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[] = {x, y}; 817544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 818544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_SEGMENTS 819544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("stroker_line_to(%f, %f)\n", x, y); 820544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 821544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!stroker->segments->num_elements) 822544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2); 823544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 824544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_add_segment(stroker, VG_LINE_TO_ABS, coords, 2); 825544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 826544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 827544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, 828544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat px2, VGfloat py2, 829544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat x, VGfloat y) 830544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 831544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[] = {px1, py1, 832544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px2, py2, 833544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin x, y}; 834544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_SEGMENTS 835544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("stroker_curve_to(%f, %f, %f, %f, %f, %f)\n", 836544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin px1, py1, px2, py2, x, y); 837544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 838544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!stroker->segments->num_elements) 839544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2); 840544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 841544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_add_segment(stroker, VG_CUBIC_TO_ABS, coords, 6); 842544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 843544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 844544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGboolean is_segment_null(VGPathCommand cmd, 845544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *coords, 846544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *res) 847544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 848544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin switch(cmd) { 849544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_MOVE_TO_ABS: 850544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_LINE_TO_ABS: 851544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return floatsEqual(coords[0], res[0]) && 852544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], res[1]); 853544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 854544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin case VG_CUBIC_TO_ABS: 855544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return floatsEqual(coords[0], res[0]) && 856544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[1], res[1]) && 857544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[2], res[0]) && 858544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[3], res[1]) && 859544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[4], res[0]) && 860544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(coords[5], res[1]); 861544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin break; 862544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default: 863544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin assert(0); 864544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 865544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 866544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 867544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 868544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic VGboolean vg_stroke_outline(struct stroke_iterator *it, 869544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroker *stroker, 870544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean cap_first, 871544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat *start_tangent) 872544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 873e5b5d84e8a87a5603a84f8c4625592a278bcf9afChia-I Wu#define MAX_OFFSET 16 874544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier offset_curves[MAX_OFFSET]; 875544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand first_element; 876544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat start[2], prev[2]; 877544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean first = VG_TRUE; 878544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset; 879544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 880544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin first_element = stroke_itr_command(it); 881544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (first_element != VG_MOVE_TO_ABS) { 882544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_move_to(stroker, 0.f, 0.f); 883544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0] = 0.f; 884544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[1] = 0.f; 885544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 886544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(it, start); 887544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_DEBUG 888544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf(" -> (side) [%.2f, %.2f]\n", 889544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start[0], 890544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start[1]); 891544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 892544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 893544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0] = start[0]; 894544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[1] = start[1]; 895544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 896544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset = stroker->stroke_width / 2; 897544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 898544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!it->has_next(it)) { 899544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* single point */ 900544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 901544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 902544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 903544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 904544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while (it->has_next(it)) { 905544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand cmd; 906544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8]; 907544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 908544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin it->next(it); 909544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(it); 910544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(it, coords); 911544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 912544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cmd == VG_LINE_TO_ABS) { 913544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line[4] = {prev[0], prev[1], coords[0], coords[1]}; 914544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat normal[4]; 915544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_normal(line, normal); 916544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 917544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_DEBUG 918544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("\n ---> (side) lineto [%.2f, %.2f]\n", coords[0], coords[1]); 919544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 920544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_set_length(normal, offset); 921544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(line, line_dx(normal), line_dy(normal)); 922544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 923544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if we are starting a new subpath, move to correct starting point */ 924544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (first) { 925544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cap_first) 926544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, prev[0], prev[1], line, 927544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cap_mode(stroker)); 928544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else 929544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_move_to(stroker, line[0], line[1]); 930544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memcpy(start_tangent, line, 931544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sizeof(VGfloat) * 4); 932544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin first = VG_FALSE; 933544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 934544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, prev[0], prev[1], line, 935544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_join_mode(stroker)); 936544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 937544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 938544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* add the stroke for this line */ 939544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, line[2], line[3]); 940544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0] = coords[0]; 941544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[1] = coords[1]; 942544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (cmd == VG_CUBIC_TO_ABS) { 943544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_DEBUG 944544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("\n ---> (side) cubicTo [%.2f, %.2f]\n", 945544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[4], 946544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[5]); 947544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 948544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier bezier; 949544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int count; 950544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 951544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_init(&bezier, 952544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0], prev[1], coords[0], coords[1], 953544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin coords[2], coords[3], coords[4], coords[5]); 954544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 955544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin count = bezier_translate_by_normal(&bezier, 956544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset_curves, 957544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin MAX_OFFSET, 958544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset, 959544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin curve_threshold); 960544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 961544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (count) { 962544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if we are starting a new subpath, move to correct starting point */ 963544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat tangent[4]; 964544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 965544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 966544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bezier_start_tangent(&bezier, tangent); 967544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_translate(tangent, 968544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset_curves[0].x1 - bezier.x1, 969544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset_curves[0].y1 - bezier.y1); 970544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (first) { 971544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat pt[2] = {offset_curves[0].x1, 972544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset_curves[0].y1}; 973544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 974544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cap_first) { 975544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, prev[0], prev[1], tangent, 976544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cap_mode(stroker)); 977544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 978544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_move_to(stroker, pt[0], pt[1]); 979544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 980544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_tangent[0] = tangent[0]; 981544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_tangent[1] = tangent[1]; 982544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_tangent[2] = tangent[2]; 983544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin start_tangent[3] = tangent[3]; 984544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin first = VG_FALSE; 985544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 986544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, prev[0], prev[1], tangent, 987544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_join_mode(stroker)); 988544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 989544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 990544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* add these beziers */ 991544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < count; ++i) { 992544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct bezier *bez = &offset_curves[i]; 993544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_curve_to(stroker, 994544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez->x2, bez->y2, 995544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez->x3, bez->y3, 996544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bez->x4, bez->y4); 997544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 998544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 999544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1000544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0] = coords[4]; 1001544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[1] = coords[5]; 1002544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1003544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1004544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1005544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatsEqual(start[0], prev[0]) && 1006544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin floatsEqual(start[1], prev[1])) { 1007544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* closed subpath, join first and last point */ 1008544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_DEBUG 1009544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("\n stroker: closed subpath\n"); 1010544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 1011544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, prev[0], prev[1], start_tangent, 1012544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_join_mode(stroker)); 1013544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_TRUE; 1014544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 1015544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#if STROKE_DEBUG 1016544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_printf("\n stroker: open subpath\n"); 1017544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin#endif 1018544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return VG_FALSE; 1019544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1020e5b5d84e8a87a5603a84f8c4625592a278bcf9afChia-I Wu#undef MAX_OFFSET 1021544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1022544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1023544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void stroker_process_subpath(struct stroker *stroker) 1024544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1025544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean fwclosed, bwclosed; 1026544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat fw_start_tangent[4], bw_start_tangent[4]; 1027544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroke_iterator fwit; 1028544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroke_iterator bwit; 1029544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(stroker->segments->num_elements > 0); 1030544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1031544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(fw_start_tangent, 0, 1032544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sizeof(VGfloat)*4); 1033544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(bw_start_tangent, 0, 1034544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sizeof(VGfloat)*4); 1035544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1036544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_forward_iterator(&fwit, stroker->segments, 1037544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->control_points); 1038544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_backward_iterator(&bwit, stroker->segments, 1039544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->control_points); 1040544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1041544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(fwit.cmds[0] == VG_MOVE_TO_ABS); 1042544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1043544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin fwclosed = vg_stroke_outline(&fwit, stroker, VG_FALSE, fw_start_tangent); 1044544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin bwclosed = vg_stroke_outline(&bwit, stroker, !fwclosed, bw_start_tangent); 1045544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1046544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!bwclosed) 1047544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin create_joins(stroker, 1048544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin fwit.coords[0], fwit.coords[1], fw_start_tangent, 1049544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cap_mode(stroker)); 1050544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin else { 1051544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* hack to handle the requirement of the VG spec that says that strokes 1052544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * of len==0 that have butt cap or round cap still need 1053544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * to be rendered. (8.7.4 Stroke Generation) */ 1054544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->segments->num_elements <= 3) { 1055544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand cmd; 1056544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat data[8], coords[8]; 1057544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroke_iterator *it = &fwit; 1058544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1059544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_forward_iterator(it, stroker->segments, 1060544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->control_points); 1061544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(it); 1062544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(it, coords); 1063544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (cmd != VG_MOVE_TO_ABS) { 1064544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin memset(data, 0, sizeof(VGfloat) * 8); 1065544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!is_segment_null(cmd, coords, data)) 1066544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 1067544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 1068544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[0] = coords[0]; 1069544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] = coords[1]; 1070544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1071544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while (it->has_next(it)) { 1072544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin it->next(it); 1073544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(it); 1074544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(it, coords); 1075544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!is_segment_null(cmd, coords, data)) 1076544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 1077544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1078544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* generate the square/round cap */ 1079544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->cap_style == VG_CAP_SQUARE) { 1080544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset = stroker->stroke_width / 2; 1081544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_move_to(stroker, data[0] - offset, 1082544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] - offset); 1083544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, data[0] + offset, 1084544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] - offset); 1085544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, data[0] + offset, 1086544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] + offset); 1087544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, data[0] - offset, 1088544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] + offset); 1089544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_line_to(stroker, data[0] - offset, 1090544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin data[1] - offset); 1091544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else if (stroker->cap_style == VG_CAP_ROUND) { 1092544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat offset = stroker->stroke_width / 2; 1093544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat cx = data[0], cy = data[1]; 1094544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { /*circle */ 1095544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct arc arc; 1096544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct matrix matrix; 1097544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin matrix_load_identity(&matrix); 1098544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1099544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_emit_move_to(stroker, cx + offset, cy); 1100e55cf4854d594eae9ac3f6abd24f4e616eea894fDylan Noblesmith arc_init(&arc, VG_SCCWARC_TO, 1101544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx + offset, cy, 1102544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx - offset, cy, 1103544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset, offset, 0); 1104544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_stroker_emit(&arc, stroker, &matrix); 1105e55cf4854d594eae9ac3f6abd24f4e616eea894fDylan Noblesmith arc_init(&arc, VG_SCCWARC_TO, 1106544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx - offset, cy, 1107544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cx + offset, cy, 1108544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin offset, offset, 0); 1109544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin arc_stroker_emit(&arc, stroker, &matrix); 1110544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1111544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1112544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1113544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1114544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1115544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1116544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic INLINE VGfloat dash_pattern(struct dash_stroker *stroker, 1117544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint idx) 1118544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1119544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->dash_pattern[idx] < 0) 1120544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return 0.f; 1121544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return stroker->dash_pattern[idx]; 1122544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1123544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1124544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void dash_stroker_process_subpath(struct stroker *str) 1125544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1126544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct dash_stroker *stroker = (struct dash_stroker *)str; 1127544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat sum_length = 0; 1128544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint i; 1129544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint idash = 0; 1130544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat pos = 0; 1131544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat elen = 0; 1132544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat doffset = stroker->dash_phase; 1133544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat estart = 0; 1134544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat estop = 0; 1135544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat cline[4]; 1136544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct stroke_iterator it; 1137544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat prev[2]; 1138544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat move_to_pos[2]; 1139544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat line_to_pos[2]; 1140544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1141544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean has_move_to = VG_FALSE; 1142544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1143544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_flat_iterator(&it, stroker->base.segments, 1144544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.control_points); 1145544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1146544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(&it, prev); 1147544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin move_to_pos[0] = prev[0]; 1148544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin move_to_pos[1] = prev[1]; 1149544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1150544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(stroker->dash_pattern_num > 0); 1151544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1152544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < stroker->dash_pattern_num; ++i) { 1153544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin sum_length += dash_pattern(stroker, i); 1154544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1155544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1156544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (floatIsZero(sum_length)) { 1157544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin return; 1158544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1159544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1160544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin doffset -= floorf(doffset / sum_length) * sum_length; 1161544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1162544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while (!floatIsZero(doffset) && doffset >= dash_pattern(stroker, idash)) { 1163544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin doffset -= dash_pattern(stroker, idash); 1164544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin idash = (idash + 1) % stroker->dash_pattern_num; 1165544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1166544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1167544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while (it.has_next(&it)) { 1168544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGPathCommand cmd; 1169544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat coords[8]; 1170544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean done; 1171544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1172544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin it.next(&it); 1173544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cmd = stroke_itr_command(&it); 1174544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroke_itr_coords(&it, coords); 1175544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1176544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(cmd == VG_LINE_TO_ABS); 1177544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cline[0] = prev[0]; 1178544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cline[1] = prev[1]; 1179544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cline[2] = coords[0]; 1180544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin cline[3] = coords[1]; 1181544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1182544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin elen = line_lengthv(cline); 1183544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1184544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin estop = estart + elen; 1185544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1186544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin done = pos >= estop; 1187544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin while (!done) { 1188544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat p2[2]; 1189544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1190544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGint idash_incr = 0; 1191544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGboolean has_offset = doffset > 0; 1192544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin VGfloat dpos = pos + dash_pattern(stroker, idash) - doffset - estart; 1193544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1194544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin debug_assert(dpos >= 0); 1195544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1196544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (dpos > elen) { /* dash extends this line */ 1197544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin doffset = dash_pattern(stroker, idash) - (dpos - elen); 1198544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pos = estop; 1199544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin done = VG_TRUE; 1200544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p2[0] = cline[2]; 1201544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin p2[1] = cline[3]; 1202544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { /* Dash is on this line */ 1203544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_point_at(cline, dpos/elen, p2); 1204544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin pos = dpos + estart; 1205544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin done = pos >= estop; 1206544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin idash_incr = 1; 1207544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin doffset = 0; 1208544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1209544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1210544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (idash % 2 == 0) { 1211544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_to_pos[0] = p2[0]; 1212544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin line_to_pos[1] = p2[1]; 1213544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1214544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!has_offset || !has_move_to) { 1215544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_move_to(&stroker->stroker, move_to_pos[0], move_to_pos[1]); 1216544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin has_move_to = VG_TRUE; 1217544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1218544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_line_to(&stroker->stroker, line_to_pos[0], line_to_pos[1]); 1219544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } else { 1220544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin move_to_pos[0] = p2[0]; 1221544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin move_to_pos[1] = p2[1]; 1222544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1223544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1224544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin idash = (idash + idash_incr) % stroker->dash_pattern_num; 1225544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1226544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1227544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin estart = estop; 1228544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[0] = coords[0]; 1229544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin prev[1] = coords[1]; 1230544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1231544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1232544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (it.curve_poly) { 1233544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin polygon_destroy(it.curve_poly); 1234544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin it.curve_poly = 0; 1235544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1236544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1237544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.path = stroker->stroker.path; 1238544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1239544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1240544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void default_begin(struct stroker *stroker) 1241544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1242544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_reset(stroker->segments); 1243544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_reset(stroker->control_points); 1244544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1245544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1246544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void default_end(struct stroker *stroker) 1247544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1248544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (stroker->segments->num_elements > 0) 1249544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->process_subpath(stroker); 1250544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1251544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1252544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1253544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void dash_stroker_begin(struct stroker *stroker) 1254544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1255544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct dash_stroker *dasher = 1256544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (struct dash_stroker *)stroker; 1257544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1258544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default_begin(&dasher->stroker); 1259544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default_begin(stroker); 1260544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1261544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1262544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinstatic void dash_stroker_end(struct stroker *stroker) 1263544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1264544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct dash_stroker *dasher = 1265544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin (struct dash_stroker *)stroker; 1266544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1267544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default_end(stroker); 1268544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin default_end(&dasher->stroker); 1269544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1270544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1271544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_init(struct stroker *stroker, 1272544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_state *state) 1273544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1274544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->stroke_width = state->stroke.line_width.f; 1275544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->miter_limit = state->stroke.miter_limit.f; 1276544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->cap_style = state->stroke.cap_style; 1277544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->join_style = state->stroke.join_style; 1278544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1279544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->begin = default_begin; 1280544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->process_subpath = stroker_process_subpath; 1281544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->end = default_end; 1282544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1283544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->segments = array_create(sizeof(VGubyte)); 1284544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->control_points = array_create(sizeof(VGfloat)); 1285544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1286544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_x = 0; 1287544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back1_y = 0; 1288544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_x = 0; 1289544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->back2_y = 0; 1290544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1291544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->path = path_create(VG_PATH_DATATYPE_F, 1.0f, 0.0f, 1292544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 0, 0, VG_PATH_CAPABILITY_ALL); 1293544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1294e55cf4854d594eae9ac3f6abd24f4e616eea894fDylan Noblesmith /* Initialize with an invalid value */ 1295e55cf4854d594eae9ac3f6abd24f4e616eea894fDylan Noblesmith stroker->last_cmd = (VGPathCommand)0; 1296544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1297544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1298544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid dash_stroker_init(struct stroker *str, 1299544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct vg_state *state) 1300544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1301544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin struct dash_stroker *stroker = (struct dash_stroker *)str; 1302544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int i; 1303544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1304544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_init(str, state); 1305544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_init(&stroker->stroker, state); 1306544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1307544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin { 1308544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin int real_num = state->stroke.dash_pattern_num; 1309544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (real_num % 2)/* if odd, ignore the last one */ 1310544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin --real_num; 1311544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin for (i = 0; i < real_num; ++i) 1312544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->dash_pattern[i] = state->stroke.dash_pattern[i].f; 1313544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->dash_pattern_num = real_num; 1314544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin } 1315544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1316544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->dash_phase = state->stroke.dash_phase.f; 1317544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->dash_phase_reset = state->stroke.dash_phase_reset; 1318544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1319544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.begin = dash_stroker_begin; 1320544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.process_subpath = dash_stroker_process_subpath; 1321544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.end = dash_stroker_end; 1322544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(stroker->base.path); 1323544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->base.path = NULL; 1324544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1325544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1326544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_begin(struct stroker *stroker) 1327544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1328544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->begin(stroker); 1329544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1330544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1331544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_end(struct stroker *stroker) 1332544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1333544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker->end(stroker); 1334544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1335544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1336544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid stroker_cleanup(struct stroker *stroker) 1337544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1338544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(stroker->segments); 1339544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin array_destroy(stroker->control_points); 1340544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1341544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin 1342544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusinvoid dash_stroker_cleanup(struct dash_stroker *stroker) 1343544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin{ 1344544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin /* if stroker->base.path is null means we never 1345544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * processed a valid path so delete the temp one 1346544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin * we already created */ 1347544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin if (!stroker->base.path) 1348544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin path_destroy(stroker->stroker.path); 1349544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cleanup(&stroker->stroker); 1350544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin stroker_cleanup((struct stroker*)stroker); 1351544dd4b11f7be76bb00fe29a60eaf2772dcc69caZack Rusin} 1352