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