/modules/freetype2/src/base/ftglyph.c

http://github.com/zpao/v8monkey · C · 627 lines · 388 code · 153 blank · 86 comment · 59 complexity · 78d13d10f62e7fbf4f92fcee62dd5fb3 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ftglyph.c */
  4. /* */
  5. /* FreeType convenience functions to handle glyphs (body). */
  6. /* */
  7. /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 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 contains the definition of several convenience functions */
  20. /* that can be used by client applications to easily retrieve glyph */
  21. /* bitmaps and outlines from a given face. */
  22. /* */
  23. /* These functions should be optional if you are writing a font server */
  24. /* or text layout engine on top of FreeType. However, they are pretty */
  25. /* handy for many other simple uses of the library. */
  26. /* */
  27. /*************************************************************************/
  28. #include <ft2build.h>
  29. #include FT_GLYPH_H
  30. #include FT_OUTLINE_H
  31. #include FT_BITMAP_H
  32. #include FT_INTERNAL_OBJECTS_H
  33. #include "basepic.h"
  34. /*************************************************************************/
  35. /* */
  36. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  37. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  38. /* messages during execution. */
  39. /* */
  40. #undef FT_COMPONENT
  41. #define FT_COMPONENT trace_glyph
  42. /*************************************************************************/
  43. /*************************************************************************/
  44. /**** ****/
  45. /**** FT_BitmapGlyph support ****/
  46. /**** ****/
  47. /*************************************************************************/
  48. /*************************************************************************/
  49. FT_CALLBACK_DEF( FT_Error )
  50. ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,
  51. FT_GlyphSlot slot )
  52. {
  53. FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
  54. FT_Error error = FT_Err_Ok;
  55. FT_Library library = FT_GLYPH( glyph )->library;
  56. if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
  57. {
  58. error = FT_Err_Invalid_Glyph_Format;
  59. goto Exit;
  60. }
  61. glyph->left = slot->bitmap_left;
  62. glyph->top = slot->bitmap_top;
  63. /* do lazy copying whenever possible */
  64. if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  65. {
  66. glyph->bitmap = slot->bitmap;
  67. slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  68. }
  69. else
  70. {
  71. FT_Bitmap_New( &glyph->bitmap );
  72. error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
  73. }
  74. Exit:
  75. return error;
  76. }
  77. FT_CALLBACK_DEF( FT_Error )
  78. ft_bitmap_glyph_copy( FT_Glyph bitmap_source,
  79. FT_Glyph bitmap_target )
  80. {
  81. FT_Library library = bitmap_source->library;
  82. FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;
  83. FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;
  84. target->left = source->left;
  85. target->top = source->top;
  86. return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
  87. }
  88. FT_CALLBACK_DEF( void )
  89. ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )
  90. {
  91. FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
  92. FT_Library library = FT_GLYPH( glyph )->library;
  93. FT_Bitmap_Done( library, &glyph->bitmap );
  94. }
  95. FT_CALLBACK_DEF( void )
  96. ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,
  97. FT_BBox* cbox )
  98. {
  99. FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
  100. cbox->xMin = glyph->left << 6;
  101. cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
  102. cbox->yMax = glyph->top << 6;
  103. cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
  104. }
  105. FT_DEFINE_GLYPH(ft_bitmap_glyph_class,
  106. sizeof ( FT_BitmapGlyphRec ),
  107. FT_GLYPH_FORMAT_BITMAP,
  108. ft_bitmap_glyph_init,
  109. ft_bitmap_glyph_done,
  110. ft_bitmap_glyph_copy,
  111. 0, /* FT_Glyph_TransformFunc */
  112. ft_bitmap_glyph_bbox,
  113. 0 /* FT_Glyph_PrepareFunc */
  114. )
  115. /*************************************************************************/
  116. /*************************************************************************/
  117. /**** ****/
  118. /**** FT_OutlineGlyph support ****/
  119. /**** ****/
  120. /*************************************************************************/
  121. /*************************************************************************/
  122. FT_CALLBACK_DEF( FT_Error )
  123. ft_outline_glyph_init( FT_Glyph outline_glyph,
  124. FT_GlyphSlot slot )
  125. {
  126. FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
  127. FT_Error error = FT_Err_Ok;
  128. FT_Library library = FT_GLYPH( glyph )->library;
  129. FT_Outline* source = &slot->outline;
  130. FT_Outline* target = &glyph->outline;
  131. /* check format in glyph slot */
  132. if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
  133. {
  134. error = FT_Err_Invalid_Glyph_Format;
  135. goto Exit;
  136. }
  137. /* allocate new outline */
  138. error = FT_Outline_New( library, source->n_points, source->n_contours,
  139. &glyph->outline );
  140. if ( error )
  141. goto Exit;
  142. FT_Outline_Copy( source, target );
  143. Exit:
  144. return error;
  145. }
  146. FT_CALLBACK_DEF( void )
  147. ft_outline_glyph_done( FT_Glyph outline_glyph )
  148. {
  149. FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
  150. FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
  151. }
  152. FT_CALLBACK_DEF( FT_Error )
  153. ft_outline_glyph_copy( FT_Glyph outline_source,
  154. FT_Glyph outline_target )
  155. {
  156. FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;
  157. FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;
  158. FT_Error error;
  159. FT_Library library = FT_GLYPH( source )->library;
  160. error = FT_Outline_New( library, source->outline.n_points,
  161. source->outline.n_contours, &target->outline );
  162. if ( !error )
  163. FT_Outline_Copy( &source->outline, &target->outline );
  164. return error;
  165. }
  166. FT_CALLBACK_DEF( void )
  167. ft_outline_glyph_transform( FT_Glyph outline_glyph,
  168. const FT_Matrix* matrix,
  169. const FT_Vector* delta )
  170. {
  171. FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
  172. if ( matrix )
  173. FT_Outline_Transform( &glyph->outline, matrix );
  174. if ( delta )
  175. FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
  176. }
  177. FT_CALLBACK_DEF( void )
  178. ft_outline_glyph_bbox( FT_Glyph outline_glyph,
  179. FT_BBox* bbox )
  180. {
  181. FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
  182. FT_Outline_Get_CBox( &glyph->outline, bbox );
  183. }
  184. FT_CALLBACK_DEF( FT_Error )
  185. ft_outline_glyph_prepare( FT_Glyph outline_glyph,
  186. FT_GlyphSlot slot )
  187. {
  188. FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
  189. slot->format = FT_GLYPH_FORMAT_OUTLINE;
  190. slot->outline = glyph->outline;
  191. slot->outline.flags &= ~FT_OUTLINE_OWNER;
  192. return FT_Err_Ok;
  193. }
  194. FT_DEFINE_GLYPH( ft_outline_glyph_class,
  195. sizeof ( FT_OutlineGlyphRec ),
  196. FT_GLYPH_FORMAT_OUTLINE,
  197. ft_outline_glyph_init,
  198. ft_outline_glyph_done,
  199. ft_outline_glyph_copy,
  200. ft_outline_glyph_transform,
  201. ft_outline_glyph_bbox,
  202. ft_outline_glyph_prepare
  203. )
  204. /*************************************************************************/
  205. /*************************************************************************/
  206. /**** ****/
  207. /**** FT_Glyph class and API ****/
  208. /**** ****/
  209. /*************************************************************************/
  210. /*************************************************************************/
  211. static FT_Error
  212. ft_new_glyph( FT_Library library,
  213. const FT_Glyph_Class* clazz,
  214. FT_Glyph* aglyph )
  215. {
  216. FT_Memory memory = library->memory;
  217. FT_Error error;
  218. FT_Glyph glyph = NULL;
  219. *aglyph = 0;
  220. if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
  221. {
  222. glyph->library = library;
  223. glyph->clazz = clazz;
  224. glyph->format = clazz->glyph_format;
  225. *aglyph = glyph;
  226. }
  227. return error;
  228. }
  229. /* documentation is in ftglyph.h */
  230. FT_EXPORT_DEF( FT_Error )
  231. FT_Glyph_Copy( FT_Glyph source,
  232. FT_Glyph *target )
  233. {
  234. FT_Glyph copy;
  235. FT_Error error;
  236. const FT_Glyph_Class* clazz;
  237. /* check arguments */
  238. if ( !target )
  239. {
  240. error = FT_Err_Invalid_Argument;
  241. goto Exit;
  242. }
  243. *target = 0;
  244. if ( !source || !source->clazz )
  245. {
  246. error = FT_Err_Invalid_Argument;
  247. goto Exit;
  248. }
  249. clazz = source->clazz;
  250. error = ft_new_glyph( source->library, clazz, &copy );
  251. if ( error )
  252. goto Exit;
  253. copy->advance = source->advance;
  254. copy->format = source->format;
  255. if ( clazz->glyph_copy )
  256. error = clazz->glyph_copy( source, copy );
  257. if ( error )
  258. FT_Done_Glyph( copy );
  259. else
  260. *target = copy;
  261. Exit:
  262. return error;
  263. }
  264. /* documentation is in ftglyph.h */
  265. FT_EXPORT_DEF( FT_Error )
  266. FT_Get_Glyph( FT_GlyphSlot slot,
  267. FT_Glyph *aglyph )
  268. {
  269. FT_Library library;
  270. FT_Error error;
  271. FT_Glyph glyph;
  272. const FT_Glyph_Class* clazz = 0;
  273. if ( !slot )
  274. return FT_Err_Invalid_Slot_Handle;
  275. library = slot->library;
  276. if ( !aglyph )
  277. return FT_Err_Invalid_Argument;
  278. /* if it is a bitmap, that's easy :-) */
  279. if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
  280. clazz = FT_BITMAP_GLYPH_CLASS_GET;
  281. /* if it is an outline */
  282. else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
  283. clazz = FT_OUTLINE_GLYPH_CLASS_GET;
  284. else
  285. {
  286. /* try to find a renderer that supports the glyph image format */
  287. FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
  288. if ( render )
  289. clazz = &render->glyph_class;
  290. }
  291. if ( !clazz )
  292. {
  293. error = FT_Err_Invalid_Glyph_Format;
  294. goto Exit;
  295. }
  296. /* create FT_Glyph object */
  297. error = ft_new_glyph( library, clazz, &glyph );
  298. if ( error )
  299. goto Exit;
  300. /* copy advance while converting it to 16.16 format */
  301. glyph->advance.x = slot->advance.x << 10;
  302. glyph->advance.y = slot->advance.y << 10;
  303. /* now import the image from the glyph slot */
  304. error = clazz->glyph_init( glyph, slot );
  305. /* if an error occurred, destroy the glyph */
  306. if ( error )
  307. FT_Done_Glyph( glyph );
  308. else
  309. *aglyph = glyph;
  310. Exit:
  311. return error;
  312. }
  313. /* documentation is in ftglyph.h */
  314. FT_EXPORT_DEF( FT_Error )
  315. FT_Glyph_Transform( FT_Glyph glyph,
  316. FT_Matrix* matrix,
  317. FT_Vector* delta )
  318. {
  319. const FT_Glyph_Class* clazz;
  320. FT_Error error = FT_Err_Ok;
  321. if ( !glyph || !glyph->clazz )
  322. error = FT_Err_Invalid_Argument;
  323. else
  324. {
  325. clazz = glyph->clazz;
  326. if ( clazz->glyph_transform )
  327. {
  328. /* transform glyph image */
  329. clazz->glyph_transform( glyph, matrix, delta );
  330. /* transform advance vector */
  331. if ( matrix )
  332. FT_Vector_Transform( &glyph->advance, matrix );
  333. }
  334. else
  335. error = FT_Err_Invalid_Glyph_Format;
  336. }
  337. return error;
  338. }
  339. /* documentation is in ftglyph.h */
  340. FT_EXPORT_DEF( void )
  341. FT_Glyph_Get_CBox( FT_Glyph glyph,
  342. FT_UInt bbox_mode,
  343. FT_BBox *acbox )
  344. {
  345. const FT_Glyph_Class* clazz;
  346. if ( !acbox )
  347. return;
  348. acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
  349. if ( !glyph || !glyph->clazz )
  350. return;
  351. else
  352. {
  353. clazz = glyph->clazz;
  354. if ( !clazz->glyph_bbox )
  355. return;
  356. else
  357. {
  358. /* retrieve bbox in 26.6 coordinates */
  359. clazz->glyph_bbox( glyph, acbox );
  360. /* perform grid fitting if needed */
  361. if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
  362. bbox_mode == FT_GLYPH_BBOX_PIXELS )
  363. {
  364. acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
  365. acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
  366. acbox->xMax = FT_PIX_CEIL( acbox->xMax );
  367. acbox->yMax = FT_PIX_CEIL( acbox->yMax );
  368. }
  369. /* convert to integer pixels if needed */
  370. if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
  371. bbox_mode == FT_GLYPH_BBOX_PIXELS )
  372. {
  373. acbox->xMin >>= 6;
  374. acbox->yMin >>= 6;
  375. acbox->xMax >>= 6;
  376. acbox->yMax >>= 6;
  377. }
  378. }
  379. }
  380. return;
  381. }
  382. /* documentation is in ftglyph.h */
  383. FT_EXPORT_DEF( FT_Error )
  384. FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
  385. FT_Render_Mode render_mode,
  386. FT_Vector* origin,
  387. FT_Bool destroy )
  388. {
  389. FT_GlyphSlotRec dummy;
  390. FT_GlyphSlot_InternalRec dummy_internal;
  391. FT_Error error = FT_Err_Ok;
  392. FT_Glyph glyph;
  393. FT_BitmapGlyph bitmap = NULL;
  394. const FT_Glyph_Class* clazz;
  395. #ifdef FT_CONFIG_OPTION_PIC
  396. FT_Library library = FT_GLYPH( glyph )->library;
  397. #endif
  398. /* check argument */
  399. if ( !the_glyph )
  400. goto Bad;
  401. /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
  402. /* then calling FT_Render_Glyph_Internal() */
  403. glyph = *the_glyph;
  404. if ( !glyph )
  405. goto Bad;
  406. clazz = glyph->clazz;
  407. /* when called with a bitmap glyph, do nothing and return successfully */
  408. if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
  409. goto Exit;
  410. if ( !clazz || !clazz->glyph_prepare )
  411. goto Bad;
  412. FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
  413. FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
  414. dummy.internal = &dummy_internal;
  415. dummy.library = glyph->library;
  416. dummy.format = clazz->glyph_format;
  417. /* create result bitmap glyph */
  418. error = ft_new_glyph( glyph->library, FT_BITMAP_GLYPH_CLASS_GET,
  419. (FT_Glyph*)(void*)&bitmap );
  420. if ( error )
  421. goto Exit;
  422. #if 1
  423. /* if `origin' is set, translate the glyph image */
  424. if ( origin )
  425. FT_Glyph_Transform( glyph, 0, origin );
  426. #else
  427. FT_UNUSED( origin );
  428. #endif
  429. /* prepare dummy slot for rendering */
  430. error = clazz->glyph_prepare( glyph, &dummy );
  431. if ( !error )
  432. error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
  433. #if 1
  434. if ( !destroy && origin )
  435. {
  436. FT_Vector v;
  437. v.x = -origin->x;
  438. v.y = -origin->y;
  439. FT_Glyph_Transform( glyph, 0, &v );
  440. }
  441. #endif
  442. if ( error )
  443. goto Exit;
  444. /* in case of success, copy the bitmap to the glyph bitmap */
  445. error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
  446. if ( error )
  447. goto Exit;
  448. /* copy advance */
  449. bitmap->root.advance = glyph->advance;
  450. if ( destroy )
  451. FT_Done_Glyph( glyph );
  452. *the_glyph = FT_GLYPH( bitmap );
  453. Exit:
  454. if ( error && bitmap )
  455. FT_Done_Glyph( FT_GLYPH( bitmap ) );
  456. return error;
  457. Bad:
  458. error = FT_Err_Invalid_Argument;
  459. goto Exit;
  460. }
  461. /* documentation is in ftglyph.h */
  462. FT_EXPORT_DEF( void )
  463. FT_Done_Glyph( FT_Glyph glyph )
  464. {
  465. if ( glyph )
  466. {
  467. FT_Memory memory = glyph->library->memory;
  468. const FT_Glyph_Class* clazz = glyph->clazz;
  469. if ( clazz->glyph_done )
  470. clazz->glyph_done( glyph );
  471. FT_FREE( glyph );
  472. }
  473. }
  474. /* END */