/src/freetype/src/sfnt/ttkern.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 306 lines · 195 code · 77 blank · 34 comment · 34 complexity · 0fe2d7c9b7c51b44e1d8daedaa29b820 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ttkern.c */
  4. /* */
  5. /* Load the basic TrueType kerning table. This doesn't handle */
  6. /* kerning data within the GPOS table at the moment. */
  7. /* */
  8. /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 by */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. #include <ft2build.h>
  19. #include FT_INTERNAL_DEBUG_H
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_TRUETYPE_TAGS_H
  22. #include "ttkern.h"
  23. #include "sferrors.h"
  24. /*************************************************************************/
  25. /* */
  26. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  27. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  28. /* messages during execution. */
  29. /* */
  30. #undef FT_COMPONENT
  31. #define FT_COMPONENT trace_ttkern
  32. #undef TT_KERN_INDEX
  33. #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
  34. FT_LOCAL_DEF( FT_Error )
  35. tt_face_load_kern( TT_Face face,
  36. FT_Stream stream )
  37. {
  38. FT_Error error;
  39. FT_ULong table_size;
  40. FT_Byte* p;
  41. FT_Byte* p_limit;
  42. FT_UInt nn, num_tables;
  43. FT_UInt32 avail = 0, ordered = 0;
  44. /* the kern table is optional; exit silently if it is missing */
  45. error = face->goto_table( face, TTAG_kern, stream, &table_size );
  46. if ( error )
  47. goto Exit;
  48. if ( table_size < 4 ) /* the case of a malformed table */
  49. {
  50. FT_ERROR(( "tt_face_load_kern:"
  51. " kerning table is too small - ignored\n" ));
  52. error = SFNT_Err_Table_Missing;
  53. goto Exit;
  54. }
  55. if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )
  56. {
  57. FT_ERROR(( "tt_face_load_kern:"
  58. " could not extract kerning table\n" ));
  59. goto Exit;
  60. }
  61. face->kern_table_size = table_size;
  62. p = face->kern_table;
  63. p_limit = p + table_size;
  64. p += 2; /* skip version */
  65. num_tables = FT_NEXT_USHORT( p );
  66. if ( num_tables > 32 ) /* we only support up to 32 sub-tables */
  67. num_tables = 32;
  68. for ( nn = 0; nn < num_tables; nn++ )
  69. {
  70. FT_UInt num_pairs, length, coverage;
  71. FT_Byte* p_next;
  72. FT_UInt32 mask = (FT_UInt32)1UL << nn;
  73. if ( p + 6 > p_limit )
  74. break;
  75. p_next = p;
  76. p += 2; /* skip version */
  77. length = FT_NEXT_USHORT( p );
  78. coverage = FT_NEXT_USHORT( p );
  79. if ( length <= 6 )
  80. break;
  81. p_next += length;
  82. if ( p_next > p_limit ) /* handle broken table */
  83. p_next = p_limit;
  84. /* only use horizontal kerning tables */
  85. if ( ( coverage & ~8 ) != 0x0001 ||
  86. p + 8 > p_limit )
  87. goto NextTable;
  88. num_pairs = FT_NEXT_USHORT( p );
  89. p += 6;
  90. if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */
  91. num_pairs = (FT_UInt)( ( p_next - p ) / 6 );
  92. avail |= mask;
  93. /*
  94. * Now check whether the pairs in this table are ordered.
  95. * We then can use binary search.
  96. */
  97. if ( num_pairs > 0 )
  98. {
  99. FT_ULong count;
  100. FT_ULong old_pair;
  101. old_pair = FT_NEXT_ULONG( p );
  102. p += 2;
  103. for ( count = num_pairs - 1; count > 0; count-- )
  104. {
  105. FT_UInt32 cur_pair;
  106. cur_pair = FT_NEXT_ULONG( p );
  107. if ( cur_pair <= old_pair )
  108. break;
  109. p += 2;
  110. old_pair = cur_pair;
  111. }
  112. if ( count == 0 )
  113. ordered |= mask;
  114. }
  115. NextTable:
  116. p = p_next;
  117. }
  118. face->num_kern_tables = nn;
  119. face->kern_avail_bits = avail;
  120. face->kern_order_bits = ordered;
  121. Exit:
  122. return error;
  123. }
  124. FT_LOCAL_DEF( void )
  125. tt_face_done_kern( TT_Face face )
  126. {
  127. FT_Stream stream = face->root.stream;
  128. FT_FRAME_RELEASE( face->kern_table );
  129. face->kern_table_size = 0;
  130. face->num_kern_tables = 0;
  131. face->kern_avail_bits = 0;
  132. face->kern_order_bits = 0;
  133. }
  134. FT_LOCAL_DEF( FT_Int )
  135. tt_face_get_kerning( TT_Face face,
  136. FT_UInt left_glyph,
  137. FT_UInt right_glyph )
  138. {
  139. FT_Int result = 0;
  140. FT_UInt count, mask = 1;
  141. FT_Byte* p = face->kern_table;
  142. FT_Byte* p_limit = p + face->kern_table_size;
  143. p += 4;
  144. mask = 0x0001;
  145. for ( count = face->num_kern_tables;
  146. count > 0 && p + 6 <= p_limit;
  147. count--, mask <<= 1 )
  148. {
  149. FT_Byte* base = p;
  150. FT_Byte* next = base;
  151. FT_UInt version = FT_NEXT_USHORT( p );
  152. FT_UInt length = FT_NEXT_USHORT( p );
  153. FT_UInt coverage = FT_NEXT_USHORT( p );
  154. FT_UInt num_pairs;
  155. FT_Int value = 0;
  156. FT_UNUSED( version );
  157. next = base + length;
  158. if ( next > p_limit ) /* handle broken table */
  159. next = p_limit;
  160. if ( ( face->kern_avail_bits & mask ) == 0 )
  161. goto NextTable;
  162. if ( p + 8 > next )
  163. goto NextTable;
  164. num_pairs = FT_NEXT_USHORT( p );
  165. p += 6;
  166. if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */
  167. num_pairs = (FT_UInt)( ( next - p ) / 6 );
  168. switch ( coverage >> 8 )
  169. {
  170. case 0:
  171. {
  172. FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph );
  173. if ( face->kern_order_bits & mask ) /* binary search */
  174. {
  175. FT_UInt min = 0;
  176. FT_UInt max = num_pairs;
  177. while ( min < max )
  178. {
  179. FT_UInt mid = ( min + max ) >> 1;
  180. FT_Byte* q = p + 6 * mid;
  181. FT_ULong key;
  182. key = FT_NEXT_ULONG( q );
  183. if ( key == key0 )
  184. {
  185. value = FT_PEEK_SHORT( q );
  186. goto Found;
  187. }
  188. if ( key < key0 )
  189. min = mid + 1;
  190. else
  191. max = mid;
  192. }
  193. }
  194. else /* linear search */
  195. {
  196. FT_UInt count2;
  197. for ( count2 = num_pairs; count2 > 0; count2-- )
  198. {
  199. FT_ULong key = FT_NEXT_ULONG( p );
  200. if ( key == key0 )
  201. {
  202. value = FT_PEEK_SHORT( p );
  203. goto Found;
  204. }
  205. p += 2;
  206. }
  207. }
  208. }
  209. break;
  210. /*
  211. * We don't support format 2 because we haven't seen a single font
  212. * using it in real life...
  213. */
  214. default:
  215. ;
  216. }
  217. goto NextTable;
  218. Found:
  219. if ( coverage & 8 ) /* override or add */
  220. result = value;
  221. else
  222. result += value;
  223. NextTable:
  224. p = next;
  225. }
  226. return result;
  227. }
  228. #undef TT_KERN_INDEX
  229. /* END */