PageRenderTime 66ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/src/freetype/src/smooth/ftgrays.c

https://bitbucket.org/cabalistic/ogredeps/
C | 2066 lines | 1336 code | 454 blank | 276 comment | 209 complexity | a5af0e97d28eb66b5a4f7ad82e103692 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. /* ftgrays.c */
  4. /* */
  5. /* A new `perfect' anti-aliasing renderer (body). */
  6. /* */
  7. /* Copyright 2000-2003, 2005-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 `ftgrays.h' and `ftimage.h' into the current */
  22. /* compilation directory. Typically, you could do something like */
  23. /* */
  24. /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */
  25. /* */
  26. /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
  27. /* same directory */
  28. /* */
  29. /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
  30. /* */
  31. /* cc -c -D_STANDALONE_ ftgrays.c */
  32. /* */
  33. /* The renderer can be initialized with a call to */
  34. /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */
  35. /* with a call to `ft_gray_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 new anti-aliasing scan-converter for FreeType 2. The */
  44. /* algorithm used here is _very_ different from the one in the standard */
  45. /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
  46. /* coverage of the outline on each pixel cell. */
  47. /* */
  48. /* It is based on ideas that I initially found in Raph Levien's */
  49. /* excellent LibArt graphics library (see http://www.levien.com/libart */
  50. /* for more information, though the web pages do not tell anything */
  51. /* about the renderer; you'll have to dive into the source code to */
  52. /* understand how it works). */
  53. /* */
  54. /* Note, however, that this is a _very_ different implementation */
  55. /* compared to Raph's. Coverage information is stored in a very */
  56. /* different way, and I don't use sorted vector paths. Also, it doesn't */
  57. /* use floating point values. */
  58. /* */
  59. /* This renderer has the following advantages: */
  60. /* */
  61. /* - It doesn't need an intermediate bitmap. Instead, one can supply a */
  62. /* callback function that will be called by the renderer to draw gray */
  63. /* spans on any target surface. You can thus do direct composition on */
  64. /* any kind of bitmap, provided that you give the renderer the right */
  65. /* callback. */
  66. /* */
  67. /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
  68. /* each pixel cell. */
  69. /* */
  70. /* - It performs a single pass on the outline (the `standard' FT2 */
  71. /* renderer makes two passes). */
  72. /* */
  73. /* - It can easily be modified to render to _any_ number of gray levels */
  74. /* cheaply. */
  75. /* */
  76. /* - For small (< 20) pixel sizes, it is faster than the standard */
  77. /* renderer. */
  78. /* */
  79. /*************************************************************************/
  80. /*************************************************************************/
  81. /* */
  82. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  83. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  84. /* messages during execution. */
  85. /* */
  86. #undef FT_COMPONENT
  87. #define FT_COMPONENT trace_smooth
  88. #ifdef _STANDALONE_
  89. /* define this to dump debugging information */
  90. /* #define FT_DEBUG_LEVEL_TRACE */
  91. #ifdef FT_DEBUG_LEVEL_TRACE
  92. #include <stdio.h>
  93. #include <stdarg.h>
  94. #endif
  95. #include <stddef.h>
  96. #include <string.h>
  97. #include <setjmp.h>
  98. #include <limits.h>
  99. #define FT_UINT_MAX UINT_MAX
  100. #define FT_INT_MAX INT_MAX
  101. #define ft_memset memset
  102. #define ft_setjmp setjmp
  103. #define ft_longjmp longjmp
  104. #define ft_jmp_buf jmp_buf
  105. typedef ptrdiff_t FT_PtrDist;
  106. #define ErrRaster_Invalid_Mode -2
  107. #define ErrRaster_Invalid_Outline -1
  108. #define ErrRaster_Invalid_Argument -3
  109. #define ErrRaster_Memory_Overflow -4
  110. #define FT_BEGIN_HEADER
  111. #define FT_END_HEADER
  112. #include "ftimage.h"
  113. #include "ftgrays.h"
  114. /* This macro is used to indicate that a function parameter is unused. */
  115. /* Its purpose is simply to reduce compiler warnings. Note also that */
  116. /* simply defining it as `(void)x' doesn't avoid warnings with certain */
  117. /* ANSI compilers (e.g. LCC). */
  118. #define FT_UNUSED( x ) (x) = (x)
  119. /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
  120. #ifdef FT_DEBUG_LEVEL_TRACE
  121. void
  122. FT_Message( const char* fmt,
  123. ... )
  124. {
  125. va_list ap;
  126. va_start( ap, fmt );
  127. vfprintf( stderr, fmt, ap );
  128. va_end( ap );
  129. }
  130. /* we don't handle tracing levels in stand-alone mode; */
  131. #ifndef FT_TRACE5
  132. #define FT_TRACE5( varformat ) FT_Message varformat
  133. #endif
  134. #ifndef FT_TRACE7
  135. #define FT_TRACE7( varformat ) FT_Message varformat
  136. #endif
  137. #ifndef FT_ERROR
  138. #define FT_ERROR( varformat ) FT_Message varformat
  139. #endif
  140. #else /* !FT_DEBUG_LEVEL_TRACE */
  141. #define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
  142. #define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
  143. #define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
  144. #endif /* !FT_DEBUG_LEVEL_TRACE */
  145. #define FT_DEFINE_OUTLINE_FUNCS( class_, \
  146. move_to_, line_to_, \
  147. conic_to_, cubic_to_, \
  148. shift_, delta_ ) \
  149. static const FT_Outline_Funcs class_ = \
  150. { \
  151. move_to_, \
  152. line_to_, \
  153. conic_to_, \
  154. cubic_to_, \
  155. shift_, \
  156. delta_ \
  157. };
  158. #define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \
  159. raster_new_, raster_reset_, \
  160. raster_set_mode_, raster_render_, \
  161. raster_done_ ) \
  162. const FT_Raster_Funcs class_ = \
  163. { \
  164. glyph_format_, \
  165. raster_new_, \
  166. raster_reset_, \
  167. raster_set_mode_, \
  168. raster_render_, \
  169. raster_done_ \
  170. };
  171. #else /* !_STANDALONE_ */
  172. #include <ft2build.h>
  173. #include "ftgrays.h"
  174. #include FT_INTERNAL_OBJECTS_H
  175. #include FT_INTERNAL_DEBUG_H
  176. #include FT_OUTLINE_H
  177. #include "ftsmerrs.h"
  178. #include "ftspic.h"
  179. #define ErrRaster_Invalid_Mode Smooth_Err_Cannot_Render_Glyph
  180. #define ErrRaster_Invalid_Outline Smooth_Err_Invalid_Outline
  181. #define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory
  182. #define ErrRaster_Invalid_Argument Smooth_Err_Invalid_Argument
  183. #endif /* !_STANDALONE_ */
  184. #ifndef FT_MEM_SET
  185. #define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
  186. #endif
  187. #ifndef FT_MEM_ZERO
  188. #define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
  189. #endif
  190. /* as usual, for the speed hungry :-) */
  191. #undef RAS_ARG
  192. #undef RAS_ARG_
  193. #undef RAS_VAR
  194. #undef RAS_VAR_
  195. #ifndef FT_STATIC_RASTER
  196. #define RAS_ARG gray_PWorker worker
  197. #define RAS_ARG_ gray_PWorker worker,
  198. #define RAS_VAR worker
  199. #define RAS_VAR_ worker,
  200. #else /* FT_STATIC_RASTER */
  201. #define RAS_ARG /* empty */
  202. #define RAS_ARG_ /* empty */
  203. #define RAS_VAR /* empty */
  204. #define RAS_VAR_ /* empty */
  205. #endif /* FT_STATIC_RASTER */
  206. /* must be at least 6 bits! */
  207. #define PIXEL_BITS 8
  208. #undef FLOOR
  209. #undef CEILING
  210. #undef TRUNC
  211. #undef SCALED
  212. #define ONE_PIXEL ( 1L << PIXEL_BITS )
  213. #define PIXEL_MASK ( -1L << PIXEL_BITS )
  214. #define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
  215. #define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS )
  216. #define FLOOR( x ) ( (x) & -ONE_PIXEL )
  217. #define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
  218. #define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
  219. #if PIXEL_BITS >= 6
  220. #define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
  221. #define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
  222. #else
  223. #define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
  224. #define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
  225. #endif
  226. /*************************************************************************/
  227. /* */
  228. /* TYPE DEFINITIONS */
  229. /* */
  230. /* don't change the following types to FT_Int or FT_Pos, since we might */
  231. /* need to define them to "float" or "double" when experimenting with */
  232. /* new algorithms */
  233. typedef long TCoord; /* integer scanline/pixel coordinate */
  234. typedef long TPos; /* sub-pixel coordinate */
  235. /* determine the type used to store cell areas. This normally takes at */
  236. /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */
  237. /* `long' instead of `int', otherwise bad things happen */
  238. #if PIXEL_BITS <= 7
  239. typedef int TArea;
  240. #else /* PIXEL_BITS >= 8 */
  241. /* approximately determine the size of integers using an ANSI-C header */
  242. #if FT_UINT_MAX == 0xFFFFU
  243. typedef long TArea;
  244. #else
  245. typedef int TArea;
  246. #endif
  247. #endif /* PIXEL_BITS >= 8 */
  248. /* maximal number of gray spans in a call to the span callback */
  249. #define FT_MAX_GRAY_SPANS 32
  250. typedef struct TCell_* PCell;
  251. typedef struct TCell_
  252. {
  253. TPos x; /* same with gray_TWorker.ex */
  254. TCoord cover; /* same with gray_TWorker.cover */
  255. TArea area;
  256. PCell next;
  257. } TCell;
  258. typedef struct gray_TWorker_
  259. {
  260. TCoord ex, ey;
  261. TPos min_ex, max_ex;
  262. TPos min_ey, max_ey;
  263. TPos count_ex, count_ey;
  264. TArea area;
  265. TCoord cover;
  266. int invalid;
  267. PCell cells;
  268. FT_PtrDist max_cells;
  269. FT_PtrDist num_cells;
  270. TCoord cx, cy;
  271. TPos x, y;
  272. TPos last_ey;
  273. FT_Vector bez_stack[32 * 3 + 1];
  274. int lev_stack[32];
  275. FT_Outline outline;
  276. FT_Bitmap target;
  277. FT_BBox clip_box;
  278. FT_Span gray_spans[FT_MAX_GRAY_SPANS];
  279. int num_gray_spans;
  280. FT_Raster_Span_Func render_span;
  281. void* render_span_data;
  282. int span_y;
  283. int band_size;
  284. int band_shoot;
  285. ft_jmp_buf jump_buffer;
  286. void* buffer;
  287. long buffer_size;
  288. PCell* ycells;
  289. TPos ycount;
  290. } gray_TWorker, *gray_PWorker;
  291. #ifndef FT_STATIC_RASTER
  292. #define ras (*worker)
  293. #else
  294. static gray_TWorker ras;
  295. #endif
  296. typedef struct gray_TRaster_
  297. {
  298. void* buffer;
  299. long buffer_size;
  300. int band_size;
  301. void* memory;
  302. gray_PWorker worker;
  303. } gray_TRaster, *gray_PRaster;
  304. /*************************************************************************/
  305. /* */
  306. /* Initialize the cells table. */
  307. /* */
  308. static void
  309. gray_init_cells( RAS_ARG_ void* buffer,
  310. long byte_size )
  311. {
  312. ras.buffer = buffer;
  313. ras.buffer_size = byte_size;
  314. ras.ycells = (PCell*) buffer;
  315. ras.cells = NULL;
  316. ras.max_cells = 0;
  317. ras.num_cells = 0;
  318. ras.area = 0;
  319. ras.cover = 0;
  320. ras.invalid = 1;
  321. }
  322. /*************************************************************************/
  323. /* */
  324. /* Compute the outline bounding box. */
  325. /* */
  326. static void
  327. gray_compute_cbox( RAS_ARG )
  328. {
  329. FT_Outline* outline = &ras.outline;
  330. FT_Vector* vec = outline->points;
  331. FT_Vector* limit = vec + outline->n_points;
  332. if ( outline->n_points <= 0 )
  333. {
  334. ras.min_ex = ras.max_ex = 0;
  335. ras.min_ey = ras.max_ey = 0;
  336. return;
  337. }
  338. ras.min_ex = ras.max_ex = vec->x;
  339. ras.min_ey = ras.max_ey = vec->y;
  340. vec++;
  341. for ( ; vec < limit; vec++ )
  342. {
  343. TPos x = vec->x;
  344. TPos y = vec->y;
  345. if ( x < ras.min_ex ) ras.min_ex = x;
  346. if ( x > ras.max_ex ) ras.max_ex = x;
  347. if ( y < ras.min_ey ) ras.min_ey = y;
  348. if ( y > ras.max_ey ) ras.max_ey = y;
  349. }
  350. /* truncate the bounding box to integer pixels */
  351. ras.min_ex = ras.min_ex >> 6;
  352. ras.min_ey = ras.min_ey >> 6;
  353. ras.max_ex = ( ras.max_ex + 63 ) >> 6;
  354. ras.max_ey = ( ras.max_ey + 63 ) >> 6;
  355. }
  356. /*************************************************************************/
  357. /* */
  358. /* Record the current cell in the table. */
  359. /* */
  360. static PCell
  361. gray_find_cell( RAS_ARG )
  362. {
  363. PCell *pcell, cell;
  364. TPos x = ras.ex;
  365. if ( x > ras.count_ex )
  366. x = ras.count_ex;
  367. pcell = &ras.ycells[ras.ey];
  368. for (;;)
  369. {
  370. cell = *pcell;
  371. if ( cell == NULL || cell->x > x )
  372. break;
  373. if ( cell->x == x )
  374. goto Exit;
  375. pcell = &cell->next;
  376. }
  377. if ( ras.num_cells >= ras.max_cells )
  378. ft_longjmp( ras.jump_buffer, 1 );
  379. cell = ras.cells + ras.num_cells++;
  380. cell->x = x;
  381. cell->area = 0;
  382. cell->cover = 0;
  383. cell->next = *pcell;
  384. *pcell = cell;
  385. Exit:
  386. return cell;
  387. }
  388. static void
  389. gray_record_cell( RAS_ARG )
  390. {
  391. if ( !ras.invalid && ( ras.area | ras.cover ) )
  392. {
  393. PCell cell = gray_find_cell( RAS_VAR );
  394. cell->area += ras.area;
  395. cell->cover += ras.cover;
  396. }
  397. }
  398. /*************************************************************************/
  399. /* */
  400. /* Set the current cell to a new position. */
  401. /* */
  402. static void
  403. gray_set_cell( RAS_ARG_ TCoord ex,
  404. TCoord ey )
  405. {
  406. /* Move the cell pointer to a new position. We set the `invalid' */
  407. /* flag to indicate that the cell isn't part of those we're interested */
  408. /* in during the render phase. This means that: */
  409. /* */
  410. /* . the new vertical position must be within min_ey..max_ey-1. */
  411. /* . the new horizontal position must be strictly less than max_ex */
  412. /* */
  413. /* Note that if a cell is to the left of the clipping region, it is */
  414. /* actually set to the (min_ex-1) horizontal position. */
  415. /* All cells that are on the left of the clipping region go to the */
  416. /* min_ex - 1 horizontal position. */
  417. ey -= ras.min_ey;
  418. if ( ex > ras.max_ex )
  419. ex = ras.max_ex;
  420. ex -= ras.min_ex;
  421. if ( ex < 0 )
  422. ex = -1;
  423. /* are we moving to a different cell ? */
  424. if ( ex != ras.ex || ey != ras.ey )
  425. {
  426. /* record the current one if it is valid */
  427. if ( !ras.invalid )
  428. gray_record_cell( RAS_VAR );
  429. ras.area = 0;
  430. ras.cover = 0;
  431. }
  432. ras.ex = ex;
  433. ras.ey = ey;
  434. ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
  435. ex >= ras.count_ex );
  436. }
  437. /*************************************************************************/
  438. /* */
  439. /* Start a new contour at a given cell. */
  440. /* */
  441. static void
  442. gray_start_cell( RAS_ARG_ TCoord ex,
  443. TCoord ey )
  444. {
  445. if ( ex > ras.max_ex )
  446. ex = (TCoord)( ras.max_ex );
  447. if ( ex < ras.min_ex )
  448. ex = (TCoord)( ras.min_ex - 1 );
  449. ras.area = 0;
  450. ras.cover = 0;
  451. ras.ex = ex - ras.min_ex;
  452. ras.ey = ey - ras.min_ey;
  453. ras.last_ey = SUBPIXELS( ey );
  454. ras.invalid = 0;
  455. gray_set_cell( RAS_VAR_ ex, ey );
  456. }
  457. /*************************************************************************/
  458. /* */
  459. /* Render a scanline as one or more cells. */
  460. /* */
  461. static void
  462. gray_render_scanline( RAS_ARG_ TCoord ey,
  463. TPos x1,
  464. TCoord y1,
  465. TPos x2,
  466. TCoord y2 )
  467. {
  468. TCoord ex1, ex2, fx1, fx2, delta, mod, lift, rem;
  469. long p, first, dx;
  470. int incr;
  471. dx = x2 - x1;
  472. ex1 = TRUNC( x1 );
  473. ex2 = TRUNC( x2 );
  474. fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
  475. fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
  476. /* trivial case. Happens often */
  477. if ( y1 == y2 )
  478. {
  479. gray_set_cell( RAS_VAR_ ex2, ey );
  480. return;
  481. }
  482. /* everything is located in a single cell. That is easy! */
  483. /* */
  484. if ( ex1 == ex2 )
  485. {
  486. delta = y2 - y1;
  487. ras.area += (TArea)(( fx1 + fx2 ) * delta);
  488. ras.cover += delta;
  489. return;
  490. }
  491. /* ok, we'll have to render a run of adjacent cells on the same */
  492. /* scanline... */
  493. /* */
  494. p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
  495. first = ONE_PIXEL;
  496. incr = 1;
  497. if ( dx < 0 )
  498. {
  499. p = fx1 * ( y2 - y1 );
  500. first = 0;
  501. incr = -1;
  502. dx = -dx;
  503. }
  504. delta = (TCoord)( p / dx );
  505. mod = (TCoord)( p % dx );
  506. if ( mod < 0 )
  507. {
  508. delta--;
  509. mod += (TCoord)dx;
  510. }
  511. ras.area += (TArea)(( fx1 + first ) * delta);
  512. ras.cover += delta;
  513. ex1 += incr;
  514. gray_set_cell( RAS_VAR_ ex1, ey );
  515. y1 += delta;
  516. if ( ex1 != ex2 )
  517. {
  518. p = ONE_PIXEL * ( y2 - y1 + delta );
  519. lift = (TCoord)( p / dx );
  520. rem = (TCoord)( p % dx );
  521. if ( rem < 0 )
  522. {
  523. lift--;
  524. rem += (TCoord)dx;
  525. }
  526. mod -= (int)dx;
  527. while ( ex1 != ex2 )
  528. {
  529. delta = lift;
  530. mod += rem;
  531. if ( mod >= 0 )
  532. {
  533. mod -= (TCoord)dx;
  534. delta++;
  535. }
  536. ras.area += (TArea)(ONE_PIXEL * delta);
  537. ras.cover += delta;
  538. y1 += delta;
  539. ex1 += incr;
  540. gray_set_cell( RAS_VAR_ ex1, ey );
  541. }
  542. }
  543. delta = y2 - y1;
  544. ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
  545. ras.cover += delta;
  546. }
  547. /*************************************************************************/
  548. /* */
  549. /* Render a given line as a series of scanlines. */
  550. /* */
  551. static void
  552. gray_render_line( RAS_ARG_ TPos to_x,
  553. TPos to_y )
  554. {
  555. TCoord ey1, ey2, fy1, fy2, mod;
  556. TPos dx, dy, x, x2;
  557. long p, first;
  558. int delta, rem, lift, incr;
  559. ey1 = TRUNC( ras.last_ey );
  560. ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
  561. fy1 = (TCoord)( ras.y - ras.last_ey );
  562. fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
  563. dx = to_x - ras.x;
  564. dy = to_y - ras.y;
  565. /* XXX: we should do something about the trivial case where dx == 0, */
  566. /* as it happens very often! */
  567. /* perform vertical clipping */
  568. {
  569. TCoord min, max;
  570. min = ey1;
  571. max = ey2;
  572. if ( ey1 > ey2 )
  573. {
  574. min = ey2;
  575. max = ey1;
  576. }
  577. if ( min >= ras.max_ey || max < ras.min_ey )
  578. goto End;
  579. }
  580. /* everything is on a single scanline */
  581. if ( ey1 == ey2 )
  582. {
  583. gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
  584. goto End;
  585. }
  586. /* vertical line - avoid calling gray_render_scanline */
  587. incr = 1;
  588. if ( dx == 0 )
  589. {
  590. TCoord ex = TRUNC( ras.x );
  591. TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
  592. TArea area;
  593. first = ONE_PIXEL;
  594. if ( dy < 0 )
  595. {
  596. first = 0;
  597. incr = -1;
  598. }
  599. delta = (int)( first - fy1 );
  600. ras.area += (TArea)two_fx * delta;
  601. ras.cover += delta;
  602. ey1 += incr;
  603. gray_set_cell( RAS_VAR_ ex, ey1 );
  604. delta = (int)( first + first - ONE_PIXEL );
  605. area = (TArea)two_fx * delta;
  606. while ( ey1 != ey2 )
  607. {
  608. ras.area += area;
  609. ras.cover += delta;
  610. ey1 += incr;
  611. gray_set_cell( RAS_VAR_ ex, ey1 );
  612. }
  613. delta = (int)( fy2 - ONE_PIXEL + first );
  614. ras.area += (TArea)two_fx * delta;
  615. ras.cover += delta;
  616. goto End;
  617. }
  618. /* ok, we have to render several scanlines */
  619. p = ( ONE_PIXEL - fy1 ) * dx;
  620. first = ONE_PIXEL;
  621. incr = 1;
  622. if ( dy < 0 )
  623. {
  624. p = fy1 * dx;
  625. first = 0;
  626. incr = -1;
  627. dy = -dy;
  628. }
  629. delta = (int)( p / dy );
  630. mod = (int)( p % dy );
  631. if ( mod < 0 )
  632. {
  633. delta--;
  634. mod += (TCoord)dy;
  635. }
  636. x = ras.x + delta;
  637. gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
  638. ey1 += incr;
  639. gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
  640. if ( ey1 != ey2 )
  641. {
  642. p = ONE_PIXEL * dx;
  643. lift = (int)( p / dy );
  644. rem = (int)( p % dy );
  645. if ( rem < 0 )
  646. {
  647. lift--;
  648. rem += (int)dy;
  649. }
  650. mod -= (int)dy;
  651. while ( ey1 != ey2 )
  652. {
  653. delta = lift;
  654. mod += rem;
  655. if ( mod >= 0 )
  656. {
  657. mod -= (int)dy;
  658. delta++;
  659. }
  660. x2 = x + delta;
  661. gray_render_scanline( RAS_VAR_ ey1, x,
  662. (TCoord)( ONE_PIXEL - first ), x2,
  663. (TCoord)first );
  664. x = x2;
  665. ey1 += incr;
  666. gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
  667. }
  668. }
  669. gray_render_scanline( RAS_VAR_ ey1, x,
  670. (TCoord)( ONE_PIXEL - first ), to_x,
  671. fy2 );
  672. End:
  673. ras.x = to_x;
  674. ras.y = to_y;
  675. ras.last_ey = SUBPIXELS( ey2 );
  676. }
  677. static void
  678. gray_split_conic( FT_Vector* base )
  679. {
  680. TPos a, b;
  681. base[4].x = base[2].x;
  682. b = base[1].x;
  683. a = base[3].x = ( base[2].x + b ) / 2;
  684. b = base[1].x = ( base[0].x + b ) / 2;
  685. base[2].x = ( a + b ) / 2;
  686. base[4].y = base[2].y;
  687. b = base[1].y;
  688. a = base[3].y = ( base[2].y + b ) / 2;
  689. b = base[1].y = ( base[0].y + b ) / 2;
  690. base[2].y = ( a + b ) / 2;
  691. }
  692. static void
  693. gray_render_conic( RAS_ARG_ const FT_Vector* control,
  694. const FT_Vector* to )
  695. {
  696. TPos dx, dy;
  697. TPos min, max, y;
  698. int top, level;
  699. int* levels;
  700. FT_Vector* arc;
  701. levels = ras.lev_stack;
  702. arc = ras.bez_stack;
  703. arc[0].x = UPSCALE( to->x );
  704. arc[0].y = UPSCALE( to->y );
  705. arc[1].x = UPSCALE( control->x );
  706. arc[1].y = UPSCALE( control->y );
  707. arc[2].x = ras.x;
  708. arc[2].y = ras.y;
  709. top = 0;
  710. dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
  711. dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
  712. if ( dx < dy )
  713. dx = dy;
  714. if ( dx < ONE_PIXEL / 4 )
  715. goto Draw;
  716. /* short-cut the arc that crosses the current band */
  717. min = max = arc[0].y;
  718. y = arc[1].y;
  719. if ( y < min ) min = y;
  720. if ( y > max ) max = y;
  721. y = arc[2].y;
  722. if ( y < min ) min = y;
  723. if ( y > max ) max = y;
  724. if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
  725. goto Draw;
  726. level = 0;
  727. do
  728. {
  729. dx >>= 2;
  730. level++;
  731. } while ( dx > ONE_PIXEL / 4 );
  732. levels[0] = level;
  733. do
  734. {
  735. level = levels[top];
  736. if ( level > 0 )
  737. {
  738. gray_split_conic( arc );
  739. arc += 2;
  740. top++;
  741. levels[top] = levels[top - 1] = level - 1;
  742. continue;
  743. }
  744. Draw:
  745. gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
  746. top--;
  747. arc -= 2;
  748. } while ( top >= 0 );
  749. }
  750. static void
  751. gray_split_cubic( FT_Vector* base )
  752. {
  753. TPos a, b, c, d;
  754. base[6].x = base[3].x;
  755. c = base[1].x;
  756. d = base[2].x;
  757. base[1].x = a = ( base[0].x + c ) / 2;
  758. base[5].x = b = ( base[3].x + d ) / 2;
  759. c = ( c + d ) / 2;
  760. base[2].x = a = ( a + c ) / 2;
  761. base[4].x = b = ( b + c ) / 2;
  762. base[3].x = ( a + b ) / 2;
  763. base[6].y = base[3].y;
  764. c = base[1].y;
  765. d = base[2].y;
  766. base[1].y = a = ( base[0].y + c ) / 2;
  767. base[5].y = b = ( base[3].y + d ) / 2;
  768. c = ( c + d ) / 2;
  769. base[2].y = a = ( a + c ) / 2;
  770. base[4].y = b = ( b + c ) / 2;
  771. base[3].y = ( a + b ) / 2;
  772. }
  773. static void
  774. gray_render_cubic( RAS_ARG_ const FT_Vector* control1,
  775. const FT_Vector* control2,
  776. const FT_Vector* to )
  777. {
  778. FT_Vector* arc;
  779. TPos min, max, y;
  780. arc = ras.bez_stack;
  781. arc[0].x = UPSCALE( to->x );
  782. arc[0].y = UPSCALE( to->y );
  783. arc[1].x = UPSCALE( control2->x );
  784. arc[1].y = UPSCALE( control2->y );
  785. arc[2].x = UPSCALE( control1->x );
  786. arc[2].y = UPSCALE( control1->y );
  787. arc[3].x = ras.x;
  788. arc[3].y = ras.y;
  789. /* Short-cut the arc that crosses the current band. */
  790. min = max = arc[0].y;
  791. y = arc[1].y;
  792. if ( y < min )
  793. min = y;
  794. if ( y > max )
  795. max = y;
  796. y = arc[2].y;
  797. if ( y < min )
  798. min = y;
  799. if ( y > max )
  800. max = y;
  801. y = arc[3].y;
  802. if ( y < min )
  803. min = y;
  804. if ( y > max )
  805. max = y;
  806. if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
  807. goto Draw;
  808. for (;;)
  809. {
  810. /* Decide whether to split or draw. See `Rapid Termination */
  811. /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
  812. /* F. Hain, at */
  813. /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
  814. {
  815. TPos dx, dy, dx_, dy_;
  816. TPos dx1, dy1, dx2, dy2;
  817. TPos L, s, s_limit;
  818. /* dx and dy are x and y components of the P0-P3 chord vector. */
  819. dx = arc[3].x - arc[0].x;
  820. dy = arc[3].y - arc[0].y;
  821. /* L is an (under)estimate of the Euclidean distance P0-P3. */
  822. /* */
  823. /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated */
  824. /* with least maximum error by */
  825. /* */
  826. /* r_upperbound = dx + (sqrt(2) - 1) * dy , */
  827. /* */
  828. /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
  829. /* error of no more than 8.4%. */
  830. /* */
  831. /* Similarly, some elementary calculus shows that r can be */
  832. /* underestimated with least maximum error by */
  833. /* */
  834. /* r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx */
  835. /* + sqrt(2 - sqrt(2)) / 2 * dy . */
  836. /* */
  837. /* 236/256 and 97/256 are (under)estimates of the two algebraic */
  838. /* numbers, giving an error of no more than 8.1%. */
  839. dx_ = FT_ABS( dx );
  840. dy_ = FT_ABS( dy );
  841. /* This is the same as */
  842. /* */
  843. /* L = ( 236 * FT_MAX( dx_, dy_ ) */
  844. /* + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
  845. L = ( dx_ > dy_ ? 236 * dx_ + 97 * dy_
  846. : 97 * dx_ + 236 * dy_ ) >> 8;
  847. /* Avoid possible arithmetic overflow below by splitting. */
  848. if ( L > 32767 )
  849. goto Split;
  850. /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
  851. s_limit = L * (TPos)( ONE_PIXEL / 6 );
  852. /* s is L * the perpendicular distance from P1 to the line P0-P3. */
  853. dx1 = arc[1].x - arc[0].x;
  854. dy1 = arc[1].y - arc[0].y;
  855. s = FT_ABS( dy * dx1 - dx * dy1 );
  856. if ( s > s_limit )
  857. goto Split;
  858. /* s is L * the perpendicular distance from P2 to the line P0-P3. */
  859. dx2 = arc[2].x - arc[0].x;
  860. dy2 = arc[2].y - arc[0].y;
  861. s = FT_ABS( dy * dx2 - dx * dy2 );
  862. if ( s > s_limit )
  863. goto Split;
  864. /* If P1 or P2 is outside P0-P3, split the curve. */
  865. if ( dy * dy1 + dx * dx1 < 0 ||
  866. dy * dy2 + dx * dx2 < 0 ||
  867. dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||
  868. dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )
  869. goto Split;
  870. /* No reason to split. */
  871. goto Draw;
  872. }
  873. Split:
  874. gray_split_cubic( arc );
  875. arc += 3;
  876. continue;
  877. Draw:
  878. gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
  879. if ( arc == ras.bez_stack )
  880. return;
  881. arc -= 3;
  882. }
  883. }
  884. static int
  885. gray_move_to( const FT_Vector* to,
  886. gray_PWorker worker )
  887. {
  888. TPos x, y;
  889. /* record current cell, if any */
  890. gray_record_cell( RAS_VAR );
  891. /* start to a new position */
  892. x = UPSCALE( to->x );
  893. y = UPSCALE( to->y );
  894. gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
  895. worker->x = x;
  896. worker->y = y;
  897. return 0;
  898. }
  899. static int
  900. gray_line_to( const FT_Vector* to,
  901. gray_PWorker worker )
  902. {
  903. gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
  904. return 0;
  905. }
  906. static int
  907. gray_conic_to( const FT_Vector* control,
  908. const FT_Vector* to,
  909. gray_PWorker worker )
  910. {
  911. gray_render_conic( RAS_VAR_ control, to );
  912. return 0;
  913. }
  914. static int
  915. gray_cubic_to( const FT_Vector* control1,
  916. const FT_Vector* control2,
  917. const FT_Vector* to,
  918. gray_PWorker worker )
  919. {
  920. gray_render_cubic( RAS_VAR_ control1, control2, to );
  921. return 0;
  922. }
  923. static void
  924. gray_render_span( int y,
  925. int count,
  926. const FT_Span* spans,
  927. gray_PWorker worker )
  928. {
  929. unsigned char* p;
  930. FT_Bitmap* map = &worker->target;
  931. /* first of all, compute the scanline offset */
  932. p = (unsigned char*)map->buffer - y * map->pitch;
  933. if ( map->pitch >= 0 )
  934. p += (unsigned)( ( map->rows - 1 ) * map->pitch );
  935. for ( ; count > 0; count--, spans++ )
  936. {
  937. unsigned char coverage = spans->coverage;
  938. if ( coverage )
  939. {
  940. /* For small-spans it is faster to do it by ourselves than
  941. * calling `memset'. This is mainly due to the cost of the
  942. * function call.
  943. */
  944. if ( spans->len >= 8 )
  945. FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
  946. else
  947. {
  948. unsigned char* q = p + spans->x;
  949. switch ( spans->len )
  950. {
  951. case 7: *q++ = (unsigned char)coverage;
  952. case 6: *q++ = (unsigned char)coverage;
  953. case 5: *q++ = (unsigned char)coverage;
  954. case 4: *q++ = (unsigned char)coverage;
  955. case 3: *q++ = (unsigned char)coverage;
  956. case 2: *q++ = (unsigned char)coverage;
  957. case 1: *q = (unsigned char)coverage;
  958. default:
  959. ;
  960. }
  961. }
  962. }
  963. }
  964. }
  965. static void
  966. gray_hline( RAS_ARG_ TCoord x,
  967. TCoord y,
  968. TPos area,
  969. TCoord acount )
  970. {
  971. FT_Span* span;
  972. int count;
  973. int coverage;
  974. /* compute the coverage line's coverage, depending on the */
  975. /* outline fill rule */
  976. /* */
  977. /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
  978. /* */
  979. coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
  980. /* use range 0..256 */
  981. if ( coverage < 0 )
  982. coverage = -coverage;
  983. if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
  984. {
  985. coverage &= 511;
  986. if ( coverage > 256 )
  987. coverage = 512 - coverage;
  988. else if ( coverage == 256 )
  989. coverage = 255;
  990. }
  991. else
  992. {
  993. /* normal non-zero winding rule */
  994. if ( coverage >= 256 )
  995. coverage = 255;
  996. }
  997. y += (TCoord)ras.min_ey;
  998. x += (TCoord)ras.min_ex;
  999. /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
  1000. if ( x >= 32767 )
  1001. x = 32767;
  1002. /* FT_Span.y is an integer, so limit our coordinates appropriately */
  1003. if ( y >= FT_INT_MAX )
  1004. y = FT_INT_MAX;
  1005. if ( coverage )
  1006. {
  1007. /* see whether we can add this span to the current list */
  1008. count = ras.num_gray_spans;
  1009. span = ras.gray_spans + count - 1;
  1010. if ( count > 0 &&
  1011. ras.span_y == y &&
  1012. (int)span->x + span->len == (int)x &&
  1013. span->coverage == coverage )
  1014. {
  1015. span->len = (unsigned short)( span->len + acount );
  1016. return;
  1017. }
  1018. if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
  1019. {
  1020. if ( ras.render_span && count > 0 )
  1021. ras.render_span( ras.span_y, count, ras.gray_spans,
  1022. ras.render_span_data );
  1023. #ifdef FT_DEBUG_LEVEL_TRACE
  1024. if ( count > 0 )
  1025. {
  1026. int n;
  1027. FT_TRACE7(( "y = %3d ", ras.span_y ));
  1028. span = ras.gray_spans;
  1029. for ( n = 0; n < count; n++, span++ )
  1030. FT_TRACE7(( "[%d..%d]:%02x ",
  1031. span->x, span->x + span->len - 1, span->coverage ));
  1032. FT_TRACE7(( "\n" ));
  1033. }
  1034. #endif /* FT_DEBUG_LEVEL_TRACE */
  1035. ras.num_gray_spans = 0;
  1036. ras.span_y = (int)y;
  1037. count = 0;
  1038. span = ras.gray_spans;
  1039. }
  1040. else
  1041. span++;
  1042. /* add a gray span to the current list */
  1043. span->x = (short)x;
  1044. span->len = (unsigned short)acount;
  1045. span->coverage = (unsigned char)coverage;
  1046. ras.num_gray_spans++;
  1047. }
  1048. }
  1049. #ifdef FT_DEBUG_LEVEL_TRACE
  1050. /* to be called while in the debugger -- */
  1051. /* this function causes a compiler warning since it is unused otherwise */
  1052. static void
  1053. gray_dump_cells( RAS_ARG )
  1054. {
  1055. int yindex;
  1056. for ( yindex = 0; yindex < ras.ycount; yindex++ )
  1057. {
  1058. PCell cell;
  1059. printf( "%3d:", yindex );
  1060. for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
  1061. printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
  1062. printf( "\n" );
  1063. }
  1064. }
  1065. #endif /* FT_DEBUG_LEVEL_TRACE */
  1066. static void
  1067. gray_sweep( RAS_ARG_ const FT_Bitmap* target )
  1068. {
  1069. int yindex;
  1070. FT_UNUSED( target );
  1071. if ( ras.num_cells == 0 )
  1072. return;
  1073. ras.num_gray_spans = 0;
  1074. FT_TRACE7(( "gray_sweep: start\n" ));
  1075. for ( yindex = 0; yindex < ras.ycount; yindex++ )
  1076. {
  1077. PCell cell = ras.ycells[yindex];
  1078. TCoord cover = 0;
  1079. TCoord x = 0;
  1080. for ( ; cell != NULL; cell = cell->next )
  1081. {
  1082. TPos area;
  1083. if ( cell->x > x && cover != 0 )
  1084. gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
  1085. cell->x - x );
  1086. cover += cell->cover;
  1087. area = cover * ( ONE_PIXEL * 2 ) - cell->area;
  1088. if ( area != 0 && cell->x >= 0 )
  1089. gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
  1090. x = cell->x + 1;
  1091. }
  1092. if ( cover != 0 )
  1093. gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
  1094. ras.count_ex - x );
  1095. }
  1096. if ( ras.render_span && ras.num_gray_spans > 0 )
  1097. ras.render_span( ras.span_y, ras.num_gray_spans,
  1098. ras.gray_spans, ras.render_span_data );
  1099. FT_TRACE7(( "gray_sweep: end\n" ));
  1100. }
  1101. #ifdef _STANDALONE_
  1102. /*************************************************************************/
  1103. /* */
  1104. /* The following function should only compile in stand-alone mode, */
  1105. /* i.e., when building this component without the rest of FreeType. */
  1106. /* */
  1107. /*************************************************************************/
  1108. /*************************************************************************/
  1109. /* */
  1110. /* <Function> */
  1111. /* FT_Outline_Decompose */
  1112. /* */
  1113. /* <Description> */
  1114. /* Walk over an outline's structure to decompose it into individual */
  1115. /* segments and BÄ‚Å zier arcs. This function is also able to emit */
  1116. /* `move to' and `close to' operations to indicate the start and end */
  1117. /* of new contours in the outline. */
  1118. /* */
  1119. /* <Input> */
  1120. /* outline :: A pointer to the source target. */
  1121. /* */
  1122. /* func_interface :: A table of `emitters', i.e., function pointers */
  1123. /* called during decomposition to indicate path */
  1124. /* operations. */
  1125. /* */
  1126. /* <InOut> */
  1127. /* user :: A typeless pointer which is passed to each */
  1128. /* emitter during the decomposition. It can be */
  1129. /* used to store the state during the */
  1130. /* decomposition. */
  1131. /* */
  1132. /* <Return> */
  1133. /* Error code. 0 means success. */
  1134. /* */
  1135. static int
  1136. FT_Outline_Decompose( const FT_Outline* outline,
  1137. const FT_Outline_Funcs* func_interface,
  1138. void* user )
  1139. {
  1140. #undef SCALED
  1141. #define SCALED( x ) ( ( (x) << shift ) - delta )
  1142. FT_Vector v_last;
  1143. FT_Vector v_control;
  1144. FT_Vector v_start;
  1145. FT_Vector* point;
  1146. FT_Vector* limit;
  1147. char* tags;
  1148. int error;
  1149. int n; /* index of contour in outline */
  1150. int first; /* index of first point in contour */
  1151. char tag; /* current point's state */
  1152. int shift;
  1153. TPos delta;
  1154. if ( !outline || !func_interface )
  1155. return ErrRaster_Invalid_Argument;
  1156. shift = func_interface->shift;
  1157. delta = func_interface->delta;
  1158. first = 0;
  1159. for ( n = 0; n < outline->n_contours; n++ )
  1160. {
  1161. int last; /* index of last point in contour */
  1162. FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
  1163. last = outline->contours[n];
  1164. if ( last < 0 )
  1165. goto Invalid_Outline;
  1166. limit = outline->points + last;
  1167. v_start = outline->points[first];
  1168. v_start.x = SCALED( v_start.x );
  1169. v_start.y = SCALED( v_start.y );
  1170. v_last = outline->points[last];
  1171. v_last.x = SCALED( v_last.x );
  1172. v_last.y = SCALED( v_last.y );
  1173. v_control = v_start;
  1174. point = outline->points + first;
  1175. tags = outline->tags + first;
  1176. tag = FT_CURVE_TAG( tags[0] );
  1177. /* A contour cannot start with a cubic control point! */
  1178. if ( tag == FT_CURVE_TAG_CUBIC )
  1179. goto Invalid_Outline;
  1180. /* check first point to determine origin */
  1181. if ( tag == FT_CURVE_TAG_CONIC )
  1182. {
  1183. /* first point is conic control. Yes, this happens. */
  1184. if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
  1185. {
  1186. /* start at last point if it is on the curve */
  1187. v_start = v_last;
  1188. limit--;
  1189. }
  1190. else
  1191. {
  1192. /* if both first and last points are conic, */
  1193. /* start at their middle and record its position */
  1194. /* for closure */
  1195. v_start.x = ( v_start.x + v_last.x ) / 2;
  1196. v_start.y = ( v_start.y + v_last.y ) / 2;
  1197. v_last = v_start;
  1198. }
  1199. point--;
  1200. tags--;
  1201. }
  1202. FT_TRACE5(( " move to (%.2f, %.2f)\n",
  1203. v_start.x / 64.0, v_start.y / 64.0 ));
  1204. error = func_interface->move_to( &v_start, user );
  1205. if ( error )
  1206. goto Exit;
  1207. while ( point < limit )
  1208. {
  1209. point++;
  1210. tags++;
  1211. tag = FT_CURVE_TAG( tags[0] );
  1212. switch ( tag )
  1213. {
  1214. case FT_CURVE_TAG_ON: /* emit a single line_to */
  1215. {
  1216. FT_Vector vec;
  1217. vec.x = SCALED( point->x );
  1218. vec.y = SCALED( point->y );
  1219. FT_TRACE5(( " line to (%.2f, %.2f)\n",
  1220. vec.x / 64.0, vec.y / 64.0 ));
  1221. error = func_interface->line_to( &vec, user );
  1222. if ( error )
  1223. goto Exit;
  1224. continue;
  1225. }
  1226. case FT_CURVE_TAG_CONIC: /* consume conic arcs */
  1227. v_control.x = SCALED( point->x );
  1228. v_control.y = SCALED( point->y );
  1229. Do_Conic:
  1230. if ( point < limit )
  1231. {
  1232. FT_Vector vec;
  1233. FT_Vector v_middle;
  1234. point++;
  1235. tags++;
  1236. tag = FT_CURVE_TAG( tags[0] );
  1237. vec.x = SCALED( point->x );
  1238. vec.y = SCALED( point->y );
  1239. if ( tag == FT_CURVE_TAG_ON )
  1240. {
  1241. FT_TRACE5(( " conic to (%.2f, %.2f)"
  1242. " with control (%.2f, %.2f)\n",
  1243. vec.x / 64.0, vec.y / 64.0,
  1244. v_control.x / 64.0, v_control.y / 64.0 ));
  1245. error = func_interface->conic_to( &v_control, &vec, user );
  1246. if ( error )
  1247. goto Exit;
  1248. continue;
  1249. }
  1250. if ( tag != FT_CURVE_TAG_CONIC )
  1251. goto Invalid_Outline;
  1252. v_middle.x = ( v_control.x + vec.x ) / 2;
  1253. v_middle.y = ( v_control.y + vec.y ) / 2;
  1254. FT_TRACE5(( " conic to (%.2f, %.2f)"
  1255. " with control (%.2f, %.2f)\n",
  1256. v_middle.x / 64.0, v_middle.y / 64.0,
  1257. v_control.x / 64.0, v_control.y / 64.0 ));
  1258. error = func_interface->conic_to( &v_control, &v_middle, user );
  1259. if ( error )
  1260. goto Exit;
  1261. v_control = vec;
  1262. goto Do_Conic;
  1263. }
  1264. FT_TRACE5(( " conic to (%.2f, %.2f)"
  1265. " with control (%.2f, %.2f)\n",
  1266. v_start.x / 64.0, v_start.y / 64.0,
  1267. v_control.x / 64.0, v_control.y / 64.0 ));
  1268. error = func_interface->conic_to( &v_control, &v_start, user );
  1269. goto Close;
  1270. default: /* FT_CURVE_TAG_CUBIC */
  1271. {
  1272. FT_Vector vec1, vec2;
  1273. if ( point + 1 > limit ||
  1274. FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
  1275. goto Invalid_Outline;
  1276. point += 2;
  1277. tags += 2;
  1278. vec1.x = SCALED( point[-2].x );
  1279. vec1.y = SCALED( point[-2].y );
  1280. vec2.x = SCALED( point[-1].x );
  1281. vec2.y = SCALED( point[-1].y );
  1282. if ( point <= limit )
  1283. {
  1284. FT_Vector vec;
  1285. vec.x = SCALED( point->x );
  1286. vec.y = SCALED( point->y );
  1287. FT_TRACE5(( " cubic to (%.2f, %.2f)"
  1288. " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
  1289. vec.x / 64.0, vec.y / 64.0,
  1290. vec1.x / 64.0, vec1.y / 64.0,
  1291. vec2.x / 64.0, vec2.y / 64.0 ));
  1292. error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
  1293. if ( error )
  1294. goto Exit;
  1295. continue;
  1296. }
  1297. FT_TRACE5(( " cubic to (%.2f, %.2f)"
  1298. " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
  1299. v_start.x / 64.0, v_start.y / 64.0,
  1300. vec1.x / 64.0, vec1.y / 64.0,
  1301. vec2.x / 64.0, vec2.y / 64.0 ));
  1302. error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
  1303. goto Close;
  1304. }
  1305. }
  1306. }
  1307. /* close the contour with a line segment */
  1308. FT_TRACE5(( " line to (%.2f, %.2f)\n",
  1309. v_start.x / 64.0, v_start.y / 64.0 ));
  1310. error = func_interface->line_to( &v_start, user );
  1311. Close:
  1312. if ( error )
  1313. goto Exit;
  1314. first = last + 1;
  1315. }
  1316. FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
  1317. return 0;
  1318. Exit:
  1319. FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
  1320. return error;
  1321. Invalid_Outline:
  1322. return ErrRaster_Invalid_Outline;
  1323. }
  1324. #endif /* _STANDALONE_ */
  1325. typedef struct gray_TBand_
  1326. {
  1327. TPos min, max;
  1328. } gray_TBand;
  1329. FT_DEFINE_OUTLINE_FUNCS(func_interface,
  1330. (FT_Outline_MoveTo_Func) gray_move_to,
  1331. (FT_Outline_LineTo_Func) gray_line_to,
  1332. (FT_Outline_ConicTo_Func)gray_conic_to,
  1333. (FT_Outline_CubicTo_Func)gray_cubic_to,
  1334. 0,
  1335. 0
  1336. )
  1337. static int
  1338. gray_convert_glyph_inner( RAS_ARG )
  1339. {
  1340. volatile int error = 0;
  1341. #ifdef FT_CONFIG_OPTION_PIC
  1342. FT_Outline_Funcs func_interface;
  1343. Init_Class_func_interface(&func_interface);
  1344. #endif
  1345. if ( ft_setjmp( ras.jump_buffer ) == 0 )
  1346. {
  1347. error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
  1348. gray_record_cell( RAS_VAR );
  1349. }
  1350. else
  1351. error = ErrRaster_Memory_Overflow;
  1352. return error;
  1353. }
  1354. static int
  1355. gray_convert_glyph( RAS_ARG )
  1356. {
  1357. gray_TBand bands[40];
  1358. gray_TBand* volatile band;
  1359. int volatile n, num_bands;
  1360. TPos volatile min, max, max_y;
  1361. FT_BBox* clip;
  1362. /* Set up state in the raster object */
  1363. gray_compute_cbox( RAS_VAR );
  1364. /* clip to target bitmap, exit if nothing to do */
  1365. clip = &ras.clip_box;
  1366. if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
  1367. ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
  1368. return 0;
  1369. if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
  1370. if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
  1371. if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
  1372. if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
  1373. ras.count_ex = ras.max_ex - ras.min_ex;
  1374. ras.count_ey = ras.max_ey - ras.min_ey;
  1375. /* set up vertical bands */
  1376. num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
  1377. if ( num_bands == 0 )
  1378. num_bands = 1;
  1379. if ( num_bands >= 39 )
  1380. num_bands = 39;
  1381. ras.band_shoot = 0;
  1382. min = ras.min_ey;
  1383. max_y = ras.max_ey;
  1384. for ( n = 0; n < num_bands; n++, min = max )
  1385. {
  1386. max = min + ras.band_size;
  1387. if ( n == num_bands - 1 || max > max_y )
  1388. max = max_y;
  1389. bands[0].min = min;
  1390. bands[0].max = max;
  1391. band = bands;
  1392. while ( band >= bands )
  1393. {
  1394. TPos bottom, top, middle;
  1395. int error;
  1396. {
  1397. PCell cells_max;
  1398. int yindex;
  1399. long cell_start, cell_end, cell_mod;
  1400. ras.ycells = (PCell*)ras.buffer;
  1401. ras.ycount = band->max - band->min;
  1402. cell_start = sizeof ( PCell ) * ras.ycount;
  1403. cell_mod = cell_start % sizeof ( TCell );
  1404. if ( cell_mod > 0 )
  1405. cell_start += sizeof ( TCell ) - cell_mod;
  1406. cell_end = ras.buffer_size;
  1407. cell_end -= cell_end % sizeof ( TCell );
  1408. cells_max = (PCell)( (char*)ras.buffer + cell_end );
  1409. ras.cells = (PCell)( (char*)ras.buffer + cell_start );
  1410. if ( ras.cells >= cells_max )
  1411. goto ReduceBands;
  1412. ras.max_cells = cells_max - ras.cells;
  1413. if ( ras.max_cells < 2 )
  1414. goto ReduceBands;
  1415. for ( yindex = 0; yindex < ras.ycount; yindex++ )
  1416. ras.ycells[yindex] = NULL;
  1417. }
  1418. ras.num_cells = 0;
  1419. ras.invalid = 1;
  1420. ras.min_ey = band->min;
  1421. ras.max_ey = band->max;
  1422. ras.count_ey = band->max - band->min;
  1423. error = gray_convert_glyph_inner( RAS_VAR );
  1424. if ( !error )
  1425. {
  1426. gray_sweep( RAS_VAR_ &ras.target );
  1427. band--;
  1428. continue;
  1429. }
  1430. else if ( error != ErrRaster_Memory_Overflow )
  1431. return 1;
  1432. ReduceBands:
  1433. /* render pool overflow; we will reduce the render band by half */
  1434. bottom = band->min;
  1435. top = band->max;
  1436. middle = bottom + ( ( top - bottom ) >> 1 );
  1437. /* This is too complex for a single scanline; there must */
  1438. /* be some problems. */
  1439. if ( middle == bottom )
  1440. {
  1441. #ifdef FT_DEBUG_LEVEL_TRACE
  1442. FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
  1443. #endif
  1444. return 1;
  1445. }
  1446. if ( bottom-top >= ras.band_size )
  1447. ras.band_shoot++;
  1448. band[1].min = bottom;
  1449. band[1].max = middle;
  1450. band[0].min = middle;
  1451. band[0].max = top;
  1452. band++;
  1453. }
  1454. }
  1455. if ( ras.band_shoot > 8 && ras.band_size > 16 )
  1456. ras.band_size = ras.band_size / 2;
  1457. return 0;
  1458. }
  1459. static int
  1460. gray_raster_render( gray_PRaster raster,
  1461. const FT_Raster_Params* params )
  1462. {
  1463. const FT_Outline* outline = (const FT_Outline*)params->source;
  1464. const FT_Bitmap* target_map = params->target;
  1465. gray_PWorker worker;
  1466. if ( !raster || !raster->buffer || !raster->buffer_size )
  1467. return ErrRaster_Invalid_Argument;
  1468. if ( !outline )
  1469. return ErrRaster_Invalid_Outline;
  1470. /* return immediately if the outline is empty */
  1471. if ( outline->n_points == 0 || outline->n_contours <= 0 )
  1472. return 0;
  1473. if ( !outline->contours || !outline->points )
  1474. return ErrRaster_Invalid_Outline;
  1475. if ( outline->n_points !=
  1476. outline->contours[outline->n_contours - 1] + 1 )
  1477. return ErrRaster_Invalid_Outline;
  1478. worker = raster->worker;
  1479. /* if direct mode is not set, we must have a target bitmap */
  1480. if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
  1481. {
  1482. if ( !target_map )
  1483. return ErrRaster_Invalid_Argument;
  1484. /* nothing to do */
  1485. if ( !target_map->width || !target_map->rows )
  1486. return 0;
  1487. if ( !target_map->buffer )
  1488. return ErrRaster_Invalid_Argument;
  1489. }
  1490. /* this version does not support monochrome rendering */
  1491. if ( !( params->flags & FT_RASTER_FLAG_AA ) )
  1492. return ErrRaster_Invalid_Mode;
  1493. /* compute clipping box */
  1494. if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
  1495. {
  1496. /* compute clip box from target pixmap */
  1497. ras.clip_box.xMin = 0;
  1498. ras.clip_box.yMin = 0;
  1499. ras.clip_box.xMax = target_map->width;
  1500. ras.clip_box.yMax = target_map->rows;
  1501. }
  1502. else if ( params->flags & FT_RASTER_FLAG_CLIP )
  1503. ras.clip_box = params->clip_box;
  1504. else
  1505. {
  1506. ras.clip_box.xMin = -32768L;
  1507. ras.clip_box.yMin = -32768L;
  1508. ras.clip_box.xMax = 32767L;
  1509. ras.clip_box.yMax = 32767L;
  1510. }
  1511. gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
  1512. ras.outline = *outline;
  1513. ras.num_cells = 0;
  1514. ras.invalid = 1;
  1515. ras.band_size = raster->band_size;
  1516. ras.num_gray_spans = 0;
  1517. if ( params->flags & FT_RASTER_FLAG_DIRECT )
  1518. {
  1519. ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
  1520. ras.render_span_data = params->user;
  1521. }
  1522. else
  1523. {
  1524. ras.target = *target_map;
  1525. ras.render_span = (FT_Raster_Span_Func)gray_render_span;
  1526. ras.render_span_data = &ras;
  1527. }
  1528. return gray_convert_glyph( RAS_VAR );
  1529. }
  1530. /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
  1531. /**** a static object. *****/
  1532. #ifdef _STANDALONE_
  1533. static int
  1534. gray_raster_new( void* memory,
  1535. FT_Raster* araster )
  1536. {
  1537. static gray_TRaster the_raster;
  1538. FT_UNUSED( memory );
  1539. *araster = (FT_Raster)&the_raster;
  1540. FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
  1541. return 0;
  1542. }
  1543. static void
  1544. gray_raster_done( FT_Raster raster )
  1545. {
  1546. /* nothing */
  1547. FT_UNUSED( raster );
  1548. }
  1549. #else /* !_STANDALONE_ */
  1550. static int
  1551. gray_raster_new( FT_Memory memory,
  1552. FT_Raster* araster )
  1553. {
  1554. FT_Error error;
  1555. gray_PRaster raster = NULL;
  1556. *araster = 0;
  1557. if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
  1558. {
  1559. raster->memory = memory;
  1560. *araster = (FT_Raster)raster;
  1561. }
  1562. return error;
  1563. }
  1564. static void
  1565. gray_raster_done( FT_Raster raster )
  1566. {
  1567. FT_Memory memory = (FT_Memory)((gray_PRaster)raster)->memory;
  1568. FT_FREE( raster );
  1569. }
  1570. #endif /* !_STANDALONE_ */
  1571. static void
  1572. gray_raster_reset( FT_Raster raster,
  1573. char* pool_base,
  1574. long pool_size )
  1575. {
  1576. gray_PRaster rast = (gray_PRaster)raster;
  1577. if ( raster )
  1578. {
  1579. if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
  1580. {
  1581. gray_PWorker worker = (gray_PWorker)pool_base;
  1582. rast->worker = worker;
  1583. rast->buffer = pool_base +
  1584. ( ( sizeof ( gray_TWorker ) +
  1585. sizeof ( TCell ) - 1 ) &
  1586. ~( sizeof ( TCell ) - 1 ) );
  1587. rast->buffer_size = (long)( ( pool_base + pool_size ) -
  1588. (char*)rast->buffer ) &
  1589. ~( sizeof ( TCell ) - 1 );
  1590. rast->band_size = (int)( rast->buffer_size /
  1591. ( sizeof ( TCell ) * 8 ) );
  1592. }
  1593. else
  1594. {
  1595. rast->buffer = NULL;
  1596. rast->buffer_size = 0;
  1597. rast->worker = NULL;
  1598. }
  1599. }
  1600. }
  1601. FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
  1602. FT_GLYPH_FORMAT_OUTLINE,
  1603. (FT_Raster_New_Func) gray_raster_new,
  1604. (FT_Raster_Reset_Func) gray_raster_reset,
  1605. (FT_Raster_Set_Mode_Func)0,
  1606. (FT_Raster_Render_Func) gray_raster_render,
  1607. (FT_Raster_Done_Func) gray_raster_done
  1608. )
  1609. /* END */
  1610. /* Local Variables: */
  1611. /* coding: utf-8 */
  1612. /* End: */