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/* */ 80a0c22569deab933df21127e75db5c81f724f292Werner Lemberg/* Copyright 1996-2018 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" )); 64059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg error = FT_THROW( 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 { 883e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg FT_UInt num_pairs, length, coverage, format; 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 102f70d9342e65cd2cb44e9f26b6d7edeedf191fc6cWerner Lemberg if ( length <= 6 + 8 ) 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 1103e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg format = coverage >> 8; 1113e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg 1123e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg /* we currently only support format 0 kerning tables */ 1133e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg if ( format != 0 ) 1143e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg goto NextTable; 1153e4b79970e0681bd2481392420a0eb4dc7820b70Werner Lemberg 116e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg /* only use horizontal kerning tables */ 117565f5a7d19d23aa7b3d6f917e5ef6b297b89f384Wojciech Mamrak if ( ( coverage & 3U ) != 0x0001 || 118565f5a7d19d23aa7b3d6f917e5ef6b297b89f384Wojciech Mamrak p + 8 > p_next ) 119e5680279b21106173e342eab28552ae0e027196aDavid Turner goto NextTable; 120e5680279b21106173e342eab28552ae0e027196aDavid Turner 121e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg num_pairs = FT_NEXT_USHORT( p ); 122e5680279b21106173e342eab28552ae0e027196aDavid Turner p += 6; 123e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 1240ae6cf214ff1eec6499c347726a18b8a9809ab2cWerner Lemberg if ( ( p_next - p ) < 6 * (int)num_pairs ) /* handle broken count */ 12542f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg num_pairs = (FT_UInt)( ( p_next - p ) / 6 ); 126e5680279b21106173e342eab28552ae0e027196aDavid Turner 127e5680279b21106173e342eab28552ae0e027196aDavid Turner avail |= mask; 128e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 129e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg /* 130e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg * Now check whether the pairs in this table are ordered. 131e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg * We then can use binary search. 132e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg */ 133e5680279b21106173e342eab28552ae0e027196aDavid Turner if ( num_pairs > 0 ) 134e5680279b21106173e342eab28552ae0e027196aDavid Turner { 1352a2beb47c4b7b61be75ca92c96976ef9f33c64f0Suzuki, Toshiya (鈴木俊哉) FT_ULong count; 1362a2beb47c4b7b61be75ca92c96976ef9f33c64f0Suzuki, Toshiya (鈴木俊哉) FT_ULong old_pair; 137e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 138e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 139e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg old_pair = FT_NEXT_ULONG( p ); 140e5680279b21106173e342eab28552ae0e027196aDavid Turner p += 2; 141e5680279b21106173e342eab28552ae0e027196aDavid Turner 142e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg for ( count = num_pairs - 1; count > 0; count-- ) 143e5680279b21106173e342eab28552ae0e027196aDavid Turner { 144e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_UInt32 cur_pair; 145e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 146e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 147e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg cur_pair = FT_NEXT_ULONG( p ); 148e5680279b21106173e342eab28552ae0e027196aDavid Turner if ( cur_pair <= old_pair ) 149e5680279b21106173e342eab28552ae0e027196aDavid Turner break; 150e5680279b21106173e342eab28552ae0e027196aDavid Turner 151e5680279b21106173e342eab28552ae0e027196aDavid Turner p += 2; 152e5680279b21106173e342eab28552ae0e027196aDavid Turner old_pair = cur_pair; 153e5680279b21106173e342eab28552ae0e027196aDavid Turner } 154e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 155e5680279b21106173e342eab28552ae0e027196aDavid Turner if ( count == 0 ) 156e5680279b21106173e342eab28552ae0e027196aDavid Turner ordered |= mask; 157e5680279b21106173e342eab28552ae0e027196aDavid Turner } 158e5680279b21106173e342eab28552ae0e027196aDavid Turner 159e5680279b21106173e342eab28552ae0e027196aDavid Turner NextTable: 160e5680279b21106173e342eab28552ae0e027196aDavid Turner p = p_next; 161e5680279b21106173e342eab28552ae0e027196aDavid Turner } 162e5680279b21106173e342eab28552ae0e027196aDavid Turner 163e5680279b21106173e342eab28552ae0e027196aDavid Turner face->num_kern_tables = nn; 164e5680279b21106173e342eab28552ae0e027196aDavid Turner face->kern_avail_bits = avail; 165e5680279b21106173e342eab28552ae0e027196aDavid Turner face->kern_order_bits = ordered; 166e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 167e5680279b21106173e342eab28552ae0e027196aDavid Turner Exit: 168e5680279b21106173e342eab28552ae0e027196aDavid Turner return error; 169e5680279b21106173e342eab28552ae0e027196aDavid Turner } 170e5680279b21106173e342eab28552ae0e027196aDavid Turner 171e5680279b21106173e342eab28552ae0e027196aDavid Turner 172e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_LOCAL_DEF( void ) 173e5680279b21106173e342eab28552ae0e027196aDavid Turner tt_face_done_kern( TT_Face face ) 174e5680279b21106173e342eab28552ae0e027196aDavid Turner { 175e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_Stream stream = face->root.stream; 176e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 177e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 178e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_FRAME_RELEASE( face->kern_table ); 179e5680279b21106173e342eab28552ae0e027196aDavid Turner face->kern_table_size = 0; 180e5680279b21106173e342eab28552ae0e027196aDavid Turner face->num_kern_tables = 0; 181e5680279b21106173e342eab28552ae0e027196aDavid Turner face->kern_avail_bits = 0; 182e5680279b21106173e342eab28552ae0e027196aDavid Turner face->kern_order_bits = 0; 183e5680279b21106173e342eab28552ae0e027196aDavid Turner } 184e5680279b21106173e342eab28552ae0e027196aDavid Turner 185e5680279b21106173e342eab28552ae0e027196aDavid Turner 186e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_LOCAL_DEF( FT_Int ) 187e5680279b21106173e342eab28552ae0e027196aDavid Turner tt_face_get_kerning( TT_Face face, 188e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_UInt left_glyph, 189e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_UInt right_glyph ) 190e5680279b21106173e342eab28552ae0e027196aDavid Turner { 191e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_Int result = 0; 192e8ed2d621e4182956488ce15c5611472345e63beWerner Lemberg FT_UInt count, mask; 193e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_Byte* p = face->kern_table; 194ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner FT_Byte* p_limit = p + face->kern_table_size; 195e5680279b21106173e342eab28552ae0e027196aDavid Turner 196e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 197e5680279b21106173e342eab28552ae0e027196aDavid Turner p += 4; 198e5680279b21106173e342eab28552ae0e027196aDavid Turner mask = 0x0001; 199e5680279b21106173e342eab28552ae0e027196aDavid Turner 200ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner for ( count = face->num_kern_tables; 201ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner count > 0 && p + 6 <= p_limit; 202ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner count--, mask <<= 1 ) 203e5680279b21106173e342eab28552ae0e027196aDavid Turner { 204e5680279b21106173e342eab28552ae0e027196aDavid Turner FT_Byte* base = p; 205e8ed2d621e4182956488ce15c5611472345e63beWerner Lemberg FT_Byte* next; 206e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt version = FT_NEXT_USHORT( p ); 207e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt length = FT_NEXT_USHORT( p ); 208e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt coverage = FT_NEXT_USHORT( p ); 209ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner FT_UInt num_pairs; 210fa0eb0c95fa954a3097d62c440303c403f466942David Turner FT_Int value = 0; 211e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 212b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_UNUSED( version ); 213b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 214e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 215e5680279b21106173e342eab28552ae0e027196aDavid Turner next = base + length; 216e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 21742f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg if ( next > p_limit ) /* handle broken table */ 218ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner next = p_limit; 219ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner 220e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg if ( ( face->kern_avail_bits & mask ) == 0 ) 221e5680279b21106173e342eab28552ae0e027196aDavid Turner goto NextTable; 222e5680279b21106173e342eab28552ae0e027196aDavid Turner 223565f5a7d19d23aa7b3d6f917e5ef6b297b89f384Wojciech Mamrak FT_ASSERT( p + 8 <= next ); /* tested in tt_face_load_kern */ 224e5680279b21106173e342eab28552ae0e027196aDavid Turner 225ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner num_pairs = FT_NEXT_USHORT( p ); 226ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner p += 6; 227ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner 2280ae6cf214ff1eec6499c347726a18b8a9809ab2cWerner Lemberg if ( ( next - p ) < 6 * (int)num_pairs ) /* handle broken count */ 22942f5c714c055d9d8cade2ede35c3abb5ae448a2cWerner Lemberg num_pairs = (FT_UInt)( ( next - p ) / 6 ); 230ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner 231e5680279b21106173e342eab28552ae0e027196aDavid Turner switch ( coverage >> 8 ) 232e5680279b21106173e342eab28552ae0e027196aDavid Turner { 233e5680279b21106173e342eab28552ae0e027196aDavid Turner case 0: 234e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg { 235ab7e52b1c78b27d74e9555c6488c46bd62101804David Turner FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); 236e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 237e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 238e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg if ( face->kern_order_bits & mask ) /* binary search */ 239e5680279b21106173e342eab28552ae0e027196aDavid Turner { 240e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt min = 0; 241e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt max = num_pairs; 242fa0eb0c95fa954a3097d62c440303c403f466942David Turner 243e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 244e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg while ( min < max ) 245e5680279b21106173e342eab28552ae0e027196aDavid Turner { 246e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_UInt mid = ( min + max ) >> 1; 247e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_Byte* q = p + 6 * mid; 248e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_ULong key; 249e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 250e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 251e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg key = FT_NEXT_ULONG( q ); 252e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 253e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg if ( key == key0 ) 254e5680279b21106173e342eab28552ae0e027196aDavid Turner { 255e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg value = FT_PEEK_SHORT( q ); 256e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg goto Found; 257e5680279b21106173e342eab28552ae0e027196aDavid Turner } 258e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg if ( key < key0 ) 259e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg min = mid + 1; 260e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg else 261e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg max = mid; 262e5680279b21106173e342eab28552ae0e027196aDavid Turner } 263e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg } 264e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg else /* linear search */ 265e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg { 26642137bc6145c426702b90d0cec5c5acd332739aeDavid Turner FT_UInt count2; 26742137bc6145c426702b90d0cec5c5acd332739aeDavid Turner 268fa3651e7d8af95b080db00d25a5ada0a5f77ef3dWerner Lemberg 26942137bc6145c426702b90d0cec5c5acd332739aeDavid Turner for ( count2 = num_pairs; count2 > 0; count2-- ) 270e5680279b21106173e342eab28552ae0e027196aDavid Turner { 271e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg FT_ULong key = FT_NEXT_ULONG( p ); 272e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 273e5680279b21106173e342eab28552ae0e027196aDavid Turner 274e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg if ( key == key0 ) 275e5680279b21106173e342eab28552ae0e027196aDavid Turner { 276e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg value = FT_PEEK_SHORT( p ); 277e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg goto Found; 278e5680279b21106173e342eab28552ae0e027196aDavid Turner } 279e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg p += 2; 280e5680279b21106173e342eab28552ae0e027196aDavid Turner } 281e5680279b21106173e342eab28552ae0e027196aDavid Turner } 282e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg } 283e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg break; 284e5680279b21106173e342eab28552ae0e027196aDavid Turner 285e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg /* 286fa3651e7d8af95b080db00d25a5ada0a5f77ef3dWerner Lemberg * We don't support format 2 because we haven't seen a single font 287e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg * using it in real life... 288e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg */ 289e5680279b21106173e342eab28552ae0e027196aDavid Turner 290e5680279b21106173e342eab28552ae0e027196aDavid Turner default: 291e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg ; 292e5680279b21106173e342eab28552ae0e027196aDavid Turner } 293e5680279b21106173e342eab28552ae0e027196aDavid Turner 294fa0eb0c95fa954a3097d62c440303c403f466942David Turner goto NextTable; 295e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 296fa0eb0c95fa954a3097d62c440303c403f466942David Turner Found: 2976e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg if ( coverage & 8 ) /* override or add */ 298e5680279b21106173e342eab28552ae0e027196aDavid Turner result = value; 299e5680279b21106173e342eab28552ae0e027196aDavid Turner else 300e5680279b21106173e342eab28552ae0e027196aDavid Turner result += value; 301e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 302e5680279b21106173e342eab28552ae0e027196aDavid Turner NextTable: 303e5680279b21106173e342eab28552ae0e027196aDavid Turner p = next; 304e5680279b21106173e342eab28552ae0e027196aDavid Turner } 305e5680279b21106173e342eab28552ae0e027196aDavid Turner 306e5680279b21106173e342eab28552ae0e027196aDavid Turner return result; 307e5680279b21106173e342eab28552ae0e027196aDavid Turner } 308e5680279b21106173e342eab28552ae0e027196aDavid Turner 309e5680279b21106173e342eab28552ae0e027196aDavid Turner#undef TT_KERN_INDEX 310e793092d0a9f4d4d383315bcefd485dcbe4804b3Werner Lemberg 311e5680279b21106173e342eab28552ae0e027196aDavid Turner/* END */ 312