Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

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