QtBase  v6.3.1
ftgrays.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * ftgrays.c
4  *
5  * A new `perfect' anti-aliasing renderer (body).
6  *
7  * Copyright (C) 2000-2020 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  * This file can be compiled without the rest of the FreeType engine, by
21  * defining the STANDALONE_ macro when compiling it. You also need to
22  * put the files `ftgrays.h' and `ftimage.h' into the current
23  * compilation directory. Typically, you could do something like
24  *
25  * - copy `src/smooth/ftgrays.c' (this file) to your current directory
26  *
27  * - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the
28  * same directory
29  *
30  * - compile `ftgrays' with the STANDALONE_ macro defined, as in
31  *
32  * cc -c -DSTANDALONE_ ftgrays.c
33  *
34  * The renderer can be initialized with a call to
35  * `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated
36  * with a call to `ft_gray_raster.raster_render'.
37  *
38  * See the comments and documentation in the file `ftimage.h' for more
39  * details on how the raster works.
40  *
41  */
42 
43  /**************************************************************************
44  *
45  * This is a new anti-aliasing scan-converter for FreeType 2. The
46  * algorithm used here is _very_ different from the one in the standard
47  * `ftraster' module. Actually, `ftgrays' computes the _exact_
48  * coverage of the outline on each pixel cell by straight segments.
49  *
50  * It is based on ideas that I initially found in Raph Levien's
51  * excellent LibArt graphics library (see https://www.levien.com/libart
52  * for more information, though the web pages do not tell anything
53  * about the renderer; you'll have to dive into the source code to
54  * understand how it works).
55  *
56  * Note, however, that this is a _very_ different implementation
57  * compared to Raph's. Coverage information is stored in a very
58  * different way, and I don't use sorted vector paths. Also, it doesn't
59  * use floating point values.
60  *
61  * Bézier segments are flattened by splitting them until their deviation
62  * from straight line becomes much smaller than a pixel. Therefore, the
63  * pixel coverage by a Bézier curve is calculated approximately. To
64  * estimate the deviation, we use the distance from the control point
65  * to the conic chord centre or the cubic chord trisection. These
66  * distances vanish fast after each split. In the conic case, they vanish
67  * predictably and the number of necessary splits can be calculated.
68  *
69  * This renderer has the following advantages:
70  *
71  * - It doesn't need an intermediate bitmap. Instead, one can supply a
72  * callback function that will be called by the renderer to draw gray
73  * spans on any target surface. You can thus do direct composition on
74  * any kind of bitmap, provided that you give the renderer the right
75  * callback.
76  *
77  * - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on
78  * each pixel cell by straight segments.
79  *
80  * - It performs a single pass on the outline (the `standard' FT2
81  * renderer makes two passes).
82  *
83  * - It can easily be modified to render to _any_ number of gray levels
84  * cheaply.
85  *
86  * - For small (< 80) pixel sizes, it is faster than the standard
87  * renderer.
88  *
89  */
90 
91 
92  /**************************************************************************
93  *
94  * The macro FT_COMPONENT is used in trace mode. It is an implicit
95  * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
96  * messages during execution.
97  */
98 #undef FT_COMPONENT
99 #define FT_COMPONENT smooth
100 
101 
102 #ifdef STANDALONE_
103 
104 
105  /* The size in bytes of the render pool used by the scan-line converter */
106  /* to do all of its work. */
107 #define FT_RENDER_POOL_SIZE 16384L
108 
109 
110  /* Auxiliary macros for token concatenation. */
111 #define FT_ERR_XCAT( x, y ) x ## y
112 #define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
113 
114 #define FT_BEGIN_STMNT do {
115 #define FT_END_STMNT } while ( 0 )
116 
117 #define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
118 #define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
119 #define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
120 
121 
122  /*
123  * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
124  * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
125  * largest error less than 7% compared to the exact value.
126  */
127 #define FT_HYPOT( x, y ) \
128  ( x = FT_ABS( x ), \
129  y = FT_ABS( y ), \
130  x > y ? x + ( 3 * y >> 3 ) \
131  : y + ( 3 * x >> 3 ) )
132 
133 
134  /* define this to dump debugging information */
135 /* #define FT_DEBUG_LEVEL_TRACE */
136 
137 
138 #ifdef FT_DEBUG_LEVEL_TRACE
139 #include <stdio.h>
140 #include <stdarg.h>
141 #endif
142 
143 #include <stddef.h>
144 #include <string.h>
145 #include <setjmp.h>
146 #include <limits.h>
147 #define FT_CHAR_BIT CHAR_BIT
148 #define FT_UINT_MAX UINT_MAX
149 #define FT_INT_MAX INT_MAX
150 #define FT_ULONG_MAX ULONG_MAX
151 
152 #define ADD_LONG( a, b ) \
153  (long)( (unsigned long)(a) + (unsigned long)(b) )
154 #define SUB_LONG( a, b ) \
155  (long)( (unsigned long)(a) - (unsigned long)(b) )
156 #define MUL_LONG( a, b ) \
157  (long)( (unsigned long)(a) * (unsigned long)(b) )
158 #define NEG_LONG( a ) \
159  (long)( -(unsigned long)(a) )
160 
161 
162 #define ft_memset memset
163 
164 #define ft_setjmp setjmp
165 #define ft_longjmp longjmp
166 #define ft_jmp_buf jmp_buf
167 
168 typedef ptrdiff_t FT_PtrDist;
169 
170 
171 #define ErrRaster_Invalid_Mode -2
172 #define ErrRaster_Invalid_Outline -1
173 #define ErrRaster_Invalid_Argument -3
174 #define ErrRaster_Memory_Overflow -4
175 
176 #define FT_BEGIN_HEADER
177 #define FT_END_HEADER
178 
179 #include "ftimage.h"
180 #include "ftgrays.h"
181 
182 
183  /* This macro is used to indicate that a function parameter is unused. */
184  /* Its purpose is simply to reduce compiler warnings. Note also that */
185  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
186  /* ANSI compilers (e.g. LCC). */
187 #define FT_UNUSED( x ) (x) = (x)
188 
189 
190  /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
191 
192 #ifdef FT_DEBUG_LEVEL_TRACE
193 
194  void
195  FT_Message( const char* fmt,
196  ... )
197  {
198  va_list ap;
199 
200 
201  va_start( ap, fmt );
202  vfprintf( stderr, fmt, ap );
203  va_end( ap );
204  }
205 
206 
207  /* empty function useful for setting a breakpoint to catch errors */
208  int
209  FT_Throw( int error,
210  int line,
211  const char* file )
212  {
213  FT_UNUSED( error );
214  FT_UNUSED( line );
215  FT_UNUSED( file );
216 
217  return 0;
218  }
219 
220 
221  /* we don't handle tracing levels in stand-alone mode; */
222 #ifndef FT_TRACE5
223 #define FT_TRACE5( varformat ) FT_Message varformat
224 #endif
225 #ifndef FT_TRACE7
226 #define FT_TRACE7( varformat ) FT_Message varformat
227 #endif
228 #ifndef FT_ERROR
229 #define FT_ERROR( varformat ) FT_Message varformat
230 #endif
231 
232 #define FT_THROW( e ) \
233  ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ), \
234  __LINE__, \
235  __FILE__ ) | \
236  FT_ERR_CAT( ErrRaster_, e ) )
237 
238 #else /* !FT_DEBUG_LEVEL_TRACE */
239 
240 #define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
241 #define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
242 #define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
243 #define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e )
244 
245 
246 #endif /* !FT_DEBUG_LEVEL_TRACE */
247 
248 
249 #define FT_DEFINE_OUTLINE_FUNCS( class_, \
250  move_to_, line_to_, \
251  conic_to_, cubic_to_, \
252  shift_, delta_ ) \
253  static const FT_Outline_Funcs class_ = \
254  { \
255  move_to_, \
256  line_to_, \
257  conic_to_, \
258  cubic_to_, \
259  shift_, \
260  delta_ \
261  };
262 
263 #define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \
264  raster_new_, raster_reset_, \
265  raster_set_mode_, raster_render_, \
266  raster_done_ ) \
267  const FT_Raster_Funcs class_ = \
268  { \
269  glyph_format_, \
270  raster_new_, \
271  raster_reset_, \
272  raster_set_mode_, \
273  raster_render_, \
274  raster_done_ \
275  };
276 
277 
278 #else /* !STANDALONE_ */
279 
280 
281 #include "ftgrays.h"
285 #include <freetype/ftoutln.h>
286 
287 #include "ftsmerrs.h"
288 
289 #define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
290 #define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory
291 #define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
292 
293 
294 #endif /* !STANDALONE_ */
295 
296 
297 #ifndef FT_MEM_SET
298 #define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
299 #endif
300 
301 #ifndef FT_MEM_ZERO
302 #define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
303 #endif
304 
305 #ifndef FT_ZERO
306 #define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )
307 #endif
308 
309  /* as usual, for the speed hungry :-) */
310 
311 #undef RAS_ARG
312 #undef RAS_ARG_
313 #undef RAS_VAR
314 #undef RAS_VAR_
315 
316 #ifndef FT_STATIC_RASTER
317 
318 #define RAS_ARG gray_PWorker worker
319 #define RAS_ARG_ gray_PWorker worker,
320 
321 #define RAS_VAR worker
322 #define RAS_VAR_ worker,
323 
324 #else /* FT_STATIC_RASTER */
325 
326 #define RAS_ARG void
327 #define RAS_ARG_ /* empty */
328 #define RAS_VAR /* empty */
329 #define RAS_VAR_ /* empty */
330 
331 #endif /* FT_STATIC_RASTER */
332 
333 
334  /* must be at least 6 bits! */
335 #define PIXEL_BITS 8
336 
337 #define ONE_PIXEL ( 1 << PIXEL_BITS )
338 #define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS )
339 #define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) )
340 
341 #if PIXEL_BITS >= 6
342 #define UPSCALE( x ) ( (x) * ( ONE_PIXEL >> 6 ) )
343 #define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
344 #else
345 #define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
346 #define DOWNSCALE( x ) ( (x) * ( 64 >> PIXEL_BITS ) )
347 #endif
348 
349 
350  /* Compute `dividend / divisor' and return both its quotient and */
351  /* remainder, cast to a specific type. This macro also ensures that */
352  /* the remainder is always positive. We use the remainder to keep */
353  /* track of accumulating errors and compensate for them. */
354 #define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
355  FT_BEGIN_STMNT \
356  (quotient) = (type)( (dividend) / (divisor) ); \
357  (remainder) = (type)( (dividend) % (divisor) ); \
358  if ( (remainder) < 0 ) \
359  { \
360  (quotient)--; \
361  (remainder) += (type)(divisor); \
362  } \
363  FT_END_STMNT
364 
365 #ifdef __arm__
366  /* Work around a bug specific to GCC which make the compiler fail to */
367  /* optimize a division and modulo operation on the same parameters */
368  /* into a single call to `__aeabi_idivmod'. See */
369  /* */
370  /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
371 #undef FT_DIV_MOD
372 #define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
373  FT_BEGIN_STMNT \
374  (quotient) = (type)( (dividend) / (divisor) ); \
375  (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \
376  if ( (remainder) < 0 ) \
377  { \
378  (quotient)--; \
379  (remainder) += (type)(divisor); \
380  } \
381  FT_END_STMNT
382 #endif /* __arm__ */
383 
384 
385  /* These macros speed up repetitive divisions by replacing them */
386  /* with multiplications and right shifts. */
387 #define FT_UDIVPREP( c, b ) \
388  long b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \
389  : 0
390 #define FT_UDIV( a, b ) \
391  (TCoord)( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
392  ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
393 
394 
395  /**************************************************************************
396  *
397  * TYPE DEFINITIONS
398  */
399 
400  /* don't change the following types to FT_Int or FT_Pos, since we might */
401  /* need to define them to "float" or "double" when experimenting with */
402  /* new algorithms */
403 
404  typedef long TPos; /* subpixel coordinate */
405  typedef int TCoord; /* integer scanline/pixel coordinate */
406  typedef int TArea; /* cell areas, coordinate products */
407 
408 
409  typedef struct TCell_* PCell;
410 
411  typedef struct TCell_
412  {
413  TCoord x; /* same with gray_TWorker.ex */
414  TCoord cover; /* same with gray_TWorker.cover */
417 
418  } TCell;
419 
420  typedef struct TPixmap_
421  {
422  unsigned char* origin; /* pixmap origin at the bottom-left */
423  int pitch; /* pitch to go down one row */
424 
426 
427  /* maximum number of gray cells in the buffer */
428 #if FT_RENDER_POOL_SIZE > 2048
429 #define FT_MAX_GRAY_POOL ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) )
430 #else
431 #define FT_MAX_GRAY_POOL ( 2048 / sizeof ( TCell ) )
432 #endif
433 
434  /* FT_Span buffer size for direct rendering only */
435 #define FT_MAX_GRAY_SPANS 10
436 
437 
438 #if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
439  /* We disable the warning `structure was padded due to */
440  /* __declspec(align())' in order to compile cleanly with */
441  /* the maximum level of warnings. */
442 #pragma warning( push )
443 #pragma warning( disable : 4324 )
444 #endif /* _MSC_VER */
445 
446  typedef struct gray_TWorker_
447  {
449 
453 
456  int invalid;
457 
462 
463  TPos x, y;
464 
467 
472 
474 
475 #if defined( _MSC_VER )
476 #pragma warning( pop )
477 #endif
478 
479 
480 #ifndef FT_STATIC_RASTER
481 #define ras (*worker)
482 #else
483  static gray_TWorker ras;
484 #endif
485 
486 
487  typedef struct gray_TRaster_
488  {
489  void* memory;
490 
492 
493 
494 #ifdef FT_DEBUG_LEVEL_TRACE
495 
496  /* to be called while in the debugger -- */
497  /* this function causes a compiler warning since it is unused otherwise */
498  static void
499  gray_dump_cells( RAS_ARG )
500  {
501  int y;
502 
503 
504  for ( y = ras.min_ey; y < ras.max_ey; y++ )
505  {
506  PCell cell = ras.ycells[y - ras.min_ey];
507 
508 
509  printf( "%3d:", y );
510 
511  for ( ; cell != NULL; cell = cell->next )
512  printf( " (%3d, c:%4d, a:%6d)",
513  cell->x, cell->cover, cell->area );
514  printf( "\n" );
515  }
516  }
517 
518 #endif /* FT_DEBUG_LEVEL_TRACE */
519 
520 
521  /**************************************************************************
522  *
523  * Record the current cell in the linked list.
524  */
525  static void
526  gray_record_cell( RAS_ARG )
527  {
528  PCell *pcell, cell;
529  TCoord x = ras.ex;
530 
531 
532  pcell = &ras.ycells[ras.ey - ras.min_ey];
533  while ( ( cell = *pcell ) )
534  {
535  if ( cell->x > x )
536  break;
537 
538  if ( cell->x == x )
539  goto Found;
540 
541  pcell = &cell->next;
542  }
543 
544  if ( ras.num_cells >= ras.max_cells )
545  ft_longjmp( ras.jump_buffer, 1 );
546 
547  /* insert new cell */
548  cell = ras.cells + ras.num_cells++;
549  cell->x = x;
550  cell->area = ras.area;
551  cell->cover = ras.cover;
552 
553  cell->next = *pcell;
554  *pcell = cell;
555 
556  return;
557 
558  Found:
559  /* update old cell */
560  cell->area += ras.area;
561  cell->cover += ras.cover;
562  }
563 
564 
565  /**************************************************************************
566  *
567  * Set the current cell to a new position.
568  */
569  static void
570  gray_set_cell( RAS_ARG_ TCoord ex,
571  TCoord ey )
572  {
573  /* Move the cell pointer to a new position. We set the `invalid' */
574  /* flag to indicate that the cell isn't part of those we're interested */
575  /* in during the render phase. This means that: */
576  /* */
577  /* . the new vertical position must be within min_ey..max_ey-1. */
578  /* . the new horizontal position must be strictly less than max_ex */
579  /* */
580  /* Note that if a cell is to the left of the clipping region, it is */
581  /* actually set to the (min_ex-1) horizontal position. */
582 
583  /* record the current one if it is valid and substantial */
584  if ( !ras.invalid && ( ras.area || ras.cover ) )
585  gray_record_cell( RAS_VAR );
586 
587  ras.area = 0;
588  ras.cover = 0;
589  ras.ex = FT_MAX( ex, ras.min_ex - 1 );
590  ras.ey = ey;
591 
592  ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
593  ex >= ras.max_ex );
594  }
595 
596 
597 #ifndef FT_LONG64
598 
599  /**************************************************************************
600  *
601  * Render a scanline as one or more cells.
602  */
603  static void
604  gray_render_scanline( RAS_ARG_ TCoord ey,
605  TPos x1,
606  TCoord y1,
607  TPos x2,
608  TCoord y2 )
609  {
610  TCoord ex1, ex2, fx1, fx2, first, dy, delta, mod;
611  TPos p, dx;
612  int incr;
613 
614 
615  ex1 = TRUNC( x1 );
616  ex2 = TRUNC( x2 );
617 
618  /* trivial case. Happens often */
619  if ( y1 == y2 )
620  {
621  gray_set_cell( RAS_VAR_ ex2, ey );
622  return;
623  }
624 
625  fx1 = FRACT( x1 );
626  fx2 = FRACT( x2 );
627 
628  /* everything is located in a single cell. That is easy! */
629  /* */
630  if ( ex1 == ex2 )
631  goto End;
632 
633  /* ok, we'll have to render a run of adjacent cells on the same */
634  /* scanline... */
635  /* */
636  dx = x2 - x1;
637  dy = y2 - y1;
638 
639  if ( dx > 0 )
640  {
641  p = ( ONE_PIXEL - fx1 ) * dy;
642  first = ONE_PIXEL;
643  incr = 1;
644  }
645  else
646  {
647  p = fx1 * dy;
648  first = 0;
649  incr = -1;
650  dx = -dx;
651  }
652 
653  /* the fractional part of y-delta is mod/dx. It is essential to */
654  /* keep track of its accumulation for accurate rendering. */
655  /* XXX: y-delta and x-delta below should be related. */
656  FT_DIV_MOD( TCoord, p, dx, delta, mod );
657 
658  ras.area += (TArea)( ( fx1 + first ) * delta );
659  ras.cover += delta;
660  y1 += delta;
661  ex1 += incr;
662  gray_set_cell( RAS_VAR_ ex1, ey );
663 
664  if ( ex1 != ex2 )
665  {
666  TCoord lift, rem;
667 
668 
669  p = ONE_PIXEL * dy;
670  FT_DIV_MOD( TCoord, p, dx, lift, rem );
671 
672  do
673  {
674  delta = lift;
675  mod += rem;
676  if ( mod >= (TCoord)dx )
677  {
678  mod -= (TCoord)dx;
679  delta++;
680  }
681 
682  ras.area += (TArea)( ONE_PIXEL * delta );
683  ras.cover += delta;
684  y1 += delta;
685  ex1 += incr;
686  gray_set_cell( RAS_VAR_ ex1, ey );
687  } while ( ex1 != ex2 );
688  }
689 
690  fx1 = ONE_PIXEL - first;
691 
692  End:
693  dy = y2 - y1;
694 
695  ras.area += (TArea)( ( fx1 + fx2 ) * dy );
696  ras.cover += dy;
697  }
698 
699 
700  /**************************************************************************
701  *
702  * Render a given line as a series of scanlines.
703  */
704  static void
705  gray_render_line( RAS_ARG_ TPos to_x,
706  TPos to_y )
707  {
708  TCoord ey1, ey2, fy1, fy2, first, delta, mod;
709  TPos p, dx, dy, x, x2;
710  int incr;
711 
712 
713  ey1 = TRUNC( ras.y );
714  ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
715 
716  /* perform vertical clipping */
717  if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
718  ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
719  goto End;
720 
721  fy1 = FRACT( ras.y );
722  fy2 = FRACT( to_y );
723 
724  /* everything is on a single scanline */
725  if ( ey1 == ey2 )
726  {
727  gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
728  goto End;
729  }
730 
731  dx = to_x - ras.x;
732  dy = to_y - ras.y;
733 
734  /* vertical line - avoid calling gray_render_scanline */
735  if ( dx == 0 )
736  {
737  TCoord ex = TRUNC( ras.x );
738  TCoord two_fx = FRACT( ras.x ) << 1;
739  TArea area;
740 
741 
742  if ( dy > 0)
743  {
744  first = ONE_PIXEL;
745  incr = 1;
746  }
747  else
748  {
749  first = 0;
750  incr = -1;
751  }
752 
753  delta = first - fy1;
754  ras.area += (TArea)two_fx * delta;
755  ras.cover += delta;
756  ey1 += incr;
757 
758  gray_set_cell( RAS_VAR_ ex, ey1 );
759 
760  delta = first + first - ONE_PIXEL;
761  area = (TArea)two_fx * delta;
762  while ( ey1 != ey2 )
763  {
764  ras.area += area;
765  ras.cover += delta;
766  ey1 += incr;
767 
768  gray_set_cell( RAS_VAR_ ex, ey1 );
769  }
770 
771  delta = fy2 - ONE_PIXEL + first;
772  ras.area += (TArea)two_fx * delta;
773  ras.cover += delta;
774 
775  goto End;
776  }
777 
778  /* ok, we have to render several scanlines */
779  if ( dy > 0)
780  {
781  p = ( ONE_PIXEL - fy1 ) * dx;
782  first = ONE_PIXEL;
783  incr = 1;
784  }
785  else
786  {
787  p = fy1 * dx;
788  first = 0;
789  incr = -1;
790  dy = -dy;
791  }
792 
793  /* the fractional part of x-delta is mod/dy. It is essential to */
794  /* keep track of its accumulation for accurate rendering. */
795  FT_DIV_MOD( TCoord, p, dy, delta, mod );
796 
797  x = ras.x + delta;
798  gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
799 
800  ey1 += incr;
801  gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
802 
803  if ( ey1 != ey2 )
804  {
805  TCoord lift, rem;
806 
807 
808  p = ONE_PIXEL * dx;
809  FT_DIV_MOD( TCoord, p, dy, lift, rem );
810 
811  do
812  {
813  delta = lift;
814  mod += rem;
815  if ( mod >= (TCoord)dy )
816  {
817  mod -= (TCoord)dy;
818  delta++;
819  }
820 
821  x2 = x + delta;
822  gray_render_scanline( RAS_VAR_ ey1,
823  x, ONE_PIXEL - first,
824  x2, first );
825  x = x2;
826 
827  ey1 += incr;
828  gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
829  } while ( ey1 != ey2 );
830  }
831 
832  gray_render_scanline( RAS_VAR_ ey1,
833  x, ONE_PIXEL - first,
834  to_x, fy2 );
835 
836  End:
837  ras.x = to_x;
838  ras.y = to_y;
839  }
840 
841 #else
842 
843  /**************************************************************************
844  *
845  * Render a straight line across multiple cells in any direction.
846  */
847  static void
848  gray_render_line( RAS_ARG_ TPos to_x,
849  TPos to_y )
850  {
851  TPos dx, dy;
852  TCoord fx1, fy1, fx2, fy2;
853  TCoord ex1, ey1, ex2, ey2;
854 
855 
856  ey1 = TRUNC( ras.y );
857  ey2 = TRUNC( to_y );
858 
859  /* perform vertical clipping */
860  if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
861  ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
862  goto End;
863 
864  ex1 = TRUNC( ras.x );
865  ex2 = TRUNC( to_x );
866 
867  fx1 = FRACT( ras.x );
868  fy1 = FRACT( ras.y );
869 
870  dx = to_x - ras.x;
871  dy = to_y - ras.y;
872 
873  if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
874  ;
875  else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
876  {
877  gray_set_cell( RAS_VAR_ ex2, ey2 );
878  goto End;
879  }
880  else if ( dx == 0 )
881  {
882  if ( dy > 0 ) /* vertical line up */
883  do
884  {
885  fy2 = ONE_PIXEL;
886  ras.cover += ( fy2 - fy1 );
887  ras.area += ( fy2 - fy1 ) * fx1 * 2;
888  fy1 = 0;
889  ey1++;
890  gray_set_cell( RAS_VAR_ ex1, ey1 );
891  } while ( ey1 != ey2 );
892  else /* vertical line down */
893  do
894  {
895  fy2 = 0;
896  ras.cover += ( fy2 - fy1 );
897  ras.area += ( fy2 - fy1 ) * fx1 * 2;
898  fy1 = ONE_PIXEL;
899  ey1--;
900  gray_set_cell( RAS_VAR_ ex1, ey1 );
901  } while ( ey1 != ey2 );
902  }
903  else /* any other line */
904  {
905  TPos prod = dx * (TPos)fy1 - dy * (TPos)fx1;
906  FT_UDIVPREP( ex1 != ex2, dx );
907  FT_UDIVPREP( ey1 != ey2, dy );
908 
909 
910  /* The fundamental value `prod' determines which side and the */
911  /* exact coordinate where the line exits current cell. It is */
912  /* also easily updated when moving from one cell to the next. */
913  do
914  {
915  if ( prod <= 0 &&
916  prod - dx * ONE_PIXEL > 0 ) /* left */
917  {
918  fx2 = 0;
919  fy2 = FT_UDIV( -prod, -dx );
920  prod -= dy * ONE_PIXEL;
921  ras.cover += ( fy2 - fy1 );
922  ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
923  fx1 = ONE_PIXEL;
924  fy1 = fy2;
925  ex1--;
926  }
927  else if ( prod - dx * ONE_PIXEL <= 0 &&
928  prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
929  {
930  prod -= dx * ONE_PIXEL;
931  fx2 = FT_UDIV( -prod, dy );
932  fy2 = ONE_PIXEL;
933  ras.cover += ( fy2 - fy1 );
934  ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
935  fx1 = fx2;
936  fy1 = 0;
937  ey1++;
938  }
939  else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
940  prod + dy * ONE_PIXEL >= 0 ) /* right */
941  {
942  prod += dy * ONE_PIXEL;
943  fx2 = ONE_PIXEL;
944  fy2 = FT_UDIV( prod, dx );
945  ras.cover += ( fy2 - fy1 );
946  ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
947  fx1 = 0;
948  fy1 = fy2;
949  ex1++;
950  }
951  else /* ( prod + dy * ONE_PIXEL < 0 &&
952  prod > 0 ) down */
953  {
954  fx2 = FT_UDIV( prod, -dy );
955  fy2 = 0;
956  prod += dx * ONE_PIXEL;
957  ras.cover += ( fy2 - fy1 );
958  ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
959  fx1 = fx2;
960  fy1 = ONE_PIXEL;
961  ey1--;
962  }
963 
964  gray_set_cell( RAS_VAR_ ex1, ey1 );
965  } while ( ex1 != ex2 || ey1 != ey2 );
966  }
967 
968  fx2 = FRACT( to_x );
969  fy2 = FRACT( to_y );
970 
971  ras.cover += ( fy2 - fy1 );
972  ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
973 
974  End:
975  ras.x = to_x;
976  ras.y = to_y;
977  }
978 
979 #endif
980 
981  static void
982  gray_split_conic( FT_Vector* base )
983  {
984  TPos a, b;
985 
986 
987  base[4].x = base[2].x;
988  a = base[0].x + base[1].x;
989  b = base[1].x + base[2].x;
990  base[3].x = b >> 1;
991  base[2].x = ( a + b ) >> 2;
992  base[1].x = a >> 1;
993 
994  base[4].y = base[2].y;
995  a = base[0].y + base[1].y;
996  b = base[1].y + base[2].y;
997  base[3].y = b >> 1;
998  base[2].y = ( a + b ) >> 2;
999  base[1].y = a >> 1;
1000  }
1001 
1002 
1003  static void
1004  gray_render_conic( RAS_ARG_ const FT_Vector* control,
1005  const FT_Vector* to )
1006  {
1007  FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */
1008  FT_Vector* arc = bez_stack;
1009  TPos dx, dy;
1010  int draw, split;
1011 
1012 
1013  arc[0].x = UPSCALE( to->x );
1014  arc[0].y = UPSCALE( to->y );
1015  arc[1].x = UPSCALE( control->x );
1016  arc[1].y = UPSCALE( control->y );
1017  arc[2].x = ras.x;
1018  arc[2].y = ras.y;
1019 
1020  /* short-cut the arc that crosses the current band */
1021  if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
1022  TRUNC( arc[1].y ) >= ras.max_ey &&
1023  TRUNC( arc[2].y ) >= ras.max_ey ) ||
1024  ( TRUNC( arc[0].y ) < ras.min_ey &&
1025  TRUNC( arc[1].y ) < ras.min_ey &&
1026  TRUNC( arc[2].y ) < ras.min_ey ) )
1027  {
1028  ras.x = arc[0].x;
1029  ras.y = arc[0].y;
1030  return;
1031  }
1032 
1033  dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
1034  dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
1035  if ( dx < dy )
1036  dx = dy;
1037 
1038  /* We can calculate the number of necessary bisections because */
1039  /* each bisection predictably reduces deviation exactly 4-fold. */
1040  /* Even 32-bit deviation would vanish after 16 bisections. */
1041  draw = 1;
1042  while ( dx > ONE_PIXEL / 4 )
1043  {
1044  dx >>= 2;
1045  draw <<= 1;
1046  }
1047 
1048  /* We use decrement counter to count the total number of segments */
1049  /* to draw starting from 2^level. Before each draw we split as */
1050  /* many times as there are trailing zeros in the counter. */
1051  do
1052  {
1053  split = draw & ( -draw ); /* isolate the rightmost 1-bit */
1054  while ( ( split >>= 1 ) )
1055  {
1056  gray_split_conic( arc );
1057  arc += 2;
1058  }
1059 
1060  gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
1061  arc -= 2;
1062 
1063  } while ( --draw );
1064  }
1065 
1066 
1067  static void
1068  gray_split_cubic( FT_Vector* base )
1069  {
1070  TPos a, b, c;
1071 
1072 
1073  base[6].x = base[3].x;
1074  a = base[0].x + base[1].x;
1075  b = base[1].x + base[2].x;
1076  c = base[2].x + base[3].x;
1077  base[5].x = c >> 1;
1078  c += b;
1079  base[4].x = c >> 2;
1080  base[1].x = a >> 1;
1081  a += b;
1082  base[2].x = a >> 2;
1083  base[3].x = ( a + c ) >> 3;
1084 
1085  base[6].y = base[3].y;
1086  a = base[0].y + base[1].y;
1087  b = base[1].y + base[2].y;
1088  c = base[2].y + base[3].y;
1089  base[5].y = c >> 1;
1090  c += b;
1091  base[4].y = c >> 2;
1092  base[1].y = a >> 1;
1093  a += b;
1094  base[2].y = a >> 2;
1095  base[3].y = ( a + c ) >> 3;
1096  }
1097 
1098 
1099  static void
1100  gray_render_cubic( RAS_ARG_ const FT_Vector* control1,
1101  const FT_Vector* control2,
1102  const FT_Vector* to )
1103  {
1104  FT_Vector bez_stack[16 * 3 + 1]; /* enough to accommodate bisections */
1105  FT_Vector* arc = bez_stack;
1106 
1107 
1108  arc[0].x = UPSCALE( to->x );
1109  arc[0].y = UPSCALE( to->y );
1110  arc[1].x = UPSCALE( control2->x );
1111  arc[1].y = UPSCALE( control2->y );
1112  arc[2].x = UPSCALE( control1->x );
1113  arc[2].y = UPSCALE( control1->y );
1114  arc[3].x = ras.x;
1115  arc[3].y = ras.y;
1116 
1117  /* short-cut the arc that crosses the current band */
1118  if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
1119  TRUNC( arc[1].y ) >= ras.max_ey &&
1120  TRUNC( arc[2].y ) >= ras.max_ey &&
1121  TRUNC( arc[3].y ) >= ras.max_ey ) ||
1122  ( TRUNC( arc[0].y ) < ras.min_ey &&
1123  TRUNC( arc[1].y ) < ras.min_ey &&
1124  TRUNC( arc[2].y ) < ras.min_ey &&
1125  TRUNC( arc[3].y ) < ras.min_ey ) )
1126  {
1127  ras.x = arc[0].x;
1128  ras.y = arc[0].y;
1129  return;
1130  }
1131 
1132  for (;;)
1133  {
1134  /* with each split, control points quickly converge towards */
1135  /* chord trisection points and the vanishing distances below */
1136  /* indicate when the segment is flat enough to draw */
1137  if ( FT_ABS( 2 * arc[0].x - 3 * arc[1].x + arc[3].x ) > ONE_PIXEL / 2 ||
1138  FT_ABS( 2 * arc[0].y - 3 * arc[1].y + arc[3].y ) > ONE_PIXEL / 2 ||
1139  FT_ABS( arc[0].x - 3 * arc[2].x + 2 * arc[3].x ) > ONE_PIXEL / 2 ||
1140  FT_ABS( arc[0].y - 3 * arc[2].y + 2 * arc[3].y ) > ONE_PIXEL / 2 )
1141  goto Split;
1142 
1143  gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
1144 
1145  if ( arc == bez_stack )
1146  return;
1147 
1148  arc -= 3;
1149  continue;
1150 
1151  Split:
1152  gray_split_cubic( arc );
1153  arc += 3;
1154  }
1155  }
1156 
1157 
1158  static int
1159  gray_move_to( const FT_Vector* to,
1160  gray_PWorker worker )
1161  {
1162  TPos x, y;
1163 
1164 
1165  /* start to a new position */
1166  x = UPSCALE( to->x );
1167  y = UPSCALE( to->y );
1168 
1169  gray_set_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
1170 
1171  ras.x = x;
1172  ras.y = y;
1173  return 0;
1174  }
1175 
1176 
1177  static int
1178  gray_line_to( const FT_Vector* to,
1179  gray_PWorker worker )
1180  {
1181  gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
1182  return 0;
1183  }
1184 
1185 
1186  static int
1187  gray_conic_to( const FT_Vector* control,
1188  const FT_Vector* to,
1189  gray_PWorker worker )
1190  {
1191  gray_render_conic( RAS_VAR_ control, to );
1192  return 0;
1193  }
1194 
1195 
1196  static int
1197  gray_cubic_to( const FT_Vector* control1,
1198  const FT_Vector* control2,
1199  const FT_Vector* to,
1200  gray_PWorker worker )
1201  {
1202  gray_render_cubic( RAS_VAR_ control1, control2, to );
1203  return 0;
1204  }
1205 
1206 
1207  static void
1208  gray_hline( RAS_ARG_ TCoord x,
1209  TCoord y,
1210  TArea coverage,
1211  TCoord acount )
1212  {
1213  /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */
1214  coverage >>= PIXEL_BITS * 2 + 1 - 8;
1215 
1216  /* compute the line's coverage depending on the outline fill rule */
1217  if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
1218  {
1219  coverage &= 511;
1220 
1221  if ( coverage >= 256 )
1222  coverage = 511 - coverage;
1223  }
1224  else /* default non-zero winding rule */
1225  {
1226  if ( coverage < 0 )
1227  coverage = ~coverage; /* the same as -coverage - 1 */
1228 
1229  if ( coverage >= 256 )
1230  coverage = 255;
1231  }
1232 
1233  if ( ras.num_spans >= 0 ) /* for FT_RASTER_FLAG_DIRECT only */
1234  {
1235  FT_Span* span = ras.spans + ras.num_spans++;
1236 
1237 
1238  span->x = (short)x;
1239  span->len = (unsigned short)acount;
1240  span->coverage = (unsigned char)coverage;
1241 
1242  if ( ras.num_spans == FT_MAX_GRAY_SPANS )
1243  {
1244  /* flush the span buffer and reset the count */
1245  ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
1246  ras.num_spans = 0;
1247  }
1248  }
1249  else
1250  {
1251  unsigned char* q = ras.target.origin - ras.target.pitch * y + x;
1252  unsigned char c = (unsigned char)coverage;
1253 
1254 
1255  /* For small-spans it is faster to do it by ourselves than
1256  * calling `memset'. This is mainly due to the cost of the
1257  * function call.
1258  */
1259  switch ( acount )
1260  {
1261  case 7:
1262  *q++ = c;
1263  /* fall through */
1264  case 6:
1265  *q++ = c;
1266  /* fall through */
1267  case 5:
1268  *q++ = c;
1269  /* fall through */
1270  case 4:
1271  *q++ = c;
1272  /* fall through */
1273  case 3:
1274  *q++ = c;
1275  /* fall through */
1276  case 2:
1277  *q++ = c;
1278  /* fall through */
1279  case 1:
1280  *q = c;
1281  /* fall through */
1282  case 0:
1283  break;
1284  default:
1285  FT_MEM_SET( q, c, acount );
1286  }
1287  }
1288  }
1289 
1290 
1291  static void
1292  gray_sweep( RAS_ARG )
1293  {
1294  int y;
1295 
1296 
1297  for ( y = ras.min_ey; y < ras.max_ey; y++ )
1298  {
1299  PCell cell = ras.ycells[y - ras.min_ey];
1300  TCoord x = ras.min_ex;
1301  TArea cover = 0;
1302  TArea area;
1303 
1304 
1305  for ( ; cell != NULL; cell = cell->next )
1306  {
1307  if ( cover != 0 && cell->x > x )
1308  gray_hline( RAS_VAR_ x, y, cover, cell->x - x );
1309 
1310  cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
1311  area = cover - cell->area;
1312 
1313  if ( area != 0 && cell->x >= ras.min_ex )
1314  gray_hline( RAS_VAR_ cell->x, y, area, 1 );
1315 
1316  x = cell->x + 1;
1317  }
1318 
1319  if ( cover != 0 )
1320  gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
1321 
1322  if ( ras.num_spans > 0 ) /* for FT_RASTER_FLAG_DIRECT only */
1323  {
1324  /* flush the span buffer and reset the count */
1325  ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
1326  ras.num_spans = 0;
1327  }
1328  }
1329  }
1330 
1331 
1332 #ifdef STANDALONE_
1333 
1334  /**************************************************************************
1335  *
1336  * The following functions should only compile in stand-alone mode,
1337  * i.e., when building this component without the rest of FreeType.
1338  *
1339  */
1340 
1341  /**************************************************************************
1342  *
1343  * @Function:
1344  * FT_Outline_Decompose
1345  *
1346  * @Description:
1347  * Walk over an outline's structure to decompose it into individual
1348  * segments and Bézier arcs. This function is also able to emit
1349  * `move to' and `close to' operations to indicate the start and end
1350  * of new contours in the outline.
1351  *
1352  * @Input:
1353  * outline ::
1354  * A pointer to the source target.
1355  *
1356  * func_interface ::
1357  * A table of `emitters', i.e., function pointers
1358  * called during decomposition to indicate path
1359  * operations.
1360  *
1361  * @InOut:
1362  * user ::
1363  * A typeless pointer which is passed to each
1364  * emitter during the decomposition. It can be
1365  * used to store the state during the
1366  * decomposition.
1367  *
1368  * @Return:
1369  * Error code. 0 means success.
1370  */
1371  static int
1372  FT_Outline_Decompose( const FT_Outline* outline,
1373  const FT_Outline_Funcs* func_interface,
1374  void* user )
1375  {
1376 #undef SCALED
1377 #define SCALED( x ) ( (x) * ( 1L << shift ) - delta )
1378 
1379  FT_Vector v_last;
1380  FT_Vector v_control;
1381  FT_Vector v_start;
1382 
1383  FT_Vector* point;
1384  FT_Vector* limit;
1385  char* tags;
1386 
1387  int error;
1388 
1389  int n; /* index of contour in outline */
1390  int first; /* index of first point in contour */
1391  char tag; /* current point's state */
1392 
1393  int shift;
1394  TPos delta;
1395 
1396 
1397  if ( !outline )
1398  return FT_THROW( Invalid_Outline );
1399 
1400  if ( !func_interface )
1401  return FT_THROW( Invalid_Argument );
1402 
1403  shift = func_interface->shift;
1404  delta = func_interface->delta;
1405  first = 0;
1406 
1407  for ( n = 0; n < outline->n_contours; n++ )
1408  {
1409  int last; /* index of last point in contour */
1410 
1411 
1412  FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
1413 
1414  last = outline->contours[n];
1415  if ( last < 0 )
1416  goto Invalid_Outline;
1417  limit = outline->points + last;
1418 
1419  v_start = outline->points[first];
1420  v_start.x = SCALED( v_start.x );
1421  v_start.y = SCALED( v_start.y );
1422 
1423  v_last = outline->points[last];
1424  v_last.x = SCALED( v_last.x );
1425  v_last.y = SCALED( v_last.y );
1426 
1427  v_control = v_start;
1428 
1429  point = outline->points + first;
1430  tags = outline->tags + first;
1431  tag = FT_CURVE_TAG( tags[0] );
1432 
1433  /* A contour cannot start with a cubic control point! */
1434  if ( tag == FT_CURVE_TAG_CUBIC )
1435  goto Invalid_Outline;
1436 
1437  /* check first point to determine origin */
1438  if ( tag == FT_CURVE_TAG_CONIC )
1439  {
1440  /* first point is conic control. Yes, this happens. */
1441  if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
1442  {
1443  /* start at last point if it is on the curve */
1444  v_start = v_last;
1445  limit--;
1446  }
1447  else
1448  {
1449  /* if both first and last points are conic, */
1450  /* start at their middle and record its position */
1451  /* for closure */
1452  v_start.x = ( v_start.x + v_last.x ) / 2;
1453  v_start.y = ( v_start.y + v_last.y ) / 2;
1454 
1455  v_last = v_start;
1456  }
1457  point--;
1458  tags--;
1459  }
1460 
1461  FT_TRACE5(( " move to (%.2f, %.2f)\n",
1462  v_start.x / 64.0, v_start.y / 64.0 ));
1463  error = func_interface->move_to( &v_start, user );
1464  if ( error )
1465  goto Exit;
1466 
1467  while ( point < limit )
1468  {
1469  point++;
1470  tags++;
1471 
1472  tag = FT_CURVE_TAG( tags[0] );
1473  switch ( tag )
1474  {
1475  case FT_CURVE_TAG_ON: /* emit a single line_to */
1476  {
1477  FT_Vector vec;
1478 
1479 
1480  vec.x = SCALED( point->x );
1481  vec.y = SCALED( point->y );
1482 
1483  FT_TRACE5(( " line to (%.2f, %.2f)\n",
1484  vec.x / 64.0, vec.y / 64.0 ));
1485  error = func_interface->line_to( &vec, user );
1486  if ( error )
1487  goto Exit;
1488  continue;
1489  }
1490 
1491  case FT_CURVE_TAG_CONIC: /* consume conic arcs */
1492  v_control.x = SCALED( point->x );
1493  v_control.y = SCALED( point->y );
1494 
1495  Do_Conic:
1496  if ( point < limit )
1497  {
1498  FT_Vector vec;
1499  FT_Vector v_middle;
1500 
1501 
1502  point++;
1503  tags++;
1504  tag = FT_CURVE_TAG( tags[0] );
1505 
1506  vec.x = SCALED( point->x );
1507  vec.y = SCALED( point->y );
1508 
1509  if ( tag == FT_CURVE_TAG_ON )
1510  {
1511  FT_TRACE5(( " conic to (%.2f, %.2f)"
1512  " with control (%.2f, %.2f)\n",
1513  vec.x / 64.0, vec.y / 64.0,
1514  v_control.x / 64.0, v_control.y / 64.0 ));
1515  error = func_interface->conic_to( &v_control, &vec, user );
1516  if ( error )
1517  goto Exit;
1518  continue;
1519  }
1520 
1521  if ( tag != FT_CURVE_TAG_CONIC )
1522  goto Invalid_Outline;
1523 
1524  v_middle.x = ( v_control.x + vec.x ) / 2;
1525  v_middle.y = ( v_control.y + vec.y ) / 2;
1526 
1527  FT_TRACE5(( " conic to (%.2f, %.2f)"
1528  " with control (%.2f, %.2f)\n",
1529  v_middle.x / 64.0, v_middle.y / 64.0,
1530  v_control.x / 64.0, v_control.y / 64.0 ));
1531  error = func_interface->conic_to( &v_control, &v_middle, user );
1532  if ( error )
1533  goto Exit;
1534 
1535  v_control = vec;
1536  goto Do_Conic;
1537  }
1538 
1539  FT_TRACE5(( " conic to (%.2f, %.2f)"
1540  " with control (%.2f, %.2f)\n",
1541  v_start.x / 64.0, v_start.y / 64.0,
1542  v_control.x / 64.0, v_control.y / 64.0 ));
1543  error = func_interface->conic_to( &v_control, &v_start, user );
1544  goto Close;
1545 
1546  default: /* FT_CURVE_TAG_CUBIC */
1547  {
1548  FT_Vector vec1, vec2;
1549 
1550 
1551  if ( point + 1 > limit ||
1552  FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1553  goto Invalid_Outline;
1554 
1555  point += 2;
1556  tags += 2;
1557 
1558  vec1.x = SCALED( point[-2].x );
1559  vec1.y = SCALED( point[-2].y );
1560 
1561  vec2.x = SCALED( point[-1].x );
1562  vec2.y = SCALED( point[-1].y );
1563 
1564  if ( point <= limit )
1565  {
1566  FT_Vector vec;
1567 
1568 
1569  vec.x = SCALED( point->x );
1570  vec.y = SCALED( point->y );
1571 
1572  FT_TRACE5(( " cubic to (%.2f, %.2f)"
1573  " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
1574  vec.x / 64.0, vec.y / 64.0,
1575  vec1.x / 64.0, vec1.y / 64.0,
1576  vec2.x / 64.0, vec2.y / 64.0 ));
1577  error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
1578  if ( error )
1579  goto Exit;
1580  continue;
1581  }
1582 
1583  FT_TRACE5(( " cubic to (%.2f, %.2f)"
1584  " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
1585  v_start.x / 64.0, v_start.y / 64.0,
1586  vec1.x / 64.0, vec1.y / 64.0,
1587  vec2.x / 64.0, vec2.y / 64.0 ));
1588  error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
1589  goto Close;
1590  }
1591  }
1592  }
1593 
1594  /* close the contour with a line segment */
1595  FT_TRACE5(( " line to (%.2f, %.2f)\n",
1596  v_start.x / 64.0, v_start.y / 64.0 ));
1597  error = func_interface->line_to( &v_start, user );
1598 
1599  Close:
1600  if ( error )
1601  goto Exit;
1602 
1603  first = last + 1;
1604  }
1605 
1606  FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
1607  return 0;
1608 
1609  Exit:
1610  FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
1611  return error;
1612 
1613  Invalid_Outline:
1614  return FT_THROW( Invalid_Outline );
1615  }
1616 
1617 #endif /* STANDALONE_ */
1618 
1619 
1621  func_interface,
1622 
1623  (FT_Outline_MoveTo_Func) gray_move_to, /* move_to */
1624  (FT_Outline_LineTo_Func) gray_line_to, /* line_to */
1625  (FT_Outline_ConicTo_Func)gray_conic_to, /* conic_to */
1626  (FT_Outline_CubicTo_Func)gray_cubic_to, /* cubic_to */
1627 
1628  0, /* shift */
1629  0 /* delta */
1630  )
1631 
1632 
1633  static int
1634  gray_convert_glyph_inner( RAS_ARG,
1636  {
1637  int error;
1638 
1639 
1640  if ( ft_setjmp( ras.jump_buffer ) == 0 )
1641  {
1642  if ( continued )
1643  FT_Trace_Disable();
1644  error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
1645  if ( continued )
1646  FT_Trace_Enable();
1647 
1648  if ( !ras.invalid )
1649  gray_record_cell( RAS_VAR );
1650 
1651  FT_TRACE7(( "band [%d..%d]: %ld cell%s\n",
1652  ras.min_ey,
1653  ras.max_ey,
1654  ras.num_cells,
1655  ras.num_cells == 1 ? "" : "s" ));
1656  }
1657  else
1658  {
1659  error = FT_THROW( Memory_Overflow );
1660 
1661  FT_TRACE7(( "band [%d..%d]: to be bisected\n",
1662  ras.min_ey, ras.max_ey ));
1663  }
1664 
1665  return error;
1666  }
1667 
1668 
1669  static int
1670  gray_convert_glyph( RAS_ARG )
1671  {
1672  const TCoord yMin = ras.min_ey;
1673  const TCoord yMax = ras.max_ey;
1674 
1676  size_t height = (size_t)( yMax - yMin );
1677  size_t n = FT_MAX_GRAY_POOL / 8;
1678  TCoord y;
1679  TCoord bands[32]; /* enough to accommodate bisections */
1680  TCoord* band;
1681 
1682  int continued = 0;
1683 
1684 
1685  /* set up vertical bands */
1686  if ( height > n )
1687  {
1688  /* two divisions rounded up */
1689  n = ( height + n - 1 ) / n;
1690  height = ( height + n - 1 ) / n;
1691  }
1692 
1693  /* memory management */
1694  n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell );
1695 
1696  ras.cells = buffer + n;
1697  ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n );
1698  ras.ycells = (PCell*)buffer;
1699 
1700  for ( y = yMin; y < yMax; )
1701  {
1702  ras.min_ey = y;
1703  y += height;
1704  ras.max_ey = FT_MIN( y, yMax );
1705 
1706  band = bands;
1707  band[1] = ras.min_ey;
1708  band[0] = ras.max_ey;
1709 
1710  do
1711  {
1712  TCoord width = band[0] - band[1];
1713  int error;
1714 
1715 
1716  FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
1717 
1718  ras.num_cells = 0;
1719  ras.invalid = 1;
1720  ras.min_ey = band[1];
1721  ras.max_ey = band[0];
1722 
1723  error = gray_convert_glyph_inner( RAS_VAR, continued );
1724  continued = 1;
1725 
1726  if ( !error )
1727  {
1728  gray_sweep( RAS_VAR );
1729  band--;
1730  continue;
1731  }
1732  else if ( error != ErrRaster_Memory_Overflow )
1733  return 1;
1734 
1735  /* render pool overflow; we will reduce the render band by half */
1736  width >>= 1;
1737 
1738  /* this should never happen even with tiny rendering pool */
1739  if ( width == 0 )
1740  {
1741  FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
1742  return 1;
1743  }
1744 
1745  band++;
1746  band[1] = band[0];
1747  band[0] += width;
1748  } while ( band >= bands );
1749  }
1750 
1751  return 0;
1752  }
1753 
1754 
1755  static int
1756  gray_raster_render( FT_Raster raster,
1757  const FT_Raster_Params* params )
1758  {
1759  const FT_Outline* outline = (const FT_Outline*)params->source;
1760  const FT_Bitmap* target_map = params->target;
1761 
1762 #ifndef FT_STATIC_RASTER
1763  gray_TWorker worker[1];
1764 #endif
1765 
1766 
1767  if ( !raster )
1768  return FT_THROW( Invalid_Argument );
1769 
1770  /* this version does not support monochrome rendering */
1771  if ( !( params->flags & FT_RASTER_FLAG_AA ) )
1772  return FT_THROW( Invalid_Mode );
1773 
1774  if ( !outline )
1775  return FT_THROW( Invalid_Outline );
1776 
1777  /* return immediately if the outline is empty */
1778  if ( outline->n_points == 0 || outline->n_contours <= 0 )
1779  return 0;
1780 
1781  if ( !outline->contours || !outline->points )
1782  return FT_THROW( Invalid_Outline );
1783 
1784  if ( outline->n_points !=
1785  outline->contours[outline->n_contours - 1] + 1 )
1786  return FT_THROW( Invalid_Outline );
1787 
1788  ras.outline = *outline;
1789 
1790  if ( params->flags & FT_RASTER_FLAG_DIRECT )
1791  {
1792  if ( !params->gray_spans )
1793  return 0;
1794 
1795  ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
1796  ras.render_span_data = params->user;
1797  ras.num_spans = 0;
1798 
1799  ras.min_ex = params->clip_box.xMin;
1800  ras.min_ey = params->clip_box.yMin;
1801  ras.max_ex = params->clip_box.xMax;
1802  ras.max_ey = params->clip_box.yMax;
1803  }
1804  else
1805  {
1806  /* if direct mode is not set, we must have a target bitmap */
1807  if ( !target_map )
1808  return FT_THROW( Invalid_Argument );
1809 
1810  /* nothing to do */
1811  if ( !target_map->width || !target_map->rows )
1812  return 0;
1813 
1814  if ( !target_map->buffer )
1815  return FT_THROW( Invalid_Argument );
1816 
1817  if ( target_map->pitch < 0 )
1818  ras.target.origin = target_map->buffer;
1819  else
1820  ras.target.origin = target_map->buffer
1821  + ( target_map->rows - 1 ) * (unsigned int)target_map->pitch;
1822 
1823  ras.target.pitch = target_map->pitch;
1824 
1825  ras.render_span = (FT_Raster_Span_Func)NULL;
1826  ras.render_span_data = NULL;
1827  ras.num_spans = -1; /* invalid */
1828 
1829  ras.min_ex = 0;
1830  ras.min_ey = 0;
1831  ras.max_ex = (FT_Pos)target_map->width;
1832  ras.max_ey = (FT_Pos)target_map->rows;
1833  }
1834 
1835  /* exit if nothing to do */
1836  if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
1837  return 0;
1838 
1839  return gray_convert_glyph( RAS_VAR );
1840  }
1841 
1842 
1843  /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
1844  /**** a static object. *****/
1845 
1846 #ifdef STANDALONE_
1847 
1848  static int
1849  gray_raster_new( void* memory,
1850  FT_Raster* araster )
1851  {
1852  static gray_TRaster the_raster;
1853 
1854  FT_UNUSED( memory );
1855 
1856 
1857  *araster = (FT_Raster)&the_raster;
1858  FT_ZERO( &the_raster );
1859 
1860  return 0;
1861  }
1862 
1863 
1864  static void
1865  gray_raster_done( FT_Raster raster )
1866  {
1867  /* nothing */
1868  FT_UNUSED( raster );
1869  }
1870 
1871 #else /* !STANDALONE_ */
1872 
1873  static int
1874  gray_raster_new( FT_Memory memory,
1875  FT_Raster* araster )
1876  {
1877  FT_Error error;
1878  gray_PRaster raster = NULL;
1879 
1880 
1881  *araster = 0;
1882  if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
1883  {
1884  raster->memory = memory;
1885  *araster = (FT_Raster)raster;
1886  }
1887 
1888  return error;
1889  }
1890 
1891 
1892  static void
1893  gray_raster_done( FT_Raster raster )
1894  {
1896 
1897 
1898  FT_FREE( raster );
1899  }
1900 
1901 #endif /* !STANDALONE_ */
1902 
1903 
1904  static void
1905  gray_raster_reset( FT_Raster raster,
1906  unsigned char* pool_base,
1907  unsigned long pool_size )
1908  {
1909  FT_UNUSED( raster );
1910  FT_UNUSED( pool_base );
1911  FT_UNUSED( pool_size );
1912  }
1913 
1914 
1915  static int
1916  gray_raster_set_mode( FT_Raster raster,
1917  unsigned long mode,
1918  void* args )
1919  {
1920  FT_UNUSED( raster );
1921  FT_UNUSED( mode );
1922  FT_UNUSED( args );
1923 
1924 
1925  return 0; /* nothing to do */
1926  }
1927 
1928 
1930  ft_grays_raster,
1931 
1932  FT_GLYPH_FORMAT_OUTLINE,
1933 
1934  (FT_Raster_New_Func) gray_raster_new, /* raster_new */
1935  (FT_Raster_Reset_Func) gray_raster_reset, /* raster_reset */
1936  (FT_Raster_Set_Mode_Func)gray_raster_set_mode, /* raster_set_mode */
1937  (FT_Raster_Render_Func) gray_raster_render, /* raster_render */
1938  (FT_Raster_Done_Func) gray_raster_done /* raster_done */
1939  )
1940 
1941 
1942 /* END */
1943 
1944 
1945 /* Local Variables: */
1946 /* coding: utf-8 */
1947 /* End: */
sizeof(AF_ModuleRec)
int y
the y coordinate of the widget relative to its parent and including any window frame
Definition: qwidget.h:144
int x
the x coordinate of the widget relative to its parent including any window frame
Definition: qwidget.h:143
Definition: base.h:37
FT_Vector * vec
Definition: ftbbox.c:469
#define FT_TRACE5(varformat)
Definition: ftdebug.h:192
FT_Trace_Disable(void)
Definition: ftdebug.c:300
#define FT_THROW(e)
Definition: ftdebug.h:243
FT_Trace_Enable(void)
Definition: ftdebug.c:309
struct TPixmap_ TPixmap
#define RAS_ARG
Definition: ftgrays.c:318
if(ft_setjmp(ras.jump_buffer)==0)
Definition: ftgrays.c:1640
#define UPSCALE(x)
Definition: ftgrays.c:342
#define ErrRaster_Memory_Overflow
Definition: ftgrays.c:291
long TPos
Definition: ftgrays.c:404
#define TRUNC(x)
Definition: ftgrays.c:338
#define FT_UDIVPREP(c, b)
Definition: ftgrays.c:387
FT_TRACE7(("band [%d..%d]: to be bisected\n", ras.min_ey, ras.max_ey))
int TArea
Definition: ftgrays.c:406
int TCoord
Definition: ftgrays.c:405
struct gray_TRaster_ gray_TRaster
#define FT_MEM_SET(d, s, c)
Definition: ftgrays.c:298
#define RAS_VAR
Definition: ftgrays.c:321
struct TCell_ TCell
#define RAS_VAR_
Definition: ftgrays.c:322
#define PIXEL_BITS
Definition: ftgrays.c:335
#define FRACT(x)
Definition: ftgrays.c:339
struct gray_TRaster_ * gray_PRaster
#define FT_ZERO(p)
Definition: ftgrays.c:306
#define ras
Definition: ftgrays.c:481
#define RAS_ARG_
Definition: ftgrays.c:319
#define FT_UDIV(a, b)
Definition: ftgrays.c:390
struct gray_TWorker_ gray_TWorker
struct TCell_ * PCell
Definition: ftgrays.c:409
return error
Definition: ftgrays.c:1665
#define FT_MAX_GRAY_POOL
Definition: ftgrays.c:431
#define FT_MEM_ZERO(dest, count)
Definition: ftgrays.c:302
struct gray_TWorker_ * gray_PWorker
#define FT_DIV_MOD(type, dividend, divisor, quotient, remainder)
Definition: ftgrays.c:354
FT_DEFINE_OUTLINE_FUNCS(func_interface,(FT_Outline_MoveTo_Func) gray_move_to,(FT_Outline_LineTo_Func) gray_line_to,(FT_Outline_ConicTo_Func) gray_conic_to,(FT_Outline_CubicTo_Func) gray_cubic_to, 0, 0) static int gray_convert_glyph_inner(RAS_ARG
#define ONE_PIXEL
Definition: ftgrays.c:337
int continued
Definition: ftgrays.c:1636
#define FT_MAX_GRAY_SPANS
Definition: ftgrays.c:435
#define FT_CURVE_TAG_CUBIC
Definition: ftimage.h:464
#define FT_RASTER_FLAG_AA
Definition: ftimage.h:967
#define FT_Raster_Span_Func
Definition: ftimage.h:903
#define FT_CURVE_TAG_CONIC
Definition: ftimage.h:463
#define FT_Raster_Render_Func
Definition: ftimage.h:1199
#define FT_OUTLINE_EVEN_ODD_FILL
Definition: ftimage.h:436
#define FT_Outline_CubicTo_Func
Definition: ftimage.h:612
struct FT_RasterRec_ * FT_Raster
Definition: ftimage.h:828
#define FT_Outline_LineTo_Func
Definition: ftimage.h:540
#define FT_Raster_Reset_Func
Definition: ftimage.h:1134
#define FT_RASTER_FLAG_DIRECT
Definition: ftimage.h:968
#define FT_CURVE_TAG(flag)
Definition: ftimage.h:459
#define FT_Outline_ConicTo_Func
Definition: ftimage.h:575
#define FT_CURVE_TAG_ON
Definition: ftimage.h:462
#define FT_Raster_New_Func
Definition: ftimage.h:1080
#define FT_Raster_Set_Mode_Func
Definition: ftimage.h:1162
#define FT_Outline_MoveTo_Func
Definition: ftimage.h:511
#define FT_Raster_Done_Func
Definition: ftimage.h:1098
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:57
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:311
#define FT_FREE(ptr)
Definition: ftmemory.h:337
#define NULL
Definition: ftobjs.h:61
#define FT_ABS(a)
Definition: ftobjs.h:73
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, raster_reset_, raster_set_mode_, raster_render_, raster_done_)
Definition: ftobjs.h:1031
#define FT_MAX(a, b)
Definition: ftobjs.h:71
#define SCALED(x)
FT_BEGIN_HEADER FT_Outline_Decompose(FT_Outline *outline, const FT_Outline_Funcs *func_interface, void *user)
Definition: ftoutln.c:43
#define ft_jmp_buf
Definition: ftstdlib.h:158
#define ft_longjmp
Definition: ftstdlib.h:162
#define ft_setjmp(b)
Definition: ftstdlib.h:163
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
ft_ptrdiff_t FT_PtrDist
Definition: fttypes.h:336
int FT_Error
Definition: fttypes.h:299
va_end(ap)
static void const void const char bool unsigned int int const char va_start(ap, message)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if
#define FT_UNUSED(arg)
@ Split
Definition: qbezier.cpp:211
bool int shift
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLenum GLuint buffer
GLint GLsizei width
GLint first
GLfloat n
GLsizei GLenum GLsizei GLsizei GLuint memory
GLint y
void ** params
const GLubyte * c
Definition: qopenglext.h:12701
GLfixed GLfixed GLfixed y2
Definition: qopenglext.h:5231
GLint limit
Definition: qopenglext.h:9975
GLfixed GLfixed x2
Definition: qopenglext.h:5231
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLenum GLenum GLsizei void GLsizei void void * span
Definition: qopenglext.h:2747
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
QFile file
[0]
myFilter draw(painter, QPoint(0, 0), originalPixmap)
FT_Outline_ConicToFunc conic_to
Definition: ftimage.h:662
FT_Outline_LineToFunc line_to
Definition: ftimage.h:661
FT_Outline_CubicToFunc cubic_to
Definition: ftimage.h:663
FT_Outline_MoveToFunc move_to
Definition: ftimage.h:660
short n_contours
Definition: ftimage.h:338
short * contours
Definition: ftimage.h:343
FT_Vector * points
Definition: ftimage.h:341
short n_points
Definition: ftimage.h:339
char * tags
Definition: ftimage.h:342
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
TCoord cover
Definition: ftgrays.c:414
PCell next
Definition: ftgrays.c:416
TCoord x
Definition: ftgrays.c:413
TArea area
Definition: ftgrays.c:415
int pitch
Definition: ftgrays.c:423
unsigned char * origin
Definition: ftgrays.c:422
void * memory
Definition: ftgrays.c:489
PCell cells
Definition: ftgrays.c:459
FT_PtrDist max_cells
Definition: ftgrays.c:460
TCoord ex
Definition: ftgrays.c:450
FT_Raster_Span_Func render_span
Definition: ftgrays.c:468
FT_Span spans[FT_MAX_GRAY_SPANS]
Definition: ftgrays.c:470
int num_spans
Definition: ftgrays.c:471
TArea area
Definition: ftgrays.c:454
TCoord ey
Definition: ftgrays.c:450
TCoord max_ex
Definition: ftgrays.c:451
TCoord min_ex
Definition: ftgrays.c:451
ft_jmp_buf jump_buffer
Definition: ftgrays.c:448
TCoord max_ey
Definition: ftgrays.c:452
FT_PtrDist num_cells
Definition: ftgrays.c:461
PCell * ycells
Definition: ftgrays.c:458
FT_Outline outline
Definition: ftgrays.c:465
void * render_span_data
Definition: ftgrays.c:469
TPixmap target
Definition: ftgrays.c:466
TCoord min_ey
Definition: ftgrays.c:452
TCoord cover
Definition: ftgrays.c:455
virtual HRESULT STDMETHODCALLTYPE Close(void)=0
XmlOutput::xml_output tag(const QString &name)
Definition: xmloutput.h:154