1 /***************************************************************************/
2 /* */
3 /* ftoutln.c */
4 /* */
5 /* FreeType outline management (body). */
6 /* */
7 /* Copyright 1996-2018 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
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. */
15 /* */
16 /***************************************************************************/
17
18
19 /*************************************************************************/
20 /* */
21 /* All functions are declared in freetype.h. */
22 /* */
23 /*************************************************************************/
24
25
26 #include <ft2build.h>
27 #include FT_OUTLINE_H
28 #include FT_INTERNAL_OBJECTS_H
29 #include FT_INTERNAL_CALC_H
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_TRIGONOMETRY_H
32
33
34 /*************************************************************************/
35 /* */
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
39 /* */
40 #undef FT_COMPONENT
41 #define FT_COMPONENT trace_outline
42
43
44 static
45 const FT_Outline null_outline = { 0, 0, NULL, NULL, NULL, 0 };
46
47
48 /* documentation is in ftoutln.h */
49
50 FT_EXPORT_DEF( FT_Error )
51 FT_Outline_Decompose( FT_Outline* outline,
52 const FT_Outline_Funcs* func_interface,
53 void* user )
54 {
55 #undef SCALED
56 #define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \
57 : ( (x) << shift ) ) - delta )
58
59 FT_Vector v_last;
60 FT_Vector v_control;
61 FT_Vector v_start;
279 Close:
280 if ( error )
281 goto Exit;
282
283 first = (FT_UInt)last + 1;
284 }
285
286 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
287 return FT_Err_Ok;
288
289 Invalid_Outline:
290 error = FT_THROW( Invalid_Outline );
291 /* fall through */
292
293 Exit:
294 FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
295 return error;
296 }
297
298
299 FT_EXPORT_DEF( FT_Error )
300 FT_Outline_New_Internal( FT_Memory memory,
301 FT_UInt numPoints,
302 FT_Int numContours,
303 FT_Outline *anoutline )
304 {
305 FT_Error error;
306
307
308 if ( !anoutline || !memory )
309 return FT_THROW( Invalid_Argument );
310
311 *anoutline = null_outline;
312
313 if ( numContours < 0 ||
314 (FT_UInt)numContours > numPoints )
315 return FT_THROW( Invalid_Argument );
316
317 if ( numPoints > FT_OUTLINE_POINTS_MAX )
318 return FT_THROW( Array_Too_Large );
319
320 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) ||
321 FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
322 FT_NEW_ARRAY( anoutline->contours, numContours ) )
323 goto Fail;
324
325 anoutline->n_points = (FT_Short)numPoints;
326 anoutline->n_contours = (FT_Short)numContours;
327 anoutline->flags |= FT_OUTLINE_OWNER;
328
329 return FT_Err_Ok;
330
331 Fail:
332 anoutline->flags |= FT_OUTLINE_OWNER;
333 FT_Outline_Done_Internal( memory, anoutline );
334
335 return error;
336 }
337
338
339 /* documentation is in ftoutln.h */
340
341 FT_EXPORT_DEF( FT_Error )
342 FT_Outline_New( FT_Library library,
343 FT_UInt numPoints,
344 FT_Int numContours,
345 FT_Outline *anoutline )
346 {
347 if ( !library )
348 return FT_THROW( Invalid_Library_Handle );
349
350 return FT_Outline_New_Internal( library->memory, numPoints,
351 numContours, anoutline );
352 }
353
354
355 /* documentation is in ftoutln.h */
356
357 FT_EXPORT_DEF( FT_Error )
358 FT_Outline_Check( FT_Outline* outline )
359 {
360 if ( outline )
361 {
362 FT_Int n_points = outline->n_points;
363 FT_Int n_contours = outline->n_contours;
364 FT_Int end0, end;
365 FT_Int n;
366
367
368 /* empty glyph? */
369 if ( n_points == 0 && n_contours == 0 )
370 return FT_Err_Ok;
371
372 /* check point and contour counts */
373 if ( n_points <= 0 || n_contours <= 0 )
374 goto Bad;
375
376 end0 = end = -1;
377 for ( n = 0; n < n_contours; n++ )
419 if ( source->n_points )
420 {
421 FT_ARRAY_COPY( target->points, source->points, source->n_points );
422 FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
423 }
424
425 if ( source->n_contours )
426 FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
427
428 /* copy all flags, except the `FT_OUTLINE_OWNER' one */
429 is_owner = target->flags & FT_OUTLINE_OWNER;
430 target->flags = source->flags;
431
432 target->flags &= ~FT_OUTLINE_OWNER;
433 target->flags |= is_owner;
434
435 return FT_Err_Ok;
436 }
437
438
439 FT_EXPORT_DEF( FT_Error )
440 FT_Outline_Done_Internal( FT_Memory memory,
441 FT_Outline* outline )
442 {
443 if ( !outline )
444 return FT_THROW( Invalid_Outline );
445
446 if ( !memory )
447 return FT_THROW( Invalid_Argument );
448
449 if ( outline->flags & FT_OUTLINE_OWNER )
450 {
451 FT_FREE( outline->points );
452 FT_FREE( outline->tags );
453 FT_FREE( outline->contours );
454 }
455 *outline = null_outline;
456
457 return FT_Err_Ok;
458 }
459
460
461 /* documentation is in ftoutln.h */
462
463 FT_EXPORT_DEF( FT_Error )
464 FT_Outline_Done( FT_Library library,
465 FT_Outline* outline )
466 {
467 /* check for valid `outline' in FT_Outline_Done_Internal() */
468
469 if ( !library )
470 return FT_THROW( Invalid_Library_Handle );
471
472 return FT_Outline_Done_Internal( library->memory, outline );
473 }
474
475
476 /* documentation is in ftoutln.h */
477
478 FT_EXPORT_DEF( void )
479 FT_Outline_Get_CBox( const FT_Outline* outline,
480 FT_BBox *acbox )
481 {
482 FT_Pos xMin, yMin, xMax, yMax;
483
484
485 if ( outline && acbox )
486 {
487 if ( outline->n_points == 0 )
488 {
489 xMin = 0;
490 yMin = 0;
491 xMax = 0;
492 yMax = 0;
493 }
494 else
495 {
496 FT_Vector* vec = outline->points;
497 FT_Vector* limit = vec + outline->n_points;
602 }
603 }
604
605 first = last + 1;
606 }
607
608 outline->flags ^= FT_OUTLINE_REVERSE_FILL;
609 }
610
611
612 /* documentation is in ftoutln.h */
613
614 FT_EXPORT_DEF( FT_Error )
615 FT_Outline_Render( FT_Library library,
616 FT_Outline* outline,
617 FT_Raster_Params* params )
618 {
619 FT_Error error;
620 FT_Renderer renderer;
621 FT_ListNode node;
622
623
624 if ( !library )
625 return FT_THROW( Invalid_Library_Handle );
626
627 if ( !outline )
628 return FT_THROW( Invalid_Outline );
629
630 if ( !params )
631 return FT_THROW( Invalid_Argument );
632
633 renderer = library->cur_renderer;
634 node = library->renderers.head;
635
636 params->source = (void*)outline;
637
638 error = FT_ERR( Cannot_Render_Glyph );
639 while ( renderer )
640 {
641 error = renderer->raster_render( renderer->raster, params );
642 if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
643 break;
644
645 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
646 /* is unsupported by the current renderer for this glyph image */
647 /* format */
648
649 /* now, look for another renderer that supports the same */
650 /* format */
651 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
652 &node );
896
897 /* documentation is in ftoutln.h */
898
899 FT_EXPORT_DEF( FT_Error )
900 FT_Outline_Embolden( FT_Outline* outline,
901 FT_Pos strength )
902 {
903 return FT_Outline_EmboldenXY( outline, strength, strength );
904 }
905
906
907 /* documentation is in ftoutln.h */
908
909 FT_EXPORT_DEF( FT_Error )
910 FT_Outline_EmboldenXY( FT_Outline* outline,
911 FT_Pos xstrength,
912 FT_Pos ystrength )
913 {
914 FT_Vector* points;
915 FT_Int c, first, last;
916 FT_Int orientation;
917
918
919 if ( !outline )
920 return FT_THROW( Invalid_Outline );
921
922 xstrength /= 2;
923 ystrength /= 2;
924 if ( xstrength == 0 && ystrength == 0 )
925 return FT_Err_Ok;
926
927 orientation = FT_Outline_Get_Orientation( outline );
928 if ( orientation == FT_ORIENTATION_NONE )
929 {
930 if ( outline->n_contours )
931 return FT_THROW( Invalid_Argument );
932 else
933 return FT_Err_Ok;
934 }
935
936 points = outline->points;
1027 }
1028 else
1029 i = j;
1030
1031 in = out;
1032 l_in = l_out;
1033 }
1034
1035 first = last + 1;
1036 }
1037
1038 return FT_Err_Ok;
1039 }
1040
1041
1042 /* documentation is in ftoutln.h */
1043
1044 FT_EXPORT_DEF( FT_Orientation )
1045 FT_Outline_Get_Orientation( FT_Outline* outline )
1046 {
1047 FT_BBox cbox;
1048 FT_Int xshift, yshift;
1049 FT_Vector* points;
1050 FT_Vector v_prev, v_cur;
1051 FT_Int c, n, first;
1052 FT_Pos area = 0;
1053
1054
1055 if ( !outline || outline->n_points <= 0 )
1056 return FT_ORIENTATION_TRUETYPE;
1057
1058 /* We use the nonzero winding rule to find the orientation. */
1059 /* Since glyph outlines behave much more `regular' than arbitrary */
1060 /* cubic or quadratic curves, this test deals with the polygon */
1061 /* only that is spanned up by the control points. */
1062
1063 FT_Outline_Get_CBox( outline, &cbox );
1064
1065 /* Handle collapsed outlines to avoid undefined FT_MSB. */
1066 if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax )
1067 return FT_ORIENTATION_NONE;
1073 yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14;
1074 yshift = FT_MAX( yshift, 0 );
1075
1076 points = outline->points;
1077
1078 first = 0;
1079 for ( c = 0; c < outline->n_contours; c++ )
1080 {
1081 FT_Int last = outline->contours[c];
1082
1083
1084 v_prev.x = points[last].x >> xshift;
1085 v_prev.y = points[last].y >> yshift;
1086
1087 for ( n = first; n <= last; n++ )
1088 {
1089 v_cur.x = points[n].x >> xshift;
1090 v_cur.y = points[n].y >> yshift;
1091
1092 area = ADD_LONG( area,
1093 ( v_cur.y - v_prev.y ) * ( v_cur.x + v_prev.x ) );
1094
1095 v_prev = v_cur;
1096 }
1097
1098 first = last + 1;
1099 }
1100
1101 if ( area > 0 )
1102 return FT_ORIENTATION_POSTSCRIPT;
1103 else if ( area < 0 )
1104 return FT_ORIENTATION_TRUETYPE;
1105 else
1106 return FT_ORIENTATION_NONE;
1107 }
1108
1109
1110 /* END */
|
1 /****************************************************************************
2 *
3 * ftoutln.c
4 *
5 * FreeType outline management (body).
6 *
7 * Copyright (C) 1996-2019 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
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.
15 *
16 */
17
18
19 #include <ft2build.h>
20 #include FT_OUTLINE_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_CALC_H
23 #include FT_INTERNAL_DEBUG_H
24 #include FT_TRIGONOMETRY_H
25
26
27 /**************************************************************************
28 *
29 * The macro FT_COMPONENT is used in trace mode. It is an implicit
30 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
31 * messages during execution.
32 */
33 #undef FT_COMPONENT
34 #define FT_COMPONENT outline
35
36
37 static
38 const FT_Outline null_outline = { 0, 0, NULL, NULL, NULL, 0 };
39
40
41 /* documentation is in ftoutln.h */
42
43 FT_EXPORT_DEF( FT_Error )
44 FT_Outline_Decompose( FT_Outline* outline,
45 const FT_Outline_Funcs* func_interface,
46 void* user )
47 {
48 #undef SCALED
49 #define SCALED( x ) ( ( (x) < 0 ? -( -(x) << shift ) \
50 : ( (x) << shift ) ) - delta )
51
52 FT_Vector v_last;
53 FT_Vector v_control;
54 FT_Vector v_start;
272 Close:
273 if ( error )
274 goto Exit;
275
276 first = (FT_UInt)last + 1;
277 }
278
279 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
280 return FT_Err_Ok;
281
282 Invalid_Outline:
283 error = FT_THROW( Invalid_Outline );
284 /* fall through */
285
286 Exit:
287 FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
288 return error;
289 }
290
291
292 /* documentation is in ftoutln.h */
293
294 FT_EXPORT_DEF( FT_Error )
295 FT_Outline_New( FT_Library library,
296 FT_UInt numPoints,
297 FT_Int numContours,
298 FT_Outline *anoutline )
299 {
300 FT_Error error;
301 FT_Memory memory;
302
303
304 if ( !library )
305 return FT_THROW( Invalid_Library_Handle );
306
307 memory = library->memory;
308
309 if ( !anoutline || !memory )
310 return FT_THROW( Invalid_Argument );
311
312 *anoutline = null_outline;
313
314 if ( numContours < 0 ||
315 (FT_UInt)numContours > numPoints )
316 return FT_THROW( Invalid_Argument );
317
318 if ( numPoints > FT_OUTLINE_POINTS_MAX )
319 return FT_THROW( Array_Too_Large );
320
321 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) ||
322 FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
323 FT_NEW_ARRAY( anoutline->contours, numContours ) )
324 goto Fail;
325
326 anoutline->n_points = (FT_Short)numPoints;
327 anoutline->n_contours = (FT_Short)numContours;
328 anoutline->flags |= FT_OUTLINE_OWNER;
329
330 return FT_Err_Ok;
331
332 Fail:
333 anoutline->flags |= FT_OUTLINE_OWNER;
334 FT_Outline_Done( library, anoutline );
335
336 return error;
337 }
338
339
340 /* documentation is in ftoutln.h */
341
342 FT_EXPORT_DEF( FT_Error )
343 FT_Outline_Check( FT_Outline* outline )
344 {
345 if ( outline )
346 {
347 FT_Int n_points = outline->n_points;
348 FT_Int n_contours = outline->n_contours;
349 FT_Int end0, end;
350 FT_Int n;
351
352
353 /* empty glyph? */
354 if ( n_points == 0 && n_contours == 0 )
355 return FT_Err_Ok;
356
357 /* check point and contour counts */
358 if ( n_points <= 0 || n_contours <= 0 )
359 goto Bad;
360
361 end0 = end = -1;
362 for ( n = 0; n < n_contours; n++ )
404 if ( source->n_points )
405 {
406 FT_ARRAY_COPY( target->points, source->points, source->n_points );
407 FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
408 }
409
410 if ( source->n_contours )
411 FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
412
413 /* copy all flags, except the `FT_OUTLINE_OWNER' one */
414 is_owner = target->flags & FT_OUTLINE_OWNER;
415 target->flags = source->flags;
416
417 target->flags &= ~FT_OUTLINE_OWNER;
418 target->flags |= is_owner;
419
420 return FT_Err_Ok;
421 }
422
423
424 /* documentation is in ftoutln.h */
425
426 FT_EXPORT_DEF( FT_Error )
427 FT_Outline_Done( FT_Library library,
428 FT_Outline* outline )
429 {
430 FT_Memory memory;
431
432
433 if ( !library )
434 return FT_THROW( Invalid_Library_Handle );
435
436 if ( !outline )
437 return FT_THROW( Invalid_Outline );
438
439 memory = library->memory;
440
441 if ( !memory )
442 return FT_THROW( Invalid_Argument );
443
444 if ( outline->flags & FT_OUTLINE_OWNER )
445 {
446 FT_FREE( outline->points );
447 FT_FREE( outline->tags );
448 FT_FREE( outline->contours );
449 }
450 *outline = null_outline;
451
452 return FT_Err_Ok;
453 }
454
455
456 /* documentation is in ftoutln.h */
457
458 FT_EXPORT_DEF( void )
459 FT_Outline_Get_CBox( const FT_Outline* outline,
460 FT_BBox *acbox )
461 {
462 FT_Pos xMin, yMin, xMax, yMax;
463
464
465 if ( outline && acbox )
466 {
467 if ( outline->n_points == 0 )
468 {
469 xMin = 0;
470 yMin = 0;
471 xMax = 0;
472 yMax = 0;
473 }
474 else
475 {
476 FT_Vector* vec = outline->points;
477 FT_Vector* limit = vec + outline->n_points;
582 }
583 }
584
585 first = last + 1;
586 }
587
588 outline->flags ^= FT_OUTLINE_REVERSE_FILL;
589 }
590
591
592 /* documentation is in ftoutln.h */
593
594 FT_EXPORT_DEF( FT_Error )
595 FT_Outline_Render( FT_Library library,
596 FT_Outline* outline,
597 FT_Raster_Params* params )
598 {
599 FT_Error error;
600 FT_Renderer renderer;
601 FT_ListNode node;
602 FT_BBox cbox;
603
604
605 if ( !library )
606 return FT_THROW( Invalid_Library_Handle );
607
608 if ( !outline )
609 return FT_THROW( Invalid_Outline );
610
611 if ( !params )
612 return FT_THROW( Invalid_Argument );
613
614 FT_Outline_Get_CBox( outline, &cbox );
615 if ( cbox.xMin < -0x1000000L || cbox.yMin < -0x1000000L ||
616 cbox.xMax > 0x1000000L || cbox.yMax > 0x1000000L )
617 return FT_THROW( Invalid_Outline );
618
619 renderer = library->cur_renderer;
620 node = library->renderers.head;
621
622 params->source = (void*)outline;
623
624 error = FT_ERR( Cannot_Render_Glyph );
625 while ( renderer )
626 {
627 error = renderer->raster_render( renderer->raster, params );
628 if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
629 break;
630
631 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
632 /* is unsupported by the current renderer for this glyph image */
633 /* format */
634
635 /* now, look for another renderer that supports the same */
636 /* format */
637 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
638 &node );
882
883 /* documentation is in ftoutln.h */
884
885 FT_EXPORT_DEF( FT_Error )
886 FT_Outline_Embolden( FT_Outline* outline,
887 FT_Pos strength )
888 {
889 return FT_Outline_EmboldenXY( outline, strength, strength );
890 }
891
892
893 /* documentation is in ftoutln.h */
894
895 FT_EXPORT_DEF( FT_Error )
896 FT_Outline_EmboldenXY( FT_Outline* outline,
897 FT_Pos xstrength,
898 FT_Pos ystrength )
899 {
900 FT_Vector* points;
901 FT_Int c, first, last;
902 FT_Orientation orientation;
903
904
905 if ( !outline )
906 return FT_THROW( Invalid_Outline );
907
908 xstrength /= 2;
909 ystrength /= 2;
910 if ( xstrength == 0 && ystrength == 0 )
911 return FT_Err_Ok;
912
913 orientation = FT_Outline_Get_Orientation( outline );
914 if ( orientation == FT_ORIENTATION_NONE )
915 {
916 if ( outline->n_contours )
917 return FT_THROW( Invalid_Argument );
918 else
919 return FT_Err_Ok;
920 }
921
922 points = outline->points;
1013 }
1014 else
1015 i = j;
1016
1017 in = out;
1018 l_in = l_out;
1019 }
1020
1021 first = last + 1;
1022 }
1023
1024 return FT_Err_Ok;
1025 }
1026
1027
1028 /* documentation is in ftoutln.h */
1029
1030 FT_EXPORT_DEF( FT_Orientation )
1031 FT_Outline_Get_Orientation( FT_Outline* outline )
1032 {
1033 FT_BBox cbox = { 0, 0, 0, 0 };
1034 FT_Int xshift, yshift;
1035 FT_Vector* points;
1036 FT_Vector v_prev, v_cur;
1037 FT_Int c, n, first;
1038 FT_Pos area = 0;
1039
1040
1041 if ( !outline || outline->n_points <= 0 )
1042 return FT_ORIENTATION_TRUETYPE;
1043
1044 /* We use the nonzero winding rule to find the orientation. */
1045 /* Since glyph outlines behave much more `regular' than arbitrary */
1046 /* cubic or quadratic curves, this test deals with the polygon */
1047 /* only that is spanned up by the control points. */
1048
1049 FT_Outline_Get_CBox( outline, &cbox );
1050
1051 /* Handle collapsed outlines to avoid undefined FT_MSB. */
1052 if ( cbox.xMin == cbox.xMax || cbox.yMin == cbox.yMax )
1053 return FT_ORIENTATION_NONE;
1059 yshift = FT_MSB( (FT_UInt32)( cbox.yMax - cbox.yMin ) ) - 14;
1060 yshift = FT_MAX( yshift, 0 );
1061
1062 points = outline->points;
1063
1064 first = 0;
1065 for ( c = 0; c < outline->n_contours; c++ )
1066 {
1067 FT_Int last = outline->contours[c];
1068
1069
1070 v_prev.x = points[last].x >> xshift;
1071 v_prev.y = points[last].y >> yshift;
1072
1073 for ( n = first; n <= last; n++ )
1074 {
1075 v_cur.x = points[n].x >> xshift;
1076 v_cur.y = points[n].y >> yshift;
1077
1078 area = ADD_LONG( area,
1079 MUL_LONG( v_cur.y - v_prev.y,
1080 v_cur.x + v_prev.x ) );
1081
1082 v_prev = v_cur;
1083 }
1084
1085 first = last + 1;
1086 }
1087
1088 if ( area > 0 )
1089 return FT_ORIENTATION_POSTSCRIPT;
1090 else if ( area < 0 )
1091 return FT_ORIENTATION_TRUETYPE;
1092 else
1093 return FT_ORIENTATION_NONE;
1094 }
1095
1096
1097 /* END */
|