ReactOS 0.4.16-dev-2332-g4cba65d
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
168typedef 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#ifndef __REACTOS__ /* win32ss/drivers/font/ftfd/rosglue.c defines this */
195 void
196 FT_Message( const char* fmt,
197 ... )
198 {
199 va_list ap;
200
201
202 va_start( ap, fmt );
203 vfprintf( stderr, fmt, ap );
204 va_end( ap );
205 }
206#endif
207
208
209 /* empty function useful for setting a breakpoint to catch errors */
210 int
211 FT_Throw( int error,
212 int line,
213 const char* file )
214 {
215 FT_UNUSED( error );
216 FT_UNUSED( line );
217 FT_UNUSED( file );
218
219 return 0;
220 }
221
222
223 /* we don't handle tracing levels in stand-alone mode; */
224#ifndef FT_TRACE5
225#define FT_TRACE5( varformat ) FT_Message varformat
226#endif
227#ifndef FT_TRACE7
228#define FT_TRACE7( varformat ) FT_Message varformat
229#endif
230#ifndef FT_ERROR
231#define FT_ERROR( varformat ) FT_Message varformat
232#endif
233
234#define FT_THROW( e ) \
235 ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ), \
236 __LINE__, \
237 __FILE__ ) | \
238 FT_ERR_CAT( ErrRaster_, e ) )
239
240#else /* !FT_DEBUG_LEVEL_TRACE */
241
242#define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
243#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
244#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
245#define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e )
246
247
248#endif /* !FT_DEBUG_LEVEL_TRACE */
249
250
251#define FT_DEFINE_OUTLINE_FUNCS( class_, \
252 move_to_, line_to_, \
253 conic_to_, cubic_to_, \
254 shift_, delta_ ) \
255 static const FT_Outline_Funcs class_ = \
256 { \
257 move_to_, \
258 line_to_, \
259 conic_to_, \
260 cubic_to_, \
261 shift_, \
262 delta_ \
263 };
264
265#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \
266 raster_new_, raster_reset_, \
267 raster_set_mode_, raster_render_, \
268 raster_done_ ) \
269 const FT_Raster_Funcs class_ = \
270 { \
271 glyph_format_, \
272 raster_new_, \
273 raster_reset_, \
274 raster_set_mode_, \
275 raster_render_, \
276 raster_done_ \
277 };
278
279
280#else /* !STANDALONE_ */
281
282
283#include "ftgrays.h"
287#include <freetype/ftoutln.h>
288
289#include "ftsmerrs.h"
290
291#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
292#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory
293#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
294
295
296#endif /* !STANDALONE_ */
297
298
299#ifndef FT_MEM_SET
300#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
301#endif
302
303#ifndef FT_MEM_ZERO
304#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
305#endif
306
307#ifndef FT_ZERO
308#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )
309#endif
310
311 /* as usual, for the speed hungry :-) */
312
313#undef RAS_ARG
314#undef RAS_ARG_
315#undef RAS_VAR
316#undef RAS_VAR_
317
318#ifndef FT_STATIC_RASTER
319
320#define RAS_ARG gray_PWorker worker
321#define RAS_ARG_ gray_PWorker worker,
322
323#define RAS_VAR worker
324#define RAS_VAR_ worker,
325
326#else /* FT_STATIC_RASTER */
327
328#define RAS_ARG void
329#define RAS_ARG_ /* empty */
330#define RAS_VAR /* empty */
331#define RAS_VAR_ /* empty */
332
333#endif /* FT_STATIC_RASTER */
334
335
336 /* must be at least 6 bits! */
337#define PIXEL_BITS 8
338
339#define ONE_PIXEL ( 1 << PIXEL_BITS )
340#define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS )
341#define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) )
342
343#if PIXEL_BITS >= 6
344#define UPSCALE( x ) ( (x) * ( ONE_PIXEL >> 6 ) )
345#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
346#else
347#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
348#define DOWNSCALE( x ) ( (x) * ( 64 >> PIXEL_BITS ) )
349#endif
350
351
352 /* Compute `dividend / divisor' and return both its quotient and */
353 /* remainder, cast to a specific type. This macro also ensures that */
354 /* the remainder is always positive. We use the remainder to keep */
355 /* track of accumulating errors and compensate for them. */
356#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
357 FT_BEGIN_STMNT \
358 (quotient) = (type)( (dividend) / (divisor) ); \
359 (remainder) = (type)( (dividend) % (divisor) ); \
360 if ( (remainder) < 0 ) \
361 { \
362 (quotient)--; \
363 (remainder) += (type)(divisor); \
364 } \
365 FT_END_STMNT
366
367#ifdef __arm__
368 /* Work around a bug specific to GCC which make the compiler fail to */
369 /* optimize a division and modulo operation on the same parameters */
370 /* into a single call to `__aeabi_idivmod'. See */
371 /* */
372 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
373#undef FT_DIV_MOD
374#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
375 FT_BEGIN_STMNT \
376 (quotient) = (type)( (dividend) / (divisor) ); \
377 (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \
378 if ( (remainder) < 0 ) \
379 { \
380 (quotient)--; \
381 (remainder) += (type)(divisor); \
382 } \
383 FT_END_STMNT
384#endif /* __arm__ */
385
386
387 /* These macros speed up repetitive divisions by replacing them */
388 /* with multiplications and right shifts. */
389#define FT_UDIVPREP( c, b ) \
390 long b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \
391 : 0
392#define FT_UDIV( a, b ) \
393 (TCoord)( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
394 ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
395
396
397 /**************************************************************************
398 *
399 * TYPE DEFINITIONS
400 */
401
402 /* don't change the following types to FT_Int or FT_Pos, since we might */
403 /* need to define them to "float" or "double" when experimenting with */
404 /* new algorithms */
405
406 typedef long TPos; /* subpixel coordinate */
407 typedef int TCoord; /* integer scanline/pixel coordinate */
408 typedef int TArea; /* cell areas, coordinate products */
409
410
411 typedef struct TCell_* PCell;
412
413 typedef struct TCell_
414 {
415 TCoord x; /* same with gray_TWorker.ex */
416 TCoord cover; /* same with gray_TWorker.cover */
419
421
422 typedef struct TPixmap_
423 {
424 unsigned char* origin; /* pixmap origin at the bottom-left */
425 int pitch; /* pitch to go down one row */
426
428
429 /* maximum number of gray cells in the buffer */
430#if FT_RENDER_POOL_SIZE > 2048
431#define FT_MAX_GRAY_POOL ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) )
432#else
433#define FT_MAX_GRAY_POOL ( 2048 / sizeof ( TCell ) )
434#endif
435
436 /* FT_Span buffer size for direct rendering only */
437#define FT_MAX_GRAY_SPANS 10
438
439
440#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
441 /* We disable the warning `structure was padded due to */
442 /* __declspec(align())' in order to compile cleanly with */
443 /* the maximum level of warnings. */
444#pragma warning( push )
445#pragma warning( disable : 4324 )
446#endif /* _MSC_VER */
447
448 typedef struct gray_TWorker_
449 {
451
455
459
464
466
469
474
476
477#if defined( _MSC_VER )
478#pragma warning( pop )
479#endif
480
481
482#ifndef FT_STATIC_RASTER
483#define ras (*worker)
484#else
485 static gray_TWorker ras;
486#endif
487
488
489 typedef struct gray_TRaster_
490 {
491 void* memory;
492
494
495
496#ifdef FT_DEBUG_LEVEL_TRACE
497
498 /* to be called while in the debugger -- */
499 /* this function causes a compiler warning since it is unused otherwise */
500 static void
501 gray_dump_cells( RAS_ARG )
502 {
503 int y;
504
505
506 for ( y = ras.min_ey; y < ras.max_ey; y++ )
507 {
508 PCell cell = ras.ycells[y - ras.min_ey];
509
510
511 printf( "%3d:", y );
512
513 for ( ; cell != NULL; cell = cell->next )
514 printf( " (%3d, c:%4d, a:%6d)",
515 cell->x, cell->cover, cell->area );
516 printf( "\n" );
517 }
518 }
519
520#endif /* FT_DEBUG_LEVEL_TRACE */
521
522
523 /**************************************************************************
524 *
525 * Record the current cell in the linked list.
526 */
527 static void
529 {
530 PCell *pcell, cell;
531 TCoord x = ras.ex;
532
533
534 pcell = &ras.ycells[ras.ey - ras.min_ey];
535 while ( ( cell = *pcell ) )
536 {
537 if ( cell->x > x )
538 break;
539
540 if ( cell->x == x )
541 goto Found;
542
543 pcell = &cell->next;
544 }
545
546 if ( ras.num_cells >= ras.max_cells )
547 ft_longjmp( ras.jump_buffer, 1 );
548
549 /* insert new cell */
550 cell = ras.cells + ras.num_cells++;
551 cell->x = x;
552 cell->area = ras.area;
553 cell->cover = ras.cover;
554
555 cell->next = *pcell;
556 *pcell = cell;
557
558 return;
559
560 Found:
561 /* update old cell */
562 cell->area += ras.area;
563 cell->cover += ras.cover;
564 }
565
566
567 /**************************************************************************
568 *
569 * Set the current cell to a new position.
570 */
571 static void
573 TCoord ey )
574 {
575 /* Move the cell pointer to a new position. We set the `invalid' */
576 /* flag to indicate that the cell isn't part of those we're interested */
577 /* in during the render phase. This means that: */
578 /* */
579 /* . the new vertical position must be within min_ey..max_ey-1. */
580 /* . the new horizontal position must be strictly less than max_ex */
581 /* */
582 /* Note that if a cell is to the left of the clipping region, it is */
583 /* actually set to the (min_ex-1) horizontal position. */
584
585 /* record the current one if it is valid and substantial */
586 if ( !ras.invalid && ( ras.area || ras.cover ) )
588
589 ras.area = 0;
590 ras.cover = 0;
591 ras.ex = FT_MAX( ex, ras.min_ex - 1 );
592 ras.ey = ey;
593
594 ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
595 ex >= ras.max_ex );
596 }
597
598
599#ifndef FT_LONG64
600
601 /**************************************************************************
602 *
603 * Render a scanline as one or more cells.
604 */
605 static void
607 TPos x1,
608 TCoord y1,
609 TPos x2,
610 TCoord y2 )
611 {
612 TCoord ex1, ex2, fx1, fx2, first, dy, delta, mod;
613 TPos p, dx;
614 int incr;
615
616
617 ex1 = TRUNC( x1 );
618 ex2 = TRUNC( x2 );
619
620 /* trivial case. Happens often */
621 if ( y1 == y2 )
622 {
623 gray_set_cell( RAS_VAR_ ex2, ey );
624 return;
625 }
626
627 fx1 = FRACT( x1 );
628 fx2 = FRACT( x2 );
629
630 /* everything is located in a single cell. That is easy! */
631 /* */
632 if ( ex1 == ex2 )
633 goto End;
634
635 /* ok, we'll have to render a run of adjacent cells on the same */
636 /* scanline... */
637 /* */
638 dx = x2 - x1;
639 dy = y2 - y1;
640
641 if ( dx > 0 )
642 {
643 p = ( ONE_PIXEL - fx1 ) * dy;
645 incr = 1;
646 }
647 else
648 {
649 p = fx1 * dy;
650 first = 0;
651 incr = -1;
652 dx = -dx;
653 }
654
655 /* the fractional part of y-delta is mod/dx. It is essential to */
656 /* keep track of its accumulation for accurate rendering. */
657 /* XXX: y-delta and x-delta below should be related. */
658 FT_DIV_MOD( TCoord, p, dx, delta, mod );
659
660 ras.area += (TArea)( ( fx1 + first ) * delta );
661 ras.cover += delta;
662 y1 += delta;
663 ex1 += incr;
664 gray_set_cell( RAS_VAR_ ex1, ey );
665
666 if ( ex1 != ex2 )
667 {
668 TCoord lift, rem;
669
670
671 p = ONE_PIXEL * dy;
672 FT_DIV_MOD( TCoord, p, dx, lift, rem );
673
674 do
675 {
676 delta = lift;
677 mod += rem;
678 if ( mod >= (TCoord)dx )
679 {
680 mod -= (TCoord)dx;
681 delta++;
682 }
683
684 ras.area += (TArea)( ONE_PIXEL * delta );
685 ras.cover += delta;
686 y1 += delta;
687 ex1 += incr;
688 gray_set_cell( RAS_VAR_ ex1, ey );
689 } while ( ex1 != ex2 );
690 }
691
692 fx1 = ONE_PIXEL - first;
693
694 End:
695 dy = y2 - y1;
696
697 ras.area += (TArea)( ( fx1 + fx2 ) * dy );
698 ras.cover += dy;
699 }
700
701
702 /**************************************************************************
703 *
704 * Render a given line as a series of scanlines.
705 */
706 static void
708 TPos to_y )
709 {
710 TCoord ey1, ey2, fy1, fy2, first, delta, mod;
711 TPos p, dx, dy, x, x2;
712 int incr;
713
714
715 ey1 = TRUNC( ras.y );
716 ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
717
718 /* perform vertical clipping */
719 if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
720 ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
721 goto End;
722
723 fy1 = FRACT( ras.y );
724 fy2 = FRACT( to_y );
725
726 /* everything is on a single scanline */
727 if ( ey1 == ey2 )
728 {
729 gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
730 goto End;
731 }
732
733 dx = to_x - ras.x;
734 dy = to_y - ras.y;
735
736 /* vertical line - avoid calling gray_render_scanline */
737 if ( dx == 0 )
738 {
739 TCoord ex = TRUNC( ras.x );
740 TCoord two_fx = FRACT( ras.x ) << 1;
741 TArea area;
742
743
744 if ( dy > 0)
745 {
747 incr = 1;
748 }
749 else
750 {
751 first = 0;
752 incr = -1;
753 }
754
755 delta = first - fy1;
756 ras.area += (TArea)two_fx * delta;
757 ras.cover += delta;
758 ey1 += incr;
759
760 gray_set_cell( RAS_VAR_ ex, ey1 );
761
762 delta = first + first - ONE_PIXEL;
763 area = (TArea)two_fx * delta;
764 while ( ey1 != ey2 )
765 {
766 ras.area += area;
767 ras.cover += delta;
768 ey1 += incr;
769
770 gray_set_cell( RAS_VAR_ ex, ey1 );
771 }
772
773 delta = fy2 - ONE_PIXEL + first;
774 ras.area += (TArea)two_fx * delta;
775 ras.cover += delta;
776
777 goto End;
778 }
779
780 /* ok, we have to render several scanlines */
781 if ( dy > 0)
782 {
783 p = ( ONE_PIXEL - fy1 ) * dx;
785 incr = 1;
786 }
787 else
788 {
789 p = fy1 * dx;
790 first = 0;
791 incr = -1;
792 dy = -dy;
793 }
794
795 /* the fractional part of x-delta is mod/dy. It is essential to */
796 /* keep track of its accumulation for accurate rendering. */
797 FT_DIV_MOD( TCoord, p, dy, delta, mod );
798
799 x = ras.x + delta;
800 gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
801
802 ey1 += incr;
803 gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
804
805 if ( ey1 != ey2 )
806 {
807 TCoord lift, rem;
808
809
810 p = ONE_PIXEL * dx;
811 FT_DIV_MOD( TCoord, p, dy, lift, rem );
812
813 do
814 {
815 delta = lift;
816 mod += rem;
817 if ( mod >= (TCoord)dy )
818 {
819 mod -= (TCoord)dy;
820 delta++;
821 }
822
823 x2 = x + delta;
825 x, ONE_PIXEL - first,
826 x2, first );
827 x = x2;
828
829 ey1 += incr;
830 gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
831 } while ( ey1 != ey2 );
832 }
833
835 x, ONE_PIXEL - first,
836 to_x, fy2 );
837
838 End:
839 ras.x = to_x;
840 ras.y = to_y;
841 }
842
843#else
844
845 /**************************************************************************
846 *
847 * Render a straight line across multiple cells in any direction.
848 */
849 static void
851 TPos to_y )
852 {
853 TPos dx, dy;
854 TCoord fx1, fy1, fx2, fy2;
855 TCoord ex1, ey1, ex2, ey2;
856
857
858 ey1 = TRUNC( ras.y );
859 ey2 = TRUNC( to_y );
860
861 /* perform vertical clipping */
862 if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
863 ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
864 goto End;
865
866 ex1 = TRUNC( ras.x );
867 ex2 = TRUNC( to_x );
868
869 fx1 = FRACT( ras.x );
870 fy1 = FRACT( ras.y );
871
872 dx = to_x - ras.x;
873 dy = to_y - ras.y;
874
875 if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
876 ;
877 else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
878 {
879 gray_set_cell( RAS_VAR_ ex2, ey2 );
880 goto End;
881 }
882 else if ( dx == 0 )
883 {
884 if ( dy > 0 ) /* vertical line up */
885 do
886 {
887 fy2 = ONE_PIXEL;
888 ras.cover += ( fy2 - fy1 );
889 ras.area += ( fy2 - fy1 ) * fx1 * 2;
890 fy1 = 0;
891 ey1++;
892 gray_set_cell( RAS_VAR_ ex1, ey1 );
893 } while ( ey1 != ey2 );
894 else /* vertical line down */
895 do
896 {
897 fy2 = 0;
898 ras.cover += ( fy2 - fy1 );
899 ras.area += ( fy2 - fy1 ) * fx1 * 2;
900 fy1 = ONE_PIXEL;
901 ey1--;
902 gray_set_cell( RAS_VAR_ ex1, ey1 );
903 } while ( ey1 != ey2 );
904 }
905 else /* any other line */
906 {
907 TPos prod = dx * (TPos)fy1 - dy * (TPos)fx1;
908 FT_UDIVPREP( ex1 != ex2, dx );
909 FT_UDIVPREP( ey1 != ey2, dy );
910
911
912 /* The fundamental value `prod' determines which side and the */
913 /* exact coordinate where the line exits current cell. It is */
914 /* also easily updated when moving from one cell to the next. */
915 do
916 {
917 if ( prod <= 0 &&
918 prod - dx * ONE_PIXEL > 0 ) /* left */
919 {
920 fx2 = 0;
921 fy2 = FT_UDIV( -prod, -dx );
922 prod -= dy * ONE_PIXEL;
923 ras.cover += ( fy2 - fy1 );
924 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
925 fx1 = ONE_PIXEL;
926 fy1 = fy2;
927 ex1--;
928 }
929 else if ( prod - dx * ONE_PIXEL <= 0 &&
930 prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
931 {
932 prod -= dx * ONE_PIXEL;
933 fx2 = FT_UDIV( -prod, dy );
934 fy2 = ONE_PIXEL;
935 ras.cover += ( fy2 - fy1 );
936 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
937 fx1 = fx2;
938 fy1 = 0;
939 ey1++;
940 }
941 else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
942 prod + dy * ONE_PIXEL >= 0 ) /* right */
943 {
944 prod += dy * ONE_PIXEL;
945 fx2 = ONE_PIXEL;
946 fy2 = FT_UDIV( prod, dx );
947 ras.cover += ( fy2 - fy1 );
948 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
949 fx1 = 0;
950 fy1 = fy2;
951 ex1++;
952 }
953 else /* ( prod + dy * ONE_PIXEL < 0 &&
954 prod > 0 ) down */
955 {
956 fx2 = FT_UDIV( prod, -dy );
957 fy2 = 0;
958 prod += dx * ONE_PIXEL;
959 ras.cover += ( fy2 - fy1 );
960 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
961 fx1 = fx2;
962 fy1 = ONE_PIXEL;
963 ey1--;
964 }
965
966 gray_set_cell( RAS_VAR_ ex1, ey1 );
967 } while ( ex1 != ex2 || ey1 != ey2 );
968 }
969
970 fx2 = FRACT( to_x );
971 fy2 = FRACT( to_y );
972
973 ras.cover += ( fy2 - fy1 );
974 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
975
976 End:
977 ras.x = to_x;
978 ras.y = to_y;
979 }
980
981#endif
982
983 static void
985 {
986 TPos a, b;
987
988
989 base[4].x = base[2].x;
990 a = base[0].x + base[1].x;
991 b = base[1].x + base[2].x;
992 base[3].x = b >> 1;
993 base[2].x = ( a + b ) >> 2;
994 base[1].x = a >> 1;
995
996 base[4].y = base[2].y;
997 a = base[0].y + base[1].y;
998 b = base[1].y + base[2].y;
999 base[3].y = b >> 1;
1000 base[2].y = ( a + b ) >> 2;
1001 base[1].y = a >> 1;
1002 }
1003
1004
1005 static void
1007 const FT_Vector* to )
1008 {
1009 FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */
1010 FT_Vector* arc = bez_stack;
1011 TPos dx, dy;
1012 int draw, split;
1013
1014
1015 arc[0].x = UPSCALE( to->x );
1016 arc[0].y = UPSCALE( to->y );
1017 arc[1].x = UPSCALE( control->x );
1018 arc[1].y = UPSCALE( control->y );
1019 arc[2].x = ras.x;
1020 arc[2].y = ras.y;
1021
1022 /* short-cut the arc that crosses the current band */
1023 if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
1024 TRUNC( arc[1].y ) >= ras.max_ey &&
1025 TRUNC( arc[2].y ) >= ras.max_ey ) ||
1026 ( TRUNC( arc[0].y ) < ras.min_ey &&
1027 TRUNC( arc[1].y ) < ras.min_ey &&
1028 TRUNC( arc[2].y ) < ras.min_ey ) )
1029 {
1030 ras.x = arc[0].x;
1031 ras.y = arc[0].y;
1032 return;
1033 }
1034
1035 dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
1036 dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
1037 if ( dx < dy )
1038 dx = dy;
1039
1040 /* We can calculate the number of necessary bisections because */
1041 /* each bisection predictably reduces deviation exactly 4-fold. */
1042 /* Even 32-bit deviation would vanish after 16 bisections. */
1043 draw = 1;
1044 while ( dx > ONE_PIXEL / 4 )
1045 {
1046 dx >>= 2;
1047 draw <<= 1;
1048 }
1049
1050 /* We use decrement counter to count the total number of segments */
1051 /* to draw starting from 2^level. Before each draw we split as */
1052 /* many times as there are trailing zeros in the counter. */
1053 do
1054 {
1055 split = draw & ( -draw ); /* isolate the rightmost 1-bit */
1056 while ( ( split >>= 1 ) )
1057 {
1058 gray_split_conic( arc );
1059 arc += 2;
1060 }
1061
1062 gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
1063 arc -= 2;
1064
1065 } while ( --draw );
1066 }
1067
1068
1069 static void
1071 {
1072 TPos a, b, c;
1073
1074
1075 base[6].x = base[3].x;
1076 a = base[0].x + base[1].x;
1077 b = base[1].x + base[2].x;
1078 c = base[2].x + base[3].x;
1079 base[5].x = c >> 1;
1080 c += b;
1081 base[4].x = c >> 2;
1082 base[1].x = a >> 1;
1083 a += b;
1084 base[2].x = a >> 2;
1085 base[3].x = ( a + c ) >> 3;
1086
1087 base[6].y = base[3].y;
1088 a = base[0].y + base[1].y;
1089 b = base[1].y + base[2].y;
1090 c = base[2].y + base[3].y;
1091 base[5].y = c >> 1;
1092 c += b;
1093 base[4].y = c >> 2;
1094 base[1].y = a >> 1;
1095 a += b;
1096 base[2].y = a >> 2;
1097 base[3].y = ( a + c ) >> 3;
1098 }
1099
1100
1101 static void
1103 const FT_Vector* control2,
1104 const FT_Vector* to )
1105 {
1106 FT_Vector bez_stack[16 * 3 + 1]; /* enough to accommodate bisections */
1107 FT_Vector* arc = bez_stack;
1108
1109
1110 arc[0].x = UPSCALE( to->x );
1111 arc[0].y = UPSCALE( to->y );
1112 arc[1].x = UPSCALE( control2->x );
1113 arc[1].y = UPSCALE( control2->y );
1114 arc[2].x = UPSCALE( control1->x );
1115 arc[2].y = UPSCALE( control1->y );
1116 arc[3].x = ras.x;
1117 arc[3].y = ras.y;
1118
1119 /* short-cut the arc that crosses the current band */
1120 if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
1121 TRUNC( arc[1].y ) >= ras.max_ey &&
1122 TRUNC( arc[2].y ) >= ras.max_ey &&
1123 TRUNC( arc[3].y ) >= ras.max_ey ) ||
1124 ( TRUNC( arc[0].y ) < ras.min_ey &&
1125 TRUNC( arc[1].y ) < ras.min_ey &&
1126 TRUNC( arc[2].y ) < ras.min_ey &&
1127 TRUNC( arc[3].y ) < ras.min_ey ) )
1128 {
1129 ras.x = arc[0].x;
1130 ras.y = arc[0].y;
1131 return;
1132 }
1133
1134 for (;;)
1135 {
1136 /* with each split, control points quickly converge towards */
1137 /* chord trisection points and the vanishing distances below */
1138 /* indicate when the segment is flat enough to draw */
1139 if ( FT_ABS( 2 * arc[0].x - 3 * arc[1].x + arc[3].x ) > ONE_PIXEL / 2 ||
1140 FT_ABS( 2 * arc[0].y - 3 * arc[1].y + arc[3].y ) > ONE_PIXEL / 2 ||
1141 FT_ABS( arc[0].x - 3 * arc[2].x + 2 * arc[3].x ) > ONE_PIXEL / 2 ||
1142 FT_ABS( arc[0].y - 3 * arc[2].y + 2 * arc[3].y ) > ONE_PIXEL / 2 )
1143 goto Split;
1144
1145 gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
1146
1147 if ( arc == bez_stack )
1148 return;
1149
1150 arc -= 3;
1151 continue;
1152
1153 Split:
1154 gray_split_cubic( arc );
1155 arc += 3;
1156 }
1157 }
1158
1159
1160 static int
1162 gray_PWorker worker )
1163 {
1164 TPos x, y;
1165
1166
1167 /* start to a new position */
1168 x = UPSCALE( to->x );
1169 y = UPSCALE( to->y );
1170
1171 gray_set_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
1172
1173 ras.x = x;
1174 ras.y = y;
1175 return 0;
1176 }
1177
1178
1179 static int
1181 gray_PWorker worker )
1182 {
1183 gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
1184 return 0;
1185 }
1186
1187
1188 static int
1190 const FT_Vector* to,
1191 gray_PWorker worker )
1192 {
1194 return 0;
1195 }
1196
1197
1198 static int
1199 gray_cubic_to( const FT_Vector* control1,
1200 const FT_Vector* control2,
1201 const FT_Vector* to,
1202 gray_PWorker worker )
1203 {
1204 gray_render_cubic( RAS_VAR_ control1, control2, to );
1205 return 0;
1206 }
1207
1208
1209 static void
1211 TCoord y,
1212 TArea coverage,
1213 TCoord acount )
1214 {
1215 /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256 */
1216 coverage >>= PIXEL_BITS * 2 + 1 - 8;
1217
1218 /* compute the line's coverage depending on the outline fill rule */
1219 if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
1220 {
1221 coverage &= 511;
1222
1223 if ( coverage >= 256 )
1224 coverage = 511 - coverage;
1225 }
1226 else /* default non-zero winding rule */
1227 {
1228 if ( coverage < 0 )
1229 coverage = ~coverage; /* the same as -coverage - 1 */
1230
1231 if ( coverage >= 256 )
1232 coverage = 255;
1233 }
1234
1235 if ( ras.num_spans >= 0 ) /* for FT_RASTER_FLAG_DIRECT only */
1236 {
1237 FT_Span* span = ras.spans + ras.num_spans++;
1238
1239
1240 span->x = (short)x;
1241 span->len = (unsigned short)acount;
1242 span->coverage = (unsigned char)coverage;
1243
1244 if ( ras.num_spans == FT_MAX_GRAY_SPANS )
1245 {
1246 /* flush the span buffer and reset the count */
1247 ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
1248 ras.num_spans = 0;
1249 }
1250 }
1251 else
1252 {
1253 unsigned char* q = ras.target.origin - ras.target.pitch * y + x;
1254 unsigned char c = (unsigned char)coverage;
1255
1256
1257 /* For small-spans it is faster to do it by ourselves than
1258 * calling `memset'. This is mainly due to the cost of the
1259 * function call.
1260 */
1261 switch ( acount )
1262 {
1263 case 7:
1264 *q++ = c;
1265 /* fall through */
1266 case 6:
1267 *q++ = c;
1268 /* fall through */
1269 case 5:
1270 *q++ = c;
1271 /* fall through */
1272 case 4:
1273 *q++ = c;
1274 /* fall through */
1275 case 3:
1276 *q++ = c;
1277 /* fall through */
1278 case 2:
1279 *q++ = c;
1280 /* fall through */
1281 case 1:
1282 *q = c;
1283 /* fall through */
1284 case 0:
1285 break;
1286 default:
1287 FT_MEM_SET( q, c, acount );
1288 }
1289 }
1290 }
1291
1292
1293 static void
1295 {
1296 int y;
1297
1298
1299 for ( y = ras.min_ey; y < ras.max_ey; y++ )
1300 {
1301 PCell cell = ras.ycells[y - ras.min_ey];
1302 TCoord x = ras.min_ex;
1303 TArea cover = 0;
1304 TArea area;
1305
1306
1307 for ( ; cell != NULL; cell = cell->next )
1308 {
1309 if ( cover != 0 && cell->x > x )
1310 gray_hline( RAS_VAR_ x, y, cover, cell->x - x );
1311
1312 cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
1313 area = cover - cell->area;
1314
1315 if ( area != 0 && cell->x >= ras.min_ex )
1316 gray_hline( RAS_VAR_ cell->x, y, area, 1 );
1317
1318 x = cell->x + 1;
1319 }
1320
1321 if ( cover != 0 )
1322 gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
1323
1324 if ( ras.num_spans > 0 ) /* for FT_RASTER_FLAG_DIRECT only */
1325 {
1326 /* flush the span buffer and reset the count */
1327 ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
1328 ras.num_spans = 0;
1329 }
1330 }
1331 }
1332
1333
1334#ifdef STANDALONE_
1335
1336 /**************************************************************************
1337 *
1338 * The following functions should only compile in stand-alone mode,
1339 * i.e., when building this component without the rest of FreeType.
1340 *
1341 */
1342
1343 /**************************************************************************
1344 *
1345 * @Function:
1346 * FT_Outline_Decompose
1347 *
1348 * @Description:
1349 * Walk over an outline's structure to decompose it into individual
1350 * segments and Bézier arcs. This function is also able to emit
1351 * `move to' and `close to' operations to indicate the start and end
1352 * of new contours in the outline.
1353 *
1354 * @Input:
1355 * outline ::
1356 * A pointer to the source target.
1357 *
1358 * func_interface ::
1359 * A table of `emitters', i.e., function pointers
1360 * called during decomposition to indicate path
1361 * operations.
1362 *
1363 * @InOut:
1364 * user ::
1365 * A typeless pointer which is passed to each
1366 * emitter during the decomposition. It can be
1367 * used to store the state during the
1368 * decomposition.
1369 *
1370 * @Return:
1371 * Error code. 0 means success.
1372 */
1373 static int
1375 const FT_Outline_Funcs* func_interface,
1376 void* user )
1377 {
1378#undef SCALED
1379#define SCALED( x ) ( (x) * ( 1L << shift ) - delta )
1380
1381 FT_Vector v_last;
1382 FT_Vector v_control;
1383 FT_Vector v_start;
1384
1387 char* tags;
1388
1389 int error;
1390
1391 int n; /* index of contour in outline */
1392 int first; /* index of first point in contour */
1393 char tag; /* current point's state */
1394
1395 int shift;
1396 TPos delta;
1397
1398
1399 if ( !outline )
1400 return FT_THROW( Invalid_Outline );
1401
1402 if ( !func_interface )
1403 return FT_THROW( Invalid_Argument );
1404
1405 shift = func_interface->shift;
1406 delta = func_interface->delta;
1407 first = 0;
1408
1409 for ( n = 0; n < outline->n_contours; n++ )
1410 {
1411 int last; /* index of last point in contour */
1412
1413
1414 FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
1415
1416 last = outline->contours[n];
1417 if ( last < 0 )
1418 goto Invalid_Outline;
1419 limit = outline->points + last;
1420
1421 v_start = outline->points[first];
1422 v_start.x = SCALED( v_start.x );
1423 v_start.y = SCALED( v_start.y );
1424
1425 v_last = outline->points[last];
1426 v_last.x = SCALED( v_last.x );
1427 v_last.y = SCALED( v_last.y );
1428
1429 v_control = v_start;
1430
1431 point = outline->points + first;
1432 tags = outline->tags + first;
1433 tag = FT_CURVE_TAG( tags[0] );
1434
1435 /* A contour cannot start with a cubic control point! */
1436 if ( tag == FT_CURVE_TAG_CUBIC )
1437 goto Invalid_Outline;
1438
1439 /* check first point to determine origin */
1440 if ( tag == FT_CURVE_TAG_CONIC )
1441 {
1442 /* first point is conic control. Yes, this happens. */
1443 if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
1444 {
1445 /* start at last point if it is on the curve */
1446 v_start = v_last;
1447 limit--;
1448 }
1449 else
1450 {
1451 /* if both first and last points are conic, */
1452 /* start at their middle and record its position */
1453 /* for closure */
1454 v_start.x = ( v_start.x + v_last.x ) / 2;
1455 v_start.y = ( v_start.y + v_last.y ) / 2;
1456
1457 v_last = v_start;
1458 }
1459 point--;
1460 tags--;
1461 }
1462
1463 FT_TRACE5(( " move to (%.2f, %.2f)\n",
1464 v_start.x / 64.0, v_start.y / 64.0 ));
1465 error = func_interface->move_to( &v_start, user );
1466 if ( error )
1467 goto Exit;
1468
1469 while ( point < limit )
1470 {
1471 point++;
1472 tags++;
1473
1474 tag = FT_CURVE_TAG( tags[0] );
1475 switch ( tag )
1476 {
1477 case FT_CURVE_TAG_ON: /* emit a single line_to */
1478 {
1479 FT_Vector vec;
1480
1481
1482 vec.x = SCALED( point->x );
1483 vec.y = SCALED( point->y );
1484
1485 FT_TRACE5(( " line to (%.2f, %.2f)\n",
1486 vec.x / 64.0, vec.y / 64.0 ));
1487 error = func_interface->line_to( &vec, user );
1488 if ( error )
1489 goto Exit;
1490 continue;
1491 }
1492
1493 case FT_CURVE_TAG_CONIC: /* consume conic arcs */
1494 v_control.x = SCALED( point->x );
1495 v_control.y = SCALED( point->y );
1496
1497 Do_Conic:
1498 if ( point < limit )
1499 {
1500 FT_Vector vec;
1501 FT_Vector v_middle;
1502
1503
1504 point++;
1505 tags++;
1506 tag = FT_CURVE_TAG( tags[0] );
1507
1508 vec.x = SCALED( point->x );
1509 vec.y = SCALED( point->y );
1510
1511 if ( tag == FT_CURVE_TAG_ON )
1512 {
1513 FT_TRACE5(( " conic to (%.2f, %.2f)"
1514 " with control (%.2f, %.2f)\n",
1515 vec.x / 64.0, vec.y / 64.0,
1516 v_control.x / 64.0, v_control.y / 64.0 ));
1517 error = func_interface->conic_to( &v_control, &vec, user );
1518 if ( error )
1519 goto Exit;
1520 continue;
1521 }
1522
1523 if ( tag != FT_CURVE_TAG_CONIC )
1524 goto Invalid_Outline;
1525
1526 v_middle.x = ( v_control.x + vec.x ) / 2;
1527 v_middle.y = ( v_control.y + vec.y ) / 2;
1528
1529 FT_TRACE5(( " conic to (%.2f, %.2f)"
1530 " with control (%.2f, %.2f)\n",
1531 v_middle.x / 64.0, v_middle.y / 64.0,
1532 v_control.x / 64.0, v_control.y / 64.0 ));
1533 error = func_interface->conic_to( &v_control, &v_middle, user );
1534 if ( error )
1535 goto Exit;
1536
1537 v_control = vec;
1538 goto Do_Conic;
1539 }
1540
1541 FT_TRACE5(( " conic to (%.2f, %.2f)"
1542 " with control (%.2f, %.2f)\n",
1543 v_start.x / 64.0, v_start.y / 64.0,
1544 v_control.x / 64.0, v_control.y / 64.0 ));
1545 error = func_interface->conic_to( &v_control, &v_start, user );
1546 goto Close;
1547
1548 default: /* FT_CURVE_TAG_CUBIC */
1549 {
1550 FT_Vector vec1, vec2;
1551
1552
1553 if ( point + 1 > limit ||
1555 goto Invalid_Outline;
1556
1557 point += 2;
1558 tags += 2;
1559
1560 vec1.x = SCALED( point[-2].x );
1561 vec1.y = SCALED( point[-2].y );
1562
1563 vec2.x = SCALED( point[-1].x );
1564 vec2.y = SCALED( point[-1].y );
1565
1566 if ( point <= limit )
1567 {
1568 FT_Vector vec;
1569
1570
1571 vec.x = SCALED( point->x );
1572 vec.y = SCALED( point->y );
1573
1574 FT_TRACE5(( " cubic to (%.2f, %.2f)"
1575 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
1576 vec.x / 64.0, vec.y / 64.0,
1577 vec1.x / 64.0, vec1.y / 64.0,
1578 vec2.x / 64.0, vec2.y / 64.0 ));
1579 error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
1580 if ( error )
1581 goto Exit;
1582 continue;
1583 }
1584
1585 FT_TRACE5(( " cubic to (%.2f, %.2f)"
1586 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
1587 v_start.x / 64.0, v_start.y / 64.0,
1588 vec1.x / 64.0, vec1.y / 64.0,
1589 vec2.x / 64.0, vec2.y / 64.0 ));
1590 error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
1591 goto Close;
1592 }
1593 }
1594 }
1595
1596 /* close the contour with a line segment */
1597 FT_TRACE5(( " line to (%.2f, %.2f)\n",
1598 v_start.x / 64.0, v_start.y / 64.0 ));
1599 error = func_interface->line_to( &v_start, user );
1600
1601 Close:
1602 if ( error )
1603 goto Exit;
1604
1605 first = last + 1;
1606 }
1607
1608 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
1609 return 0;
1610
1611 Exit:
1612 FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
1613 return error;
1614
1615 Invalid_Outline:
1616 return FT_THROW( Invalid_Outline );
1617 }
1618
1619#endif /* STANDALONE_ */
1620
1621
1623 func_interface,
1624
1625 (FT_Outline_MoveTo_Func) gray_move_to, /* move_to */
1626 (FT_Outline_LineTo_Func) gray_line_to, /* line_to */
1627 (FT_Outline_ConicTo_Func)gray_conic_to, /* conic_to */
1628 (FT_Outline_CubicTo_Func)gray_cubic_to, /* cubic_to */
1629
1630 0, /* shift */
1631 0 /* delta */
1632 )
1633
1634
1635 static int
1636 gray_convert_glyph_inner( RAS_ARG,
1638 {
1639 int error;
1640
1641
1642 if ( ft_setjmp( ras.jump_buffer ) == 0 )
1643 {
1644 if ( continued )
1646 error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
1647 if ( continued )
1649
1650 if ( !ras.invalid )
1652
1653 FT_TRACE7(( "band [%d..%d]: %ld cell%s\n",
1654 ras.min_ey,
1655 ras.max_ey,
1656 ras.num_cells,
1657 ras.num_cells == 1 ? "" : "s" ));
1658 }
1659 else
1660 {
1661 error = FT_THROW( Memory_Overflow );
1662
1663 FT_TRACE7(( "band [%d..%d]: to be bisected\n",
1664 ras.min_ey, ras.max_ey ));
1665 }
1666
1667 return error;
1668 }
1669
1670
1671 static int
1673 {
1674 const TCoord yMin = ras.min_ey;
1675 const TCoord yMax = ras.max_ey;
1676
1677#ifdef __REACTOS__
1679 if (!buffer)
1680 return 1;
1681 {
1682#else
1684#endif
1685 size_t height = (size_t)( yMax - yMin );
1686 size_t n = FT_MAX_GRAY_POOL / 8;
1687 TCoord y;
1688 TCoord bands[32]; /* enough to accommodate bisections */
1689 TCoord* band;
1690
1691 int continued = 0;
1692
1693
1694 /* set up vertical bands */
1695 if ( height > n )
1696 {
1697 /* two divisions rounded up */
1698 n = ( height + n - 1 ) / n;
1699 height = ( height + n - 1 ) / n;
1700 }
1701
1702 /* memory management */
1703 n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell );
1704
1705 ras.cells = buffer + n;
1706 ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n );
1707 ras.ycells = (PCell*)buffer;
1708
1709 for ( y = yMin; y < yMax; )
1710 {
1711 ras.min_ey = y;
1712 y += height;
1713 ras.max_ey = FT_MIN( y, yMax );
1714
1715 band = bands;
1716 band[1] = ras.min_ey;
1717 band[0] = ras.max_ey;
1718
1719 do
1720 {
1721 TCoord width = band[0] - band[1];
1722 int error;
1723
1724
1725 FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
1726
1727 ras.num_cells = 0;
1728 ras.invalid = 1;
1729 ras.min_ey = band[1];
1730 ras.max_ey = band[0];
1731
1732 error = gray_convert_glyph_inner( RAS_VAR, continued );
1733 continued = 1;
1734
1735 if ( !error )
1736 {
1738 band--;
1739 continue;
1740 }
1741 else if ( error != ErrRaster_Memory_Overflow )
1742#ifdef __REACTOS__
1743 {
1744 free(buffer);
1745 return 1;
1746 }
1747#else
1748 return 1;
1749#endif
1750
1751 /* render pool overflow; we will reduce the render band by half */
1752 width >>= 1;
1753
1754 /* this should never happen even with tiny rendering pool */
1755 if ( width == 0 )
1756 {
1757 FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
1758#ifdef __REACTOS__
1759 free(buffer);
1760#endif
1761 return 1;
1762 }
1763
1764 band++;
1765 band[1] = band[0];
1766 band[0] += width;
1767 } while ( band >= bands );
1768 }
1769
1770#ifdef __REACTOS__
1771 free(buffer);
1772 }
1773#endif
1774 return 0;
1775 }
1776
1777
1778 static int
1780 const FT_Raster_Params* params )
1781 {
1782 const FT_Outline* outline = (const FT_Outline*)params->source;
1783 const FT_Bitmap* target_map = params->target;
1784
1785#ifndef FT_STATIC_RASTER
1786#ifdef __REACTOS__
1787 gray_TWorker *worker;
1788#else
1789 gray_TWorker worker[1];
1790#endif
1791#endif
1792
1793
1794 if ( !raster )
1795 return FT_THROW( Invalid_Argument );
1796
1797 /* this version does not support monochrome rendering */
1798 if ( !( params->flags & FT_RASTER_FLAG_AA ) )
1799 return FT_THROW( Invalid_Mode );
1800
1801 if ( !outline )
1802 return FT_THROW( Invalid_Outline );
1803
1804 /* return immediately if the outline is empty */
1805 if ( outline->n_points == 0 || outline->n_contours <= 0 )
1806 return 0;
1807
1808 if ( !outline->contours || !outline->points )
1809 return FT_THROW( Invalid_Outline );
1810
1811 if ( outline->n_points !=
1812 outline->contours[outline->n_contours - 1] + 1 )
1813 return FT_THROW( Invalid_Outline );
1814
1815#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1816 worker = malloc(sizeof(*worker));
1817 if (!worker)
1818 return FT_THROW(Out_Of_Memory);
1819#endif /* !defined(FT_STATIC_RASTER) && defined(__REACTOS__) */
1820
1821 ras.outline = *outline;
1822
1823 if ( params->flags & FT_RASTER_FLAG_DIRECT )
1824 {
1825 if ( !params->gray_spans )
1826#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1827 {
1828 free(worker);
1829 return 0;
1830 }
1831#else
1832 return 0;
1833#endif
1834
1835 ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
1836 ras.render_span_data = params->user;
1837 ras.num_spans = 0;
1838
1839 ras.min_ex = params->clip_box.xMin;
1840 ras.min_ey = params->clip_box.yMin;
1841 ras.max_ex = params->clip_box.xMax;
1842 ras.max_ey = params->clip_box.yMax;
1843 }
1844 else
1845 {
1846 /* if direct mode is not set, we must have a target bitmap */
1847 if ( !target_map )
1848#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1849 {
1850 free(worker);
1851 return FT_THROW( Invalid_Argument );
1852 }
1853#else
1854 return FT_THROW( Invalid_Argument );
1855#endif
1856
1857 /* nothing to do */
1858 if ( !target_map->width || !target_map->rows )
1859#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1860 {
1861 free(worker);
1862 return 0;
1863 }
1864#else
1865 return 0;
1866#endif
1867
1868 if ( !target_map->buffer )
1869#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1870 {
1871 free(worker);
1872 return FT_THROW( Invalid_Argument );
1873 }
1874#else
1875 return FT_THROW( Invalid_Argument );
1876#endif
1877
1878 if ( target_map->pitch < 0 )
1879 ras.target.origin = target_map->buffer;
1880 else
1881 ras.target.origin = target_map->buffer
1882 + ( target_map->rows - 1 ) * (unsigned int)target_map->pitch;
1883
1884 ras.target.pitch = target_map->pitch;
1885
1886 ras.render_span = (FT_Raster_Span_Func)NULL;
1887 ras.render_span_data = NULL;
1888 ras.num_spans = -1; /* invalid */
1889
1890 ras.min_ex = 0;
1891 ras.min_ey = 0;
1892 ras.max_ex = (FT_Pos)target_map->width;
1893 ras.max_ey = (FT_Pos)target_map->rows;
1894 }
1895
1896 /* exit if nothing to do */
1897 if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
1898#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1899 {
1900 free(worker);
1901 return 0;
1902 }
1903#else
1904 return 0;
1905#endif
1906
1907#if !defined(FT_STATIC_RASTER) && defined(__REACTOS__)
1908 {
1910 free(worker);
1911 return error;
1912 }
1913#else
1914 return gray_convert_glyph( RAS_VAR );
1915#endif
1916 }
1917
1918
1919 /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
1920 /**** a static object. *****/
1921
1922#ifdef STANDALONE_
1923
1924 static int
1925 gray_raster_new( void* memory,
1926 FT_Raster* araster )
1927 {
1928 static gray_TRaster the_raster;
1929
1930 FT_UNUSED( memory );
1931
1932
1933 *araster = (FT_Raster)&the_raster;
1934 FT_ZERO( &the_raster );
1935
1936 return 0;
1937 }
1938
1939
1940 static void
1941 gray_raster_done( FT_Raster raster )
1942 {
1943 /* nothing */
1944 FT_UNUSED( raster );
1945 }
1946
1947#else /* !STANDALONE_ */
1948
1949 static int
1951 FT_Raster* araster )
1952 {
1954 gray_PRaster raster = NULL;
1955
1956
1957 *araster = 0;
1958 if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
1959 {
1960 raster->memory = memory;
1961 *araster = (FT_Raster)raster;
1962 }
1963
1964 return error;
1965 }
1966
1967
1968 static void
1970 {
1972
1973
1974 FT_FREE( raster );
1975 }
1976
1977#endif /* !STANDALONE_ */
1978
1979
1980 static void
1982 unsigned char* pool_base,
1983 unsigned long pool_size )
1984 {
1985 FT_UNUSED( raster );
1986 FT_UNUSED( pool_base );
1987 FT_UNUSED( pool_size );
1988 }
1989
1990
1991 static int
1993 unsigned long mode,
1994 void* args )
1995 {
1996 FT_UNUSED( raster );
1997 FT_UNUSED( mode );
1998 FT_UNUSED( args );
1999
2000
2001 return 0; /* nothing to do */
2002 }
2003
2004
2006 ft_grays_raster,
2007
2008 FT_GLYPH_FORMAT_OUTLINE,
2009
2010 (FT_Raster_New_Func) gray_raster_new, /* raster_new */
2011 (FT_Raster_Reset_Func) gray_raster_reset, /* raster_reset */
2012 (FT_Raster_Set_Mode_Func)gray_raster_set_mode, /* raster_set_mode */
2013 (FT_Raster_Render_Func) gray_raster_render, /* raster_render */
2014 (FT_Raster_Done_Func) gray_raster_done /* raster_done */
2015 )
2016
2017
2018/* END */
2019
2020
2021/* Local Variables: */
2022/* coding: utf-8 */
2023/* End: */
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:66
void user(int argc, const char *argv[])
Definition: cmds.c:1350
return Found
Definition: dirsup.c:1270
static LPSTR * split(LPSTR s, LPINT args)
Definition: cmdcons.c:163
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
int CDECL vfprintf(FILE *file, const char *format, va_list valist)
Definition: file.c:5349
unsigned int size_t
Definition: corecrt.h:203
int ptrdiff_t
Definition: corecrt.h:194
#define stderr
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
unsigned char
Definition: typeof.h:29
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
POINTL point
Definition: edittest.c:50
#define printf
Definition: freeldr.h:104
FT_Vector * vec
Definition: ftbbox.c:469
FT_Trace_Disable(void)
Definition: ftdebug.c:315
FT_Trace_Enable(void)
Definition: ftdebug.c:324
#define FT_TRACE5(varformat)
Definition: ftdebug.h:192
#define FT_TRACE7(varformat)
Definition: ftdebug.h:194
#define FT_THROW(e)
Definition: ftdebug.h:243
void FT_Message(const char *format,...)
Definition: rosglue.c:16
struct TPixmap_ TPixmap
static void gray_render_conic(RAS_ARG_ const FT_Vector *control, const FT_Vector *to)
Definition: ftgrays.c:1006
static void gray_record_cell(RAS_ARG)
Definition: ftgrays.c:528
#define RAS_ARG
Definition: ftgrays.c:320
static int gray_conic_to(const FT_Vector *control, const FT_Vector *to, gray_PWorker worker)
Definition: ftgrays.c:1189
#define UPSCALE(x)
Definition: ftgrays.c:344
#define ErrRaster_Memory_Overflow
Definition: ftgrays.c:293
static int gray_line_to(const FT_Vector *to, gray_PWorker worker)
Definition: ftgrays.c:1180
long TPos
Definition: ftgrays.c:406
static void gray_hline(RAS_ARG_ TCoord x, TCoord y, TArea coverage, TCoord acount)
Definition: ftgrays.c:1210
#define TRUNC(x)
Definition: ftgrays.c:340
static void gray_render_line(RAS_ARG_ TPos to_x, TPos to_y)
Definition: ftgrays.c:707
#define FT_UDIVPREP(c, b)
Definition: ftgrays.c:389
int TArea
Definition: ftgrays.c:408
int TCoord
Definition: ftgrays.c:407
struct gray_TRaster_ gray_TRaster
static int gray_raster_new(FT_Memory memory, FT_Raster *araster)
Definition: ftgrays.c:1950
static int gray_move_to(const FT_Vector *to, gray_PWorker worker)
Definition: ftgrays.c:1161
#define FT_MEM_SET(d, s, c)
Definition: ftgrays.c:300
static void gray_sweep(RAS_ARG)
Definition: ftgrays.c:1294
#define RAS_VAR
Definition: ftgrays.c:323
static int gray_convert_glyph(RAS_ARG)
Definition: ftgrays.c:1672
struct TCell_ TCell
static void gray_render_cubic(RAS_ARG_ const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to)
Definition: ftgrays.c:1102
#define RAS_VAR_
Definition: ftgrays.c:324
#define PIXEL_BITS
Definition: ftgrays.c:337
#define FRACT(x)
Definition: ftgrays.c:341
struct gray_TRaster_ * gray_PRaster
static void gray_raster_done(FT_Raster raster)
Definition: ftgrays.c:1969
#define FT_ZERO(p)
Definition: ftgrays.c:308
#define ras
Definition: ftgrays.c:483
#define RAS_ARG_
Definition: ftgrays.c:321
#define FT_UDIV(a, b)
Definition: ftgrays.c:392
struct gray_TWorker_ gray_TWorker
struct TCell_ * PCell
Definition: ftgrays.c:411
static void gray_set_cell(RAS_ARG_ TCoord ex, TCoord ey)
Definition: ftgrays.c:572
static void gray_split_cubic(FT_Vector *base)
Definition: ftgrays.c:1070
static int gray_raster_set_mode(FT_Raster raster, unsigned long mode, void *args)
Definition: ftgrays.c:1992
return error
Definition: ftgrays.c:1667
static int gray_cubic_to(const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, gray_PWorker worker)
Definition: ftgrays.c:1199
#define FT_MAX_GRAY_POOL
Definition: ftgrays.c:433
#define FT_MEM_ZERO(dest, count)
Definition: ftgrays.c:304
struct gray_TWorker_ * gray_PWorker
static void gray_render_scanline(RAS_ARG_ TCoord ey, TPos x1, TCoord y1, TPos x2, TCoord y2)
Definition: ftgrays.c:606
#define FT_DIV_MOD(type, dividend, divisor, quotient, remainder)
Definition: ftgrays.c:356
static void gray_split_conic(FT_Vector *base)
Definition: ftgrays.c:984
static void gray_raster_reset(FT_Raster raster, unsigned char *pool_base, unsigned long pool_size)
Definition: ftgrays.c:1981
static int gray_raster_render(FT_Raster raster, const FT_Raster_Params *params)
Definition: ftgrays.c:1779
#define ONE_PIXEL
Definition: ftgrays.c:339
int continued
Definition: ftgrays.c:1638
#define FT_MAX_GRAY_SPANS
Definition: ftgrays.c:437
#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 FT_DEFINE_OUTLINE_FUNCS( class_, move_to_, line_to_, conic_to_, cubic_to_, shift_, delta_)
Definition: ftobjs.h:1002
#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
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum GLenum GLvoid GLvoid GLvoid * span
Definition: glext.h:5664
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLint limit
Definition: glext.h:10326
GLenum mode
Definition: glext.h:6217
GLenum const GLfloat * params
Definition: glext.h:5645
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
const char * tags[99]
Definition: apphelp.c:216
static UINT UINT last
Definition: font.c:45
static char memory[1024 *256]
Definition: process.c:122
#define shift
Definition: input.c:1755
static Real area(Real A[2], Real B[2], Real C[2])
Definition: polyDBG.cc:50
#define FT_UNUSED(arg)
@ Close
Definition: sacdrv.h:268
static void Exit(void)
Definition: sock.c:1330
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
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
TCoord cover
Definition: ftgrays.c:416
PCell next
Definition: ftgrays.c:418
TCoord x
Definition: ftgrays.c:415
TArea area
Definition: ftgrays.c:417
int pitch
Definition: ftgrays.c:425
unsigned char * origin
Definition: ftgrays.c:424
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
Definition: match.c:390
Definition: dialog.c:52
Definition: comerr.c:44
Definition: fci.c:127
Definition: dsound.c:943
void * memory
Definition: ftgrays.c:491
PCell cells
Definition: ftgrays.c:461
FT_PtrDist max_cells
Definition: ftgrays.c:462
TCoord ex
Definition: ftgrays.c:452
FT_Raster_Span_Func render_span
Definition: ftgrays.c:470
FT_Span spans[FT_MAX_GRAY_SPANS]
Definition: ftgrays.c:472
int num_spans
Definition: ftgrays.c:473
TArea area
Definition: ftgrays.c:456
TCoord ey
Definition: ftgrays.c:452
TCoord max_ex
Definition: ftgrays.c:453
TCoord min_ex
Definition: ftgrays.c:453
ft_jmp_buf jump_buffer
Definition: ftgrays.c:450
TCoord max_ey
Definition: ftgrays.c:454
FT_PtrDist num_cells
Definition: ftgrays.c:463
PCell * ycells
Definition: ftgrays.c:460
FT_Outline outline
Definition: ftgrays.c:467
void * render_span_data
Definition: ftgrays.c:471
TPixmap target
Definition: ftgrays.c:468
TCoord min_ey
Definition: ftgrays.c:454
TCoord cover
Definition: ftgrays.c:457
Definition: parser.c:49
Definition: mesh.c:5330
Definition: ecma_167.h:138
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList