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