1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* ftoutln.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* FreeType outline management (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Copyright 1996-2008, 2010, 2012-2014 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* All functions are declared in freetype.h. */ 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include <ft2build.h> 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_OUTLINE_H 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_OBJECTS_H 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_CALC_H 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_INTERNAL_DEBUG_H 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include FT_TRIGONOMETRY_H 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_outline 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Decompose( FT_Outline* outline, 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Outline_Funcs* func_interface, 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* user ) 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef SCALED 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define SCALED( x ) ( ( (x) << shift ) - delta ) 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_last; 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_control; 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_start; 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* point; 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* limit; 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* tags; 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; /* index of contour in outline */ 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt first; /* index of first point in contour */ 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int tag; /* current point's state */ 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift; 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos delta; 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !outline ) 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_Outline ); 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !func_interface ) 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = func_interface->shift; 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = func_interface->delta; 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < outline->n_contours; n++ ) 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int last; /* index of last point in contour */ 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = outline->contours[n]; 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( last < 0 ) 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = outline->points + last; 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start = outline->points[first]; 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x = SCALED( v_start.x ); 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.y = SCALED( v_start.y ); 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last = outline->points[last]; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last.x = SCALED( v_last.x ); 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last.y = SCALED( v_last.y ); 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control = v_start; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point = outline->points + first; 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags = outline->tags + first; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A contour cannot start with a cubic control point! */ 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_CUBIC ) 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check first point to determine origin */ 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_CONIC ) 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first point is conic control. Yes, this happens. */ 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start at last point if it is on the curve */ 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start = v_last; 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit--; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if both first and last points are conic, */ 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start at their middle and record its position */ 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for closure */ 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x = ( v_start.x + v_last.x ) / 2; 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.y = ( v_start.y + v_last.y ) / 2; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* v_last = v_start; */ 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point--; 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags--; 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " move to (%.2f, %.2f)\n", 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0 )); 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->move_to( &v_start, user ); 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( point < limit ) 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point++; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags++; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( tag ) 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case FT_CURVE_TAG_ON: /* emit a single line_to */ 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " line to (%.2f, %.2f)\n", 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0 )); 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->line_to( &vec, user ); 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x = SCALED( point->x ); 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.y = SCALED( point->y ); 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Do_Conic: 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point < limit ) 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_middle; 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point++; 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags++; 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_ON ) 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0, 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &vec, user ); 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag != FT_CURVE_TAG_CONIC ) 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.x = ( v_control.x + vec.x ) / 2; 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.y = ( v_control.y + vec.y ) / 2; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.x / 64.0, v_middle.y / 64.0, 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &v_middle, user ); 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control = vec; 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Do_Conic; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0, 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &v_start, user ); 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Close; 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: /* FT_CURVE_TAG_CUBIC */ 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec1, vec2; 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point + 1 > limit || 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point += 2; 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags += 2; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x = SCALED( point[-2].x ); 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.y = SCALED( point[-2].y ); 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x = SCALED( point[-1].x ); 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.y = SCALED( point[-1].y ); 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point <= limit ) 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " cubic to (%.2f, %.2f)" 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0, 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x / 64.0, vec1.y / 64.0, 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x / 64.0, vec2.y / 64.0 )); 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " cubic to (%.2f, %.2f)" 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0, 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x / 64.0, vec1.y / 64.0, 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x / 64.0, vec2.y / 64.0 )); 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Close; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* close the contour with a line segment */ 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " line to (%.2f, %.2f)\n", 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0 )); 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->line_to( &v_start, user ); 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Close: 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = last + 1; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Invalid_Outline: 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Outline ); 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_New_Internal( FT_Memory memory, 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt numPoints, 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int numContours, 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline *anoutline ) 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !anoutline || !memory ) 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *anoutline = null_outline; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( numContours < 0 || 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_UInt)numContours > numPoints ) 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( numPoints > FT_OUTLINE_POINTS_MAX ) 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Array_Too_Large ); 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( anoutline->tags, numPoints ) || 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( anoutline->contours, numContours ) ) 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail; 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov anoutline->n_points = (FT_UShort)numPoints; 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov anoutline->n_contours = (FT_Short)numContours; 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov anoutline->flags |= FT_OUTLINE_OWNER; 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail: 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov anoutline->flags |= FT_OUTLINE_OWNER; 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Done_Internal( memory, anoutline ); 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_New( FT_Library library, 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt numPoints, 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int numContours, 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline *anoutline ) 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !library ) 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Library_Handle ); 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Outline_New_Internal( library->memory, numPoints, 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numContours, anoutline ); 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Check( FT_Outline* outline ) 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline ) 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n_points = outline->n_points; 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n_contours = outline->n_contours; 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int end0, end; 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* empty glyph? */ 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n_points == 0 && n_contours == 0 ) 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_Err_Ok; 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check point and contour counts */ 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n_points <= 0 || n_contours <= 0 ) 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Bad; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end0 = end = -1; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < n_contours; n++ ) 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end = outline->contours[n]; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* note that we don't accept empty contours */ 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( end <= end0 || end >= n_points ) 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Bad; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov end0 = end; 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( end != n_points - 1 ) 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Bad; 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: check the tags array */ 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_Err_Ok; 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Bad: 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Copy( const FT_Outline* source, 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline *target ) 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int is_owner; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !source || !target ) 408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_Outline ); 409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( source->n_points != target->n_points || 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov source->n_contours != target->n_contours ) 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( source == target ) 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ARRAY_COPY( target->points, source->points, source->n_points ); 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* copy all flags, except the `FT_OUTLINE_OWNER' one */ 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov is_owner = target->flags & FT_OUTLINE_OWNER; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov target->flags = source->flags; 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov target->flags &= ~FT_OUTLINE_OWNER; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov target->flags |= is_owner; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Done_Internal( FT_Memory memory, 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline ) 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !outline ) 439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_Outline ); 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !memory ) 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( outline->flags & FT_OUTLINE_OWNER ) 445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_FREE( outline->points ); 447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_FREE( outline->tags ); 448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FT_FREE( outline->contours ); 449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outline = null_outline; 451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_Err_Ok; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Done( FT_Library library, 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline ) 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check for valid `outline' in FT_Outline_Done_Internal() */ 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !library ) 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Library_Handle ); 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Outline_Done_Internal( library->memory, outline ); 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_CBox( const FT_Outline* outline, 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox *acbox ) 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos xMin, yMin, xMax, yMax; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline && acbox ) 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_points == 0 ) 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xMin = 0; 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yMin = 0; 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xMax = 0; 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yMax = 0; 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec = outline->points; 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* limit = vec + outline->n_points; 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xMin = xMax = vec->x; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yMin = yMax = vec->y; 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec++; 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; vec < limit; vec++ ) 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, y; 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = vec->x; 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x < xMin ) xMin = x; 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x > xMax ) xMax = x; 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = vec->y; 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < yMin ) yMin = y; 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > yMax ) yMax = y; 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov acbox->xMin = xMin; 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov acbox->xMax = xMax; 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov acbox->yMin = yMin; 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov acbox->yMax = yMax; 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Translate( const FT_Outline* outline, 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos xOffset, 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos yOffset ) 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort n; 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec; 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline ) 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec = outline->points; 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < outline->n_points; n++ ) 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x += xOffset; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y += yOffset; 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec++; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Reverse( FT_Outline* outline ) 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort n; 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int first, last; 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline ) 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < outline->n_contours; n++ ) 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = outline->contours[n]; 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reverse point table */ 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* p = outline->points + first; 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* q = outline->points + last; 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector swap; 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( p < q ) 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov swap = *p; 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p = *q; 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *q = swap; 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p++; 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q--; 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* reverse tags table */ 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* p = outline->tags + first; 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* q = outline->tags + last; 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( p < q ) 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 589e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov char swap; 590e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 591e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov swap = *p; 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *p = *q; 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *q = swap; 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p++; 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q--; 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = last + 1; 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->flags ^= FT_OUTLINE_REVERSE_FILL; 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Render( FT_Library library, 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline, 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Raster_Params* params ) 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bool update = FALSE; 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Renderer renderer; 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ListNode node; 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !library ) 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Library_Handle ); 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !outline ) 624e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_Outline ); 625e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 626e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( !params ) 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov renderer = library->cur_renderer; 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov node = library->renderers.head; 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov params->source = (void*)outline; 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_ERR( Cannot_Render_Glyph ); 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( renderer ) 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = renderer->raster_render( renderer->raster, params ); 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) ) 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* is unsupported by the current renderer for this glyph image */ 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format */ 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* now, look for another renderer that supports the same */ 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* format */ 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &node ); 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov update = TRUE; 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if we changed the current renderer for the glyph image format */ 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we need to select it as the next current one */ 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error && update && renderer ) 655e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FT_Set_Renderer( library, renderer, 0, 0 ); 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_Bitmap( FT_Library library, 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline, 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Bitmap *abitmap ) 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Raster_Params params; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !abitmap ) 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 674e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* other checks are delayed to `FT_Outline_Render' */ 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov params.target = abitmap; 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov params.flags = 0; 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov abitmap->pixel_mode == FT_PIXEL_MODE_LCD || 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov params.flags |= FT_RASTER_FLAG_AA; 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Outline_Render( library, outline, ¶ms ); 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in freetype.h */ 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Transform( FT_Vector* vector, 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Matrix* matrix ) 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos xz, yz; 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !vector || !matrix ) 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xz = FT_MulFix( vector->x, matrix->xx ) + 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MulFix( vector->y, matrix->xy ); 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yz = FT_MulFix( vector->x, matrix->yx ) + 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MulFix( vector->y, matrix->yy ); 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vector->x = xz; 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vector->y = yz; 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Transform( const FT_Outline* outline, 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Matrix* matrix ) 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec; 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* limit; 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline || !matrix ) 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec = outline->points; 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = vec + outline->n_points; 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; vec < limit; vec++ ) 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Transform( vec, matrix ); 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if 0 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \ 735e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov do \ 736e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { \ 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (first) = ( c > 0 ) ? (outline)->points + \ 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (outline)->contours[c - 1] + 1 \ 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : (outline)->points; \ 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (last) = (outline)->points + (outline)->contours[c]; \ 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( 0 ) 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Is a point in some contour? */ 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We treat every point of the contour as if it */ 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* it were ON. That is, we allow false positives, */ 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* but disallow false negatives. (XXX really?) */ 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Bool 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_contour_has( FT_Outline* outline, 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short c, 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* point ) 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* first; 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* last; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* a; 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* b; 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n = 0; 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( a = first; a <= last; a++ ) 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x; 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int intersect; 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = ( a == last ) ? first : a + 1; 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov intersect = ( a->y - point->y ) ^ ( b->y - point->y ); 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* a and b are on the same side */ 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( intersect >= 0 ) 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( intersect == 0 && a->y == point->y ) 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ( a->x <= point->x && b->x >= point->x ) || 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( a->x >= point->x && b->x <= point->x ) ) 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y ); 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x < point->x ) 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n++; 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( x == point->x ) 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return n & 1; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Bool 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_contour_enclosed( FT_Outline* outline, 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort c ) 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* first; 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* last; 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short i; 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < outline->n_contours; i++ ) 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( i != c && ft_contour_has( outline, i, first ) ) 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* pt; 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( pt = first + 1; pt <= last; pt++ ) 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !ft_contour_has( outline, i, pt ) ) 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This version differs from the public one in that each */ 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* part (contour not enclosed in another contour) of the */ 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* outline is checked for orientation. This is */ 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* necessary for some buggy CJK fonts. */ 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Orientation 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_outline_get_orientation( FT_Outline* outline ) 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short i; 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* first; 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* last; 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Orientation orient = FT_ORIENTATION_NONE; 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = outline->points; 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < outline->n_contours; i++, first = last + 1 ) 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* point; 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* xmin_point; 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos xmin; 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = outline->points + outline->contours[i]; 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* skip degenerate contours */ 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( last < first + 2 ) 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ft_contour_enclosed( outline, i ) ) 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xmin = first->x; 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xmin_point = first; 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( point = first + 1; point <= last; point++ ) 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point->x < xmin ) 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xmin = point->x; 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xmin_point = point; 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check the orientation of the contour */ 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* prev; 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* next; 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Orientation o; 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prev = ( xmin_point == first ) ? last : xmin_point - 1; 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next = ( xmin_point == last ) ? first : xmin_point + 1; 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) > 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) ) 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov o = FT_ORIENTATION_POSTSCRIPT; 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov o = FT_ORIENTATION_TRUETYPE; 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( orient == FT_ORIENTATION_NONE ) 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov orient = o; 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( orient != o ) 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ORIENTATION_NONE; 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return orient; 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */ 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Embolden( FT_Outline* outline, 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos strength ) 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Outline_EmboldenXY( outline, strength, strength ); 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Error ) 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_EmboldenXY( FT_Outline* outline, 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos xstrength, 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos ystrength ) 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* points; 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_prev, v_first, v_next, v_cur; 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int c, n, first; 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int orientation; 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline ) 923e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_THROW( Invalid_Outline ); 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xstrength /= 2; 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ystrength /= 2; 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( xstrength == 0 && ystrength == 0 ) 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov orientation = FT_Outline_Get_Orientation( outline ); 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( orientation == FT_ORIENTATION_NONE ) 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_contours ) 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points = outline->points; 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( c = 0; c < outline->n_contours; c++ ) 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector in, out, shift; 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed l_in, l_out, l, q, d; 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last = outline->contours[c]; 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_first = points[first]; 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_prev = points[last]; 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_cur = v_first; 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute incoming normalized vector */ 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in.x = v_cur.x - v_prev.x; 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in.y = v_cur.y - v_prev.y; 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_in = FT_Vector_Length( &in ); 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( l_in ) 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in.x = FT_DivFix( in.x, l_in ); 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in.y = FT_DivFix( in.y, l_in ); 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = first; n <= last; n++ ) 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n < last ) 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_next = points[n + 1]; 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_next = v_first; 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute outgoing normalized vector */ 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out.x = v_next.x - v_cur.x; 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out.y = v_next.y - v_cur.y; 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_out = FT_Vector_Length( &out ); 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( l_out ) 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out.x = FT_DivFix( out.x, l_out ); 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out.y = FT_DivFix( out.y, l_out ); 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* shift only if turn is less than ~160 degrees */ 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( d > -0xF000L ) 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = d + 0x10000L; 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* shift components are aligned along lateral bisector */ 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* and directed according to the outline orientation. */ 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.x = in.y + out.y; 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.y = in.x + out.x; 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( orientation == FT_ORIENTATION_TRUETYPE ) 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.x = -shift.x; 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.y = -shift.y; 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* restrict shift magnitude to better handle collapsing segments */ 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( orientation == FT_ORIENTATION_TRUETYPE ) 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov q = -q; 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l = FT_MIN( l_in, l_out ); 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) ) 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.x = FT_MulDiv( shift.x, xstrength, d ); 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.x = FT_MulDiv( shift.x, l, q ); 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) ) 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.y = FT_MulDiv( shift.y, ystrength, d ); 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.y = FT_MulDiv( shift.y, l, q ); 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift.x = shift.y = 0; 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->points[n].x = v_cur.x + xstrength + shift.x; 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->points[n].y = v_cur.y + ystrength + shift.y; 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in = out; 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_in = l_out; 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_cur = v_next; 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = last + 1; 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in ftoutln.h */ 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Orientation ) 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_Orientation( FT_Outline* outline ) 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox cbox; 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int xshift, yshift; 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* points; 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_prev, v_cur; 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int c, n, first; 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos area = 0; 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline || outline->n_points <= 0 ) 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ORIENTATION_TRUETYPE; 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We use the nonzero winding rule to find the orientation. */ 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Since glyph outlines behave much more `regular' than arbitrary */ 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cubic or quadratic curves, this test deals with the polygon */ 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* only which is spanned up by the control points. */ 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Get_CBox( outline, &cbox ); 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1057e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Handle collapsed outlines to avoid undefined FT_MSB. */ 1058e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax ) 1059e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FT_ORIENTATION_NONE; 1060e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14; 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xshift = FT_MAX( xshift, 0 ); 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14; 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov yshift = FT_MAX( yshift, 0 ); 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points = outline->points; 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( c = 0; c < outline->n_contours; c++ ) 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int last = outline->contours[c]; 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_prev = points[last]; 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = first; n <= last; n++ ) 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_cur = points[n]; 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov area += ( ( v_cur.y - v_prev.y ) >> yshift ) * 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( ( v_cur.x + v_prev.x ) >> xshift ); 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_prev = v_cur; 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = last + 1; 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( area > 0 ) 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ORIENTATION_POSTSCRIPT; 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( area < 0 ) 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ORIENTATION_TRUETYPE; 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ORIENTATION_NONE; 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 1098