PageRenderTime 69ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/freetype/src/raster/ftraster.c

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