/src/compiler/android-ndk/jni/freetype/src/base/ftgloadr.c

http://ftk.googlecode.com/ · C · 401 lines · 230 code · 95 blank · 76 comment · 20 complexity · 6d81b4b5ca43e46a93dac5d9db16732d MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ftgloadr.c */
  4. /* */
  5. /* The FreeType glyph loader (body). */
  6. /* */
  7. /* Copyright 2002, 2003, 2004, 2005, 2006 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. #include <ft2build.h>
  18. #include FT_INTERNAL_GLYPH_LOADER_H
  19. #include FT_INTERNAL_MEMORY_H
  20. #include FT_INTERNAL_OBJECTS_H
  21. #undef FT_COMPONENT
  22. #define FT_COMPONENT trace_gloader
  23. /*************************************************************************/
  24. /*************************************************************************/
  25. /*************************************************************************/
  26. /***** *****/
  27. /***** *****/
  28. /***** G L Y P H L O A D E R *****/
  29. /***** *****/
  30. /***** *****/
  31. /*************************************************************************/
  32. /*************************************************************************/
  33. /*************************************************************************/
  34. /*************************************************************************/
  35. /* */
  36. /* The glyph loader is a simple object which is used to load a set of */
  37. /* glyphs easily. It is critical for the correct loading of composites. */
  38. /* */
  39. /* Ideally, one can see it as a stack of abstract `glyph' objects. */
  40. /* */
  41. /* loader.base Is really the bottom of the stack. It describes a */
  42. /* single glyph image made of the juxtaposition of */
  43. /* several glyphs (those `in the stack'). */
  44. /* */
  45. /* loader.current Describes the top of the stack, on which a new */
  46. /* glyph can be loaded. */
  47. /* */
  48. /* Rewind Clears the stack. */
  49. /* Prepare Set up `loader.current' for addition of a new glyph */
  50. /* image. */
  51. /* Add Add the `current' glyph image to the `base' one, */
  52. /* and prepare for another one. */
  53. /* */
  54. /* The glyph loader is now a base object. Each driver used to */
  55. /* re-implement it in one way or the other, which wasted code and */
  56. /* energy. */
  57. /* */
  58. /*************************************************************************/
  59. /* create a new glyph loader */
  60. FT_BASE_DEF( FT_Error )
  61. FT_GlyphLoader_New( FT_Memory memory,
  62. FT_GlyphLoader *aloader )
  63. {
  64. FT_GlyphLoader loader;
  65. FT_Error error;
  66. if ( !FT_NEW( loader ) )
  67. {
  68. loader->memory = memory;
  69. *aloader = loader;
  70. }
  71. return error;
  72. }
  73. /* rewind the glyph loader - reset counters to 0 */
  74. FT_BASE_DEF( void )
  75. FT_GlyphLoader_Rewind( FT_GlyphLoader loader )
  76. {
  77. FT_GlyphLoad base = &loader->base;
  78. FT_GlyphLoad current = &loader->current;
  79. base->outline.n_points = 0;
  80. base->outline.n_contours = 0;
  81. base->num_subglyphs = 0;
  82. *current = *base;
  83. }
  84. /* reset the glyph loader, frees all allocated tables */
  85. /* and starts from zero */
  86. FT_BASE_DEF( void )
  87. FT_GlyphLoader_Reset( FT_GlyphLoader loader )
  88. {
  89. FT_Memory memory = loader->memory;
  90. FT_FREE( loader->base.outline.points );
  91. FT_FREE( loader->base.outline.tags );
  92. FT_FREE( loader->base.outline.contours );
  93. FT_FREE( loader->base.extra_points );
  94. FT_FREE( loader->base.subglyphs );
  95. loader->base.extra_points2 = NULL;
  96. loader->max_points = 0;
  97. loader->max_contours = 0;
  98. loader->max_subglyphs = 0;
  99. FT_GlyphLoader_Rewind( loader );
  100. }
  101. /* delete a glyph loader */
  102. FT_BASE_DEF( void )
  103. FT_GlyphLoader_Done( FT_GlyphLoader loader )
  104. {
  105. if ( loader )
  106. {
  107. FT_Memory memory = loader->memory;
  108. FT_GlyphLoader_Reset( loader );
  109. FT_FREE( loader );
  110. }
  111. }
  112. /* re-adjust the `current' outline fields */
  113. static void
  114. FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader )
  115. {
  116. FT_Outline* base = &loader->base.outline;
  117. FT_Outline* current = &loader->current.outline;
  118. current->points = base->points + base->n_points;
  119. current->tags = base->tags + base->n_points;
  120. current->contours = base->contours + base->n_contours;
  121. /* handle extra points table - if any */
  122. if ( loader->use_extra )
  123. {
  124. loader->current.extra_points = loader->base.extra_points +
  125. base->n_points;
  126. loader->current.extra_points2 = loader->base.extra_points2 +
  127. base->n_points;
  128. }
  129. }
  130. FT_BASE_DEF( FT_Error )
  131. FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader )
  132. {
  133. FT_Error error;
  134. FT_Memory memory = loader->memory;
  135. if ( !FT_NEW_ARRAY( loader->base.extra_points, 2 * loader->max_points ) )
  136. {
  137. loader->use_extra = 1;
  138. loader->base.extra_points2 = loader->base.extra_points +
  139. loader->max_points;
  140. FT_GlyphLoader_Adjust_Points( loader );
  141. }
  142. return error;
  143. }
  144. /* re-adjust the `current' subglyphs field */
  145. static void
  146. FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader )
  147. {
  148. FT_GlyphLoad base = &loader->base;
  149. FT_GlyphLoad current = &loader->current;
  150. current->subglyphs = base->subglyphs + base->num_subglyphs;
  151. }
  152. /* Ensure that we can add `n_points' and `n_contours' to our glyph. */
  153. /* This function reallocates its outline tables if necessary. Note that */
  154. /* it DOESN'T change the number of points within the loader! */
  155. /* */
  156. FT_BASE_DEF( FT_Error )
  157. FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader,
  158. FT_UInt n_points,
  159. FT_UInt n_contours )
  160. {
  161. FT_Memory memory = loader->memory;
  162. FT_Error error = FT_Err_Ok;
  163. FT_Outline* base = &loader->base.outline;
  164. FT_Outline* current = &loader->current.outline;
  165. FT_Bool adjust = 0;
  166. FT_UInt new_max, old_max;
  167. /* check points & tags */
  168. new_max = base->n_points + current->n_points + n_points;
  169. old_max = loader->max_points;
  170. if ( new_max > old_max )
  171. {
  172. new_max = FT_PAD_CEIL( new_max, 8 );
  173. if ( new_max > FT_OUTLINE_POINTS_MAX )
  174. return FT_Err_Array_Too_Large;
  175. if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
  176. FT_RENEW_ARRAY( base->tags, old_max, new_max ) )
  177. goto Exit;
  178. if ( loader->use_extra )
  179. {
  180. if ( FT_RENEW_ARRAY( loader->base.extra_points,
  181. old_max * 2, new_max * 2 ) )
  182. goto Exit;
  183. FT_ARRAY_MOVE( loader->base.extra_points + new_max,
  184. loader->base.extra_points + old_max,
  185. old_max );
  186. loader->base.extra_points2 = loader->base.extra_points + new_max;
  187. }
  188. adjust = 1;
  189. loader->max_points = new_max;
  190. }
  191. /* check contours */
  192. old_max = loader->max_contours;
  193. new_max = base->n_contours + current->n_contours +
  194. n_contours;
  195. if ( new_max > old_max )
  196. {
  197. new_max = FT_PAD_CEIL( new_max, 4 );
  198. if ( new_max > FT_OUTLINE_CONTOURS_MAX )
  199. return FT_Err_Array_Too_Large;
  200. if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
  201. goto Exit;
  202. adjust = 1;
  203. loader->max_contours = new_max;
  204. }
  205. if ( adjust )
  206. FT_GlyphLoader_Adjust_Points( loader );
  207. Exit:
  208. return error;
  209. }
  210. /* Ensure that we can add `n_subglyphs' to our glyph. this function */
  211. /* reallocates its subglyphs table if necessary. Note that it DOES */
  212. /* NOT change the number of subglyphs within the loader! */
  213. /* */
  214. FT_BASE_DEF( FT_Error )
  215. FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader,
  216. FT_UInt n_subs )
  217. {
  218. FT_Memory memory = loader->memory;
  219. FT_Error error = FT_Err_Ok;
  220. FT_UInt new_max, old_max;
  221. FT_GlyphLoad base = &loader->base;
  222. FT_GlyphLoad current = &loader->current;
  223. new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
  224. old_max = loader->max_subglyphs;
  225. if ( new_max > old_max )
  226. {
  227. new_max = FT_PAD_CEIL( new_max, 2 );
  228. if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) )
  229. goto Exit;
  230. loader->max_subglyphs = new_max;
  231. FT_GlyphLoader_Adjust_Subglyphs( loader );
  232. }
  233. Exit:
  234. return error;
  235. }
  236. /* prepare loader for the addition of a new glyph on top of the base one */
  237. FT_BASE_DEF( void )
  238. FT_GlyphLoader_Prepare( FT_GlyphLoader loader )
  239. {
  240. FT_GlyphLoad current = &loader->current;
  241. current->outline.n_points = 0;
  242. current->outline.n_contours = 0;
  243. current->num_subglyphs = 0;
  244. FT_GlyphLoader_Adjust_Points ( loader );
  245. FT_GlyphLoader_Adjust_Subglyphs( loader );
  246. }
  247. /* add current glyph to the base image - and prepare for another */
  248. FT_BASE_DEF( void )
  249. FT_GlyphLoader_Add( FT_GlyphLoader loader )
  250. {
  251. FT_GlyphLoad base;
  252. FT_GlyphLoad current;
  253. FT_UInt n_curr_contours;
  254. FT_UInt n_base_points;
  255. FT_UInt n;
  256. if ( !loader )
  257. return;
  258. base = &loader->base;
  259. current = &loader->current;
  260. n_curr_contours = current->outline.n_contours;
  261. n_base_points = base->outline.n_points;
  262. base->outline.n_points =
  263. (short)( base->outline.n_points + current->outline.n_points );
  264. base->outline.n_contours =
  265. (short)( base->outline.n_contours + current->outline.n_contours );
  266. base->num_subglyphs += current->num_subglyphs;
  267. /* adjust contours count in newest outline */
  268. for ( n = 0; n < n_curr_contours; n++ )
  269. current->outline.contours[n] =
  270. (short)( current->outline.contours[n] + n_base_points );
  271. /* prepare for another new glyph image */
  272. FT_GlyphLoader_Prepare( loader );
  273. }
  274. FT_BASE_DEF( FT_Error )
  275. FT_GlyphLoader_CopyPoints( FT_GlyphLoader target,
  276. FT_GlyphLoader source )
  277. {
  278. FT_Error error;
  279. FT_UInt num_points = source->base.outline.n_points;
  280. FT_UInt num_contours = source->base.outline.n_contours;
  281. error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours );
  282. if ( !error )
  283. {
  284. FT_Outline* out = &target->base.outline;
  285. FT_Outline* in = &source->base.outline;
  286. FT_ARRAY_COPY( out->points, in->points,
  287. num_points );
  288. FT_ARRAY_COPY( out->tags, in->tags,
  289. num_points );
  290. FT_ARRAY_COPY( out->contours, in->contours,
  291. num_contours );
  292. /* do we need to copy the extra points? */
  293. if ( target->use_extra && source->use_extra )
  294. {
  295. FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points,
  296. num_points );
  297. FT_ARRAY_COPY( target->base.extra_points2, source->base.extra_points2,
  298. num_points );
  299. }
  300. out->n_points = (short)num_points;
  301. out->n_contours = (short)num_contours;
  302. FT_GlyphLoader_Adjust_Points( target );
  303. }
  304. return error;
  305. }
  306. /* END */