1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* ftstroke.c */ 4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* FreeType path stroker (body). */ 6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 7c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner/* Copyright 2002-2006, 2008-2011 by */ 8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* This file is part of the FreeType project, and may only be used, */ 11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* modified, and distributed under the terms of the FreeType project */ 12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* this file you indicate that you have read the license and */ 14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* understand and accept it fully. */ 15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h> 20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_STROKER_H 21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRIGONOMETRY_H 22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_OUTLINE_H 23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_MEMORY_H 24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H 25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H 26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_StrokerBorder ) 31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_GetInsideBorder( FT_Outline* outline ) 32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Orientation o = FT_Outline_Get_Orientation( outline ); 34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT 37c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner : FT_STROKER_BORDER_LEFT; 38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_StrokerBorder ) 44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_GetOutsideBorder( FT_Outline* outline ) 45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Orientation o = FT_Outline_Get_Orientation( outline ); 47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT 50c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner : FT_STROKER_BORDER_RIGHT; 51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 54c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 55c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 56c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 57c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** BEZIER COMPUTATIONS *****/ 58c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 59c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 60c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 ) 63c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 ) 64c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_EPSILON 2 66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON ) 68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_pos_abs( FT_Pos x ) 72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 73c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner return x >= 0 ? x : -x; 74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_conic_split( FT_Vector* base ) 79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos a, b; 81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[4].x = base[2].x; 84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b = base[1].x; 85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a = base[3].x = ( base[2].x + b ) / 2; 86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b = base[1].x = ( base[0].x + b ) / 2; 87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[2].x = ( a + b ) / 2; 88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[4].y = base[2].y; 90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b = base[1].y; 91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a = base[3].y = ( base[2].y + b ) / 2; 92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b = base[1].y = ( base[0].y + b ) / 2; 93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[2].y = ( a + b ) / 2; 94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Bool 98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_conic_is_small_enough( FT_Vector* base, 99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle *angle_in, 100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle *angle_out ) 101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector d1, d2; 103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle theta; 104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int close1, close2; 105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1.x = base[1].x - base[2].x; 108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1.y = base[1].y - base[2].y; 109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2.x = base[0].x - base[1].x; 110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2.y = base[0].y - base[1].y; 111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); 113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); 114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( close1 ) 116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( close2 ) 118c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 119c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* basically a point; */ 120c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* do nothing to retain original direction */ 121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d2.x, d2.y ); 126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close1 */ 129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 130c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close2 ) 131c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 132c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d1.x, d1.y ); 134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 135c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 136c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = FT_Atan2( d1.x, d1.y ); 138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d2.x, d2.y ); 139c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) ); 143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD ); 145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_cubic_split( FT_Vector* base ) 150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos a, b, c, d; 152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[6].x = base[3].x; 155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project c = base[1].x; 156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d = base[2].x; 157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[1].x = a = ( base[0].x + c ) / 2; 158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[5].x = b = ( base[3].x + d ) / 2; 159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project c = ( c + d ) / 2; 160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[2].x = a = ( a + c ) / 2; 161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[4].x = b = ( b + c ) / 2; 162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[3].x = ( a + b ) / 2; 163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[6].y = base[3].y; 165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project c = base[1].y; 166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d = base[2].y; 167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[1].y = a = ( base[0].y + c ) / 2; 168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[5].y = b = ( base[3].y + d ) / 2; 169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project c = ( c + d ) / 2; 170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[2].y = a = ( a + c ) / 2; 171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[4].y = b = ( b + c ) / 2; 172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project base[3].y = ( a + b ) / 2; 173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 176c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Return the average of `angle1' and `angle2'. */ 177c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* This gives correct result even if `angle1' and `angle2' */ 178c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* have opposite signs. */ 179c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner static FT_Angle 180c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_angle_mean( FT_Angle angle1, 181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle angle2 ) 182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2; 184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Bool 188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_cubic_is_small_enough( FT_Vector* base, 189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle *angle_in, 190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle *angle_mid, 191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle *angle_out ) 192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector d1, d2, d3; 194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle theta1, theta2; 195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int close1, close2, close3; 196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1.x = base[2].x - base[3].x; 199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1.y = base[2].y - base[3].y; 200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2.x = base[1].x - base[2].x; 201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2.y = base[1].y - base[2].y; 202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d3.x = base[0].x - base[1].x; 203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d3.y = base[0].y - base[1].y; 204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); 206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); 207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y ); 208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 209c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close1 ) 210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( close2 ) 212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 213c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close3 ) 214c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 215c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* basically a point; */ 216c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* do nothing to retain original direction */ 217c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 218c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close3 */ 219c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 220c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 221c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = 222c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d3.x, d3.y ); 223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close2 */ 226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close3 ) 228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = 231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d2.x, d2.y ); 232c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 233c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close3 */ 234c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 235c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 236c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = FT_Atan2( d2.x, d2.y ); 237c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d3.x, d3.y ); 238c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close1 */ 242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 243c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close2 ) 244c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close3 ) 246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = 248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = 249c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d1.x, d1.y ); 250c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 251c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close3 */ 252c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 253c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = FT_Atan2( d1.x, d1.y ); 254c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d3.x, d3.y ); 255c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = ft_angle_mean( *angle_in, *angle_out ); 256c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 257c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 258c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close2 */ 259c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 260c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( close3 ) 261c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = FT_Atan2( d1.x, d1.y ); 263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = 264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d2.x, d2.y ); 265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* !close3 */ 267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_in = FT_Atan2( d1.x, d1.y ); 269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_mid = FT_Atan2( d2.x, d2.y ); 270c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *angle_out = FT_Atan2( d3.x, d3.y ); 271c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 272c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) ); 276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) ); 277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD && 279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta2 < FT_SMALL_CUBIC_THRESHOLD ); 280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 283c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 284c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 285c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 286c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** STROKE BORDERS *****/ 287c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 289c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project typedef enum FT_StrokeTags_ 292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_STROKE_TAG_ON = 1, /* on-curve point */ 294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */ 295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_STROKE_TAG_BEGIN = 4, /* sub-path start */ 296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_STROKE_TAG_END = 8 /* sub-path end */ 297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } FT_StrokeTags; 299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 300c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) 301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project typedef struct FT_StrokeBorderRec_ 303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points; 305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt max_points; 306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* points; 307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tags; 308c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool movable; /* TRUE for ends of lineto borders */ 309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int start; /* index of current sub-path start point */ 310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory; 311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool valid; 312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } FT_StrokeBorderRec, *FT_StrokeBorder; 314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_grow( FT_StrokeBorder border, 318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt new_points ) 319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt old_max = border->max_points; 321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt new_max = border->num_points + new_points; 32277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( new_max > old_max ) 326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt cur_max = old_max; 328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = border->memory; 329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( cur_max < new_max ) 332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_max += ( cur_max >> 1 ) + 16; 333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) || 335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_RENEW_ARRAY( border->tags, old_max, cur_max ) ) 336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->max_points = cur_max; 339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 34077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner 341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_close( FT_StrokeBorder border, 348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool reverse ) 349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt start = border->start; 351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = border->num_points; 352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( border->start >= 0 ); 355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* don't record empty paths! */ 357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( count <= start + 1U ) 358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points = start; 359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* copy the last point to the start of this sub-path, since */ 362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* it contains the `adjusted' starting coordinates */ 363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points = --count; 364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->points[start] = border->points[count]; 365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( reverse ) 367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* reverse the points */ 369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec1 = border->points + start + 1; 371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec2 = border->points + count - 1; 372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; vec1 < vec2; vec1++, vec2-- ) 375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector tmp; 377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tmp = *vec1; 380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *vec1 = *vec2; 381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *vec2 = tmp; 382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* then the tags */ 386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tag1 = border->tags + start + 1; 388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tag2 = border->tags + count - 1; 389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; tag1 < tag2; tag1++, tag2-- ) 392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte tmp; 394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tmp = *tag1; 397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *tag1 = *tag2; 398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *tag2 = tmp; 399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->tags[start ] |= FT_STROKE_TAG_BEGIN; 404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->tags[count - 1] |= FT_STROKE_TAG_END; 405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->start = -1; 40877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_lineto( FT_StrokeBorder border, 414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to, 415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool movable ) 416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 41777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( border->start >= 0 ); 421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border->movable ) 423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* move last point */ 425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->points[border->num_points - 1] = *to; 426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 429c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* don't add zero-length lineto */ 430c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( border->num_points > 0 && 431c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) && 432c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) ) 433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner return error; 434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add one point */ 436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_grow( border, 1 ); 437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !error ) 438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = border->points + border->num_points; 440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tag = border->tags + border->num_points; 441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[0] = *to; 444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[0] = FT_STROKE_TAG_ON; 445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points += 1; 447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->movable = movable; 450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_conicto( FT_StrokeBorder border, 456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control, 457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( border->start >= 0 ); 463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_grow( border, 2 ); 465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !error ) 466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = border->points + border->num_points; 468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tag = border->tags + border->num_points; 469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[0] = *control; 472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[1] = *to; 473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[0] = 0; 475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[1] = FT_STROKE_TAG_ON; 476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points += 2; 478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 48077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_cubicto( FT_StrokeBorder border, 488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control1, 489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control2, 490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( border->start >= 0 ); 496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_grow( border, 3 ); 498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !error ) 499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = border->points + border->num_points; 501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tag = border->tags + border->num_points; 502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[0] = *control1; 505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[1] = *control2; 506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[2] = *to; 507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[0] = FT_STROKE_TAG_CUBIC; 509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[1] = FT_STROKE_TAG_CUBIC; 510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag[2] = FT_STROKE_TAG_ON; 511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points += 3; 513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 51577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 ) 522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_arcto( FT_StrokeBorder border, 526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* center, 527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed radius, 528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_start, 529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_diff ) 530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle total, angle, step, rotate, next, theta; 532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector a, b, a2, b2; 533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed length; 53477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute start point */ 538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &a, radius, angle_start ); 539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a.x += center->x; 540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a.y += center->y; 541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project total = angle_diff; 543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project angle = angle_start; 544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2; 545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( total != 0 ) 547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project step = total; 549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( step > FT_ARC_CUBIC_ANGLE ) 550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project step = FT_ARC_CUBIC_ANGLE; 551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( step < -FT_ARC_CUBIC_ANGLE ) 553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project step = -FT_ARC_CUBIC_ANGLE; 554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project next = angle + step; 556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta = step; 557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( theta < 0 ) 558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta = -theta; 559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta >>= 1; 561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute end point */ 563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &b, radius, next ); 564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b.x += center->x; 565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b.y += center->y; 566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute first and second control points */ 568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_MulDiv( radius, FT_Sin( theta ) * 4, 569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( 0x10000L + FT_Cos( theta ) ) * 3 ); 570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &a2, length, angle + rotate ); 572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a2.x += a.x; 573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a2.y += a.y; 574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &b2, length, next - rotate ); 576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b2.x += b.x; 577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project b2.y += b.y; 578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add cubic arc */ 580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_cubicto( border, &a2, &b2, &b ); 581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the rest of the arc ?? */ 585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project a = b; 586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project total -= step; 587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project angle = next; 588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_moveto( FT_StrokeBorder border, 596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* close current open path if any ? */ 599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border->start >= 0 ) 60077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner ft_stroke_border_close( border, FALSE ); 601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 602c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->start = border->num_points; 60377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 60577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner return ft_stroke_border_lineto( border, to, FALSE ); 606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_init( FT_StrokeBorder border, 611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory ) 612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->memory = memory; 614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->points = NULL; 615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->tags = NULL; 616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points = 0; 618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->max_points = 0; 619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->start = -1; 62077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->valid = FALSE; 621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_reset( FT_StrokeBorder border ) 626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points = 0; 628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->start = -1; 62977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->valid = FALSE; 630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_done( FT_StrokeBorder border ) 635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = border->memory; 637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( border->points ); 640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( border->tags ); 641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points = 0; 643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->max_points = 0; 644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->start = -1; 64577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->valid = FALSE; 646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_get_counts( FT_StrokeBorder border, 651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_points, 652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_contours ) 653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 65477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points = 0; 656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_contours = 0; 657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = border->num_points; 659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* point = border->points; 660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tags = border->tags; 661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int in_contour = 0; 662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, num_points++, point++, tags++ ) 665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tags[0] & FT_STROKE_TAG_BEGIN ) 667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( in_contour != 0 ) 669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_contour = 1; 672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( in_contour == 0 ) 674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tags[0] & FT_STROKE_TAG_END ) 677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_contour = 0; 679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours++; 680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( in_contour != 0 ) 684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 68677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->valid = TRUE; 687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_points = num_points; 690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_contours = num_contours; 691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Fail: 694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points = 0; 695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours = 0; 696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_export( FT_StrokeBorder border, 702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline ) 703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* copy point locations */ 705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ARRAY_COPY( outline->points + outline->n_points, 706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->points, 707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border->num_points ); 708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* copy tags */ 710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = border->num_points; 712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* read = border->tags; 713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points; 714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, read++, write++ ) 717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( *read & FT_STROKE_TAG_ON ) 719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *write = FT_CURVE_TAG_ON; 720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( *read & FT_STROKE_TAG_CUBIC ) 721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *write = FT_CURVE_TAG_CUBIC; 722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *write = FT_CURVE_TAG_CONIC; 724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* copy contours */ 728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = border->num_points; 730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* tags = border->tags; 731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Short* write = outline->contours + outline->n_contours; 732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Short idx = (FT_Short)outline->n_points; 733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, tags++, idx++ ) 736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( *tags & FT_STROKE_TAG_END ) 738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *write++ = idx; 740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_contours++; 741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 745c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner outline->n_points = (short)( outline->n_points + border->num_points ); 746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( FT_Outline_Check( outline ) == 0 ); 748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 751c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 752c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 753c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 754c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** STROKER *****/ 755c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /***** *****/ 756c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 757c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI ) 760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project typedef struct FT_StrokerRec_ 762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 763c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle angle_in; /* direction into curr join */ 764c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle angle_out; /* direction out of join */ 765c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector center; /* current position */ 766c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length; /* length of last lineto */ 767c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool first_point; /* is this the start? */ 768c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool subpath_open; /* is the subpath open? */ 769c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle subpath_angle; /* subpath start direction */ 770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector subpath_start; /* subpath start position */ 771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed subpath_line_length; /* subpath start lineto len */ 772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool handle_wide_strokes; /* use wide strokes logic? */ 773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineCap line_cap; 775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineJoin line_join; 776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Stroker_LineJoin line_join_saved; 777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed miter_limit; 778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed radius; 779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorderRec borders[2]; 781295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Library library; 782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } FT_StrokerRec; 784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_New( FT_Library library, 790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker *astroker ) 791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory; 794c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Stroker stroker = NULL; 795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !library ) 798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return FT_Err_Invalid_Argument; 799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory = library->memory; 801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !FT_NEW( stroker ) ) 803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 804295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner stroker->library = library; 805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_init( &stroker->borders[0], memory ); 807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_init( &stroker->borders[1], memory ); 808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 809c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *astroker = stroker; 811c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Set( FT_Stroker stroker, 820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed radius, 821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineCap line_cap, 822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineJoin line_join, 823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed miter_limit ) 824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->radius = radius; 826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->line_cap = line_cap; 827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->line_join = line_join; 828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->miter_limit = miter_limit; 829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 830c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* ensure miter limit has sensible value */ 831c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->miter_limit < 0x10000 ) 832c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->miter_limit = 0x10000; 833c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 834c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* save line join style: */ 835c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* line join style can be temporarily changed when stroking curves */ 836c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join_saved = line_join; 837c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Rewind( stroker ); 839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Rewind( FT_Stroker stroker ) 846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker ) 848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_reset( &stroker->borders[0] ); 850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_reset( &stroker->borders[1] ); 851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Done( FT_Stroker stroker ) 859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker ) 861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 862295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Memory memory = stroker->library->memory; 863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_done( &stroker->borders[0] ); 866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_done( &stroker->borders[1] ); 867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 868295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner stroker->library = NULL; 869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( stroker ); 870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 874c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* create a circular arc at a corner or cap */ 875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_arcto( FT_Stroker stroker, 877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int side ) 878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle total, rotate; 880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed radius = stroker->radius; 88177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border = stroker->borders + side; 883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); 888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( total == FT_ANGLE_PI ) 889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project total = -rotate * 2; 890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_arcto( border, 892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &stroker->center, 893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project radius, 894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_in + rotate, 895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project total ); 89677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add a cap at the end of an opened path */ 902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_cap( FT_Stroker stroker, 904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle, 905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int side ) 906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 90777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND ) 911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add a round cap */ 913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_in = angle; 914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out = angle + FT_ANGLE_PI; 915c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_arcto( stroker, side ); 917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE ) 919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add a square cap */ 921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta, delta2; 922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle rotate = FT_SIDE_TO_ROTATE( side ); 923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed radius = stroker->radius; 924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border = stroker->borders + side; 925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta2, radius, angle + rotate ); 928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, radius, angle ); 929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += stroker->center.x + delta2.x; 931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += stroker->center.y + delta2.y; 932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 93377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta2, radius, angle - rotate ); 938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, radius, angle ); 939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += delta2.x + stroker->center.x; 941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += delta2.y + stroker->center.y; 942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 94377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 945295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT ) 946295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner { 947295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner /* add a butt ending */ 948295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Vector delta; 949295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Angle rotate = FT_SIDE_TO_ROTATE( side ); 950295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Fixed radius = stroker->radius; 951295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_StrokeBorder border = stroker->borders + side; 952295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 953295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 954295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Vector_From_Polar( &delta, radius, angle + rotate ); 955295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 956295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner delta.x += stroker->center.x; 957295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner delta.y += stroker->center.y; 958295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 959295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 960295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner if ( error ) 961295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner goto Exit; 962295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 963295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_Vector_From_Polar( &delta, radius, angle - rotate ); 964295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 965295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner delta.x += stroker->center.x; 966295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner delta.y += stroker->center.y; 967295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner 968c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 969295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner } 970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process an inside corner, i.e. compute intersection */ 977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_inside( FT_Stroker stroker, 979c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side, 980c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border = stroker->borders + side; 983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle phi, theta, rotate; 984c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length, thcos; 985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 98677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 987c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool intersect; /* use intersection of lines? */ 988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 992c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2; 993c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 994c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Only intersect borders if between two lineto's and both */ 995c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* lines are long enough (line_length is zero for curves). */ 996c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !border->movable || line_length == 0 ) 997c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner intersect = FALSE; 998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 999c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1000c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute minimum required length of lines */ 1001c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed min_length = ft_pos_abs( FT_MulFix( stroker->radius, 1002c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Tan( theta ) ) ); 1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1005c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner intersect = FT_BOOL( stroker->line_length >= min_length && 1006c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner line_length >= min_length ); 1007c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1009c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !intersect ) 1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, stroker->radius, 1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out + rotate ); 1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += stroker->center.x; 1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += stroker->center.y; 1015c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 101677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner border->movable = FALSE; 1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1020c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute median angle */ 1021c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi = stroker->angle_in + theta; 1022c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1023c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner thcos = FT_Cos( theta ); 1024c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_DivFix( stroker->radius, thcos ); 1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, length, phi + rotate ); 1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += stroker->center.x; 1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += stroker->center.y; 1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 103277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process an outside corner, i.e. compute bevel/miter/round */ 1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_outside( FT_Stroker stroker, 1041c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side, 1042c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border = stroker->borders + side; 1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle rotate; 1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND ) 1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_arcto( stroker, side ); 1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1053c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* this is a mitered (pointed) or beveled (truncated) corner */ 1054c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed sigma = 0, radius = stroker->radius; 1055c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle theta = 0, phi = 0; 1056c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed thcos = 0; 1057c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool bevel, fixed_bevel; 1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1062c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bevel = 1063c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL ); 1064c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1065c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner fixed_bevel = 1066c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE ); 1067c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1068c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !bevel ) 1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1070c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); 1071c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1072c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( theta == FT_ANGLE_PI ) 1073c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1074c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta = rotate; 1075c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi = stroker->angle_in; 1076c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1077c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 1078c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1079c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta /= 2; 1080c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi = stroker->angle_in + theta + rotate; 1081c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1082c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1083c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner thcos = FT_Cos( theta ); 1084c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sigma = FT_MulFix( stroker->miter_limit, thcos ); 1085c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1086c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* is miter limit exceeded? */ 1087c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( sigma < 0x10000L ) 1088c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1089c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* don't create variable bevels for very small deviations; */ 1090c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* FT_Sin(x) = 0 for x <= 57 */ 1091c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( fixed_bevel || ft_pos_abs( theta ) > 57 ) 1092c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bevel = TRUE; 1093c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1095c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1096c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( bevel ) /* this is a bevel (broken angle) */ 1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1098c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( fixed_bevel ) 1099c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1100c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* the outer corners are simply joined together */ 1101c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector delta; 1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1104c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add bevel */ 1105c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, 1106c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner radius, 1107c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out + rotate ); 1108c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += stroker->center.x; 1109c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += stroker->center.y; 1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1111c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->movable = FALSE; 1112c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1113c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1114c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* variable bevel */ 1115c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1116c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* the miter is truncated */ 1117c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector middle, delta; 1118c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length; 1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute middle point */ 1122c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &middle, 1123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_MulFix( radius, stroker->miter_limit ), 1124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi ); 1125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner middle.x += stroker->center.x; 1126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner middle.y += stroker->center.y; 1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute first angle point */ 1129c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner length = FT_MulFix( radius, 1130c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_DivFix( 0x10000L - sigma, 1131c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_pos_abs( FT_Sin( theta ) ) ) ); 1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, length, phi + rotate ); 1134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += middle.x; 1135c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += middle.y; 1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1139c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1141c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute second angle point */ 1142c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, length, phi - rotate ); 1143c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += middle.x; 1144c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += middle.y; 1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1146c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1147c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1148c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1150c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* finally, add an end point; only needed if not lineto */ 1151c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1152c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( line_length == 0 ) 1153c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1154c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, 1155c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner radius, 1156c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out + rotate ); 1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1158c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += stroker->center.x; 1159c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += stroker->center.y; 1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1161c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1162c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1163c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1164c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1165c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* this is a miter (intersection) */ 1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed length; 1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_DivFix( stroker->radius, thcos ); 1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, length, phi ); 1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += stroker->center.x; 1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += stroker->center.y; 1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 117777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 117877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner if ( error ) 117977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner goto Exit; 1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* now add an end point; only needed if not lineto */ 1182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( line_length == 0 ) 1184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, 1186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->radius, 1187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out + rotate ); 1188c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += stroker->center.x; 1189c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += stroker->center.y; 1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1191c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1192c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1202c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroker_process_corner( FT_Stroker stroker, 1203c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 120577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle turn; 1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int inside_side; 1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); 1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* no specific corner processing is required if the turn is 0 */ 1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn == 0 ) 1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* when we turn to the right, the inside side is 0 */ 1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 0; 1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* otherwise, the inside side is 1 */ 1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn < 0 ) 1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 1; 1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the inside side */ 1224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_inside( stroker, inside_side, line_length ); 1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the outside side */ 1229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_outside( stroker, 1 - inside_side, line_length ); 1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add two points to the left and right borders corresponding to the */ 123777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* start of the subpath */ 1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_subpath_start( FT_Stroker stroker, 1240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle start_angle, 1241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector point; 1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border; 1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, stroker->radius, 1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start_angle + FT_ANGLE_PI2 ); 1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = stroker->center.x + delta.x; 1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = stroker->center.y + delta.y; 1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = stroker->borders; 1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_moveto( border, &point ); 1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = stroker->center.x - delta.x; 1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = stroker->center.y - delta.y; 1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border++; 1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_moveto( border, &point ); 1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* save angle, position, and line length for last join */ 1267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_angle = start_angle; 1269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->first_point = FALSE; 1270c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length = line_length; 1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineTo( FT_Stroker stroker, 1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 128377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border; 1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle; 1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int side; 1288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length; 1289c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x = to->x - stroker->center.x; 1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y = to->y - stroker->center.y; 1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1294c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* a zero-length lineto is a no-op; avoid creating a spurious corner */ 1295c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( delta.x == 0 && delta.y == 0 ) 1296c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1297c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1298c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute length of line */ 1299c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner line_length = FT_Vector_Length( &delta ); 1300c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project angle = FT_Atan2( delta.x, delta.y ); 1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 ); 1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* This is the first segment of a subpath. We need to */ 1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add a point to each border at their respective starting */ 1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* point locations. */ 1310c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle, line_length ); 1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the current corner */ 1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out = angle; 1318c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, line_length ); 1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 132377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* now add a line segment to both the `inside' and `outside' paths */ 1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) 1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector point; 1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = to->x + delta.x; 1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = to->y + delta.y; 1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1332c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* the ends of lineto borders are movable */ 133377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &point, TRUE ); 1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x = -delta.x; 1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y = -delta.y; 1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle; 1342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1343c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_length = line_length; 1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ConicTo( FT_Stroker stroker, 1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control, 1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 135777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector bez_stack[34]; 1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* arc; 1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit = bez_stack + 30; 136177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Bool first_arc = TRUE; 1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if all control points are coincident, this is a no-op; */ 1365c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* avoid creating a spurious corner */ 1366c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_IS_SMALL( stroker->center.x - control->x ) && 1367c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( stroker->center.y - control->y ) && 1368c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control->x - to->x ) && 1369c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control->y - to->y ) ) 1370c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1371c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1372c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1373c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1374c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc = bez_stack; 1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[0] = *to; 1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[1] = *control; 1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[2] = stroker->center; 1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( arc >= bez_stack ) 1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_in, angle_out; 1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1385c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* initialize with current direction */ 1386c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner angle_in = angle_out = stroker->angle_in; 1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( arc < limit && 1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) 1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1391c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->first_point ) 1392c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_in; 1393c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_conic_split( arc ); 1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc += 2; 1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( first_arc ) 1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 140177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner first_arc = FALSE; 1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1405c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle_in, 0 ); 1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1408c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1409c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1412c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > 1413c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_SMALL_CONIC_THRESHOLD / 4 ) 1414c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1415c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if the deviation from one arc to the next is too great, */ 1416c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add a round corner */ 1417c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = arc[2]; 1418c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1419c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = FT_STROKER_LINEJOIN_ROUND; 1420c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1421c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1422c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1423c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* reinstate line join style */ 1424c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = stroker->line_join_saved; 1425c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1426c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1427c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1428c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the arc's angle is small enough; we can add it directly to each */ 1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* border */ 1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector ctrl, end; 1434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle theta, phi, rotate, alpha0 = 0; 1435c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length; 1436c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_StrokeBorder border; 1437c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side; 1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta = FT_Angle_Diff( angle_in, angle_out ) / 2; 1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project phi = angle_in + theta; 1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_DivFix( stroker->radius, FT_Cos( theta ) ); 1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1444c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute direction of original arc */ 1445c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1446c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y ); 1447c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1448c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( border = stroker->borders, side = 0; 1449c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side <= 1; 1450c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side++, border++ ) 1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute control point */ 1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl, length, phi + rotate ); 1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl.x += arc[1].x; 1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl.y += arc[1].y; 1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute end point */ 1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); 1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.x += arc[0].x; 1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.y += arc[0].y; 1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1464c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1465c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1466c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector start; 1467c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle alpha1; 1468c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1469c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* determine whether the border radius is greater than the */ 1471c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* radius of curvature of the original arc */ 1472c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner start = border->points[border->num_points - 1]; 1473c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1474c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); 1475c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1476c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* is the direction of the border arc opposite to */ 1477c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* that of the original arc? */ 1478c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > 1479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ANGLE_PI / 2 ) 1480c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle beta, gamma; 1482c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector bvec, delta; 1483c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed blen, sinA, sinB, alen; 1484c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1485c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1486c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* use the sine rule to find the intersection point */ 1487c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y ); 1488c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); 1489c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1490c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.x = end.x - start.x; 1491c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.y = end.y - start.y; 1492c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1493c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blen = FT_Vector_Length( &bvec ); 1494c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1495c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); 1496c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); 1497c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1498c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB ); 1499c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1500c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, alen, beta ); 1501c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += start.x; 1502c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += start.y; 1503c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1504c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* circumnavigate the negative sector backwards */ 1505c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->movable = FALSE; 1506c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1507c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1508c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1509c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1510c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1511c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1512c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_conicto( border, &ctrl, &start ); 1513c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1515c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* and then move to the endpoint */ 1516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1518c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1519c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1520c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1521c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1522c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1523c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* else fall through */ 1524c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1525c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1526c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* simply add an arc */ 1527c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_conicto( border, &ctrl, &end ); 1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc -= 2; 1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1535c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_out; 1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = *to; 1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_CubicTo( FT_Stroker stroker, 1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control1, 1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control2, 1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 155377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector bez_stack[37]; 1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* arc; 1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit = bez_stack + 32; 155777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Bool first_arc = TRUE; 1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1560c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if all control points are coincident, this is a no-op; */ 1561c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* avoid creating a spurious corner */ 1562c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_IS_SMALL( stroker->center.x - control1->x ) && 1563c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( stroker->center.y - control1->y ) && 1564c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control1->x - control2->x ) && 1565c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control1->y - control2->y ) && 1566c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control2->x - to->x ) && 1567c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control2->y - to->y ) ) 1568c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1569c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1570c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1571c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1572c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc = bez_stack; 1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[0] = *to; 1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[1] = *control2; 1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[2] = *control1; 1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[3] = stroker->center; 1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( arc >= bez_stack ) 1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_in, angle_mid, angle_out; 1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1584c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* initialize with current direction */ 1585c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner angle_in = angle_out = angle_mid = stroker->angle_in; 1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( arc < limit && 1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !ft_cubic_is_small_enough( arc, &angle_in, 1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &angle_mid, &angle_out ) ) 1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1591c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->first_point ) 1592c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_in; 1593c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_cubic_split( arc ); 1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc += 3; 1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( first_arc ) 1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 160177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner first_arc = FALSE; 1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1605c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle_in, 0 ); 1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1608c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1609c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1612c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > 1613c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_SMALL_CUBIC_THRESHOLD / 4 ) 1614c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1615c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if the deviation from one arc to the next is too great, */ 1616c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add a round corner */ 1617c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = arc[3]; 1618c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1619c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = FT_STROKER_LINEJOIN_ROUND; 1620c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1621c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1622c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1623c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* reinstate line join style */ 1624c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = stroker->line_join_saved; 1625c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1626c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1627c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1628c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the arc's angle is small enough; we can add it directly to each */ 1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* border */ 1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1633c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector ctrl1, ctrl2, end; 1634c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; 1635c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length1, length2; 1636c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_StrokeBorder border; 1637c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side; 1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1640c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2; 1641c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2; 1642c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi1 = ft_angle_mean( angle_in, angle_mid ); 1643c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi2 = ft_angle_mean( angle_mid, angle_out ); 1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) ); 1645295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) ); 1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1647c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute direction of original arc */ 1648c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1649c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y ); 1650c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1651c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( border = stroker->borders, side = 0; 1652c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side <= 1; 1653c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side++, border++ ) 1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute control points */ 1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate ); 1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl1.x += arc[2].x; 1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl1.y += arc[2].y; 1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate ); 1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl2.x += arc[1].x; 1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl2.y += arc[1].y; 1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute end point */ 1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); 1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.x += arc[0].x; 1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.y += arc[0].y; 1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1671c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1672c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1673c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector start; 1674c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle alpha1; 1675c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1676c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1677c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* determine whether the border radius is greater than the */ 1678c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* radius of curvature of the original arc */ 1679c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner start = border->points[border->num_points - 1]; 1680c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1681c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); 1682c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1683c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* is the direction of the border arc opposite to */ 1684c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* that of the original arc? */ 1685c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > 1686c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ANGLE_PI / 2 ) 1687c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1688c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle beta, gamma; 1689c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector bvec, delta; 1690c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed blen, sinA, sinB, alen; 1691c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1692c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1693c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* use the sine rule to find the intersection point */ 1694c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y ); 1695c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); 1696c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1697c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.x = end.x - start.x; 1698c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.y = end.y - start.y; 1699c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1700c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blen = FT_Vector_Length( &bvec ); 1701c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1702c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); 1703c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); 1704c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1705c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB ); 1706c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1707c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, alen, beta ); 1708c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += start.x; 1709c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += start.y; 1710c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1711c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* circumnavigate the negative sector backwards */ 1712c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->movable = FALSE; 1713c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1714c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1715c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1716c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1717c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1718c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1719c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_cubicto( border, 1720c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &ctrl2, 1721c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &ctrl1, 1722c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &start ); 1723c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1724c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1725c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* and then move to the endpoint */ 1726c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1727c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1728c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1729c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1730c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1731c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1732c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1733c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* else fall through */ 1734c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1735c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1736c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* simply add an arc */ 1737c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end ); 1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc -= 3; 1744c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1745c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_out; 1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = *to; 1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_BeginSubPath( FT_Stroker stroker, 1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to, 1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool open ) 1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We cannot process the first point, because there is not enough */ 1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* information regarding its corner/cap. The latter will be processed */ 176477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* in the `FT_Stroker_EndSubPath' routine. */ 1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 176677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->first_point = TRUE; 176777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->center = *to; 176877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->subpath_open = open; 1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Determine if we need to check whether the border radius is greater */ 1771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* than the radius of curvature of a curve, to handle this case */ 1772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* specially. This is only required if bevel joins or butt caps may */ 1773c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* be created, because round & miter joins and round & square caps */ 1774c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* cover the negative sector created with wide strokes. */ 1775c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->handle_wide_strokes = 1776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND || 1777c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ( stroker->subpath_open && 1778c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_cap == FT_STROKER_LINECAP_BUTT ) ); 1779c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 178077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* record the subpath start point for each border */ 1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->subpath_start = *to; 178277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner 1783c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = 0; 1784c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 178577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner return FT_Err_Ok; 1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_add_reverse_left( FT_Stroker stroker, 1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool open ) 1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 179377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_StrokeBorder right = stroker->borders + 0; 179477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_StrokeBorder left = stroker->borders + 1; 1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int new_points; 179677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( left->start >= 0 ); 1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project new_points = left->num_points - left->start; 1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( new_points > 0 ) 1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_grow( right, (FT_UInt)new_points ); 1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* dst_point = right->points + right->num_points; 1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* dst_tag = right->tags + right->num_points; 1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* src_point = left->points + left->num_points - 1; 1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* src_tag = left->tags + left->num_points - 1; 1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1814c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( src_point >= left->points + left->start ) 1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *dst_point = *src_point; 1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *dst_tag = *src_tag; 1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( open ) 1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END; 1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1824c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Byte ttag = 1825c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END ); 1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* switch begin/end tags if necessary */ 1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ttag == FT_STROKE_TAG_BEGIN || 1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ttag == FT_STROKE_TAG_END ) 1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END; 1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project src_point--; 1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project src_tag--; 1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_point++; 1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag++; 1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->num_points = left->start; 1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->num_points += new_points; 1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 184477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner right->movable = FALSE; 184577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner left->movable = FALSE; 1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* there's a lot of magic in this function! */ 1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_EndSubPath( FT_Stroker stroker ) 1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 185977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 186077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner 1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->subpath_open ) 1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder right = stroker->borders; 1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1866c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* All right, this is an opened path, we need to add a cap between */ 1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* right & left, add the reverse of left, then add a final cap */ 1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* between left & right. */ 1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_cap( stroker, stroker->angle_in, 0 ); 1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 187477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* add reversed points from `left' to `right' */ 187577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroker_add_reverse_left( stroker, TRUE ); 1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now add the final cap */ 1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = stroker->subpath_start; 1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_cap( stroker, 1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->subpath_angle + FT_ANGLE_PI, 0 ); 1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Now end the right subpath accordingly. The left one is */ 1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* rewind and doesn't need further processing. */ 188877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner ft_stroke_border_close( right, FALSE ); 1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle turn; 1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int inside_side; 1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1895c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* close the path if needed */ 1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->center.x != stroker->subpath_start.x || 1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center.y != stroker->subpath_start.y ) 1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1900c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); 1901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1902c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the corner */ 1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out = stroker->subpath_angle; 1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project turn = FT_Angle_Diff( stroker->angle_in, 1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out ); 1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* no specific corner processing is required if the turn is 0 */ 1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn != 0 ) 1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* when we turn to the right, the inside side is 0 */ 1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 0; 1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* otherwise, the inside side is 1 */ 1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn < 0 ) 1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 1; 1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1920c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_inside( stroker, 1921c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner inside_side, 1922c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length ); 1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the outside side */ 1927c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_outside( stroker, 1928c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1 - inside_side, 1929c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length ); 1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* then end our two subpaths */ 1935c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroke_border_close( stroker->borders + 0, FALSE ); 1936c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroke_border_close( stroker->borders + 1, TRUE ); 1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_GetBorderCounts( FT_Stroker stroker, 1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border, 1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_points, 1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_contours ) 1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points = 0, num_contours = 0; 1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !stroker || border > 1 ) 1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Err_Invalid_Argument; 1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + border, 1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &num_points, &num_contours ); 1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( anum_points ) 1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_points = num_points; 1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( anum_contours ) 1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_contours = num_contours; 1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_GetCounts( FT_Stroker stroker, 1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_points, 1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_contours ) 1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count1, count2, num_points = 0; 1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count3, count4, num_contours = 0; 1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + 0, 1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &count1, &count2 ); 1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + 1, 1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &count3, &count4 ); 1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points = count1 + count3; 1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours = count2 + count4; 1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_points = num_points; 2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_contours = num_contours; 2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( FT_Stroker stroker, 2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border, 2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline ) 2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border == FT_STROKER_BORDER_LEFT || 2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border == FT_STROKER_BORDER_RIGHT ) 2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder sborder = & stroker->borders[border]; 2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( sborder->valid ) 2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_export( sborder, outline ); 2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Export( FT_Stroker stroker, 2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline ) 2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline ); 2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline ); 2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * The following is very similar to FT_Outline_Decompose, except 2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * that we do support opened paths, and do not scale the outline. 2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ParseOutline( FT_Stroker stroker, 2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline, 2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool opened ) 2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_last; 2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_control; 2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_start; 2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* point; 2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit; 2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project char* tags; 2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2058c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int n; /* index of contour in outline */ 2059c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt first; /* index of first point in contour */ 2060c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int tag; /* current point's state */ 2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !outline || !stroker ) 2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return FT_Err_Invalid_Argument; 2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Rewind( stroker ); 2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = 0; 2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < outline->n_contours; n++ ) 2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt last; /* index of last point in contour */ 2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project last = outline->contours[n]; 2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit = outline->points + last; 2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip empty points; we don't stroke these */ 2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( last <= first ) 2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = last + 1; 2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start = outline->points[first]; 2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_last = outline->points[last]; 2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control = v_start; 2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = outline->points + first; 209177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner tags = outline->tags + first; 2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* A contour cannot start with a cubic control point! */ 2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_CUBIC ) 2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check first point to determine origin */ 2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_CONIC ) 2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* First point is conic control. Yes, this happens. */ 2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* start at last point if it is on the curve */ 2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start = v_last; 2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit--; 2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2110295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner /* if both first and last points are conic, */ 2111295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner /* start at their middle */ 2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start.x = ( v_start.x + v_last.x ) / 2; 2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start.y = ( v_start.y + v_last.y ) / 2; 2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point--; 2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags--; 2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); 2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( point < limit ) 2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags++; 2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project switch ( tag ) 2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case FT_CURVE_TAG_ON: /* emit a single line_to */ 2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec.x = point->x; 2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec.y = point->y; 2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_LineTo( stroker, &vec ); 2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control.x = point->x; 2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control.y = point->y; 2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Do_Conic: 2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point < limit ) 2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_middle; 2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags++; 2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec = point[0]; 2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_ON ) 2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); 2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag != FT_CURVE_TAG_CONIC ) 2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_middle.x = ( v_control.x + vec.x ) / 2; 2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_middle.y = ( v_control.y + vec.y ) / 2; 2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); 2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control = vec; 2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Do_Conic; 2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); 2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Close; 2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project default: /* FT_CURVE_TAG_CUBIC */ 2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec1, vec2; 2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point + 1 > limit || 2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point += 2; 2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags += 2; 2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec1 = point[-2]; 2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec2 = point[-1]; 2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point <= limit ) 2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec = point[0]; 2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); 2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); 2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Close; 2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Close: 2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* don't try to end the path if no segments have been generated */ 2226c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !stroker->first_point ) 2227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 2228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Stroker_EndSubPath( stroker ); 2229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 2230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 2231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = last + 1; 2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 223677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner return FT_Err_Ok; 2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Invalid_Outline: 2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return FT_Err_Invalid_Outline; 2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* declare an extern to access `ft_outline_glyph_class' globally */ 2247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */ 2248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* macro to access it when FT_CONFIG_OPTION_PIC is defined */ 2249295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_CONFIG_OPTION_PIC 2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project extern const FT_Glyph_Class ft_outline_glyph_class; 2251295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif 2252295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "basepic.h" 2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph_Stroke( FT_Glyph *pglyph, 2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker stroker, 2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool destroy ) 2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Error error = FT_Err_Invalid_Argument; 2263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Glyph glyph = NULL; 2264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Library library = stroker->library; 2265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UNUSED( library ); 2267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pglyph == NULL ) 2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = *pglyph; 2273295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) 2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph copy; 2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Glyph_Copy( glyph, © ); 2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = copy; 2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; 2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline = &oglyph->outline; 2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points, num_contours; 2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 229377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); 2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours ); 2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_Done( glyph->library, outline ); 2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Outline_New( glyph->library, 2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points, num_contours, outline ); 2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_points = 0; 2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_contours = 0; 2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Export( stroker, outline ); 2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( destroy ) 2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( *pglyph ); 2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = glyph; 2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Fail: 2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( glyph ); 2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = NULL; 2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !destroy ) 2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = NULL; 2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph_StrokeBorder( FT_Glyph *pglyph, 2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker stroker, 2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool inside, 2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool destroy ) 2337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2338c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Error error = FT_Err_Invalid_Argument; 2339c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Glyph glyph = NULL; 2340c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Library library = stroker->library; 2341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UNUSED( library ); 2343c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pglyph == NULL ) 2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = *pglyph; 2349295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) 2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph copy; 2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Glyph_Copy( glyph, © ); 2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = copy; 2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; 2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border; 2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline = &oglyph->outline; 2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points, num_contours; 2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_Outline_GetOutsideBorder( outline ); 2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( inside ) 2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border == FT_STROKER_BORDER_LEFT ) 2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_STROKER_BORDER_RIGHT; 2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_STROKER_BORDER_LEFT; 2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 237977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); 2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (void)FT_Stroker_GetBorderCounts( stroker, border, 2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &num_points, &num_contours ); 2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_Done( glyph->library, outline ); 2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Outline_New( glyph->library, 2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points, 2390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours, 2391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline ); 2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_points = 0; 2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_contours = 0; 2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, border, outline ); 2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( destroy ) 2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( *pglyph ); 2403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = glyph; 2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Fail: 2408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( glyph ); 2409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = NULL; 2410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !destroy ) 2412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = NULL; 2413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */ 2420