1 /***************************************************************************/
5 /* FreeType outline management (body). */
7 /* Copyright 1996-2001, 2002 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
19 /*************************************************************************/
21 /* All functions are declared in freetype.h. */
23 /*************************************************************************/
28 #include FT_INTERNAL_OBJECTS_H
31 /*************************************************************************/
33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35 /* messages during execution. */
38 #define FT_COMPONENT trace_outline
42 const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };
45 /* documentation is in ftoutln.h */
47 FT_EXPORT_DEF( FT_Error )
48 FT_Outline_Decompose( FT_Outline* outline,
49 const FT_Outline_Funcs* func_interface,
53 #define SCALED( x ) ( ( (x) << shift ) - delta )
65 FT_Int n; /* index of contour in outline */
66 FT_UInt first; /* index of first point in contour */
67 FT_Int tag; /* current point's state */
73 if ( !outline || !func_interface )
74 return FT_Err_Invalid_Argument;
76 shift = func_interface->shift;
77 delta = func_interface->delta;
80 for ( n = 0; n < outline->n_contours; n++ )
82 FT_Int last; /* index of last point in contour */
85 last = outline->contours[n];
86 limit = outline->points + last;
88 v_start = outline->points[first];
89 v_last = outline->points[last];
91 v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
92 v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
96 point = outline->points + first;
97 tags = outline->tags + first;
98 tag = FT_CURVE_TAG( tags[0] );
100 /* A contour cannot start with a cubic control point! */
101 if ( tag == FT_CURVE_TAG_CUBIC )
102 goto Invalid_Outline;
104 /* check first point to determine origin */
105 if ( tag == FT_CURVE_TAG_CONIC )
107 /* first point is conic control. Yes, this happens. */
108 if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
110 /* start at last point if it is on the curve */
116 /* if both first and last points are conic, */
117 /* start at their middle and record its position */
119 v_start.x = ( v_start.x + v_last.x ) / 2;
120 v_start.y = ( v_start.y + v_last.y ) / 2;
128 error = func_interface->move_to( &v_start, user );
132 while ( point < limit )
137 tag = FT_CURVE_TAG( tags[0] );
140 case FT_CURVE_TAG_ON: /* emit a single line_to */
145 vec.x = SCALED( point->x );
146 vec.y = SCALED( point->y );
148 error = func_interface->line_to( &vec, user );
154 case FT_CURVE_TAG_CONIC: /* consume conic arcs */
155 v_control.x = SCALED( point->x );
156 v_control.y = SCALED( point->y );
167 tag = FT_CURVE_TAG( tags[0] );
169 vec.x = SCALED( point->x );
170 vec.y = SCALED( point->y );
172 if ( tag == FT_CURVE_TAG_ON )
174 error = func_interface->conic_to( &v_control, &vec, user );
180 if ( tag != FT_CURVE_TAG_CONIC )
181 goto Invalid_Outline;
183 v_middle.x = ( v_control.x + vec.x ) / 2;
184 v_middle.y = ( v_control.y + vec.y ) / 2;
186 error = func_interface->conic_to( &v_control, &v_middle, user );
194 error = func_interface->conic_to( &v_control, &v_start, user );
197 default: /* FT_CURVE_TAG_CUBIC */
199 FT_Vector vec1, vec2;
202 if ( point + 1 > limit ||
203 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
204 goto Invalid_Outline;
209 vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
210 vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
212 if ( point <= limit )
217 vec.x = SCALED( point->x );
218 vec.y = SCALED( point->y );
220 error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
226 error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
232 /* close the contour with a line segment */
233 error = func_interface->line_to( &v_start, user );
248 return FT_Err_Invalid_Outline;
252 FT_EXPORT_DEF( FT_Error )
253 FT_Outline_New_Internal( FT_Memory memory,
256 FT_Outline *anoutline )
261 if ( !anoutline || !memory )
262 return FT_Err_Invalid_Argument;
264 *anoutline = null_outline;
266 if ( FT_NEW_ARRAY( anoutline->points, numPoints * 2L ) ||
267 FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
268 FT_NEW_ARRAY( anoutline->contours, numContours ) )
271 anoutline->n_points = (FT_UShort)numPoints;
272 anoutline->n_contours = (FT_Short)numContours;
273 anoutline->flags |= FT_OUTLINE_OWNER;
278 anoutline->flags |= FT_OUTLINE_OWNER;
279 FT_Outline_Done_Internal( memory, anoutline );
285 /* documentation is in ftoutln.h */
287 FT_EXPORT_DEF( FT_Error )
288 FT_Outline_New( FT_Library library,
291 FT_Outline *anoutline )
294 return FT_Err_Invalid_Library_Handle;
296 return FT_Outline_New_Internal( library->memory, numPoints,
297 numContours, anoutline );
301 /* documentation is in ftoutln.h */
303 FT_EXPORT_DEF( FT_Error )
304 FT_Outline_Check( FT_Outline* outline )
308 FT_Int n_points = outline->n_points;
309 FT_Int n_contours = outline->n_contours;
315 if ( n_points == 0 && n_contours == 0 )
318 /* check point and contour counts */
319 if ( n_points <= 0 || n_contours <= 0 )
323 for ( n = 0; n < n_contours; n++ )
325 end = outline->contours[n];
327 /* note that we don't accept empty contours */
328 if ( end <= end0 || end >= n_points )
334 if ( end != n_points - 1 )
337 /* XXX: check the tags array */
342 return FT_Err_Invalid_Argument;
346 /* documentation is in ftoutln.h */
348 FT_EXPORT_DEF( FT_Error )
349 FT_Outline_Copy( FT_Outline* source,
355 if ( !source || !target ||
356 source->n_points != target->n_points ||
357 source->n_contours != target->n_contours )
358 return FT_Err_Invalid_Argument;
360 FT_MEM_COPY( target->points, source->points,
361 source->n_points * sizeof ( FT_Vector ) );
363 FT_MEM_COPY( target->tags, source->tags,
364 source->n_points * sizeof ( FT_Byte ) );
366 FT_MEM_COPY( target->contours, source->contours,
367 source->n_contours * sizeof ( FT_Short ) );
369 /* copy all flags, except the `FT_OUTLINE_OWNER' one */
370 is_owner = target->flags & FT_OUTLINE_OWNER;
371 target->flags = source->flags;
373 target->flags &= ~FT_OUTLINE_OWNER;
374 target->flags |= is_owner;
380 FT_EXPORT_DEF( FT_Error )
381 FT_Outline_Done_Internal( FT_Memory memory,
382 FT_Outline* outline )
386 if ( outline->flags & FT_OUTLINE_OWNER )
388 FT_FREE( outline->points );
389 FT_FREE( outline->tags );
390 FT_FREE( outline->contours );
392 *outline = null_outline;
397 return FT_Err_Invalid_Argument;
401 /* documentation is in ftoutln.h */
403 FT_EXPORT_DEF( FT_Error )
404 FT_Outline_Done( FT_Library library,
405 FT_Outline* outline )
407 /* check for valid `outline' in FT_Outline_Done_Internal() */
410 return FT_Err_Invalid_Library_Handle;
412 return FT_Outline_Done_Internal( library->memory, outline );
416 /* documentation is in ftoutln.h */
418 FT_EXPORT_DEF( void )
419 FT_Outline_Get_CBox( FT_Outline* outline,
422 FT_Pos xMin, yMin, xMax, yMax;
425 if ( outline && acbox )
427 if ( outline->n_points == 0 )
436 FT_Vector* vec = outline->points;
437 FT_Vector* limit = vec + outline->n_points;
440 xMin = xMax = vec->x;
441 yMin = yMax = vec->y;
444 for ( ; vec < limit; vec++ )
450 if ( x < xMin ) xMin = x;
451 if ( x > xMax ) xMax = x;
454 if ( y < yMin ) yMin = y;
455 if ( y > yMax ) yMax = y;
466 /* documentation is in ftoutln.h */
468 FT_EXPORT_DEF( void )
469 FT_Outline_Translate( FT_Outline* outline,
474 FT_Vector* vec = outline->points;
477 for ( n = 0; n < outline->n_points; n++ )
486 /* documentation is in ftoutln.h */
488 FT_EXPORT_DEF( void )
489 FT_Outline_Reverse( FT_Outline* outline )
497 for ( n = 0; n < outline->n_contours; n++ )
499 last = outline->contours[n];
501 /* reverse point table */
503 FT_Vector* p = outline->points + first;
504 FT_Vector* q = outline->points + last;
518 /* reverse tags table */
520 char* p = outline->tags + first;
521 char* q = outline->tags + last;
538 outline->flags ^= FT_OUTLINE_REVERSE_FILL;
542 /* documentation is in ftoutln.h */
544 FT_EXPORT_DEF( FT_Error )
545 FT_Outline_Render( FT_Library library,
547 FT_Raster_Params* params )
551 FT_Renderer renderer;
556 return FT_Err_Invalid_Library_Handle;
559 return FT_Err_Invalid_Argument;
561 renderer = library->cur_renderer;
562 node = library->renderers.head;
564 params->source = (void*)outline;
566 error = FT_Err_Cannot_Render_Glyph;
569 error = renderer->raster_render( renderer->raster, params );
570 if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
573 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
574 /* is unsupported by the current renderer for this glyph image */
577 /* now, look for another renderer that supports the same */
579 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
584 /* if we changed the current renderer for the glyph image format */
585 /* we need to select it as the next current one */
586 if ( !error && update && renderer )
587 FT_Set_Renderer( library, renderer, 0, 0 );
593 /* documentation is in ftoutln.h */
595 FT_EXPORT_DEF( FT_Error )
596 FT_Outline_Get_Bitmap( FT_Library library,
600 FT_Raster_Params params;
604 return FT_Err_Invalid_Argument;
606 /* other checks are delayed to FT_Outline_Render() */
608 params.target = abitmap;
611 if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
612 abitmap->pixel_mode == FT_PIXEL_MODE_LCD ||
613 abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
614 params.flags |= FT_RASTER_FLAG_AA;
616 return FT_Outline_Render( library, outline, ¶ms );
620 /* documentation is in ftoutln.h */
622 FT_EXPORT_DEF( void )
623 FT_Vector_Transform( FT_Vector* vector,
629 if ( !vector || !matrix )
632 xz = FT_MulFix( vector->x, matrix->xx ) +
633 FT_MulFix( vector->y, matrix->xy );
635 yz = FT_MulFix( vector->x, matrix->yx ) +
636 FT_MulFix( vector->y, matrix->yy );
643 /* documentation is in ftoutln.h */
645 FT_EXPORT_DEF( void )
646 FT_Outline_Transform( FT_Outline* outline,
649 FT_Vector* vec = outline->points;
650 FT_Vector* limit = vec + outline->n_points;
653 for ( ; vec < limit; vec++ )
654 FT_Vector_Transform( vec, matrix );