ttkern.c revision cad4f915555f1eb190753da9b4b8bd58130e4739
1e5680279b21106173e342eab28552ae0e027196aDavid Turner/***************************************************************************/
2e5680279b21106173e342eab28552ae0e027196aDavid Turner/*                                                                         */
3e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg/*  ttkern.c                                                               */
4e5680279b21106173e342eab28552ae0e027196aDavid Turner/*                                                                         */
5e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg/*    Load the basic TrueType kerning table.  This doesn't handle          */
6e5680279b21106173e342eab28552ae0e027196aDavid Turner/*    kerning data within the GPOS table at the moment.                    */
7e5680279b21106173e342eab28552ae0e027196aDavid Turner/*                                                                         */
842f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 by       */
9e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10e5680279b21106173e342eab28552ae0e027196aDavid Turner/*                                                                         */
11e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  This file is part of the FreeType project, and may only be used,       */
12e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  modified, and distributed under the terms of the FreeType project      */
13e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  this file you indicate that you have read the license and              */
15e5680279b21106173e342eab28552ae0e027196aDavid Turner/*  understand and accept it fully.                                        */
16e5680279b21106173e342eab28552ae0e027196aDavid Turner/*                                                                         */
17e5680279b21106173e342eab28552ae0e027196aDavid Turner/***************************************************************************/
18e5680279b21106173e342eab28552ae0e027196aDavid Turner
19e5680279b21106173e342eab28552ae0e027196aDavid Turner
20e5680279b21106173e342eab28552ae0e027196aDavid Turner#include <ft2build.h>
21e5680279b21106173e342eab28552ae0e027196aDavid Turner#include FT_INTERNAL_DEBUG_H
22e5680279b21106173e342eab28552ae0e027196aDavid Turner#include FT_INTERNAL_STREAM_H
23e5680279b21106173e342eab28552ae0e027196aDavid Turner#include FT_TRUETYPE_TAGS_H
24e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg#include "ttkern.h"
25e5680279b21106173e342eab28552ae0e027196aDavid Turner
26e5680279b21106173e342eab28552ae0e027196aDavid Turner#include "sferrors.h"
27e5680279b21106173e342eab28552ae0e027196aDavid Turner
28e5680279b21106173e342eab28552ae0e027196aDavid Turner
29e5680279b21106173e342eab28552ae0e027196aDavid Turner  /*************************************************************************/
30e5680279b21106173e342eab28552ae0e027196aDavid Turner  /*                                                                       */
31e5680279b21106173e342eab28552ae0e027196aDavid Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
32e5680279b21106173e342eab28552ae0e027196aDavid Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
33e5680279b21106173e342eab28552ae0e027196aDavid Turner  /* messages during execution.                                            */
34e5680279b21106173e342eab28552ae0e027196aDavid Turner  /*                                                                       */
35e5680279b21106173e342eab28552ae0e027196aDavid Turner#undef  FT_COMPONENT
36e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg#define FT_COMPONENT  trace_ttkern
37e5680279b21106173e342eab28552ae0e027196aDavid Turner
38e5680279b21106173e342eab28552ae0e027196aDavid Turner
39e5680279b21106173e342eab28552ae0e027196aDavid Turner#undef  TT_KERN_INDEX
40e5680279b21106173e342eab28552ae0e027196aDavid Turner#define TT_KERN_INDEX( g1, g2 )  ( ( (FT_ULong)(g1) << 16 ) | (g2) )
41e5680279b21106173e342eab28552ae0e027196aDavid Turner
42e5680279b21106173e342eab28552ae0e027196aDavid Turner
43e5680279b21106173e342eab28552ae0e027196aDavid Turner  FT_LOCAL_DEF( FT_Error )
44e5680279b21106173e342eab28552ae0e027196aDavid Turner  tt_face_load_kern( TT_Face    face,
45e5680279b21106173e342eab28552ae0e027196aDavid Turner                     FT_Stream  stream )
46e5680279b21106173e342eab28552ae0e027196aDavid Turner  {
47e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Error   error;
48e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_ULong   table_size;
49e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Byte*   p;
50e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Byte*   p_limit;
51e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_UInt    nn, num_tables;
52e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_UInt32  avail = 0, ordered = 0;
53e5680279b21106173e342eab28552ae0e027196aDavid Turner
54e5680279b21106173e342eab28552ae0e027196aDavid Turner
55e5680279b21106173e342eab28552ae0e027196aDavid Turner    /* the kern table is optional; exit silently if it is missing */
56e5680279b21106173e342eab28552ae0e027196aDavid Turner    error = face->goto_table( face, TTAG_kern, stream, &table_size );
57e5680279b21106173e342eab28552ae0e027196aDavid Turner    if ( error )
58e5680279b21106173e342eab28552ae0e027196aDavid Turner      goto Exit;
59e5680279b21106173e342eab28552ae0e027196aDavid Turner
60e5680279b21106173e342eab28552ae0e027196aDavid Turner    if ( table_size < 4 )  /* the case of a malformed table */
61e5680279b21106173e342eab28552ae0e027196aDavid Turner    {
62858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "tt_face_load_kern:"
63858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg                 " kerning table is too small - ignored\n" ));
64e5680279b21106173e342eab28552ae0e027196aDavid Turner      error = SFNT_Err_Table_Missing;
65e5680279b21106173e342eab28552ae0e027196aDavid Turner      goto Exit;
66e5680279b21106173e342eab28552ae0e027196aDavid Turner    }
67e5680279b21106173e342eab28552ae0e027196aDavid Turner
68e5680279b21106173e342eab28552ae0e027196aDavid Turner    if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )
69e5680279b21106173e342eab28552ae0e027196aDavid Turner    {
70858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "tt_face_load_kern:"
71858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg                 " could not extract kerning table\n" ));
72e5680279b21106173e342eab28552ae0e027196aDavid Turner      goto Exit;
73e5680279b21106173e342eab28552ae0e027196aDavid Turner    }
74e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
75e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_table_size = table_size;
76e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
77e5680279b21106173e342eab28552ae0e027196aDavid Turner    p       = face->kern_table;
78e5680279b21106173e342eab28552ae0e027196aDavid Turner    p_limit = p + table_size;
79e5680279b21106173e342eab28552ae0e027196aDavid Turner
80e5680279b21106173e342eab28552ae0e027196aDavid Turner    p         += 2; /* skip version */
81e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg    num_tables = FT_NEXT_USHORT( p );
82e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
83e5680279b21106173e342eab28552ae0e027196aDavid Turner    if ( num_tables > 32 ) /* we only support up to 32 sub-tables */
84e5680279b21106173e342eab28552ae0e027196aDavid Turner      num_tables = 32;
85e5680279b21106173e342eab28552ae0e027196aDavid Turner
86e5680279b21106173e342eab28552ae0e027196aDavid Turner    for ( nn = 0; nn < num_tables; nn++ )
87e5680279b21106173e342eab28552ae0e027196aDavid Turner    {
88607dec79bb6ad524a9d2e7f93b836b795fe234cfWerner Lemberg      FT_UInt    num_pairs, length, coverage;
89e5680279b21106173e342eab28552ae0e027196aDavid Turner      FT_Byte*   p_next;
90cad4f915555f1eb190753da9b4b8bd58130e4739Suzuki, Toshiya (鈴木俊哉)      FT_UInt32  mask = (FT_UInt32)1UL << nn;
91e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
92e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
93e5680279b21106173e342eab28552ae0e027196aDavid Turner      if ( p + 6 > p_limit )
94e5680279b21106173e342eab28552ae0e027196aDavid Turner        break;
95e5680279b21106173e342eab28552ae0e027196aDavid Turner
96e5680279b21106173e342eab28552ae0e027196aDavid Turner      p_next = p;
97e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
98607dec79bb6ad524a9d2e7f93b836b795fe234cfWerner Lemberg      p += 2; /* skip version */
99e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      length   = FT_NEXT_USHORT( p );
100e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      coverage = FT_NEXT_USHORT( p );
101e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
102e5680279b21106173e342eab28552ae0e027196aDavid Turner      if ( length <= 6 )
103e5680279b21106173e342eab28552ae0e027196aDavid Turner        break;
104e5680279b21106173e342eab28552ae0e027196aDavid Turner
105e5680279b21106173e342eab28552ae0e027196aDavid Turner      p_next += length;
106e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
10742f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg      if ( p_next > p_limit )  /* handle broken table */
10842f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg        p_next = p_limit;
109ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner
110e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      /* only use horizontal kerning tables */
111e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      if ( ( coverage & ~8 ) != 0x0001 ||
112e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg           p + 8 > p_limit             )
113e5680279b21106173e342eab28552ae0e027196aDavid Turner        goto NextTable;
114e5680279b21106173e342eab28552ae0e027196aDavid Turner
115e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      num_pairs = FT_NEXT_USHORT( p );
116e5680279b21106173e342eab28552ae0e027196aDavid Turner      p        += 6;
117e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
11842f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg      if ( ( p_next - p ) / 6 < (int)num_pairs ) /* handle broken count */
11942f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg        num_pairs = (FT_UInt)( ( p_next - p ) / 6 );
120e5680279b21106173e342eab28552ae0e027196aDavid Turner
121e5680279b21106173e342eab28552ae0e027196aDavid Turner      avail |= mask;
122e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
123e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      /*
124e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg       *  Now check whether the pairs in this table are ordered.
125e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg       *  We then can use binary search.
126e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg       */
127e5680279b21106173e342eab28552ae0e027196aDavid Turner      if ( num_pairs > 0 )
128e5680279b21106173e342eab28552ae0e027196aDavid Turner      {
129e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        FT_UInt  count;
130e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        FT_UInt  old_pair;
131e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
132e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
133e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        old_pair = FT_NEXT_ULONG( p );
134e5680279b21106173e342eab28552ae0e027196aDavid Turner        p       += 2;
135e5680279b21106173e342eab28552ae0e027196aDavid Turner
136e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        for ( count = num_pairs - 1; count > 0; count-- )
137e5680279b21106173e342eab28552ae0e027196aDavid Turner        {
138e5680279b21106173e342eab28552ae0e027196aDavid Turner          FT_UInt32  cur_pair;
139e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
140e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
141e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg          cur_pair = FT_NEXT_ULONG( p );
142e5680279b21106173e342eab28552ae0e027196aDavid Turner          if ( cur_pair <= old_pair )
143e5680279b21106173e342eab28552ae0e027196aDavid Turner            break;
144e5680279b21106173e342eab28552ae0e027196aDavid Turner
145e5680279b21106173e342eab28552ae0e027196aDavid Turner          p += 2;
146e5680279b21106173e342eab28552ae0e027196aDavid Turner          old_pair = cur_pair;
147e5680279b21106173e342eab28552ae0e027196aDavid Turner        }
148e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
149e5680279b21106173e342eab28552ae0e027196aDavid Turner        if ( count == 0 )
150e5680279b21106173e342eab28552ae0e027196aDavid Turner          ordered |= mask;
151e5680279b21106173e342eab28552ae0e027196aDavid Turner      }
152e5680279b21106173e342eab28552ae0e027196aDavid Turner
153e5680279b21106173e342eab28552ae0e027196aDavid Turner    NextTable:
154e5680279b21106173e342eab28552ae0e027196aDavid Turner      p = p_next;
155e5680279b21106173e342eab28552ae0e027196aDavid Turner    }
156e5680279b21106173e342eab28552ae0e027196aDavid Turner
157e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->num_kern_tables = nn;
158e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_avail_bits = avail;
159e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_order_bits = ordered;
160e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
161e5680279b21106173e342eab28552ae0e027196aDavid Turner  Exit:
162e5680279b21106173e342eab28552ae0e027196aDavid Turner    return error;
163e5680279b21106173e342eab28552ae0e027196aDavid Turner  }
164e5680279b21106173e342eab28552ae0e027196aDavid Turner
165e5680279b21106173e342eab28552ae0e027196aDavid Turner
166e5680279b21106173e342eab28552ae0e027196aDavid Turner  FT_LOCAL_DEF( void )
167e5680279b21106173e342eab28552ae0e027196aDavid Turner  tt_face_done_kern( TT_Face  face )
168e5680279b21106173e342eab28552ae0e027196aDavid Turner  {
169e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Stream  stream = face->root.stream;
170e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
171e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
172e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_FRAME_RELEASE( face->kern_table );
173e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_table_size = 0;
174e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->num_kern_tables = 0;
175e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_avail_bits = 0;
176e5680279b21106173e342eab28552ae0e027196aDavid Turner    face->kern_order_bits = 0;
177e5680279b21106173e342eab28552ae0e027196aDavid Turner  }
178e5680279b21106173e342eab28552ae0e027196aDavid Turner
179e5680279b21106173e342eab28552ae0e027196aDavid Turner
180e5680279b21106173e342eab28552ae0e027196aDavid Turner  FT_LOCAL_DEF( FT_Int )
181e5680279b21106173e342eab28552ae0e027196aDavid Turner  tt_face_get_kerning( TT_Face  face,
182e5680279b21106173e342eab28552ae0e027196aDavid Turner                       FT_UInt  left_glyph,
183e5680279b21106173e342eab28552ae0e027196aDavid Turner                       FT_UInt  right_glyph )
184e5680279b21106173e342eab28552ae0e027196aDavid Turner  {
185e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Int    result = 0;
186e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_UInt   count, mask = 1;
187e5680279b21106173e342eab28552ae0e027196aDavid Turner    FT_Byte*  p       = face->kern_table;
188ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner    FT_Byte*  p_limit = p + face->kern_table_size;
189e5680279b21106173e342eab28552ae0e027196aDavid Turner
190e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
191e5680279b21106173e342eab28552ae0e027196aDavid Turner    p   += 4;
192e5680279b21106173e342eab28552ae0e027196aDavid Turner    mask = 0x0001;
193e5680279b21106173e342eab28552ae0e027196aDavid Turner
194ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner    for ( count = face->num_kern_tables;
195ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner          count > 0 && p + 6 <= p_limit;
196ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner          count--, mask <<= 1 )
197e5680279b21106173e342eab28552ae0e027196aDavid Turner    {
198e5680279b21106173e342eab28552ae0e027196aDavid Turner      FT_Byte* base     = p;
199e5680279b21106173e342eab28552ae0e027196aDavid Turner      FT_Byte* next     = base;
200e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      FT_UInt  version  = FT_NEXT_USHORT( p );
201e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      FT_UInt  length   = FT_NEXT_USHORT( p );
202e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      FT_UInt  coverage = FT_NEXT_USHORT( p );
203ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner      FT_UInt  num_pairs;
204fa0eb0c95fa954a3097d62c440303c403f466942David Turner      FT_Int   value    = 0;
205e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
206b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg      FT_UNUSED( version );
207b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg
208e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
209e5680279b21106173e342eab28552ae0e027196aDavid Turner      next = base + length;
210e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
21142f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg      if ( next > p_limit )  /* handle broken table */
212ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner        next = p_limit;
213ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner
214e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      if ( ( face->kern_avail_bits & mask ) == 0 )
215e5680279b21106173e342eab28552ae0e027196aDavid Turner        goto NextTable;
216e5680279b21106173e342eab28552ae0e027196aDavid Turner
217e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg      if ( p + 8 > next )
218e5680279b21106173e342eab28552ae0e027196aDavid Turner        goto NextTable;
219e5680279b21106173e342eab28552ae0e027196aDavid Turner
220ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner      num_pairs = FT_NEXT_USHORT( p );
221ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner      p        += 6;
222ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner
22342f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg      if ( ( next - p ) / 6 < (int)num_pairs )  /* handle broken count  */
22442f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg        num_pairs = (FT_UInt)( ( next - p ) / 6 );
225ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner
226e5680279b21106173e342eab28552ae0e027196aDavid Turner      switch ( coverage >> 8 )
227e5680279b21106173e342eab28552ae0e027196aDavid Turner      {
228e5680279b21106173e342eab28552ae0e027196aDavid Turner      case 0:
229e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        {
230ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner          FT_ULong  key0 = TT_KERN_INDEX( left_glyph, right_glyph );
231e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
232e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
233e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg          if ( face->kern_order_bits & mask )   /* binary search */
234e5680279b21106173e342eab28552ae0e027196aDavid Turner          {
235e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg            FT_UInt   min = 0;
236e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg            FT_UInt   max = num_pairs;
237fa0eb0c95fa954a3097d62c440303c403f466942David Turner
238e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
239e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg            while ( min < max )
240e5680279b21106173e342eab28552ae0e027196aDavid Turner            {
241e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              FT_UInt   mid = ( min + max ) >> 1;
242e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              FT_Byte*  q   = p + 6 * mid;
243e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              FT_ULong  key;
244e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
245e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
246e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              key = FT_NEXT_ULONG( q );
247e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
248e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              if ( key == key0 )
249e5680279b21106173e342eab28552ae0e027196aDavid Turner              {
250e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                value = FT_PEEK_SHORT( q );
251e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                goto Found;
252e5680279b21106173e342eab28552ae0e027196aDavid Turner              }
253e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              if ( key < key0 )
254e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                min = mid + 1;
255e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              else
256e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                max = mid;
257e5680279b21106173e342eab28552ae0e027196aDavid Turner            }
258e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg          }
259e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg          else /* linear search */
260e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg          {
26142137bc6145c426702b90d0cec5c5acd332739aeDavid Turner            FT_UInt  count2;
26242137bc6145c426702b90d0cec5c5acd332739aeDavid Turner
263fa3651e7d8af95b080db00d25a5ada0a5f77ef3dWerner Lemberg
26442137bc6145c426702b90d0cec5c5acd332739aeDavid Turner            for ( count2 = num_pairs; count2 > 0; count2-- )
265e5680279b21106173e342eab28552ae0e027196aDavid Turner            {
266e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              FT_ULong  key = FT_NEXT_ULONG( p );
267e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
268e5680279b21106173e342eab28552ae0e027196aDavid Turner
269e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              if ( key == key0 )
270e5680279b21106173e342eab28552ae0e027196aDavid Turner              {
271e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                value = FT_PEEK_SHORT( p );
272e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg                goto Found;
273e5680279b21106173e342eab28552ae0e027196aDavid Turner              }
274e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg              p += 2;
275e5680279b21106173e342eab28552ae0e027196aDavid Turner            }
276e5680279b21106173e342eab28552ae0e027196aDavid Turner          }
277e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        }
278e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        break;
279e5680279b21106173e342eab28552ae0e027196aDavid Turner
280e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg       /*
281fa3651e7d8af95b080db00d25a5ada0a5f77ef3dWerner Lemberg        *  We don't support format 2 because we haven't seen a single font
282e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        *  using it in real life...
283e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        */
284e5680279b21106173e342eab28552ae0e027196aDavid Turner
285e5680279b21106173e342eab28552ae0e027196aDavid Turner      default:
286e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg        ;
287e5680279b21106173e342eab28552ae0e027196aDavid Turner      }
288e5680279b21106173e342eab28552ae0e027196aDavid Turner
289fa0eb0c95fa954a3097d62c440303c403f466942David Turner      goto NextTable;
290e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
291fa0eb0c95fa954a3097d62c440303c403f466942David Turner    Found:
2926e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg      if ( coverage & 8 ) /* override or add */
293e5680279b21106173e342eab28552ae0e027196aDavid Turner        result = value;
294e5680279b21106173e342eab28552ae0e027196aDavid Turner      else
295e5680279b21106173e342eab28552ae0e027196aDavid Turner        result += value;
296e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
297e5680279b21106173e342eab28552ae0e027196aDavid Turner    NextTable:
298e5680279b21106173e342eab28552ae0e027196aDavid Turner      p = next;
299e5680279b21106173e342eab28552ae0e027196aDavid Turner    }
300e5680279b21106173e342eab28552ae0e027196aDavid Turner
301e5680279b21106173e342eab28552ae0e027196aDavid Turner    return result;
302e5680279b21106173e342eab28552ae0e027196aDavid Turner  }
303e5680279b21106173e342eab28552ae0e027196aDavid Turner
304e5680279b21106173e342eab28552ae0e027196aDavid Turner#undef TT_KERN_INDEX
305e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg
306e5680279b21106173e342eab28552ae0e027196aDavid Turner/* END */
307