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/* */ 7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Copyright 2002-2006, 2008-2011, 2013 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 { 792a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error; /* assigned in FT_NEW */ 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 ) 798a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return FT_THROW( 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 */ 1129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang length = FT_MulDiv( radius, 0x10000L - sigma, 1130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang ft_pos_abs( FT_Sin( theta ) ) ); 1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1132c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, length, phi + rotate ); 1133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += middle.x; 1134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += middle.y; 1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1136c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1140c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute second angle point */ 1141c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, length, phi - rotate ); 1142c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += middle.x; 1143c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += middle.y; 1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1145c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1146c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1147c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1149c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* finally, add an end point; only needed if not lineto */ 1150c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1151c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( line_length == 0 ) 1152c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1153c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, 1154c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner radius, 1155c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out + rotate ); 1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1157c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += stroker->center.x; 1158c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += stroker->center.y; 1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1160c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1161c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1162c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1163c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1164c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else /* this is a miter (intersection) */ 1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed length; 1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_DivFix( stroker->radius, thcos ); 1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, length, phi ); 1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x += stroker->center.x; 1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y += stroker->center.y; 1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 117677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 117777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner if ( error ) 117877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner goto Exit; 1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1180c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* now add an end point; only needed if not lineto */ 1181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( line_length == 0 ) 1183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, 1185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->radius, 1186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out + rotate ); 1187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += stroker->center.x; 1188c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += stroker->center.y; 1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1190c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1191c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1201c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroker_process_corner( FT_Stroker stroker, 1202c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 120477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle turn; 1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int inside_side; 1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); 1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* no specific corner processing is required if the turn is 0 */ 1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn == 0 ) 1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* when we turn to the right, the inside side is 0 */ 1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 0; 1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* otherwise, the inside side is 1 */ 1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn < 0 ) 1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 1; 1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the inside side */ 1223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_inside( stroker, inside_side, line_length ); 1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the outside side */ 1228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_outside( stroker, 1 - inside_side, line_length ); 1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add two points to the left and right borders corresponding to the */ 123677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* start of the subpath */ 1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_subpath_start( FT_Stroker stroker, 1239c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle start_angle, 1240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length ) 1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector point; 1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border; 1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, stroker->radius, 1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start_angle + FT_ANGLE_PI2 ); 1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = stroker->center.x + delta.x; 1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = stroker->center.y + delta.y; 1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = stroker->borders; 1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_moveto( border, &point ); 1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = stroker->center.x - delta.x; 1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = stroker->center.y - delta.y; 1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border++; 1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_moveto( border, &point ); 1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* save angle, position, and line length for last join */ 1266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (line_length is zero for curves) */ 1267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_angle = start_angle; 1268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->first_point = FALSE; 1269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length = line_length; 1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_LineTo( FT_Stroker stroker, 1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 128277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder border; 1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector delta; 1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle; 1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int side; 1287c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed line_length; 1288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x = to->x - stroker->center.x; 1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y = to->y - stroker->center.y; 1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1293c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* a zero-length lineto is a no-op; avoid creating a spurious corner */ 1294c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( delta.x == 0 && delta.y == 0 ) 1295c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1296c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1297c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute length of line */ 1298c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner line_length = FT_Vector_Length( &delta ); 1299c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project angle = FT_Atan2( delta.x, delta.y ); 1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 ); 1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* This is the first segment of a subpath. We need to */ 1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add a point to each border at their respective starting */ 1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* point locations. */ 1309c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle, line_length ); 1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the current corner */ 1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out = angle; 1317c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, line_length ); 1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 132277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* now add a line segment to both the `inside' and `outside' paths */ 1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) 1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector point; 1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.x = to->x + delta.x; 1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point.y = to->y + delta.y; 1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1331c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* the ends of lineto borders are movable */ 133277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroke_border_lineto( border, &point, TRUE ); 1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.x = -delta.x; 1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta.y = -delta.y; 1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1340c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle; 1341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_length = line_length; 1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ConicTo( FT_Stroker stroker, 1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control, 1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 135677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector bez_stack[34]; 1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* arc; 1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit = bez_stack + 30; 136077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Bool first_arc = TRUE; 1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1363c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if all control points are coincident, this is a no-op; */ 1364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* avoid creating a spurious corner */ 1365c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_IS_SMALL( stroker->center.x - control->x ) && 1366c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( stroker->center.y - control->y ) && 1367c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control->x - to->x ) && 1368c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control->y - to->y ) ) 1369c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1370c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1371c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1372c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1373c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc = bez_stack; 1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[0] = *to; 1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[1] = *control; 1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[2] = stroker->center; 1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( arc >= bez_stack ) 1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_in, angle_out; 1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1384c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* initialize with current direction */ 1385c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner angle_in = angle_out = stroker->angle_in; 1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( arc < limit && 1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) 1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1390c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->first_point ) 1391c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_in; 1392c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_conic_split( arc ); 1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc += 2; 1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( first_arc ) 1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 140077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner first_arc = FALSE; 1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1404c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle_in, 0 ); 1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1407c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1408c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1411c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > 1412c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_SMALL_CONIC_THRESHOLD / 4 ) 1413c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1414c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if the deviation from one arc to the next is too great, */ 1415c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add a round corner */ 1416c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = arc[2]; 1417c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1418c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = FT_STROKER_LINEJOIN_ROUND; 1419c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1420c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1421c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1422c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* reinstate line join style */ 1423c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = stroker->line_join_saved; 1424c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1425c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1426c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1427c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the arc's angle is small enough; we can add it directly to each */ 1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* border */ 1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1432c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector ctrl, end; 1433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle theta, phi, rotate, alpha0 = 0; 1434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length; 1435c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_StrokeBorder border; 1436c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side; 1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project theta = FT_Angle_Diff( angle_in, angle_out ) / 2; 1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project phi = angle_in + theta; 1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length = FT_DivFix( stroker->radius, FT_Cos( theta ) ); 1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1443c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute direction of original arc */ 1444c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1445c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y ); 1446c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1447c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( border = stroker->borders, side = 0; 1448c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side <= 1; 1449c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side++, border++ ) 1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute control point */ 1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl, length, phi + rotate ); 1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl.x += arc[1].x; 1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl.y += arc[1].y; 1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute end point */ 1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); 1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.x += arc[0].x; 1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.y += arc[0].y; 1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1463c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1464c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1465c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector start; 1466c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle alpha1; 1467c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1468c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1469c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* determine whether the border radius is greater than the */ 1470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* radius of curvature of the original arc */ 1471c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner start = border->points[border->num_points - 1]; 1472c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1473c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); 1474c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1475c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* is the direction of the border arc opposite to */ 1476c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* that of the original arc? */ 1477c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > 1478c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ANGLE_PI / 2 ) 1479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1480c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle beta, gamma; 1481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector bvec, delta; 1482c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed blen, sinA, sinB, alen; 1483c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1484c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1485c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* use the sine rule to find the intersection point */ 1486c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y ); 1487c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); 1488c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1489c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.x = end.x - start.x; 1490c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.y = end.y - start.y; 1491c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1492c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blen = FT_Vector_Length( &bvec ); 1493c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1494c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); 1495c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); 1496c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1497a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang alen = FT_MulDiv( blen, sinA, sinB ); 1498c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1499c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, alen, beta ); 1500c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += start.x; 1501c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += start.y; 1502c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1503c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* circumnavigate the negative sector backwards */ 1504c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->movable = FALSE; 1505c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1506c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1507c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1508c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1509c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1510c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1511c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_conicto( border, &ctrl, &start ); 1512c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1513c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* and then move to the endpoint */ 1515c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1518c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1519c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1520c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1521c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1522c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* else fall through */ 1523c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1524c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1525c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* simply add an arc */ 1526c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_conicto( border, &ctrl, &end ); 1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc -= 2; 1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1534c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_out; 1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = *to; 1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_CubicTo( FT_Stroker stroker, 1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control1, 1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* control2, 1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to ) 1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 155277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector bez_stack[37]; 1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* arc; 1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit = bez_stack + 32; 155677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Bool first_arc = TRUE; 1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1559c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if all control points are coincident, this is a no-op; */ 1560c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* avoid creating a spurious corner */ 1561c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_IS_SMALL( stroker->center.x - control1->x ) && 1562c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( stroker->center.y - control1->y ) && 1563c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control1->x - control2->x ) && 1564c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control1->y - control2->y ) && 1565c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control2->x - to->x ) && 1566c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_IS_SMALL( control2->y - to->y ) ) 1567c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1568c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = *to; 1569c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1570c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1571c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc = bez_stack; 1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[0] = *to; 1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[1] = *control2; 1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[2] = *control1; 1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc[3] = stroker->center; 1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( arc >= bez_stack ) 1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle angle_in, angle_mid, angle_out; 1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1583c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* initialize with current direction */ 1584c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner angle_in = angle_out = angle_mid = stroker->angle_in; 1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( arc < limit && 1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !ft_cubic_is_small_enough( arc, &angle_in, 1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &angle_mid, &angle_out ) ) 1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1590c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->first_point ) 1591c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_in; 1592c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_cubic_split( arc ); 1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc += 3; 1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( first_arc ) 1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 160077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner first_arc = FALSE; 1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process corner if necessary */ 1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->first_point ) 1604c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_subpath_start( stroker, angle_in, 0 ); 1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1607c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1608c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1611c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) > 1612c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_SMALL_CUBIC_THRESHOLD / 4 ) 1613c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1614c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if the deviation from one arc to the next is too great, */ 1615c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* add a round corner */ 1616c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->center = arc[3]; 1617c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_out = angle_in; 1618c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = FT_STROKER_LINEJOIN_ROUND; 1619c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1620c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_process_corner( stroker, 0 ); 1621c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1622c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* reinstate line join style */ 1623c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_join = stroker->line_join_saved; 1624c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1625c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1626c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1627c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the arc's angle is small enough; we can add it directly to each */ 1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* border */ 1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1632c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector ctrl1, ctrl2, end; 1633c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0; 1634c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed length1, length2; 1635c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_StrokeBorder border; 1636c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int side; 1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1639c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2; 1640c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2; 1641c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi1 = ft_angle_mean( angle_in, angle_mid ); 1642c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner phi2 = ft_angle_mean( angle_mid, angle_out ); 1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) ); 1644295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) ); 1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1646c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute direction of original arc */ 1647c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1648c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y ); 1649c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1650c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( border = stroker->borders, side = 0; 1651c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side <= 1; 1652c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner side++, border++ ) 1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rotate = FT_SIDE_TO_ROTATE( side ); 1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute control points */ 1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate ); 1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl1.x += arc[2].x; 1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl1.y += arc[2].y; 1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate ); 1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl2.x += arc[1].x; 1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ctrl2.y += arc[1].y; 1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute end point */ 1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); 1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.x += arc[0].x; 1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end.y += arc[0].y; 1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1670c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( stroker->handle_wide_strokes ) 1671c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1672c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector start; 1673c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle alpha1; 1674c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1675c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1676c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* determine whether the border radius is greater than the */ 1677c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* radius of curvature of the original arc */ 1678c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner start = border->points[border->num_points - 1]; 1679c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1680c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner alpha1 = FT_Atan2( end.x - start.x, end.y - start.y ); 1681c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1682c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* is the direction of the border arc opposite to */ 1683c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* that of the original arc? */ 1684c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) > 1685c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ANGLE_PI / 2 ) 1686c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1687c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Angle beta, gamma; 1688c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector bvec, delta; 1689c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed blen, sinA, sinB, alen; 1690c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1691c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1692c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* use the sine rule to find the intersection point */ 1693c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y ); 1694c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y ); 1695c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1696c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.x = end.x - start.x; 1697c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner bvec.y = end.y - start.y; 1698c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1699c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blen = FT_Vector_Length( &bvec ); 1700c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1701c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) ); 1702c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner sinB = ft_pos_abs( FT_Sin( beta - gamma ) ); 1703c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1704a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang alen = FT_MulDiv( blen, sinA, sinB ); 1705c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1706c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector_From_Polar( &delta, alen, beta ); 1707c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.x += start.x; 1708c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta.y += start.y; 1709c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1710c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* circumnavigate the negative sector backwards */ 1711c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner border->movable = FALSE; 1712c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &delta, FALSE ); 1713c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1714c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1715c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1716c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1717c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1718c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_cubicto( border, 1719c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &ctrl2, 1720c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &ctrl1, 1721c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &start ); 1722c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1723c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1724c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* and then move to the endpoint */ 1725c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_lineto( border, &end, FALSE ); 1726c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1727c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1728c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1729c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1730c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1731c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1732c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* else fall through */ 1733c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1734c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1735c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* simply add an arc */ 1736c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end ); 1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project arc -= 3; 1743c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1744c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = angle_out; 1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = *to; 1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_BeginSubPath( FT_Stroker stroker, 1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* to, 1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool open ) 1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We cannot process the first point, because there is not enough */ 1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* information regarding its corner/cap. The latter will be processed */ 176377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* in the `FT_Stroker_EndSubPath' routine. */ 1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 176577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->first_point = TRUE; 176677f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->center = *to; 176777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner stroker->subpath_open = open; 1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1769c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Determine if we need to check whether the border radius is greater */ 1770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* than the radius of curvature of a curve, to handle this case */ 1771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* specially. This is only required if bevel joins or butt caps may */ 1772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* be created, because round & miter joins and round & square caps */ 1773c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* cover the negative sector created with wide strokes. */ 1774c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->handle_wide_strokes = 1775c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND || 1776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ( stroker->subpath_open && 1777c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->line_cap == FT_STROKER_LINECAP_BUTT ) ); 1778c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 177977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* record the subpath start point for each border */ 1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->subpath_start = *to; 178177f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner 1782c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->angle_in = 0; 1783c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 178477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner return FT_Err_Ok; 1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroker_add_reverse_left( FT_Stroker stroker, 1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool open ) 1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 179277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_StrokeBorder right = stroker->borders + 0; 179377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_StrokeBorder left = stroker->borders + 1; 1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int new_points; 179577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ASSERT( left->start >= 0 ); 1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project new_points = left->num_points - left->start; 1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( new_points > 0 ) 1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_grow( right, (FT_UInt)new_points ); 1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* dst_point = right->points + right->num_points; 1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* dst_tag = right->tags + right->num_points; 1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* src_point = left->points + left->num_points - 1; 1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* src_tag = left->tags + left->num_points - 1; 1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1813c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( src_point >= left->points + left->start ) 1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *dst_point = *src_point; 1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *dst_tag = *src_tag; 1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( open ) 1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END; 1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1823c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Byte ttag = 1824c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END ); 1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* switch begin/end tags if necessary */ 1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ttag == FT_STROKE_TAG_BEGIN || 1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ttag == FT_STROKE_TAG_END ) 1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END; 1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project src_point--; 1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project src_tag--; 1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_point++; 1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dst_tag++; 1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->num_points = left->start; 1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->num_points += new_points; 1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 184377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner right->movable = FALSE; 184477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner left->movable = FALSE; 1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* there's a lot of magic in this function! */ 1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_EndSubPath( FT_Stroker stroker ) 1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 185877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner FT_Error error = FT_Err_Ok; 185977f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner 1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->subpath_open ) 1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder right = stroker->borders; 1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1865c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* All right, this is an opened path, we need to add a cap between */ 1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* right & left, add the reverse of left, then add a final cap */ 1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* between left & right. */ 1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_cap( stroker, stroker->angle_in, 0 ); 1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 187377f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner /* add reversed points from `left' to `right' */ 187477f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = ft_stroker_add_reverse_left( stroker, TRUE ); 1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now add the final cap */ 1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center = stroker->subpath_start; 1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroker_cap( stroker, 1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->subpath_angle + FT_ANGLE_PI, 0 ); 1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Now end the right subpath accordingly. The left one is */ 1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* rewind and doesn't need further processing. */ 188777f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner ft_stroke_border_close( right, FALSE ); 1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Angle turn; 1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int inside_side; 1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1894c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* close the path if needed */ 1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( stroker->center.x != stroker->subpath_start.x || 1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->center.y != stroker->subpath_start.y ) 1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1899c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); 1900c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 1901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the corner */ 1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out = stroker->subpath_angle; 1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project turn = FT_Angle_Diff( stroker->angle_in, 1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stroker->angle_out ); 1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* no specific corner processing is required if the turn is 0 */ 1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn != 0 ) 1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* when we turn to the right, the inside side is 0 */ 1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 0; 1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* otherwise, the inside side is 1 */ 1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( turn < 0 ) 1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project inside_side = 1; 1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1919c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_inside( stroker, 1920c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner inside_side, 1921c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length ); 1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process the outside side */ 1926c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = ft_stroker_outside( stroker, 1927c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1 - inside_side, 1928c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stroker->subpath_line_length ); 1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* then end our two subpaths */ 1934c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroke_border_close( stroker->borders + 0, FALSE ); 1935c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ft_stroke_border_close( stroker->borders + 1, TRUE ); 1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_GetBorderCounts( FT_Stroker stroker, 1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border, 1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_points, 1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_contours ) 1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points = 0, num_contours = 0; 1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !stroker || border > 1 ) 1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1957a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang error = FT_THROW( Invalid_Argument ); 1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + border, 1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &num_points, &num_contours ); 1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( anum_points ) 1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_points = num_points; 1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( anum_contours ) 1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_contours = num_contours; 1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_GetCounts( FT_Stroker stroker, 1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_points, 1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt *anum_contours ) 1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count1, count2, num_points = 0; 1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count3, count4, num_contours = 0; 1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + 0, 1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &count1, &count2 ); 1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = ft_stroke_border_get_counts( stroker->borders + 1, 1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &count3, &count4 ); 1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points = count1 + count3; 1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours = count2 + count4; 1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_points = num_points; 2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *anum_contours = num_contours; 2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( FT_Stroker stroker, 2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border, 2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline ) 2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border == FT_STROKER_BORDER_LEFT || 2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border == FT_STROKER_BORDER_RIGHT ) 2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokeBorder sborder = & stroker->borders[border]; 2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( sborder->valid ) 2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ft_stroke_border_export( sborder, outline ); 2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( void ) 2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Export( FT_Stroker stroker, 2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline ) 2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline ); 2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline ); 2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * The following is very similar to FT_Outline_Decompose, except 2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * that we do support opened paths, and do not scale the outline. 2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ParseOutline( FT_Stroker stroker, 2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline, 2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool opened ) 2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_last; 2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_control; 2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_start; 2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* point; 2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* limit; 2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project char* tags; 2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2057c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int n; /* index of contour in outline */ 2058c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt first; /* index of first point in contour */ 2059c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int tag; /* current point's state */ 2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !outline || !stroker ) 2063a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return FT_THROW( Invalid_Argument ); 2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Rewind( stroker ); 2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = 0; 2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < outline->n_contours; n++ ) 2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt last; /* index of last point in contour */ 2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project last = outline->contours[n]; 2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit = outline->points + last; 2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip empty points; we don't stroke these */ 2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( last <= first ) 2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = last + 1; 2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start = outline->points[first]; 2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_last = outline->points[last]; 2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control = v_start; 2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = outline->points + first; 209077f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner tags = outline->tags + first; 2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* A contour cannot start with a cubic control point! */ 2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_CUBIC ) 2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check first point to determine origin */ 2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_CONIC ) 2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* First point is conic control. Yes, this happens. */ 2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* start at last point if it is on the curve */ 2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start = v_last; 2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit--; 2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2109295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner /* if both first and last points are conic, */ 2110295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner /* start at their middle */ 2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start.x = ( v_start.x + v_last.x ) / 2; 2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_start.y = ( v_start.y + v_last.y ) / 2; 2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point--; 2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags--; 2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); 2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( point < limit ) 2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags++; 2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project switch ( tag ) 2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case FT_CURVE_TAG_ON: /* emit a single line_to */ 2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec.x = point->x; 2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec.y = point->y; 2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_LineTo( stroker, &vec ); 2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control.x = point->x; 2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control.y = point->y; 2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Do_Conic: 2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point < limit ) 2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector v_middle; 2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags++; 2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tag = FT_CURVE_TAG( tags[0] ); 2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec = point[0]; 2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag == FT_CURVE_TAG_ON ) 2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); 2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( tag != FT_CURVE_TAG_CONIC ) 2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_middle.x = ( v_control.x + vec.x ) / 2; 2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_middle.y = ( v_control.y + vec.y ) / 2; 2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); 2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project v_control = vec; 2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Do_Conic; 2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); 2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Close; 2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project default: /* FT_CURVE_TAG_CUBIC */ 2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec1, vec2; 2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point + 1 > limit || 2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Invalid_Outline; 2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point += 2; 2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags += 2; 2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec1 = point[-2]; 2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec2 = point[-1]; 2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point <= limit ) 2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector vec; 2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec = point[0]; 2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); 2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); 2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Close; 2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Close: 2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* don't try to end the path if no segments have been generated */ 2225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !stroker->first_point ) 2226c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 2227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Stroker_EndSubPath( stroker ); 2228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 2229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 2230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = last + 1; 2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 223577f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner return FT_Err_Ok; 2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Invalid_Outline: 2241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return FT_THROW( Invalid_Outline ); 2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2244c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* declare an extern to access `ft_outline_glyph_class' globally */ 2246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */ 2247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* macro to access it when FT_CONFIG_OPTION_PIC is defined */ 2248295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_CONFIG_OPTION_PIC 2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project extern const FT_Glyph_Class ft_outline_glyph_class; 2250295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif 2251295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "basepic.h" 2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph_Stroke( FT_Glyph *pglyph, 2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker stroker, 2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool destroy ) 2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error = FT_ERR( Invalid_Argument ); 2262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Glyph glyph = NULL; 2263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Library library = stroker->library; 2264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UNUSED( library ); 2266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pglyph == NULL ) 2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = *pglyph; 2272295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) 2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph copy; 2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Glyph_Copy( glyph, © ); 2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = copy; 2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2287c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; 2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline = &oglyph->outline; 2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points, num_contours; 2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 229277f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); 2293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours ); 2297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_Done( glyph->library, outline ); 2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Outline_New( glyph->library, 2301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points, num_contours, outline ); 2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_points = 0; 2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_contours = 0; 2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_Export( stroker, outline ); 2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( destroy ) 2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( *pglyph ); 2313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = glyph; 2315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Fail: 2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( glyph ); 2319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = NULL; 2320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !destroy ) 2322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = NULL; 2323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* documentation is in ftstroke.h */ 2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_EXPORT_DEF( FT_Error ) 2332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph_StrokeBorder( FT_Glyph *pglyph, 2333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker stroker, 2334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool inside, 2335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool destroy ) 2336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2337a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error = FT_ERR( Invalid_Argument ); 2338c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Glyph glyph = NULL; 2339c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Library library = stroker->library; 2340c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UNUSED( library ); 2342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pglyph == NULL ) 2345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = *pglyph; 2348295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner if ( glyph == NULL || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET ) 2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Glyph copy; 2353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Glyph_Copy( glyph, © ); 2356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = copy; 2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2363c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph; 2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_StrokerBorder border; 2365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline = &oglyph->outline; 2366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_points, num_contours; 2367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_Outline_GetOutsideBorder( outline ); 2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( inside ) 2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( border == FT_STROKER_BORDER_LEFT ) 2373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_STROKER_BORDER_RIGHT; 2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project border = FT_STROKER_BORDER_LEFT; 2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 237877f63d23f7d380b0ff02c18fd6a154ab9063128aDavid 'Digit' Turner error = FT_Stroker_ParseOutline( stroker, outline, FALSE ); 2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (void)FT_Stroker_GetBorderCounts( stroker, border, 2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &num_points, &num_contours ); 2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline_Done( glyph->library, outline ); 2386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = FT_Outline_New( glyph->library, 2388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_points, 2389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_contours, 2390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline ); 2391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Fail; 2393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_points = 0; 2395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project outline->n_contours = 0; 2396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Stroker_ExportBorder( stroker, border, outline ); 2398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( destroy ) 2401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( *pglyph ); 2402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = glyph; 2404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Fail: 2407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Done_Glyph( glyph ); 2408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph = NULL; 2409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !destroy ) 2411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project *pglyph = NULL; 2412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */ 2419