ftoutln.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /***************************************************************************/
  2. /* */
  3. /* ftoutln.c */
  4. /* */
  5. /* FreeType outline management (body). */
  6. /* */
  7. /* Copyright 1996-2001, 2002 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. /* All functions are declared in freetype.h. */
  20. /* */
  21. /*************************************************************************/
  22. #include <ft2build.h>
  23. #include FT_OUTLINE_H
  24. #include FT_INTERNAL_OBJECTS_H
  25. /*************************************************************************/
  26. /* */
  27. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  28. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  29. /* messages during execution. */
  30. /* */
  31. #undef FT_COMPONENT
  32. #define FT_COMPONENT trace_outline
  33. static
  34. const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 };
  35. /* documentation is in ftoutln.h */
  36. FT_EXPORT_DEF( FT_Error )
  37. FT_Outline_Decompose( FT_Outline* outline,
  38. const FT_Outline_Funcs* func_interface,
  39. void* user )
  40. {
  41. #undef SCALED
  42. #define SCALED( x ) ( ( (x) << shift ) - delta )
  43. FT_Vector v_last;
  44. FT_Vector v_control;
  45. FT_Vector v_start;
  46. FT_Vector* point;
  47. FT_Vector* limit;
  48. char* tags;
  49. FT_Error error;
  50. FT_Int n; /* index of contour in outline */
  51. FT_UInt first; /* index of first point in contour */
  52. FT_Int tag; /* current point's state */
  53. FT_Int shift;
  54. FT_Pos delta;
  55. if ( !outline || !func_interface )
  56. return FT_Err_Invalid_Argument;
  57. shift = func_interface->shift;
  58. delta = func_interface->delta;
  59. first = 0;
  60. for ( n = 0; n < outline->n_contours; n++ )
  61. {
  62. FT_Int last; /* index of last point in contour */
  63. last = outline->contours[n];
  64. limit = outline->points + last;
  65. v_start = outline->points[first];
  66. v_last = outline->points[last];
  67. v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
  68. v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
  69. v_control = v_start;
  70. point = outline->points + first;
  71. tags = outline->tags + first;
  72. tag = FT_CURVE_TAG( tags[0] );
  73. /* A contour cannot start with a cubic control point! */
  74. if ( tag == FT_CURVE_TAG_CUBIC )
  75. goto Invalid_Outline;
  76. /* check first point to determine origin */
  77. if ( tag == FT_CURVE_TAG_CONIC )
  78. {
  79. /* first point is conic control. Yes, this happens. */
  80. if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
  81. {
  82. /* start at last point if it is on the curve */
  83. v_start = v_last;
  84. limit--;
  85. }
  86. else
  87. {
  88. /* if both first and last points are conic, */
  89. /* start at their middle and record its position */
  90. /* for closure */
  91. v_start.x = ( v_start.x + v_last.x ) / 2;
  92. v_start.y = ( v_start.y + v_last.y ) / 2;
  93. v_last = v_start;
  94. }
  95. point--;
  96. tags--;
  97. }
  98. error = func_interface->move_to( &v_start, user );
  99. if ( error )
  100. goto Exit;
  101. while ( point < limit )
  102. {
  103. point++;
  104. tags++;
  105. tag = FT_CURVE_TAG( tags[0] );
  106. switch ( tag )
  107. {
  108. case FT_CURVE_TAG_ON: /* emit a single line_to */
  109. {
  110. FT_Vector vec;
  111. vec.x = SCALED( point->x );
  112. vec.y = SCALED( point->y );
  113. error = func_interface->line_to( &vec, user );
  114. if ( error )
  115. goto Exit;
  116. continue;
  117. }
  118. case FT_CURVE_TAG_CONIC: /* consume conic arcs */
  119. v_control.x = SCALED( point->x );
  120. v_control.y = SCALED( point->y );
  121. Do_Conic:
  122. if ( point < limit )
  123. {
  124. FT_Vector vec;
  125. FT_Vector v_middle;
  126. point++;
  127. tags++;
  128. tag = FT_CURVE_TAG( tags[0] );
  129. vec.x = SCALED( point->x );
  130. vec.y = SCALED( point->y );
  131. if ( tag == FT_CURVE_TAG_ON )
  132. {
  133. error = func_interface->conic_to( &v_control, &vec, user );
  134. if ( error )
  135. goto Exit;
  136. continue;
  137. }
  138. if ( tag != FT_CURVE_TAG_CONIC )
  139. goto Invalid_Outline;
  140. v_middle.x = ( v_control.x + vec.x ) / 2;
  141. v_middle.y = ( v_control.y + vec.y ) / 2;
  142. error = func_interface->conic_to( &v_control, &v_middle, user );
  143. if ( error )
  144. goto Exit;
  145. v_control = vec;
  146. goto Do_Conic;
  147. }
  148. error = func_interface->conic_to( &v_control, &v_start, user );
  149. goto Close;
  150. default: /* FT_CURVE_TAG_CUBIC */
  151. {
  152. FT_Vector vec1, vec2;
  153. if ( point + 1 > limit ||
  154. FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
  155. goto Invalid_Outline;
  156. point += 2;
  157. tags += 2;
  158. vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
  159. vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
  160. if ( point <= limit )
  161. {
  162. FT_Vector vec;
  163. vec.x = SCALED( point->x );
  164. vec.y = SCALED( point->y );
  165. error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
  166. if ( error )
  167. goto Exit;
  168. continue;
  169. }
  170. error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
  171. goto Close;
  172. }
  173. }
  174. }
  175. /* close the contour with a line segment */
  176. error = func_interface->line_to( &v_start, user );
  177. Close:
  178. if ( error )
  179. goto Exit;
  180. first = last + 1;
  181. }
  182. return 0;
  183. Exit:
  184. return error;
  185. Invalid_Outline:
  186. return FT_Err_Invalid_Outline;
  187. }
  188. FT_EXPORT_DEF( FT_Error )
  189. FT_Outline_New_Internal( FT_Memory memory,
  190. FT_UInt numPoints,
  191. FT_Int numContours,
  192. FT_Outline *anoutline )
  193. {
  194. FT_Error error;
  195. if ( !anoutline || !memory )
  196. return FT_Err_Invalid_Argument;
  197. *anoutline = null_outline;
  198. if ( FT_NEW_ARRAY( anoutline->points, numPoints * 2L ) ||
  199. FT_NEW_ARRAY( anoutline->tags, numPoints ) ||
  200. FT_NEW_ARRAY( anoutline->contours, numContours ) )
  201. goto Fail;
  202. anoutline->n_points = (FT_UShort)numPoints;
  203. anoutline->n_contours = (FT_Short)numContours;
  204. anoutline->flags |= FT_OUTLINE_OWNER;
  205. return FT_Err_Ok;
  206. Fail:
  207. anoutline->flags |= FT_OUTLINE_OWNER;
  208. FT_Outline_Done_Internal( memory, anoutline );
  209. return error;
  210. }
  211. /* documentation is in ftoutln.h */
  212. FT_EXPORT_DEF( FT_Error )
  213. FT_Outline_New( FT_Library library,
  214. FT_UInt numPoints,
  215. FT_Int numContours,
  216. FT_Outline *anoutline )
  217. {
  218. if ( !library )
  219. return FT_Err_Invalid_Library_Handle;
  220. return FT_Outline_New_Internal( library->memory, numPoints,
  221. numContours, anoutline );
  222. }
  223. /* documentation is in ftoutln.h */
  224. FT_EXPORT_DEF( FT_Error )
  225. FT_Outline_Check( FT_Outline* outline )
  226. {
  227. if ( outline )
  228. {
  229. FT_Int n_points = outline->n_points;
  230. FT_Int n_contours = outline->n_contours;
  231. FT_Int end0, end;
  232. FT_Int n;
  233. /* empty glyph? */
  234. if ( n_points == 0 && n_contours == 0 )
  235. return 0;
  236. /* check point and contour counts */
  237. if ( n_points <= 0 || n_contours <= 0 )
  238. goto Bad;
  239. end0 = end = -1;
  240. for ( n = 0; n < n_contours; n++ )
  241. {
  242. end = outline->contours[n];
  243. /* note that we don't accept empty contours */
  244. if ( end <= end0 || end >= n_points )
  245. goto Bad;
  246. end0 = end;
  247. }
  248. if ( end != n_points - 1 )
  249. goto Bad;
  250. /* XXX: check the tags array */
  251. return 0;
  252. }
  253. Bad:
  254. return FT_Err_Invalid_Argument;
  255. }
  256. /* documentation is in ftoutln.h */
  257. FT_EXPORT_DEF( FT_Error )
  258. FT_Outline_Copy( FT_Outline* source,
  259. FT_Outline *target )
  260. {
  261. FT_Int is_owner;
  262. if ( !source || !target ||
  263. source->n_points != target->n_points ||
  264. source->n_contours != target->n_contours )
  265. return FT_Err_Invalid_Argument;
  266. FT_MEM_COPY( target->points, source->points,
  267. source->n_points * sizeof ( FT_Vector ) );
  268. FT_MEM_COPY( target->tags, source->tags,
  269. source->n_points * sizeof ( FT_Byte ) );
  270. FT_MEM_COPY( target->contours, source->contours,
  271. source->n_contours * sizeof ( FT_Short ) );
  272. /* copy all flags, except the `FT_OUTLINE_OWNER' one */
  273. is_owner = target->flags & FT_OUTLINE_OWNER;
  274. target->flags = source->flags;
  275. target->flags &= ~FT_OUTLINE_OWNER;
  276. target->flags |= is_owner;
  277. return FT_Err_Ok;
  278. }
  279. FT_EXPORT_DEF( FT_Error )
  280. FT_Outline_Done_Internal( FT_Memory memory,
  281. FT_Outline* outline )
  282. {
  283. if ( outline )
  284. {
  285. if ( outline->flags & FT_OUTLINE_OWNER )
  286. {
  287. FT_FREE( outline->points );
  288. FT_FREE( outline->tags );
  289. FT_FREE( outline->contours );
  290. }
  291. *outline = null_outline;
  292. return FT_Err_Ok;
  293. }
  294. else
  295. return FT_Err_Invalid_Argument;
  296. }
  297. /* documentation is in ftoutln.h */
  298. FT_EXPORT_DEF( FT_Error )
  299. FT_Outline_Done( FT_Library library,
  300. FT_Outline* outline )
  301. {
  302. /* check for valid `outline' in FT_Outline_Done_Internal() */
  303. if ( !library )
  304. return FT_Err_Invalid_Library_Handle;
  305. return FT_Outline_Done_Internal( library->memory, outline );
  306. }
  307. /* documentation is in ftoutln.h */
  308. FT_EXPORT_DEF( void )
  309. FT_Outline_Get_CBox( FT_Outline* outline,
  310. FT_BBox *acbox )
  311. {
  312. FT_Pos xMin, yMin, xMax, yMax;
  313. if ( outline && acbox )
  314. {
  315. if ( outline->n_points == 0 )
  316. {
  317. xMin = 0;
  318. yMin = 0;
  319. xMax = 0;
  320. yMax = 0;
  321. }
  322. else
  323. {
  324. FT_Vector* vec = outline->points;
  325. FT_Vector* limit = vec + outline->n_points;
  326. xMin = xMax = vec->x;
  327. yMin = yMax = vec->y;
  328. vec++;
  329. for ( ; vec < limit; vec++ )
  330. {
  331. FT_Pos x, y;
  332. x = vec->x;
  333. if ( x < xMin ) xMin = x;
  334. if ( x > xMax ) xMax = x;
  335. y = vec->y;
  336. if ( y < yMin ) yMin = y;
  337. if ( y > yMax ) yMax = y;
  338. }
  339. }
  340. acbox->xMin = xMin;
  341. acbox->xMax = xMax;
  342. acbox->yMin = yMin;
  343. acbox->yMax = yMax;
  344. }
  345. }
  346. /* documentation is in ftoutln.h */
  347. FT_EXPORT_DEF( void )
  348. FT_Outline_Translate( FT_Outline* outline,
  349. FT_Pos xOffset,
  350. FT_Pos yOffset )
  351. {
  352. FT_UShort n;
  353. FT_Vector* vec = outline->points;
  354. for ( n = 0; n < outline->n_points; n++ )
  355. {
  356. vec->x += xOffset;
  357. vec->y += yOffset;
  358. vec++;
  359. }
  360. }
  361. /* documentation is in ftoutln.h */
  362. FT_EXPORT_DEF( void )
  363. FT_Outline_Reverse( FT_Outline* outline )
  364. {
  365. FT_UShort n;
  366. FT_Int first, last;
  367. first = 0;
  368. for ( n = 0; n < outline->n_contours; n++ )
  369. {
  370. last = outline->contours[n];
  371. /* reverse point table */
  372. {
  373. FT_Vector* p = outline->points + first;
  374. FT_Vector* q = outline->points + last;
  375. FT_Vector swap;
  376. while ( p < q )
  377. {
  378. swap = *p;
  379. *p = *q;
  380. *q = swap;
  381. p++;
  382. q--;
  383. }
  384. }
  385. /* reverse tags table */
  386. {
  387. char* p = outline->tags + first;
  388. char* q = outline->tags + last;
  389. char swap;
  390. while ( p < q )
  391. {
  392. swap = *p;
  393. *p = *q;
  394. *q = swap;
  395. p++;
  396. q--;
  397. }
  398. }
  399. first = last + 1;
  400. }
  401. outline->flags ^= FT_OUTLINE_REVERSE_FILL;
  402. }
  403. /* documentation is in ftoutln.h */
  404. FT_EXPORT_DEF( FT_Error )
  405. FT_Outline_Render( FT_Library library,
  406. FT_Outline* outline,
  407. FT_Raster_Params* params )
  408. {
  409. FT_Error error;
  410. FT_Bool update = 0;
  411. FT_Renderer renderer;
  412. FT_ListNode node;
  413. if ( !library )
  414. return FT_Err_Invalid_Library_Handle;
  415. if ( !params )
  416. return FT_Err_Invalid_Argument;
  417. renderer = library->cur_renderer;
  418. node = library->renderers.head;
  419. params->source = (void*)outline;
  420. error = FT_Err_Cannot_Render_Glyph;
  421. while ( renderer )
  422. {
  423. error = renderer->raster_render( renderer->raster, params );
  424. if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
  425. break;
  426. /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
  427. /* is unsupported by the current renderer for this glyph image */
  428. /* format */
  429. /* now, look for another renderer that supports the same */
  430. /* format */
  431. renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
  432. &node );
  433. update = 1;
  434. }
  435. /* if we changed the current renderer for the glyph image format */
  436. /* we need to select it as the next current one */
  437. if ( !error && update && renderer )
  438. FT_Set_Renderer( library, renderer, 0, 0 );
  439. return error;
  440. }
  441. /* documentation is in ftoutln.h */
  442. FT_EXPORT_DEF( FT_Error )
  443. FT_Outline_Get_Bitmap( FT_Library library,
  444. FT_Outline* outline,
  445. FT_Bitmap *abitmap )
  446. {
  447. FT_Raster_Params params;
  448. if ( !abitmap )
  449. return FT_Err_Invalid_Argument;
  450. /* other checks are delayed to FT_Outline_Render() */
  451. params.target = abitmap;
  452. params.flags = 0;
  453. if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
  454. abitmap->pixel_mode == FT_PIXEL_MODE_LCD ||
  455. abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
  456. params.flags |= FT_RASTER_FLAG_AA;
  457. return FT_Outline_Render( library, outline, &params );
  458. }
  459. /* documentation is in ftoutln.h */
  460. FT_EXPORT_DEF( void )
  461. FT_Vector_Transform( FT_Vector* vector,
  462. FT_Matrix* matrix )
  463. {
  464. FT_Pos xz, yz;
  465. if ( !vector || !matrix )
  466. return;
  467. xz = FT_MulFix( vector->x, matrix->xx ) +
  468. FT_MulFix( vector->y, matrix->xy );
  469. yz = FT_MulFix( vector->x, matrix->yx ) +
  470. FT_MulFix( vector->y, matrix->yy );
  471. vector->x = xz;
  472. vector->y = yz;
  473. }
  474. /* documentation is in ftoutln.h */
  475. FT_EXPORT_DEF( void )
  476. FT_Outline_Transform( FT_Outline* outline,
  477. FT_Matrix* matrix )
  478. {
  479. FT_Vector* vec = outline->points;
  480. FT_Vector* limit = vec + outline->n_points;
  481. for ( ; vec < limit; vec++ )
  482. FT_Vector_Transform( vec, matrix );
  483. }
  484. /* END */