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