ReactOS 0.4.15-dev-7788-g1ad9096
ftraster.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* ftraster.c */
4/* */
5/* The FreeType glyph rasterizer (body). */
6/* */
7/* Copyright 1996-2018 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18 /*************************************************************************/
19 /* */
20 /* 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 `ftimage.h' and `ftmisc.h' into the $(incdir) */
23 /* directory. Typically, you should do something like */
24 /* */
25 /* - copy `src/raster/ftraster.c' (this file) to your current directory */
26 /* */
27 /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
28 /* current directory */
29 /* */
30 /* - compile `ftraster' with the STANDALONE_ macro defined, as in */
31 /* */
32 /* cc -c -DSTANDALONE_ ftraster.c */
33 /* */
34 /* The renderer can be initialized with a call to */
35 /* `ft_standard_raster.raster_new'; a bitmap can be generated */
36 /* with a call to `ft_standard_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 /* */
46 /* This is a rewrite of the FreeType 1.x scan-line converter */
47 /* */
48 /*************************************************************************/
49
50#ifdef STANDALONE_
51
52 /* The size in bytes of the render pool used by the scan-line converter */
53 /* to do all of its work. */
54#define FT_RENDER_POOL_SIZE 16384L
55
56#define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h>
57
58#include <string.h> /* for memset */
59
60#include "ftmisc.h"
61#include "ftimage.h"
62
63#else /* !STANDALONE_ */
64
65#include <ft2build.h>
66#include "ftraster.h"
67#include FT_INTERNAL_CALC_H /* for FT_MulDiv and FT_MulDiv_No_Round */
68
69#include "rastpic.h"
70
71#endif /* !STANDALONE_ */
72
73
74 /*************************************************************************/
75 /* */
76 /* A simple technical note on how the raster works */
77 /* ----------------------------------------------- */
78 /* */
79 /* Converting an outline into a bitmap is achieved in several steps: */
80 /* */
81 /* 1 - Decomposing the outline into successive `profiles'. Each */
82 /* profile is simply an array of scanline intersections on a given */
83 /* dimension. A profile's main attributes are */
84 /* */
85 /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */
86 /* */
87 /* o an array of intersection coordinates for each scanline */
88 /* between `Ymin' and `Ymax' */
89 /* */
90 /* o a direction, indicating whether it was built going `up' or */
91 /* `down', as this is very important for filling rules */
92 /* */
93 /* o its drop-out mode */
94 /* */
95 /* 2 - Sweeping the target map's scanlines in order to compute segment */
96 /* `spans' which are then filled. Additionally, this pass */
97 /* performs drop-out control. */
98 /* */
99 /* The outline data is parsed during step 1 only. The profiles are */
100 /* built from the bottom of the render pool, used as a stack. The */
101 /* following graphics shows the profile list under construction: */
102 /* */
103 /* __________________________________________________________ _ _ */
104 /* | | | | | */
105 /* | profile | coordinates for | profile | coordinates for |--> */
106 /* | 1 | profile 1 | 2 | profile 2 |--> */
107 /* |_________|_________________|_________|_________________|__ _ _ */
108 /* */
109 /* ^ ^ */
110 /* | | */
111 /* start of render pool top */
112 /* */
113 /* The top of the profile stack is kept in the `top' variable. */
114 /* */
115 /* As you can see, a profile record is pushed on top of the render */
116 /* pool, which is then followed by its coordinates/intersections. If */
117 /* a change of direction is detected in the outline, a new profile is */
118 /* generated until the end of the outline. */
119 /* */
120 /* Note that when all profiles have been generated, the function */
121 /* Finalize_Profile_Table() is used to record, for each profile, its */
122 /* bottom-most scanline as well as the scanline above its upmost */
123 /* boundary. These positions are called `y-turns' because they (sort */
124 /* of) correspond to local extrema. They are stored in a sorted list */
125 /* built from the top of the render pool as a downwards stack: */
126 /* */
127 /* _ _ _______________________________________ */
128 /* | | */
129 /* <--| sorted list of | */
130 /* <--| extrema scanlines | */
131 /* _ _ __________________|____________________| */
132 /* */
133 /* ^ ^ */
134 /* | | */
135 /* maxBuff sizeBuff = end of pool */
136 /* */
137 /* This list is later used during the sweep phase in order to */
138 /* optimize performance (see technical note on the sweep below). */
139 /* */
140 /* Of course, the raster detects whether the two stacks collide and */
141 /* handles the situation properly. */
142 /* */
143 /*************************************************************************/
144
145
146 /*************************************************************************/
147 /*************************************************************************/
151 /*************************************************************************/
152 /*************************************************************************/
153
154 /* define DEBUG_RASTER if you want to compile a debugging version */
155/* #define DEBUG_RASTER */
156
157
158 /*************************************************************************/
159 /*************************************************************************/
163 /*************************************************************************/
164 /*************************************************************************/
165
166 /*************************************************************************/
167 /* */
168 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
169 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
170 /* messages during execution. */
171 /* */
172#undef FT_COMPONENT
173#define FT_COMPONENT trace_raster
174
175
176#ifdef STANDALONE_
177
178 /* Auxiliary macros for token concatenation. */
179#define FT_ERR_XCAT( x, y ) x ## y
180#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
181
182 /* This macro is used to indicate that a function parameter is unused. */
183 /* Its purpose is simply to reduce compiler warnings. Note also that */
184 /* simply defining it as `(void)x' doesn't avoid warnings with certain */
185 /* ANSI compilers (e.g. LCC). */
186#define FT_UNUSED( x ) (x) = (x)
187
188 /* Disable the tracing mechanism for simplicity -- developers can */
189 /* activate it easily by redefining these macros. */
190#ifndef FT_ERROR
191#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
192#endif
193
194#ifndef FT_TRACE
195#define FT_TRACE( x ) do { } while ( 0 ) /* nothing */
196#define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */
197#define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */
198#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
199#endif
200
201#ifndef FT_THROW
202#define FT_THROW( e ) FT_ERR_CAT( Raster_Err_, e )
203#endif
204
205#define Raster_Err_None 0
206#define Raster_Err_Not_Ini -1
207#define Raster_Err_Overflow -2
208#define Raster_Err_Neg_Height -3
209#define Raster_Err_Invalid -4
210#define Raster_Err_Unsupported -5
211
212#define ft_memset memset
213
214#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
215 raster_reset_, raster_set_mode_, \
216 raster_render_, raster_done_ ) \
217 const FT_Raster_Funcs class_ = \
218 { \
219 glyph_format_, \
220 raster_new_, \
221 raster_reset_, \
222 raster_set_mode_, \
223 raster_render_, \
224 raster_done_ \
225 };
226
227#else /* !STANDALONE_ */
228
229
230#include FT_INTERNAL_OBJECTS_H
231#include FT_INTERNAL_DEBUG_H /* for FT_TRACE, FT_ERROR, and FT_THROW */
232
233#include "rasterrs.h"
234
235#define Raster_Err_None FT_Err_Ok
236#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized
237#define Raster_Err_Overflow Raster_Err_Raster_Overflow
238#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height
239#define Raster_Err_Invalid Raster_Err_Invalid_Outline
240#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph
241
242
243#endif /* !STANDALONE_ */
244
245
246#ifndef FT_MEM_SET
247#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
248#endif
249
250#ifndef FT_MEM_ZERO
251#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
252#endif
253
254#ifndef FT_ZERO
255#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) )
256#endif
257
258 /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */
259 /* typically a small value and the result of a*b is known to fit into */
260 /* 32 bits. */
261#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
262
263 /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
264 /* for clipping computations. It simply uses the FT_MulDiv() function */
265 /* defined in `ftcalc.h'. */
266#define SMulDiv FT_MulDiv
267#define SMulDiv_No_Round FT_MulDiv_No_Round
268
269 /* The rasterizer is a very general purpose component; please leave */
270 /* the following redefinitions there (you never know your target */
271 /* environment). */
272
273#ifndef TRUE
274#define TRUE 1
275#endif
276
277#ifndef FALSE
278#define FALSE 0
279#endif
280
281#ifndef NULL
282#define NULL (void*)0
283#endif
284
285#ifndef SUCCESS
286#define SUCCESS 0
287#endif
288
289#ifndef FAILURE
290#define FAILURE 1
291#endif
292
293
294#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
295 /* Setting this constant to more than 32 is a */
296 /* pure waste of space. */
297
298#define Pixel_Bits 6 /* fractional bits of *input* coordinates */
299
300
301 /*************************************************************************/
302 /*************************************************************************/
306 /*************************************************************************/
307 /*************************************************************************/
308
309 typedef int Int;
310 typedef unsigned int UInt;
311 typedef short Short;
312 typedef unsigned short UShort, *PUShort;
313 typedef long Long, *PLong;
314 typedef unsigned long ULong;
315
316 typedef unsigned char Byte, *PByte;
317 typedef char Bool;
318
319
320 typedef union Alignment_
321 {
323 void* p;
325
327
328
329 typedef struct TPoint_
330 {
333
335
336
337 /* values for the `flags' bit field */
338#define Flow_Up 0x08U
339#define Overshoot_Top 0x10U
340#define Overshoot_Bottom 0x20U
341
342
343 /* States of each line, arc, and profile */
344 typedef enum TStates_
345 {
350
352
353
354 typedef struct TProfile_ TProfile;
356
358 {
359 FT_F26Dot6 X; /* current coordinate during sweep */
360 PProfile link; /* link to next profile (various purposes) */
361 PLong offset; /* start of profile's data in render pool */
362 UShort flags; /* Bit 0-2: drop-out mode */
363 /* Bit 3: profile orientation (up/down) */
364 /* Bit 4: is top profile? */
365 /* Bit 5: is bottom profile? */
366 Long height; /* profile's height in scanlines */
367 Long start; /* profile's starting scanline */
368
369 Int countL; /* number of lines to step before this */
370 /* profile becomes drawable */
371
372 PProfile next; /* next profile in same contour, used */
373 /* during drop-out control */
374 };
375
378
379
380 /* Simple record used to implement a stack of bands, required */
381 /* by the sub-banding mechanism */
382 typedef struct black_TBand_
383 {
384 Short y_min; /* band's minimum */
385 Short y_max; /* band's maximum */
386
388
389
390#define AlignProfileSize \
391 ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
392
393
394#undef RAS_ARG
395#undef RAS_ARGS
396#undef RAS_VAR
397#undef RAS_VARS
398
399#ifdef FT_STATIC_RASTER
400
401
402#define RAS_ARGS /* void */
403#define RAS_ARG /* void */
404
405#define RAS_VARS /* void */
406#define RAS_VAR /* void */
407
408#define FT_UNUSED_RASTER do { } while ( 0 )
409
410
411#else /* !FT_STATIC_RASTER */
412
413
414#define RAS_ARGS black_PWorker worker,
415#define RAS_ARG black_PWorker worker
416
417#define RAS_VARS worker,
418#define RAS_VAR worker
419
420#define FT_UNUSED_RASTER FT_UNUSED( worker )
421
422
423#endif /* !FT_STATIC_RASTER */
424
425
427
428
429 /* prototypes used for sweep function dispatch */
430 typedef void
432 Short* max );
433
434 typedef void
439 PProfile right );
440
441 typedef void
443
444
445 /* NOTE: These operations are only valid on 2's complement processors */
446#undef FLOOR
447#undef CEILING
448#undef TRUNC
449#undef SCALED
450
451#define FLOOR( x ) ( (x) & -ras.precision )
452#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
453#define TRUNC( x ) ( (Long)(x) >> ras.precision_bits )
454#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
455#define SCALED( x ) ( ( (x) < 0 ? -( -(x) << ras.scale_shift ) \
456 : ( (x) << ras.scale_shift ) ) \
457 - ras.precision_half )
458
459#define IS_BOTTOM_OVERSHOOT( x ) \
460 (Bool)( CEILING( x ) - x >= ras.precision_half )
461#define IS_TOP_OVERSHOOT( x ) \
462 (Bool)( x - FLOOR( x ) >= ras.precision_half )
463
464#if FT_RENDER_POOL_SIZE > 2048
465#define FT_MAX_BLACK_POOL ( FT_RENDER_POOL_SIZE / sizeof ( Long ) )
466#else
467#define FT_MAX_BLACK_POOL ( 2048 / sizeof ( Long ) )
468#endif
469
470 /* The most used variables are positioned at the top of the structure. */
471 /* Thus, their offset can be coded with less opcodes, resulting in a */
472 /* smaller executable. */
473
475 {
476 Int precision_bits; /* precision related variables */
482
483 Int scale_shift; /* == precision_shift for bitmaps */
484 /* == precision_shift+1 for pixmaps */
485
486 PLong buff; /* The profiles buffer */
487 PLong sizeBuff; /* Render pool size */
488 PLong maxBuff; /* Profiles buffer size */
489 PLong top; /* Current cursor in buffer */
490
492
493 Int numTurns; /* number of Y-turns in outline */
494
495 TPoint* arc; /* current Bezier arc pointer */
496
497 UShort bWidth; /* target bitmap width */
498 PByte bTarget; /* target bitmap buffer */
499 PByte gTarget; /* target pixmap buffer */
500
503
504 UShort num_Profs; /* current number of profiles */
505
506 Bool fresh; /* signals a fresh new profile which */
507 /* `start' field must be completed */
508 Bool joint; /* signals that the last arc ended */
509 /* exactly on a scanline. Allows */
510 /* removal of doublets */
511 PProfile cProfile; /* current profile */
512 PProfile fProfile; /* head of linked list of profiles */
513 PProfile gProfile; /* contour's first profile in case */
514 /* of impact */
515
516 TStates state; /* rendering state */
517
518 FT_Bitmap target; /* description of target bit/pixmap */
520
521 Long traceOfs; /* current offset in target bitmap */
522 Long traceG; /* current offset in target pixmap */
523
524 Short traceIncr; /* sweep's increment in target bitmap */
525
526 /* dispatch variables */
527
532
533 Byte dropOutControl; /* current drop_out control method */
534
535 Bool second_pass; /* indicates whether a horizontal pass */
536 /* should be performed to control */
537 /* drop-out accurately when calling */
538 /* Render_Glyph. */
539
540 TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
541
542 black_TBand band_stack[16]; /* band stack used for sub-banding */
543 Int band_top; /* band stack top */
544
545 };
546
547
548 typedef struct black_TRaster_
549 {
550 void* memory;
551
553
554#ifdef FT_STATIC_RASTER
555
556 static black_TWorker cur_ras;
557#define ras cur_ras
558
559#else /* !FT_STATIC_RASTER */
560
561#define ras (*worker)
562
563#endif /* !FT_STATIC_RASTER */
564
565
566 /*************************************************************************/
567 /*************************************************************************/
571 /*************************************************************************/
572 /*************************************************************************/
573
574
575 /*************************************************************************/
576 /* */
577 /* <Function> */
578 /* Set_High_Precision */
579 /* */
580 /* <Description> */
581 /* Set precision variables according to param flag. */
582 /* */
583 /* <Input> */
584 /* High :: Set to True for high precision (typically for ppem < 24), */
585 /* false otherwise. */
586 /* */
587 static void
589 {
590 /*
591 * `precision_step' is used in `Bezier_Up' to decide when to split a
592 * given y-monotonous Bezier arc that crosses a scanline before
593 * approximating it as a straight segment. The default value of 32 (for
594 * low accuracy) corresponds to
595 *
596 * 32 / 64 == 0.5 pixels,
597 *
598 * while for the high accuracy case we have
599 *
600 * 256 / (1 << 12) = 0.0625 pixels.
601 *
602 * `precision_jitter' is an epsilon threshold used in
603 * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
604 * decomposition (after all, we are working with approximations only);
605 * it avoids switching on additional pixels which would cause artifacts
606 * otherwise.
607 *
608 * The value of `precision_jitter' has been determined heuristically.
609 *
610 */
611
612 if ( High )
613 {
614 ras.precision_bits = 12;
615 ras.precision_step = 256;
616 ras.precision_jitter = 30;
617 }
618 else
619 {
620 ras.precision_bits = 6;
621 ras.precision_step = 32;
622 ras.precision_jitter = 2;
623 }
624
625 FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
626
627 ras.precision = 1 << ras.precision_bits;
628 ras.precision_half = ras.precision / 2;
629 ras.precision_shift = ras.precision_bits - Pixel_Bits;
630 }
631
632
633 /*************************************************************************/
634 /* */
635 /* <Function> */
636 /* New_Profile */
637 /* */
638 /* <Description> */
639 /* Create a new profile in the render pool. */
640 /* */
641 /* <Input> */
642 /* aState :: The state/orientation of the new profile. */
643 /* */
644 /* overshoot :: Whether the profile's unrounded start position */
645 /* differs by at least a half pixel. */
646 /* */
647 /* <Return> */
648 /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
649 /* profile. */
650 /* */
651 static Bool
653 Bool overshoot )
654 {
655 if ( !ras.fProfile )
656 {
657 ras.cProfile = (PProfile)ras.top;
658 ras.fProfile = ras.cProfile;
659 ras.top += AlignProfileSize;
660 }
661
662 if ( ras.top >= ras.maxBuff )
663 {
664 ras.error = FT_THROW( Overflow );
665 return FAILURE;
666 }
667
668 ras.cProfile->flags = 0;
669 ras.cProfile->start = 0;
670 ras.cProfile->height = 0;
671 ras.cProfile->offset = ras.top;
672 ras.cProfile->link = (PProfile)0;
673 ras.cProfile->next = (PProfile)0;
674 ras.cProfile->flags = ras.dropOutControl;
675
676 switch ( aState )
677 {
678 case Ascending_State:
679 ras.cProfile->flags |= Flow_Up;
680 if ( overshoot )
681 ras.cProfile->flags |= Overshoot_Bottom;
682
683 FT_TRACE6(( " new ascending profile = %p\n", ras.cProfile ));
684 break;
685
686 case Descending_State:
687 if ( overshoot )
688 ras.cProfile->flags |= Overshoot_Top;
689 FT_TRACE6(( " new descending profile = %p\n", ras.cProfile ));
690 break;
691
692 default:
693 FT_ERROR(( "New_Profile: invalid profile direction\n" ));
694 ras.error = FT_THROW( Invalid );
695 return FAILURE;
696 }
697
698 if ( !ras.gProfile )
699 ras.gProfile = ras.cProfile;
700
701 ras.state = aState;
702 ras.fresh = TRUE;
703 ras.joint = FALSE;
704
705 return SUCCESS;
706 }
707
708
709 /*************************************************************************/
710 /* */
711 /* <Function> */
712 /* End_Profile */
713 /* */
714 /* <Description> */
715 /* Finalize the current profile. */
716 /* */
717 /* <Input> */
718 /* overshoot :: Whether the profile's unrounded end position differs */
719 /* by at least a half pixel. */
720 /* */
721 /* <Return> */
722 /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
723 /* */
724 static Bool
726 {
727 Long h;
728
729
730 h = (Long)( ras.top - ras.cProfile->offset );
731
732 if ( h < 0 )
733 {
734 FT_ERROR(( "End_Profile: negative height encountered\n" ));
735 ras.error = FT_THROW( Neg_Height );
736 return FAILURE;
737 }
738
739 if ( h > 0 )
740 {
741 PProfile oldProfile;
742
743
744 FT_TRACE6(( " ending profile %p, start = %ld, height = %ld\n",
745 ras.cProfile, ras.cProfile->start, h ));
746
747 ras.cProfile->height = h;
748 if ( overshoot )
749 {
750 if ( ras.cProfile->flags & Flow_Up )
751 ras.cProfile->flags |= Overshoot_Top;
752 else
753 ras.cProfile->flags |= Overshoot_Bottom;
754 }
755
756 oldProfile = ras.cProfile;
757 ras.cProfile = (PProfile)ras.top;
758
759 ras.top += AlignProfileSize;
760
761 ras.cProfile->height = 0;
762 ras.cProfile->offset = ras.top;
763
764 oldProfile->next = ras.cProfile;
765 ras.num_Profs++;
766 }
767
768 if ( ras.top >= ras.maxBuff )
769 {
770 FT_TRACE1(( "overflow in End_Profile\n" ));
771 ras.error = FT_THROW( Overflow );
772 return FAILURE;
773 }
774
775 ras.joint = FALSE;
776
777 return SUCCESS;
778 }
779
780
781 /*************************************************************************/
782 /* */
783 /* <Function> */
784 /* Insert_Y_Turn */
785 /* */
786 /* <Description> */
787 /* Insert a salient into the sorted list placed on top of the render */
788 /* pool. */
789 /* */
790 /* <Input> */
791 /* New y scanline position. */
792 /* */
793 /* <Return> */
794 /* SUCCESS on success. FAILURE in case of overflow. */
795 /* */
796 static Bool
798 {
799 PLong y_turns;
800 Int n;
801
802
803 n = ras.numTurns - 1;
804 y_turns = ras.sizeBuff - ras.numTurns;
805
806 /* look for first y value that is <= */
807 while ( n >= 0 && y < y_turns[n] )
808 n--;
809
810 /* if it is <, simply insert it, ignore if == */
811 if ( n >= 0 && y > y_turns[n] )
812 do
813 {
814 Int y2 = (Int)y_turns[n];
815
816
817 y_turns[n] = y;
818 y = y2;
819 } while ( --n >= 0 );
820
821 if ( n < 0 )
822 {
823 ras.maxBuff--;
824 if ( ras.maxBuff <= ras.top )
825 {
826 ras.error = FT_THROW( Overflow );
827 return FAILURE;
828 }
829 ras.numTurns++;
830 ras.sizeBuff[-ras.numTurns] = y;
831 }
832
833 return SUCCESS;
834 }
835
836
837 /*************************************************************************/
838 /* */
839 /* <Function> */
840 /* Finalize_Profile_Table */
841 /* */
842 /* <Description> */
843 /* Adjust all links in the profiles list. */
844 /* */
845 /* <Return> */
846 /* SUCCESS on success. FAILURE in case of overflow. */
847 /* */
848 static Bool
850 {
851 UShort n;
852 PProfile p;
853
854
855 n = ras.num_Profs;
856 p = ras.fProfile;
857
858 if ( n > 1 && p )
859 {
860 do
861 {
862 Int bottom, top;
863
864
865 if ( n > 1 )
866 p->link = (PProfile)( p->offset + p->height );
867 else
868 p->link = NULL;
869
870 if ( p->flags & Flow_Up )
871 {
872 bottom = (Int)p->start;
873 top = (Int)( p->start + p->height - 1 );
874 }
875 else
876 {
877 bottom = (Int)( p->start - p->height + 1 );
878 top = (Int)p->start;
879 p->start = bottom;
880 p->offset += p->height - 1;
881 }
882
883 if ( Insert_Y_Turn( RAS_VARS bottom ) ||
884 Insert_Y_Turn( RAS_VARS top + 1 ) )
885 return FAILURE;
886
887 p = p->link;
888 } while ( --n );
889 }
890 else
891 ras.fProfile = NULL;
892
893 return SUCCESS;
894 }
895
896
897 /*************************************************************************/
898 /* */
899 /* <Function> */
900 /* Split_Conic */
901 /* */
902 /* <Description> */
903 /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */
904 /* stack. */
905 /* */
906 /* <Input> */
907 /* None (subdivided Bezier is taken from the top of the stack). */
908 /* */
909 /* <Note> */
910 /* This routine is the `beef' of this component. It is _the_ inner */
911 /* loop that should be optimized to hell to get the best performance. */
912 /* */
913 static void
915 {
916 Long a, b;
917
918
919 base[4].x = base[2].x;
920 b = base[1].x;
921 a = base[3].x = ( base[2].x + b ) / 2;
922 b = base[1].x = ( base[0].x + b ) / 2;
923 base[2].x = ( a + b ) / 2;
924
925 base[4].y = base[2].y;
926 b = base[1].y;
927 a = base[3].y = ( base[2].y + b ) / 2;
928 b = base[1].y = ( base[0].y + b ) / 2;
929 base[2].y = ( a + b ) / 2;
930
931 /* hand optimized. gcc doesn't seem to be too good at common */
932 /* expression substitution and instruction scheduling ;-) */
933 }
934
935
936 /*************************************************************************/
937 /* */
938 /* <Function> */
939 /* Split_Cubic */
940 /* */
941 /* <Description> */
942 /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */
943 /* Bezier stack. */
944 /* */
945 /* <Note> */
946 /* This routine is the `beef' of the component. It is one of _the_ */
947 /* inner loops that should be optimized like hell to get the best */
948 /* performance. */
949 /* */
950 static void
952 {
953 Long a, b, c, d;
954
955
956 base[6].x = base[3].x;
957 c = base[1].x;
958 d = base[2].x;
959 base[1].x = a = ( base[0].x + c + 1 ) >> 1;
960 base[5].x = b = ( base[3].x + d + 1 ) >> 1;
961 c = ( c + d + 1 ) >> 1;
962 base[2].x = a = ( a + c + 1 ) >> 1;
963 base[4].x = b = ( b + c + 1 ) >> 1;
964 base[3].x = ( a + b + 1 ) >> 1;
965
966 base[6].y = base[3].y;
967 c = base[1].y;
968 d = base[2].y;
969 base[1].y = a = ( base[0].y + c + 1 ) >> 1;
970 base[5].y = b = ( base[3].y + d + 1 ) >> 1;
971 c = ( c + d + 1 ) >> 1;
972 base[2].y = a = ( a + c + 1 ) >> 1;
973 base[4].y = b = ( b + c + 1 ) >> 1;
974 base[3].y = ( a + b + 1 ) >> 1;
975 }
976
977
978 /*************************************************************************/
979 /* */
980 /* <Function> */
981 /* Line_Up */
982 /* */
983 /* <Description> */
984 /* Compute the x-coordinates of an ascending line segment and store */
985 /* them in the render pool. */
986 /* */
987 /* <Input> */
988 /* x1 :: The x-coordinate of the segment's start point. */
989 /* */
990 /* y1 :: The y-coordinate of the segment's start point. */
991 /* */
992 /* x2 :: The x-coordinate of the segment's end point. */
993 /* */
994 /* y2 :: The y-coordinate of the segment's end point. */
995 /* */
996 /* miny :: A lower vertical clipping bound value. */
997 /* */
998 /* maxy :: An upper vertical clipping bound value. */
999 /* */
1000 /* <Return> */
1001 /* SUCCESS on success, FAILURE on render pool overflow. */
1002 /* */
1003 static Bool
1005 Long y1,
1006 Long x2,
1007 Long y2,
1008 Long miny,
1009 Long maxy )
1010 {
1011 Long Dx, Dy;
1012 Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
1013 Long Ix, Rx, Ax;
1014
1015 PLong top;
1016
1017
1018 Dx = x2 - x1;
1019 Dy = y2 - y1;
1020
1021 if ( Dy <= 0 || y2 < miny || y1 > maxy )
1022 return SUCCESS;
1023
1024 if ( y1 < miny )
1025 {
1026 /* Take care: miny-y1 can be a very large value; we use */
1027 /* a slow MulDiv function to avoid clipping bugs */
1028 x1 += SMulDiv( Dx, miny - y1, Dy );
1029 e1 = (Int)TRUNC( miny );
1030 f1 = 0;
1031 }
1032 else
1033 {
1034 e1 = (Int)TRUNC( y1 );
1035 f1 = (Int)FRAC( y1 );
1036 }
1037
1038 if ( y2 > maxy )
1039 {
1040 /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
1041 e2 = (Int)TRUNC( maxy );
1042 f2 = 0;
1043 }
1044 else
1045 {
1046 e2 = (Int)TRUNC( y2 );
1047 f2 = (Int)FRAC( y2 );
1048 }
1049
1050 if ( f1 > 0 )
1051 {
1052 if ( e1 == e2 )
1053 return SUCCESS;
1054 else
1055 {
1056 x1 += SMulDiv( Dx, ras.precision - f1, Dy );
1057 e1 += 1;
1058 }
1059 }
1060 else
1061 if ( ras.joint )
1062 {
1063 ras.top--;
1064 ras.joint = FALSE;
1065 }
1066
1067 ras.joint = (char)( f2 == 0 );
1068
1069 if ( ras.fresh )
1070 {
1071 ras.cProfile->start = e1;
1072 ras.fresh = FALSE;
1073 }
1074
1075 size = e2 - e1 + 1;
1076 if ( ras.top + size >= ras.maxBuff )
1077 {
1078 ras.error = FT_THROW( Overflow );
1079 return FAILURE;
1080 }
1081
1082 if ( Dx > 0 )
1083 {
1084 Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
1085 Rx = ( ras.precision * Dx ) % Dy;
1086 Dx = 1;
1087 }
1088 else
1089 {
1090 Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
1091 Rx = ( ras.precision * -Dx ) % Dy;
1092 Dx = -1;
1093 }
1094
1095 Ax = -Dy;
1096 top = ras.top;
1097
1098 while ( size > 0 )
1099 {
1100 *top++ = x1;
1101
1102 x1 += Ix;
1103 Ax += Rx;
1104 if ( Ax >= 0 )
1105 {
1106 Ax -= Dy;
1107 x1 += Dx;
1108 }
1109 size--;
1110 }
1111
1112 ras.top = top;
1113 return SUCCESS;
1114 }
1115
1116
1117 /*************************************************************************/
1118 /* */
1119 /* <Function> */
1120 /* Line_Down */
1121 /* */
1122 /* <Description> */
1123 /* Compute the x-coordinates of an descending line segment and store */
1124 /* them in the render pool. */
1125 /* */
1126 /* <Input> */
1127 /* x1 :: The x-coordinate of the segment's start point. */
1128 /* */
1129 /* y1 :: The y-coordinate of the segment's start point. */
1130 /* */
1131 /* x2 :: The x-coordinate of the segment's end point. */
1132 /* */
1133 /* y2 :: The y-coordinate of the segment's end point. */
1134 /* */
1135 /* miny :: A lower vertical clipping bound value. */
1136 /* */
1137 /* maxy :: An upper vertical clipping bound value. */
1138 /* */
1139 /* <Return> */
1140 /* SUCCESS on success, FAILURE on render pool overflow. */
1141 /* */
1142 static Bool
1144 Long y1,
1145 Long x2,
1146 Long y2,
1147 Long miny,
1148 Long maxy )
1149 {
1150 Bool result, fresh;
1151
1152
1153 fresh = ras.fresh;
1154
1155 result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1156
1157 if ( fresh && !ras.fresh )
1158 ras.cProfile->start = -ras.cProfile->start;
1159
1160 return result;
1161 }
1162
1163
1164 /* A function type describing the functions used to split Bezier arcs */
1165 typedef void (*TSplitter)( TPoint* base );
1166
1167
1168 /*************************************************************************/
1169 /* */
1170 /* <Function> */
1171 /* Bezier_Up */
1172 /* */
1173 /* <Description> */
1174 /* Compute the x-coordinates of an ascending Bezier arc and store */
1175 /* them in the render pool. */
1176 /* */
1177 /* <Input> */
1178 /* degree :: The degree of the Bezier arc (either 2 or 3). */
1179 /* */
1180 /* splitter :: The function to split Bezier arcs. */
1181 /* */
1182 /* miny :: A lower vertical clipping bound value. */
1183 /* */
1184 /* maxy :: An upper vertical clipping bound value. */
1185 /* */
1186 /* <Return> */
1187 /* SUCCESS on success, FAILURE on render pool overflow. */
1188 /* */
1189 static Bool
1191 TSplitter splitter,
1192 Long miny,
1193 Long maxy )
1194 {
1195 Long y1, y2, e, e2, e0;
1196 Short f1;
1197
1198 TPoint* arc;
1199 TPoint* start_arc;
1200
1201 PLong top;
1202
1203
1204 arc = ras.arc;
1205 y1 = arc[degree].y;
1206 y2 = arc[0].y;
1207 top = ras.top;
1208
1209 if ( y2 < miny || y1 > maxy )
1210 goto Fin;
1211
1212 e2 = FLOOR( y2 );
1213
1214 if ( e2 > maxy )
1215 e2 = maxy;
1216
1217 e0 = miny;
1218
1219 if ( y1 < miny )
1220 e = miny;
1221 else
1222 {
1223 e = CEILING( y1 );
1224 f1 = (Short)( FRAC( y1 ) );
1225 e0 = e;
1226
1227 if ( f1 == 0 )
1228 {
1229 if ( ras.joint )
1230 {
1231 top--;
1232 ras.joint = FALSE;
1233 }
1234
1235 *top++ = arc[degree].x;
1236
1237 e += ras.precision;
1238 }
1239 }
1240
1241 if ( ras.fresh )
1242 {
1243 ras.cProfile->start = TRUNC( e0 );
1244 ras.fresh = FALSE;
1245 }
1246
1247 if ( e2 < e )
1248 goto Fin;
1249
1250 if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1251 {
1252 ras.top = top;
1253 ras.error = FT_THROW( Overflow );
1254 return FAILURE;
1255 }
1256
1257 start_arc = arc;
1258
1259 do
1260 {
1261 ras.joint = FALSE;
1262
1263 y2 = arc[0].y;
1264
1265 if ( y2 > e )
1266 {
1267 y1 = arc[degree].y;
1268 if ( y2 - y1 >= ras.precision_step )
1269 {
1270 splitter( arc );
1271 arc += degree;
1272 }
1273 else
1274 {
1275 *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
1276 e - y1, y2 - y1 );
1277 arc -= degree;
1278 e += ras.precision;
1279 }
1280 }
1281 else
1282 {
1283 if ( y2 == e )
1284 {
1285 ras.joint = TRUE;
1286 *top++ = arc[0].x;
1287
1288 e += ras.precision;
1289 }
1290 arc -= degree;
1291 }
1292 } while ( arc >= start_arc && e <= e2 );
1293
1294 Fin:
1295 ras.top = top;
1296 ras.arc -= degree;
1297 return SUCCESS;
1298 }
1299
1300
1301 /*************************************************************************/
1302 /* */
1303 /* <Function> */
1304 /* Bezier_Down */
1305 /* */
1306 /* <Description> */
1307 /* Compute the x-coordinates of an descending Bezier arc and store */
1308 /* them in the render pool. */
1309 /* */
1310 /* <Input> */
1311 /* degree :: The degree of the Bezier arc (either 2 or 3). */
1312 /* */
1313 /* splitter :: The function to split Bezier arcs. */
1314 /* */
1315 /* miny :: A lower vertical clipping bound value. */
1316 /* */
1317 /* maxy :: An upper vertical clipping bound value. */
1318 /* */
1319 /* <Return> */
1320 /* SUCCESS on success, FAILURE on render pool overflow. */
1321 /* */
1322 static Bool
1324 TSplitter splitter,
1325 Long miny,
1326 Long maxy )
1327 {
1328 TPoint* arc = ras.arc;
1329 Bool result, fresh;
1330
1331
1332 arc[0].y = -arc[0].y;
1333 arc[1].y = -arc[1].y;
1334 arc[2].y = -arc[2].y;
1335 if ( degree > 2 )
1336 arc[3].y = -arc[3].y;
1337
1338 fresh = ras.fresh;
1339
1340 result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1341
1342 if ( fresh && !ras.fresh )
1343 ras.cProfile->start = -ras.cProfile->start;
1344
1345 arc[0].y = -arc[0].y;
1346 return result;
1347 }
1348
1349
1350 /*************************************************************************/
1351 /* */
1352 /* <Function> */
1353 /* Line_To */
1354 /* */
1355 /* <Description> */
1356 /* Inject a new line segment and adjust the Profiles list. */
1357 /* */
1358 /* <Input> */
1359 /* x :: The x-coordinate of the segment's end point (its start point */
1360 /* is stored in `lastX'). */
1361 /* */
1362 /* y :: The y-coordinate of the segment's end point (its start point */
1363 /* is stored in `lastY'). */
1364 /* */
1365 /* <Return> */
1366 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1367 /* profile. */
1368 /* */
1369 static Bool
1371 Long y )
1372 {
1373 /* First, detect a change of direction */
1374
1375 switch ( ras.state )
1376 {
1377 case Unknown_State:
1378 if ( y > ras.lastY )
1379 {
1381 IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1382 return FAILURE;
1383 }
1384 else
1385 {
1386 if ( y < ras.lastY )
1388 IS_TOP_OVERSHOOT( ras.lastY ) ) )
1389 return FAILURE;
1390 }
1391 break;
1392
1393 case Ascending_State:
1394 if ( y < ras.lastY )
1395 {
1396 if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
1398 IS_TOP_OVERSHOOT( ras.lastY ) ) )
1399 return FAILURE;
1400 }
1401 break;
1402
1403 case Descending_State:
1404 if ( y > ras.lastY )
1405 {
1406 if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
1408 IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1409 return FAILURE;
1410 }
1411 break;
1412
1413 default:
1414 ;
1415 }
1416
1417 /* Then compute the lines */
1418
1419 switch ( ras.state )
1420 {
1421 case Ascending_State:
1422 if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
1423 x, y, ras.minY, ras.maxY ) )
1424 return FAILURE;
1425 break;
1426
1427 case Descending_State:
1428 if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
1429 x, y, ras.minY, ras.maxY ) )
1430 return FAILURE;
1431 break;
1432
1433 default:
1434 ;
1435 }
1436
1437 ras.lastX = x;
1438 ras.lastY = y;
1439
1440 return SUCCESS;
1441 }
1442
1443
1444 /*************************************************************************/
1445 /* */
1446 /* <Function> */
1447 /* Conic_To */
1448 /* */
1449 /* <Description> */
1450 /* Inject a new conic arc and adjust the profile list. */
1451 /* */
1452 /* <Input> */
1453 /* cx :: The x-coordinate of the arc's new control point. */
1454 /* */
1455 /* cy :: The y-coordinate of the arc's new control point. */
1456 /* */
1457 /* x :: The x-coordinate of the arc's end point (its start point is */
1458 /* stored in `lastX'). */
1459 /* */
1460 /* y :: The y-coordinate of the arc's end point (its start point is */
1461 /* stored in `lastY'). */
1462 /* */
1463 /* <Return> */
1464 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1465 /* profile. */
1466 /* */
1467 static Bool
1469 Long cy,
1470 Long x,
1471 Long y )
1472 {
1473 Long y1, y2, y3, x3, ymin, ymax;
1474 TStates state_bez;
1475
1476
1477 ras.arc = ras.arcs;
1478 ras.arc[2].x = ras.lastX;
1479 ras.arc[2].y = ras.lastY;
1480 ras.arc[1].x = cx;
1481 ras.arc[1].y = cy;
1482 ras.arc[0].x = x;
1483 ras.arc[0].y = y;
1484
1485 do
1486 {
1487 y1 = ras.arc[2].y;
1488 y2 = ras.arc[1].y;
1489 y3 = ras.arc[0].y;
1490 x3 = ras.arc[0].x;
1491
1492 /* first, categorize the Bezier arc */
1493
1494 if ( y1 <= y3 )
1495 {
1496 ymin = y1;
1497 ymax = y3;
1498 }
1499 else
1500 {
1501 ymin = y3;
1502 ymax = y1;
1503 }
1504
1505 if ( y2 < ymin || y2 > ymax )
1506 {
1507 /* this arc has no given direction, split it! */
1508 Split_Conic( ras.arc );
1509 ras.arc += 2;
1510 }
1511 else if ( y1 == y3 )
1512 {
1513 /* this arc is flat, ignore it and pop it from the Bezier stack */
1514 ras.arc -= 2;
1515 }
1516 else
1517 {
1518 /* the arc is y-monotonous, either ascending or descending */
1519 /* detect a change of direction */
1520 state_bez = y1 < y3 ? Ascending_State : Descending_State;
1521 if ( ras.state != state_bez )
1522 {
1523 Bool o = ( state_bez == Ascending_State )
1525 : IS_TOP_OVERSHOOT( y1 );
1526
1527
1528 /* finalize current profile if any */
1529 if ( ras.state != Unknown_State &&
1530 End_Profile( RAS_VARS o ) )
1531 goto Fail;
1532
1533 /* create a new profile */
1534 if ( New_Profile( RAS_VARS state_bez, o ) )
1535 goto Fail;
1536 }
1537
1538 /* now call the appropriate routine */
1539 if ( state_bez == Ascending_State )
1540 {
1541 if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1542 goto Fail;
1543 }
1544 else
1545 if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1546 goto Fail;
1547 }
1548
1549 } while ( ras.arc >= ras.arcs );
1550
1551 ras.lastX = x3;
1552 ras.lastY = y3;
1553
1554 return SUCCESS;
1555
1556 Fail:
1557 return FAILURE;
1558 }
1559
1560
1561 /*************************************************************************/
1562 /* */
1563 /* <Function> */
1564 /* Cubic_To */
1565 /* */
1566 /* <Description> */
1567 /* Inject a new cubic arc and adjust the profile list. */
1568 /* */
1569 /* <Input> */
1570 /* cx1 :: The x-coordinate of the arc's first new control point. */
1571 /* */
1572 /* cy1 :: The y-coordinate of the arc's first new control point. */
1573 /* */
1574 /* cx2 :: The x-coordinate of the arc's second new control point. */
1575 /* */
1576 /* cy2 :: The y-coordinate of the arc's second new control point. */
1577 /* */
1578 /* x :: The x-coordinate of the arc's end point (its start point is */
1579 /* stored in `lastX'). */
1580 /* */
1581 /* y :: The y-coordinate of the arc's end point (its start point is */
1582 /* stored in `lastY'). */
1583 /* */
1584 /* <Return> */
1585 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1586 /* profile. */
1587 /* */
1588 static Bool
1590 Long cy1,
1591 Long cx2,
1592 Long cy2,
1593 Long x,
1594 Long y )
1595 {
1596 Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1597 TStates state_bez;
1598
1599
1600 ras.arc = ras.arcs;
1601 ras.arc[3].x = ras.lastX;
1602 ras.arc[3].y = ras.lastY;
1603 ras.arc[2].x = cx1;
1604 ras.arc[2].y = cy1;
1605 ras.arc[1].x = cx2;
1606 ras.arc[1].y = cy2;
1607 ras.arc[0].x = x;
1608 ras.arc[0].y = y;
1609
1610 do
1611 {
1612 y1 = ras.arc[3].y;
1613 y2 = ras.arc[2].y;
1614 y3 = ras.arc[1].y;
1615 y4 = ras.arc[0].y;
1616 x4 = ras.arc[0].x;
1617
1618 /* first, categorize the Bezier arc */
1619
1620 if ( y1 <= y4 )
1621 {
1622 ymin1 = y1;
1623 ymax1 = y4;
1624 }
1625 else
1626 {
1627 ymin1 = y4;
1628 ymax1 = y1;
1629 }
1630
1631 if ( y2 <= y3 )
1632 {
1633 ymin2 = y2;
1634 ymax2 = y3;
1635 }
1636 else
1637 {
1638 ymin2 = y3;
1639 ymax2 = y2;
1640 }
1641
1642 if ( ymin2 < ymin1 || ymax2 > ymax1 )
1643 {
1644 /* this arc has no given direction, split it! */
1645 Split_Cubic( ras.arc );
1646 ras.arc += 3;
1647 }
1648 else if ( y1 == y4 )
1649 {
1650 /* this arc is flat, ignore it and pop it from the Bezier stack */
1651 ras.arc -= 3;
1652 }
1653 else
1654 {
1655 state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1656
1657 /* detect a change of direction */
1658 if ( ras.state != state_bez )
1659 {
1660 Bool o = ( state_bez == Ascending_State )
1662 : IS_TOP_OVERSHOOT( y1 );
1663
1664
1665 /* finalize current profile if any */
1666 if ( ras.state != Unknown_State &&
1667 End_Profile( RAS_VARS o ) )
1668 goto Fail;
1669
1670 if ( New_Profile( RAS_VARS state_bez, o ) )
1671 goto Fail;
1672 }
1673
1674 /* compute intersections */
1675 if ( state_bez == Ascending_State )
1676 {
1677 if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1678 goto Fail;
1679 }
1680 else
1681 if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1682 goto Fail;
1683 }
1684
1685 } while ( ras.arc >= ras.arcs );
1686
1687 ras.lastX = x4;
1688 ras.lastY = y4;
1689
1690 return SUCCESS;
1691
1692 Fail:
1693 return FAILURE;
1694 }
1695
1696
1697#undef SWAP_
1698#define SWAP_( x, y ) do \
1699 { \
1700 Long swap = x; \
1701 \
1702 \
1703 x = y; \
1704 y = swap; \
1705 } while ( 0 )
1706
1707
1708 /*************************************************************************/
1709 /* */
1710 /* <Function> */
1711 /* Decompose_Curve */
1712 /* */
1713 /* <Description> */
1714 /* Scan the outline arrays in order to emit individual segments and */
1715 /* Beziers by calling Line_To() and Bezier_To(). It handles all */
1716 /* weird cases, like when the first point is off the curve, or when */
1717 /* there are simply no `on' points in the contour! */
1718 /* */
1719 /* <Input> */
1720 /* first :: The index of the first point in the contour. */
1721 /* */
1722 /* last :: The index of the last point in the contour. */
1723 /* */
1724 /* flipped :: If set, flip the direction of the curve. */
1725 /* */
1726 /* <Return> */
1727 /* SUCCESS on success, FAILURE on error. */
1728 /* */
1729 static Bool
1731 UShort last,
1732 Int flipped )
1733 {
1734 FT_Vector v_last;
1735 FT_Vector v_control;
1736 FT_Vector v_start;
1737
1741 char* tags;
1742
1743 UInt tag; /* current point's state */
1744
1745
1746 points = ras.outline.points;
1747 limit = points + last;
1748
1749 v_start.x = SCALED( points[first].x );
1750 v_start.y = SCALED( points[first].y );
1751 v_last.x = SCALED( points[last].x );
1752 v_last.y = SCALED( points[last].y );
1753
1754 if ( flipped )
1755 {
1756 SWAP_( v_start.x, v_start.y );
1757 SWAP_( v_last.x, v_last.y );
1758 }
1759
1760 v_control = v_start;
1761
1762 point = points + first;
1763 tags = ras.outline.tags + first;
1764
1765 /* set scan mode if necessary */
1767 ras.dropOutControl = (Byte)tags[0] >> 5;
1768
1769 tag = FT_CURVE_TAG( tags[0] );
1770
1771 /* A contour cannot start with a cubic control point! */
1772 if ( tag == FT_CURVE_TAG_CUBIC )
1773 goto Invalid_Outline;
1774
1775 /* check first point to determine origin */
1776 if ( tag == FT_CURVE_TAG_CONIC )
1777 {
1778 /* first point is conic control. Yes, this happens. */
1779 if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1780 {
1781 /* start at last point if it is on the curve */
1782 v_start = v_last;
1783 limit--;
1784 }
1785 else
1786 {
1787 /* if both first and last points are conic, */
1788 /* start at their middle and record its position */
1789 /* for closure */
1790 v_start.x = ( v_start.x + v_last.x ) / 2;
1791 v_start.y = ( v_start.y + v_last.y ) / 2;
1792
1793 /* v_last = v_start; */
1794 }
1795 point--;
1796 tags--;
1797 }
1798
1799 ras.lastX = v_start.x;
1800 ras.lastY = v_start.y;
1801
1802 while ( point < limit )
1803 {
1804 point++;
1805 tags++;
1806
1807 tag = FT_CURVE_TAG( tags[0] );
1808
1809 switch ( tag )
1810 {
1811 case FT_CURVE_TAG_ON: /* emit a single line_to */
1812 {
1813 Long x, y;
1814
1815
1816 x = SCALED( point->x );
1817 y = SCALED( point->y );
1818 if ( flipped )
1819 SWAP_( x, y );
1820
1821 if ( Line_To( RAS_VARS x, y ) )
1822 goto Fail;
1823 continue;
1824 }
1825
1826 case FT_CURVE_TAG_CONIC: /* consume conic arcs */
1827 v_control.x = SCALED( point[0].x );
1828 v_control.y = SCALED( point[0].y );
1829
1830 if ( flipped )
1831 SWAP_( v_control.x, v_control.y );
1832
1833 Do_Conic:
1834 if ( point < limit )
1835 {
1836 FT_Vector v_middle;
1837 Long x, y;
1838
1839
1840 point++;
1841 tags++;
1842 tag = FT_CURVE_TAG( tags[0] );
1843
1844 x = SCALED( point[0].x );
1845 y = SCALED( point[0].y );
1846
1847 if ( flipped )
1848 SWAP_( x, y );
1849
1850 if ( tag == FT_CURVE_TAG_ON )
1851 {
1852 if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1853 goto Fail;
1854 continue;
1855 }
1856
1857 if ( tag != FT_CURVE_TAG_CONIC )
1858 goto Invalid_Outline;
1859
1860 v_middle.x = ( v_control.x + x ) / 2;
1861 v_middle.y = ( v_control.y + y ) / 2;
1862
1863 if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1864 v_middle.x, v_middle.y ) )
1865 goto Fail;
1866
1867 v_control.x = x;
1868 v_control.y = y;
1869
1870 goto Do_Conic;
1871 }
1872
1873 if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1874 v_start.x, v_start.y ) )
1875 goto Fail;
1876
1877 goto Close;
1878
1879 default: /* FT_CURVE_TAG_CUBIC */
1880 {
1881 Long x1, y1, x2, y2, x3, y3;
1882
1883
1884 if ( point + 1 > limit ||
1886 goto Invalid_Outline;
1887
1888 point += 2;
1889 tags += 2;
1890
1891 x1 = SCALED( point[-2].x );
1892 y1 = SCALED( point[-2].y );
1893 x2 = SCALED( point[-1].x );
1894 y2 = SCALED( point[-1].y );
1895
1896 if ( flipped )
1897 {
1898 SWAP_( x1, y1 );
1899 SWAP_( x2, y2 );
1900 }
1901
1902 if ( point <= limit )
1903 {
1904 x3 = SCALED( point[0].x );
1905 y3 = SCALED( point[0].y );
1906
1907 if ( flipped )
1908 SWAP_( x3, y3 );
1909
1910 if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1911 goto Fail;
1912 continue;
1913 }
1914
1915 if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1916 goto Fail;
1917 goto Close;
1918 }
1919 }
1920 }
1921
1922 /* close the contour with a line segment */
1923 if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1924 goto Fail;
1925
1926 Close:
1927 return SUCCESS;
1928
1929 Invalid_Outline:
1930 ras.error = FT_THROW( Invalid );
1931
1932 Fail:
1933 return FAILURE;
1934 }
1935
1936
1937 /*************************************************************************/
1938 /* */
1939 /* <Function> */
1940 /* Convert_Glyph */
1941 /* */
1942 /* <Description> */
1943 /* Convert a glyph into a series of segments and arcs and make a */
1944 /* profiles list with them. */
1945 /* */
1946 /* <Input> */
1947 /* flipped :: If set, flip the direction of curve. */
1948 /* */
1949 /* <Return> */
1950 /* SUCCESS on success, FAILURE if any error was encountered during */
1951 /* rendering. */
1952 /* */
1953 static Bool
1955 {
1956 Int i;
1957 UInt start;
1958
1959
1960 ras.fProfile = NULL;
1961 ras.joint = FALSE;
1962 ras.fresh = FALSE;
1963
1964 ras.maxBuff = ras.sizeBuff - AlignProfileSize;
1965
1966 ras.numTurns = 0;
1967
1968 ras.cProfile = (PProfile)ras.top;
1969 ras.cProfile->offset = ras.top;
1970 ras.num_Profs = 0;
1971
1972 start = 0;
1973
1974 for ( i = 0; i < ras.outline.n_contours; i++ )
1975 {
1976 PProfile lastProfile;
1977 Bool o;
1978
1979
1980 ras.state = Unknown_State;
1981 ras.gProfile = NULL;
1982
1984 (UShort)ras.outline.contours[i],
1985 flipped ) )
1986 return FAILURE;
1987
1988 start = (UShort)ras.outline.contours[i] + 1;
1989
1990 /* we must now check whether the extreme arcs join or not */
1991 if ( FRAC( ras.lastY ) == 0 &&
1992 ras.lastY >= ras.minY &&
1993 ras.lastY <= ras.maxY )
1994 if ( ras.gProfile &&
1995 ( ras.gProfile->flags & Flow_Up ) ==
1996 ( ras.cProfile->flags & Flow_Up ) )
1997 ras.top--;
1998 /* Note that ras.gProfile can be nil if the contour was too small */
1999 /* to be drawn. */
2000
2001 lastProfile = ras.cProfile;
2002 if ( ras.top != ras.cProfile->offset &&
2003 ( ras.cProfile->flags & Flow_Up ) )
2004 o = IS_TOP_OVERSHOOT( ras.lastY );
2005 else
2006 o = IS_BOTTOM_OVERSHOOT( ras.lastY );
2007 if ( End_Profile( RAS_VARS o ) )
2008 return FAILURE;
2009
2010 /* close the `next profile in contour' linked list */
2011 if ( ras.gProfile )
2012 lastProfile->next = ras.gProfile;
2013 }
2014
2016 return FAILURE;
2017
2018 return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
2019 }
2020
2021
2022 /*************************************************************************/
2023 /*************************************************************************/
2027 /*************************************************************************/
2028 /*************************************************************************/
2029
2030
2031 /*************************************************************************/
2032 /* */
2033 /* Init_Linked */
2034 /* */
2035 /* Initializes an empty linked list. */
2036 /* */
2037 static void
2039 {
2040 *l = NULL;
2041 }
2042
2043
2044 /*************************************************************************/
2045 /* */
2046 /* InsNew */
2047 /* */
2048 /* Inserts a new profile in a linked list. */
2049 /* */
2050 static void
2053 {
2054 PProfile *old, current;
2055 Long x;
2056
2057
2058 old = list;
2059 current = *old;
2060 x = profile->X;
2061
2062 while ( current )
2063 {
2064 if ( x < current->X )
2065 break;
2066 old = &current->link;
2067 current = *old;
2068 }
2069
2070 profile->link = current;
2071 *old = profile;
2072 }
2073
2074
2075 /*************************************************************************/
2076 /* */
2077 /* DelOld */
2078 /* */
2079 /* Removes an old profile from a linked list. */
2080 /* */
2081 static void
2084 {
2085 PProfile *old, current;
2086
2087
2088 old = list;
2089 current = *old;
2090
2091 while ( current )
2092 {
2093 if ( current == profile )
2094 {
2095 *old = current->link;
2096 return;
2097 }
2098
2099 old = &current->link;
2100 current = *old;
2101 }
2102
2103 /* we should never get there, unless the profile was not part of */
2104 /* the list. */
2105 }
2106
2107
2108 /*************************************************************************/
2109 /* */
2110 /* Sort */
2111 /* */
2112 /* Sorts a trace list. In 95%, the list is already sorted. We need */
2113 /* an algorithm which is fast in this case. Bubble sort is enough */
2114 /* and simple. */
2115 /* */
2116 static void
2118 {
2119 PProfile *old, current, next;
2120
2121
2122 /* First, set the new X coordinate of each profile */
2123 current = *list;
2124 while ( current )
2125 {
2126 current->X = *current->offset;
2127 current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
2128 current->height--;
2129 current = current->link;
2130 }
2131
2132 /* Then sort them */
2133 old = list;
2134 current = *old;
2135
2136 if ( !current )
2137 return;
2138
2139 next = current->link;
2140
2141 while ( next )
2142 {
2143 if ( current->X <= next->X )
2144 {
2145 old = &current->link;
2146 current = *old;
2147
2148 if ( !current )
2149 return;
2150 }
2151 else
2152 {
2153 *old = next;
2154 current->link = next->link;
2155 next->link = current;
2156
2157 old = list;
2158 current = *old;
2159 }
2160
2161 next = current->link;
2162 }
2163 }
2164
2165
2166 /*************************************************************************/
2167 /* */
2168 /* Vertical Sweep Procedure Set */
2169 /* */
2170 /* These four routines are used during the vertical black/white sweep */
2171 /* phase by the generic Draw_Sweep() function. */
2172 /* */
2173 /*************************************************************************/
2174
2175 static void
2177 Short* max )
2178 {
2179 Long pitch = ras.target.pitch;
2180
2181 FT_UNUSED( max );
2182
2183
2184 ras.traceIncr = (Short)-pitch;
2185 ras.traceOfs = -*min * pitch;
2186 if ( pitch > 0 )
2187 ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
2188 }
2189
2190
2191 static void
2193 FT_F26Dot6 x1,
2194 FT_F26Dot6 x2,
2195 PProfile left,
2196 PProfile right )
2197 {
2198 Long e1, e2;
2199 Byte* target;
2200
2201 Int dropOutControl = left->flags & 7;
2202
2203 FT_UNUSED( y );
2204 FT_UNUSED( left );
2205 FT_UNUSED( right );
2206
2207
2208 /* in high-precision mode, we need 12 digits after the comma to */
2209 /* represent multiples of 1/(1<<12) = 1/4096 */
2210 FT_TRACE7(( " y=%d x=[%.12f;%.12f], drop-out=%d",
2211 y,
2212 x1 / (double)ras.precision,
2213 x2 / (double)ras.precision,
2214 dropOutControl ));
2215
2216 /* Drop-out control */
2217
2218 e1 = TRUNC( CEILING( x1 ) );
2219
2220 if ( dropOutControl != 2 &&
2221 x2 - x1 - ras.precision <= ras.precision_jitter )
2222 e2 = e1;
2223 else
2224 e2 = TRUNC( FLOOR( x2 ) );
2225
2226 if ( e2 >= 0 && e1 < ras.bWidth )
2227 {
2228 Int c1, c2;
2229 Byte f1, f2;
2230
2231
2232 if ( e1 < 0 )
2233 e1 = 0;
2234 if ( e2 >= ras.bWidth )
2235 e2 = ras.bWidth - 1;
2236
2237 FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
2238
2239 c1 = (Short)( e1 >> 3 );
2240 c2 = (Short)( e2 >> 3 );
2241
2242 f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
2243 f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2244
2245 target = ras.bTarget + ras.traceOfs + c1;
2246 c2 -= c1;
2247
2248 if ( c2 > 0 )
2249 {
2250 target[0] |= f1;
2251
2252 /* memset() is slower than the following code on many platforms. */
2253 /* This is due to the fact that, in the vast majority of cases, */
2254 /* the span length in bytes is relatively small. */
2255 c2--;
2256 while ( c2 > 0 )
2257 {
2258 *(++target) = 0xFF;
2259 c2--;
2260 }
2261 target[1] |= f2;
2262 }
2263 else
2264 *target |= ( f1 & f2 );
2265 }
2266
2267 FT_TRACE7(( "\n" ));
2268 }
2269
2270
2271 static void
2273 FT_F26Dot6 x1,
2274 FT_F26Dot6 x2,
2275 PProfile left,
2276 PProfile right )
2277 {
2278 Long e1, e2, pxl;
2279 Short c1, f1;
2280
2281
2282 FT_TRACE7(( " y=%d x=[%.12f;%.12f]",
2283 y,
2284 x1 / (double)ras.precision,
2285 x2 / (double)ras.precision ));
2286
2287 /* Drop-out control */
2288
2289 /* e2 x2 x1 e1 */
2290 /* */
2291 /* ^ | */
2292 /* | | */
2293 /* +-------------+---------------------+------------+ */
2294 /* | | */
2295 /* | v */
2296 /* */
2297 /* pixel contour contour pixel */
2298 /* center center */
2299
2300 /* drop-out mode scan conversion rules (as defined in OpenType) */
2301 /* --------------------------------------------------------------- */
2302 /* 0 1, 2, 3 */
2303 /* 1 1, 2, 4 */
2304 /* 2 1, 2 */
2305 /* 3 same as mode 2 */
2306 /* 4 1, 2, 5 */
2307 /* 5 1, 2, 6 */
2308 /* 6, 7 same as mode 2 */
2309
2310 e1 = CEILING( x1 );
2311 e2 = FLOOR ( x2 );
2312 pxl = e1;
2313
2314 if ( e1 > e2 )
2315 {
2316 Int dropOutControl = left->flags & 7;
2317
2318
2319 FT_TRACE7(( ", drop-out=%d", dropOutControl ));
2320
2321 if ( e1 == e2 + ras.precision )
2322 {
2323 switch ( dropOutControl )
2324 {
2325 case 0: /* simple drop-outs including stubs */
2326 pxl = e2;
2327 break;
2328
2329 case 4: /* smart drop-outs including stubs */
2330 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2331 break;
2332
2333 case 1: /* simple drop-outs excluding stubs */
2334 case 5: /* smart drop-outs excluding stubs */
2335
2336 /* Drop-out Control Rules #4 and #6 */
2337
2338 /* The specification neither provides an exact definition */
2339 /* of a `stub' nor gives exact rules to exclude them. */
2340 /* */
2341 /* Here the constraints we use to recognize a stub. */
2342 /* */
2343 /* upper stub: */
2344 /* */
2345 /* - P_Left and P_Right are in the same contour */
2346 /* - P_Right is the successor of P_Left in that contour */
2347 /* - y is the top of P_Left and P_Right */
2348 /* */
2349 /* lower stub: */
2350 /* */
2351 /* - P_Left and P_Right are in the same contour */
2352 /* - P_Left is the successor of P_Right in that contour */
2353 /* - y is the bottom of P_Left */
2354 /* */
2355 /* We draw a stub if the following constraints are met. */
2356 /* */
2357 /* - for an upper or lower stub, there is top or bottom */
2358 /* overshoot, respectively */
2359 /* - the covered interval is greater or equal to a half */
2360 /* pixel */
2361
2362 /* upper stub test */
2363 if ( left->next == right &&
2364 left->height <= 0 &&
2365 !( left->flags & Overshoot_Top &&
2366 x2 - x1 >= ras.precision_half ) )
2367 goto Exit;
2368
2369 /* lower stub test */
2370 if ( right->next == left &&
2371 left->start == y &&
2372 !( left->flags & Overshoot_Bottom &&
2373 x2 - x1 >= ras.precision_half ) )
2374 goto Exit;
2375
2376 if ( dropOutControl == 1 )
2377 pxl = e2;
2378 else
2379 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2380 break;
2381
2382 default: /* modes 2, 3, 6, 7 */
2383 goto Exit; /* no drop-out control */
2384 }
2385
2386 /* undocumented but confirmed: If the drop-out would result in a */
2387 /* pixel outside of the bounding box, use the pixel inside of the */
2388 /* bounding box instead */
2389 if ( pxl < 0 )
2390 pxl = e1;
2391 else if ( TRUNC( pxl ) >= ras.bWidth )
2392 pxl = e2;
2393
2394 /* check that the other pixel isn't set */
2395 e1 = ( pxl == e1 ) ? e2 : e1;
2396
2397 e1 = TRUNC( e1 );
2398
2399 c1 = (Short)( e1 >> 3 );
2400 f1 = (Short)( e1 & 7 );
2401
2402 if ( e1 >= 0 && e1 < ras.bWidth &&
2403 ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
2404 goto Exit;
2405 }
2406 else
2407 goto Exit;
2408 }
2409
2410 e1 = TRUNC( pxl );
2411
2412 if ( e1 >= 0 && e1 < ras.bWidth )
2413 {
2414 FT_TRACE7(( " -> x=%d (drop-out)", e1 ));
2415
2416 c1 = (Short)( e1 >> 3 );
2417 f1 = (Short)( e1 & 7 );
2418
2419 ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2420 }
2421
2422 Exit:
2423 FT_TRACE7(( "\n" ));
2424 }
2425
2426
2427 static void
2429 {
2430 ras.traceOfs += ras.traceIncr;
2431 }
2432
2433
2434 /***********************************************************************/
2435 /* */
2436 /* Horizontal Sweep Procedure Set */
2437 /* */
2438 /* These four routines are used during the horizontal black/white */
2439 /* sweep phase by the generic Draw_Sweep() function. */
2440 /* */
2441 /***********************************************************************/
2442
2443 static void
2445 Short* max )
2446 {
2447 /* nothing, really */
2449 FT_UNUSED( min );
2450 FT_UNUSED( max );
2451 }
2452
2453
2454 static void
2456 FT_F26Dot6 x1,
2457 FT_F26Dot6 x2,
2458 PProfile left,
2459 PProfile right )
2460 {
2461 FT_UNUSED( left );
2462 FT_UNUSED( right );
2463
2464
2465 if ( x2 - x1 < ras.precision )
2466 {
2467 Long e1, e2;
2468
2469
2470 FT_TRACE7(( " x=%d y=[%.12f;%.12f]",
2471 y,
2472 x1 / (double)ras.precision,
2473 x2 / (double)ras.precision ));
2474
2475 e1 = CEILING( x1 );
2476 e2 = FLOOR ( x2 );
2477
2478 if ( e1 == e2 )
2479 {
2480 e1 = TRUNC( e1 );
2481
2482 if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
2483 {
2484 Byte f1;
2485 PByte bits;
2486 PByte p;
2487
2488
2489 FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
2490
2491 bits = ras.bTarget + ( y >> 3 );
2492 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2493 p = bits - e1 * ras.target.pitch;
2494
2495 if ( ras.target.pitch > 0 )
2496 p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2497
2498 p[0] |= f1;
2499 }
2500 }
2501
2502 FT_TRACE7(( "\n" ));
2503 }
2504 }
2505
2506
2507 static void
2509 FT_F26Dot6 x1,
2510 FT_F26Dot6 x2,
2511 PProfile left,
2512 PProfile right )
2513 {
2514 Long e1, e2, pxl;
2515 PByte bits;
2516 Byte f1;
2517
2518
2519 FT_TRACE7(( " x=%d y=[%.12f;%.12f]",
2520 y,
2521 x1 / (double)ras.precision,
2522 x2 / (double)ras.precision ));
2523
2524 /* During the horizontal sweep, we only take care of drop-outs */
2525
2526 /* e1 + <-- pixel center */
2527 /* | */
2528 /* x1 ---+--> <-- contour */
2529 /* | */
2530 /* | */
2531 /* x2 <--+--- <-- contour */
2532 /* | */
2533 /* | */
2534 /* e2 + <-- pixel center */
2535
2536 e1 = CEILING( x1 );
2537 e2 = FLOOR ( x2 );
2538 pxl = e1;
2539
2540 if ( e1 > e2 )
2541 {
2542 Int dropOutControl = left->flags & 7;
2543
2544
2545 FT_TRACE7(( ", dropout=%d", dropOutControl ));
2546
2547 if ( e1 == e2 + ras.precision )
2548 {
2549 switch ( dropOutControl )
2550 {
2551 case 0: /* simple drop-outs including stubs */
2552 pxl = e2;
2553 break;
2554
2555 case 4: /* smart drop-outs including stubs */
2556 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2557 break;
2558
2559 case 1: /* simple drop-outs excluding stubs */
2560 case 5: /* smart drop-outs excluding stubs */
2561 /* see Vertical_Sweep_Drop for details */
2562
2563 /* rightmost stub test */
2564 if ( left->next == right &&
2565 left->height <= 0 &&
2566 !( left->flags & Overshoot_Top &&
2567 x2 - x1 >= ras.precision_half ) )
2568 goto Exit;
2569
2570 /* leftmost stub test */
2571 if ( right->next == left &&
2572 left->start == y &&
2573 !( left->flags & Overshoot_Bottom &&
2574 x2 - x1 >= ras.precision_half ) )
2575 goto Exit;
2576
2577 if ( dropOutControl == 1 )
2578 pxl = e2;
2579 else
2580 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2581 break;
2582
2583 default: /* modes 2, 3, 6, 7 */
2584 goto Exit; /* no drop-out control */
2585 }
2586
2587 /* undocumented but confirmed: If the drop-out would result in a */
2588 /* pixel outside of the bounding box, use the pixel inside of the */
2589 /* bounding box instead */
2590 if ( pxl < 0 )
2591 pxl = e1;
2592 else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
2593 pxl = e2;
2594
2595 /* check that the other pixel isn't set */
2596 e1 = ( pxl == e1 ) ? e2 : e1;
2597
2598 e1 = TRUNC( e1 );
2599
2600 bits = ras.bTarget + ( y >> 3 );
2601 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2602
2603 bits -= e1 * ras.target.pitch;
2604 if ( ras.target.pitch > 0 )
2605 bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2606
2607 if ( e1 >= 0 &&
2608 (ULong)e1 < ras.target.rows &&
2609 *bits & f1 )
2610 goto Exit;
2611 }
2612 else
2613 goto Exit;
2614 }
2615
2616 e1 = TRUNC( pxl );
2617
2618 if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
2619 {
2620 FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
2621
2622 bits = ras.bTarget + ( y >> 3 );
2623 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2624 bits -= e1 * ras.target.pitch;
2625
2626 if ( ras.target.pitch > 0 )
2627 bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2628
2629 bits[0] |= f1;
2630 }
2631
2632 Exit:
2633 FT_TRACE7(( "\n" ));
2634 }
2635
2636
2637 static void
2639 {
2640 /* Nothing, really */
2642 }
2643
2644
2645 /*************************************************************************/
2646 /* */
2647 /* Generic Sweep Drawing routine */
2648 /* */
2649 /*************************************************************************/
2650
2651 static Bool
2653 {
2654 Short y, y_change, y_height;
2655
2656 PProfile P, Q, P_Left, P_Right;
2657
2658 Short min_Y, max_Y, top, bottom, dropouts;
2659
2660 Long x1, x2, xs, e1, e2;
2661
2663 TProfileList draw_left, draw_right;
2664
2665
2666 /* initialize empty linked lists */
2667
2668 Init_Linked( &waiting );
2669
2670 Init_Linked( &draw_left );
2671 Init_Linked( &draw_right );
2672
2673 /* first, compute min and max Y */
2674
2675 P = ras.fProfile;
2676 max_Y = (Short)TRUNC( ras.minY );
2677 min_Y = (Short)TRUNC( ras.maxY );
2678
2679 while ( P )
2680 {
2681 Q = P->link;
2682
2683 bottom = (Short)P->start;
2684 top = (Short)( P->start + P->height - 1 );
2685
2686 if ( min_Y > bottom )
2687 min_Y = bottom;
2688 if ( max_Y < top )
2689 max_Y = top;
2690
2691 P->X = 0;
2692 InsNew( &waiting, P );
2693
2694 P = Q;
2695 }
2696
2697 /* check the Y-turns */
2698 if ( ras.numTurns == 0 )
2699 {
2700 ras.error = FT_THROW( Invalid );
2701 return FAILURE;
2702 }
2703
2704 /* now initialize the sweep */
2705
2706 ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2707
2708 /* then compute the distance of each profile from min_Y */
2709
2710 P = waiting;
2711
2712 while ( P )
2713 {
2714 P->countL = P->start - min_Y;
2715 P = P->link;
2716 }
2717
2718 /* let's go */
2719
2720 y = min_Y;
2721 y_height = 0;
2722
2723 if ( ras.numTurns > 0 &&
2724 ras.sizeBuff[-ras.numTurns] == min_Y )
2725 ras.numTurns--;
2726
2727 while ( ras.numTurns > 0 )
2728 {
2729 /* check waiting list for new activations */
2730
2731 P = waiting;
2732
2733 while ( P )
2734 {
2735 Q = P->link;
2736 P->countL -= y_height;
2737 if ( P->countL == 0 )
2738 {
2739 DelOld( &waiting, P );
2740
2741 if ( P->flags & Flow_Up )
2742 InsNew( &draw_left, P );
2743 else
2744 InsNew( &draw_right, P );
2745 }
2746
2747 P = Q;
2748 }
2749
2750 /* sort the drawing lists */
2751
2752 Sort( &draw_left );
2753 Sort( &draw_right );
2754
2755 y_change = (Short)ras.sizeBuff[-ras.numTurns--];
2756 y_height = (Short)( y_change - y );
2757
2758 while ( y < y_change )
2759 {
2760 /* let's trace */
2761
2762 dropouts = 0;
2763
2764 P_Left = draw_left;
2765 P_Right = draw_right;
2766
2767 while ( P_Left )
2768 {
2769 x1 = P_Left ->X;
2770 x2 = P_Right->X;
2771
2772 if ( x1 > x2 )
2773 {
2774 xs = x1;
2775 x1 = x2;
2776 x2 = xs;
2777 }
2778
2779 e1 = FLOOR( x1 );
2780 e2 = CEILING( x2 );
2781
2782 if ( x2 - x1 <= ras.precision &&
2783 e1 != x1 && e2 != x2 )
2784 {
2785 if ( e1 > e2 || e2 == e1 + ras.precision )
2786 {
2787 Int dropOutControl = P_Left->flags & 7;
2788
2789
2790 if ( dropOutControl != 2 )
2791 {
2792 /* a drop-out was detected */
2793
2794 P_Left ->X = x1;
2795 P_Right->X = x2;
2796
2797 /* mark profile for drop-out processing */
2798 P_Left->countL = 1;
2799 dropouts++;
2800 }
2801
2802 goto Skip_To_Next;
2803 }
2804 }
2805
2806 ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
2807
2808 Skip_To_Next:
2809
2810 P_Left = P_Left->link;
2811 P_Right = P_Right->link;
2812 }
2813
2814 /* handle drop-outs _after_ the span drawing -- */
2815 /* drop-out processing has been moved out of the loop */
2816 /* for performance tuning */
2817 if ( dropouts > 0 )
2818 goto Scan_DropOuts;
2819
2820 Next_Line:
2821
2822 ras.Proc_Sweep_Step( RAS_VAR );
2823
2824 y++;
2825
2826 if ( y < y_change )
2827 {
2828 Sort( &draw_left );
2829 Sort( &draw_right );
2830 }
2831 }
2832
2833 /* now finalize the profiles that need it */
2834
2835 P = draw_left;
2836 while ( P )
2837 {
2838 Q = P->link;
2839 if ( P->height == 0 )
2840 DelOld( &draw_left, P );
2841 P = Q;
2842 }
2843
2844 P = draw_right;
2845 while ( P )
2846 {
2847 Q = P->link;
2848 if ( P->height == 0 )
2849 DelOld( &draw_right, P );
2850 P = Q;
2851 }
2852 }
2853
2854 /* for gray-scaling, flush the bitmap scanline cache */
2855 while ( y <= max_Y )
2856 {
2857 ras.Proc_Sweep_Step( RAS_VAR );
2858 y++;
2859 }
2860
2861 return SUCCESS;
2862
2863 Scan_DropOuts:
2864
2865 P_Left = draw_left;
2866 P_Right = draw_right;
2867
2868 while ( P_Left )
2869 {
2870 if ( P_Left->countL )
2871 {
2872 P_Left->countL = 0;
2873#if 0
2874 dropouts--; /* -- this is useful when debugging only */
2875#endif
2876 ras.Proc_Sweep_Drop( RAS_VARS y,
2877 P_Left->X,
2878 P_Right->X,
2879 P_Left,
2880 P_Right );
2881 }
2882
2883 P_Left = P_Left->link;
2884 P_Right = P_Right->link;
2885 }
2886
2887 goto Next_Line;
2888 }
2889
2890
2891 /*************************************************************************/
2892 /* */
2893 /* <Function> */
2894 /* Render_Single_Pass */
2895 /* */
2896 /* <Description> */
2897 /* Perform one sweep with sub-banding. */
2898 /* */
2899 /* <Input> */
2900 /* flipped :: If set, flip the direction of the outline. */
2901 /* */
2902 /* <Return> */
2903 /* Renderer error code. */
2904 /* */
2905 static int
2907 {
2908 Short i, j, k;
2909
2910
2911 while ( ras.band_top >= 0 )
2912 {
2913 ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
2914 ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
2915
2916 ras.top = ras.buff;
2917
2918 ras.error = Raster_Err_None;
2919
2920 if ( Convert_Glyph( RAS_VARS flipped ) )
2921 {
2922 if ( ras.error != Raster_Err_Overflow )
2923 return FAILURE;
2924
2925 ras.error = Raster_Err_None;
2926
2927 /* sub-banding */
2928
2929#ifdef DEBUG_RASTER
2930 ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
2931#endif
2932
2933 i = ras.band_stack[ras.band_top].y_min;
2934 j = ras.band_stack[ras.band_top].y_max;
2935
2936 k = (Short)( ( i + j ) / 2 );
2937
2938 if ( ras.band_top >= 7 || k < i )
2939 {
2940 ras.band_top = 0;
2941 ras.error = FT_THROW( Invalid );
2942
2943 return ras.error;
2944 }
2945
2946 ras.band_stack[ras.band_top + 1].y_min = k;
2947 ras.band_stack[ras.band_top + 1].y_max = j;
2948
2949 ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
2950
2951 ras.band_top++;
2952 }
2953 else
2954 {
2955 if ( ras.fProfile )
2956 if ( Draw_Sweep( RAS_VAR ) )
2957 return ras.error;
2958 ras.band_top--;
2959 }
2960 }
2961
2962 return SUCCESS;
2963 }
2964
2965
2966 /*************************************************************************/
2967 /* */
2968 /* <Function> */
2969 /* Render_Glyph */
2970 /* */
2971 /* <Description> */
2972 /* Render a glyph in a bitmap. Sub-banding if needed. */
2973 /* */
2974 /* <Return> */
2975 /* FreeType error code. 0 means success. */
2976 /* */
2977 static FT_Error
2979 {
2981
2982
2983 Set_High_Precision( RAS_VARS ras.outline.flags &
2985 ras.scale_shift = ras.precision_shift;
2986
2987 if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
2988 ras.dropOutControl = 2;
2989 else
2990 {
2991 if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
2992 ras.dropOutControl = 4;
2993 else
2994 ras.dropOutControl = 0;
2995
2996 if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
2997 ras.dropOutControl += 1;
2998 }
2999
3000 ras.second_pass = (Bool)( !( ras.outline.flags &
3002
3003 /* Vertical Sweep */
3004 FT_TRACE7(( "Vertical pass (ftraster)\n" ));
3005
3006 ras.Proc_Sweep_Init = Vertical_Sweep_Init;
3007 ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3008 ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3009 ras.Proc_Sweep_Step = Vertical_Sweep_Step;
3010
3011 ras.band_top = 0;
3012 ras.band_stack[0].y_min = 0;
3013 ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
3014
3015 ras.bWidth = (UShort)ras.target.width;
3016 ras.bTarget = (Byte*)ras.target.buffer;
3017
3018 if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
3019 return error;
3020
3021 /* Horizontal Sweep */
3022 if ( ras.second_pass && ras.dropOutControl != 2 )
3023 {
3024 FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
3025
3026 ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3027 ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3028 ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3029 ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3030
3031 ras.band_top = 0;
3032 ras.band_stack[0].y_min = 0;
3033 ras.band_stack[0].y_max = (Short)( ras.target.width - 1 );
3034
3035 if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3036 return error;
3037 }
3038
3039 return Raster_Err_None;
3040 }
3041
3042
3043 static void
3045 {
3046 FT_UNUSED( raster );
3047 }
3048
3049
3050 /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3051 /**** a static object. *****/
3052
3053
3054#ifdef STANDALONE_
3055
3056
3057 static int
3058 ft_black_new( void* memory,
3059 FT_Raster *araster )
3060 {
3061 static black_TRaster the_raster;
3062 FT_UNUSED( memory );
3063
3064
3065 *araster = (FT_Raster)&the_raster;
3066 FT_ZERO( &the_raster );
3067 ft_black_init( &the_raster );
3068
3069 return 0;
3070 }
3071
3072
3073 static void
3074 ft_black_done( FT_Raster raster )
3075 {
3076 /* nothing */
3077 FT_UNUSED( raster );
3078 }
3079
3080
3081#else /* !STANDALONE_ */
3082
3083
3084 static int
3086 black_PRaster *araster )
3087 {
3089 black_PRaster raster = NULL;
3090
3091
3092 *araster = 0;
3093 if ( !FT_NEW( raster ) )
3094 {
3095 raster->memory = memory;
3096 ft_black_init( raster );
3097
3098 *araster = raster;
3099 }
3100
3101 return error;
3102 }
3103
3104
3105 static void
3107 {
3108 FT_Memory memory = (FT_Memory)raster->memory;
3109
3110
3111 FT_FREE( raster );
3112 }
3113
3114
3115#endif /* !STANDALONE_ */
3116
3117
3118 static void
3120 PByte pool_base,
3121 ULong pool_size )
3122 {
3123 FT_UNUSED( raster );
3124 FT_UNUSED( pool_base );
3125 FT_UNUSED( pool_size );
3126 }
3127
3128
3129 static int
3131 ULong mode,
3132 void* args )
3133 {
3134 FT_UNUSED( raster );
3135 FT_UNUSED( mode );
3136 FT_UNUSED( args );
3137
3138 return 0;
3139 }
3140
3141
3142 static int
3144 const FT_Raster_Params* params )
3145 {
3146 const FT_Outline* outline = (const FT_Outline*)params->source;
3147 const FT_Bitmap* target_map = params->target;
3148
3149#ifdef __REACTOS__
3150 FT_Error ret;
3151 black_TWorker *worker;
3152 Long *buffer;
3153#else
3154 black_TWorker worker[1];
3155
3157#endif
3158
3159
3160 if ( !raster )
3161 return FT_THROW( Not_Ini );
3162
3163 if ( !outline )
3164 return FT_THROW( Invalid );
3165
3166 /* return immediately if the outline is empty */
3167 if ( outline->n_points == 0 || outline->n_contours <= 0 )
3168 return Raster_Err_None;
3169
3170 if ( !outline->contours || !outline->points )
3171 return FT_THROW( Invalid );
3172
3173 if ( outline->n_points !=
3174 outline->contours[outline->n_contours - 1] + 1 )
3175 return FT_THROW( Invalid );
3176
3177 /* this version of the raster does not support direct rendering, sorry */
3178 if ( params->flags & FT_RASTER_FLAG_DIRECT )
3179 return FT_THROW( Unsupported );
3180
3181 if ( params->flags & FT_RASTER_FLAG_AA )
3182 return FT_THROW( Unsupported );
3183
3184 if ( !target_map )
3185 return FT_THROW( Invalid );
3186
3187 /* nothing to do */
3188 if ( !target_map->width || !target_map->rows )
3189 return Raster_Err_None;
3190
3191 if ( !target_map->buffer )
3192 return FT_THROW( Invalid );
3193
3194 /* reject too large outline coordinates */
3195 {
3196 FT_Vector* vec = outline->points;
3197 FT_Vector* limit = vec + outline->n_points;
3198
3199
3200 for ( ; vec < limit; vec++ )
3201 {
3202 if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
3203 vec->y < -0x1000000L || vec->y > 0x1000000L )
3204 return FT_THROW( Invalid );
3205 }
3206 }
3207
3208#ifdef __REACTOS__
3209 worker = malloc(sizeof(black_TWorker));
3211 if (!worker || !buffer)
3212 {
3213 free(worker);
3214 free(buffer);
3215 return FT_THROW( Out_Of_Memory );
3216 }
3217#endif
3218
3219 ras.outline = *outline;
3220 ras.target = *target_map;
3221
3222 worker->buff = buffer;
3223#ifdef __REACTOS__
3224 worker->sizeBuff = buffer + FT_MAX_BLACK_POOL;
3225#else
3226 worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
3227#endif
3228
3229#ifdef __REACTOS__
3231 free(worker);
3232 free(buffer);
3233 return ret;
3234#else
3235 return Render_Glyph( RAS_VAR );
3236#endif
3237 }
3238
3239
3241 ft_standard_raster,
3242
3244
3245 (FT_Raster_New_Func) ft_black_new, /* raster_new */
3246 (FT_Raster_Reset_Func) ft_black_reset, /* raster_reset */
3247 (FT_Raster_Set_Mode_Func)ft_black_set_mode, /* raster_set_mode */
3248 (FT_Raster_Render_Func) ft_black_render, /* raster_render */
3249 (FT_Raster_Done_Func) ft_black_done /* raster_done */
3250 )
3251
3252
3253/* END */
@ Invalid
Definition: asmpp.cpp:30
struct __tagSort Sort
r l[0]
Definition: byte_order.h:168
Definition: list.h:37
SHORT maxy
Definition: cmdinput.c:116
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
int Int
Definition: definitions.h:37
static BOOL waiting
Definition: maze.c:75
#define FT_RENDER_POOL_SIZE
Definition: ftoption.h:366
#define P(row, col)
unsigned char Byte
Definition: zlib.h:37
unsigned char
Definition: typeof.h:29
POINTL point
Definition: edittest.c:50
int Fail
Definition: ehthrow.cxx:24
FT_Vector * vec
Definition: ftbbox.c:448
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
#define FT_TRACE7(varformat)
Definition: ftdebug.h:164
#define FT_TRACE6(varformat)
Definition: ftdebug.h:163
#define FT_THROW(e)
Definition: ftdebug.h:213
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
#define FT_CURVE_TAG_CUBIC
Definition: ftimage.h:455
#define FT_RASTER_FLAG_AA
Definition: ftimage.h:941
#define FT_OUTLINE_SMART_DROPOUTS
Definition: ftimage.h:432
#define FT_CURVE_TAG_HAS_SCANMODE
Definition: ftimage.h:457
#define FT_CURVE_TAG_CONIC
Definition: ftimage.h:454
#define FT_Raster_Render_Func
Definition: ftimage.h:1158
struct FT_RasterRec_ * FT_Raster
Definition: ftimage.h:800
#define FT_OUTLINE_IGNORE_DROPOUTS
Definition: ftimage.h:431
#define FT_OUTLINE_INCLUDE_STUBS
Definition: ftimage.h:433
#define FT_Raster_Reset_Func
Definition: ftimage.h:1091
#define FT_RASTER_FLAG_DIRECT
Definition: ftimage.h:942
#define FT_CURVE_TAG(flag)
Definition: ftimage.h:451
#define FT_CURVE_TAG_ON
Definition: ftimage.h:453
#define FT_OUTLINE_HIGH_PRECISION
Definition: ftimage.h:435
#define FT_Raster_New_Func
Definition: ftimage.h:1040
#define FT_Raster_Set_Mode_Func
Definition: ftimage.h:1117
#define FT_OUTLINE_SINGLE_PASS
Definition: ftimage.h:436
#define FT_Raster_Done_Func
Definition: ftimage.h:1057
#define FT_NEW(ptr)
Definition: ftmemory.h:331
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, raster_reset_, raster_set_mode_, raster_render_, raster_done_)
Definition: ftobjs.h:1106
#define FT_MAX(a, b)
Definition: ftobjs.h:72
struct black_TRaster_ * black_PRaster
#define NULL
Definition: ftraster.c:282
#define SMulDiv_No_Round
Definition: ftraster.c:267
static void Set_High_Precision(RAS_ARGS Int High)
Definition: ftraster.c:588
#define RAS_ARG
Definition: ftraster.c:415
unsigned short * PUShort
Definition: ftraster.c:312
#define FRAC(x)
Definition: ftraster.c:454
unsigned short UShort
Definition: ftraster.c:312
static void Horizontal_Sweep_Drop(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2508
void(* TSplitter)(TPoint *base)
Definition: ftraster.c:1165
static void Horizontal_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2455
static Bool Line_Down(RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy)
Definition: ftraster.c:1143
static int ft_black_new(FT_Memory memory, black_PRaster *araster)
Definition: ftraster.c:3085
static Bool Finalize_Profile_Table(RAS_ARG)
Definition: ftraster.c:849
TStates_
Definition: ftraster.c:345
@ Ascending_State
Definition: ftraster.c:347
@ Unknown_State
Definition: ftraster.c:346
@ Descending_State
Definition: ftraster.c:348
@ Flat_State
Definition: ftraster.c:349
static void Horizontal_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:2444
union Alignment_ * PAlignment
#define SWAP_(x, y)
Definition: ftraster.c:1698
static Bool Conic_To(RAS_ARGS Long cx, Long cy, Long x, Long y)
Definition: ftraster.c:1468
#define Flow_Up
Definition: ftraster.c:338
#define FLOOR(x)
Definition: ftraster.c:451
static void ft_black_reset(FT_Raster raster, PByte pool_base, ULong pool_size)
Definition: ftraster.c:3119
static void Init_Linked(TProfileList *l)
Definition: ftraster.c:2038
#define TRUNC(x)
Definition: ftraster.c:453
struct black_TWorker_ * black_PWorker
Definition: ftraster.c:426
static void Vertical_Sweep_Step(RAS_ARG)
Definition: ftraster.c:2428
#define MaxBezier
Definition: ftraster.c:294
#define Raster_Err_None
Definition: ftraster.c:235
long Long
Definition: ftraster.c:313
#define RAS_ARGS
Definition: ftraster.c:414
static FT_Error Render_Glyph(RAS_ARG)
Definition: ftraster.c:2978
#define Overshoot_Bottom
Definition: ftraster.c:340
static void Split_Conic(TPoint *base)
Definition: ftraster.c:914
static Bool Decompose_Curve(RAS_ARGS UShort first, UShort last, Int flipped)
Definition: ftraster.c:1730
static void Vertical_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:2176
static Bool End_Profile(RAS_ARGS Bool overshoot)
Definition: ftraster.c:725
struct black_TBand_ black_TBand
#define CEILING(x)
Definition: ftraster.c:452
#define AlignProfileSize
Definition: ftraster.c:390
static int ft_black_set_mode(FT_Raster raster, ULong mode, void *args)
Definition: ftraster.c:3130
char Bool
Definition: ftraster.c:317
#define FAILURE
Definition: ftraster.c:290
static Bool Bezier_Down(RAS_ARGS Int degree, TSplitter splitter, Long miny, Long maxy)
Definition: ftraster.c:1323
TProfile * PProfile
Definition: ftraster.c:355
#define RAS_VAR
Definition: ftraster.c:418
void Function_Sweep_Step(RAS_ARG)
Definition: ftraster.c:442
static void Split_Cubic(TPoint *base)
Definition: ftraster.c:951
unsigned long ULong
Definition: ftraster.c:314
static void ft_black_init(black_PRaster raster)
Definition: ftraster.c:3044
int Int
Definition: ftraster.c:309
PProfile TProfileList
Definition: ftraster.c:376
#define Overshoot_Top
Definition: ftraster.c:339
static void DelOld(PProfileList list, PProfile profile)
Definition: ftraster.c:2082
static Bool Line_To(RAS_ARGS Long x, Long y)
Definition: ftraster.c:1370
static Bool Convert_Glyph(RAS_ARGS Int flipped)
Definition: ftraster.c:1954
#define FT_ZERO(p)
Definition: ftraster.c:255
#define FT_UNUSED_RASTER
Definition: ftraster.c:420
static void InsNew(PProfileList list, PProfile profile)
Definition: ftraster.c:2051
static void ft_black_done(black_PRaster raster)
Definition: ftraster.c:3106
void Function_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:431
#define ras
Definition: ftraster.c:561
enum TStates_ TStates
#define FT_MAX_BLACK_POOL
Definition: ftraster.c:467
#define RAS_VARS
Definition: ftraster.c:417
#define SCALED(x)
Definition: ftraster.c:455
#define TRUE
Definition: ftraster.c:274
#define SUCCESS
Definition: ftraster.c:286
#define FALSE
Definition: ftraster.c:278
union Alignment_ Alignment
struct TPoint_ TPoint
void Function_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:435
static Bool Line_Up(RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy)
Definition: ftraster.c:1004
static Bool Cubic_To(RAS_ARGS Long cx1, Long cy1, Long cx2, Long cy2, Long x, Long y)
Definition: ftraster.c:1589
unsigned int UInt
Definition: ftraster.c:310
static void Vertical_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2192
long * PLong
Definition: ftraster.c:313
static Bool New_Profile(RAS_ARGS TStates aState, Bool overshoot)
Definition: ftraster.c:652
#define IS_BOTTOM_OVERSHOOT(x)
Definition: ftraster.c:459
static Bool Bezier_Up(RAS_ARGS Int degree, TSplitter splitter, Long miny, Long maxy)
Definition: ftraster.c:1190
#define SMulDiv
Definition: ftraster.c:266
PProfile * PProfileList
Definition: ftraster.c:377
#define FMulDiv(a, b, c)
Definition: ftraster.c:261
#define IS_TOP_OVERSHOOT(x)
Definition: ftraster.c:461
static void Vertical_Sweep_Drop(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2272
#define Pixel_Bits
Definition: ftraster.c:298
static int Render_Single_Pass(RAS_ARGS Bool flipped)
Definition: ftraster.c:2906
static void Horizontal_Sweep_Step(RAS_ARG)
Definition: ftraster.c:2638
unsigned char Byte
Definition: ftraster.c:316
struct black_TRaster_ black_TRaster
static Bool Insert_Y_Turn(RAS_ARGS Int y)
Definition: ftraster.c:797
static Bool Draw_Sweep(RAS_ARG)
Definition: ftraster.c:2652
static int ft_black_render(FT_Raster raster, const FT_Raster_Params *params)
Definition: ftraster.c:3143
unsigned char * PByte
Definition: ftraster.c:316
#define Raster_Err_Overflow
Definition: ftraster.c:237
short Short
Definition: ftraster.c:311
smooth FT_Module_Constructor FT_Module_Destructor FT_Module_Requester FT_GLYPH_FORMAT_OUTLINE
Definition: ftsmooth.c:426
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
signed long FT_F26Dot6
Definition: fttypes.h:276
int FT_Error
Definition: fttypes.h:300
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLfloat f
Definition: glext.h:7540
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
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLint left
Definition: glext.h:7726
GLint GLint bottom
Definition: glext.h:7726
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLsizei const GLfloat * points
Definition: glext.h:8112
GLenum target
Definition: glext.h:7315
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define bits
Definition: infblock.c:15
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define profile
Definition: kernel32.h:12
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
struct task_struct * current
Definition: linux.c:32
#define for
Definition: utility.h:88
const char * tags[7 *8]
Definition: apphelp.c:216
static UINT UINT last
Definition: font.c:45
static char memory[1024 *256]
Definition: process.c:116
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
static unsigned __int64 next
Definition: rand_nt.c:6
#define list
Definition: rosglue.h:35
@ Close
Definition: sacdrv.h:268
#define f2(x, y, z)
Definition: sha1.c:31
#define f1(x, y, z)
Definition: sha1.c:30
static void Exit(void)
Definition: sock.c:1330
@ High
Definition: strmini.h:378
FT_Pos x
Definition: ftimage.h:76
FT_Pos y
Definition: ftimage.h:77
Long y
Definition: ftraster.c:332
Long x
Definition: ftraster.c:331
PProfile next
Definition: ftraster.c:372
FT_F26Dot6 X
Definition: ftraster.c:359
Long start
Definition: ftraster.c:367
Int countL
Definition: ftraster.c:369
Long height
Definition: ftraster.c:366
UShort flags
Definition: ftraster.c:362
PLong offset
Definition: ftraster.c:361
PProfile link
Definition: ftraster.c:360
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
Definition: match.c:390
Short y_max
Definition: ftraster.c:385
Short y_min
Definition: ftraster.c:384
void * memory
Definition: ftraster.c:550
FT_Error error
Definition: ftraster.c:491
Int precision_bits
Definition: ftraster.c:476
TStates state
Definition: ftraster.c:516
UShort num_Profs
Definition: ftraster.c:504
Function_Sweep_Span * Proc_Sweep_Drop
Definition: ftraster.c:530
UShort bWidth
Definition: ftraster.c:497
Function_Sweep_Init * Proc_Sweep_Init
Definition: ftraster.c:528
PProfile gProfile
Definition: ftraster.c:513
Function_Sweep_Step * Proc_Sweep_Step
Definition: ftraster.c:531
TPoint * arc
Definition: ftraster.c:495
Short traceIncr
Definition: ftraster.c:524
PProfile cProfile
Definition: ftraster.c:511
Byte dropOutControl
Definition: ftraster.c:533
PByte bTarget
Definition: ftraster.c:498
PLong maxBuff
Definition: ftraster.c:488
black_TBand band_stack[16]
Definition: ftraster.c:542
Int precision_jitter
Definition: ftraster.c:481
FT_Outline outline
Definition: ftraster.c:519
PProfile fProfile
Definition: ftraster.c:512
Function_Sweep_Span * Proc_Sweep_Span
Definition: ftraster.c:529
TPoint arcs[3 *MaxBezier+1]
Definition: ftraster.c:540
Int precision_step
Definition: ftraster.c:480
Bool second_pass
Definition: ftraster.c:535
FT_Bitmap target
Definition: ftraster.c:518
PLong sizeBuff
Definition: ftraster.c:487
PByte gTarget
Definition: ftraster.c:499
Int precision_shift
Definition: ftraster.c:479
Int precision_half
Definition: ftraster.c:478
struct define * next
Definition: compiler.c:65
Definition: mesh.c:5330
Definition: ecma_167.h:138
#define max(a, b)
Definition: svc.c:63
void * p
Definition: ftraster.c:323
Long l
Definition: ftraster.c:322
int ret
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711