PageRenderTime 55ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/compiler/android-ndk/jni/freetype/src/smooth/ftgrays.c

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