1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* ttgxvar.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* TrueType GX Font Variation loader */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Copyright 2004-2013 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */ 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */ 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The documentation for `fvar' is inconsistent. At one point it says */ 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* that `countSizePairs' should be 3, at another point 2. It should */ 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* be 2. */ 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The documentation for `gvar' is not intelligible; `cvar' refers you */ 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to `gvar' and is thus also incomprehensible. */ 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The documentation for `avar' appears correct, but Apple has no fonts */ 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* with an `avar' table, so it is hard to test. */ 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Many thanks to John Jenkins (at Apple) in figuring this out. */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Apple's `kern' table has some references to tuple indices, but as */ 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* there is no indication where these indices are defined, nor how to */ 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* interpolate the kerning values (different tuples have different */ 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* classes) this issue is ignored. */ 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h" 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h" 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/config/ftconfig.h" 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftstream.h" 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/sfnt.h" 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/tttags.h" 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftmm.h" 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttpload.h" 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ttgxvar.h" 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "tterrors.h" 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_Stream_FTell( stream ) \ 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_ULong)( (stream)->cursor - (stream)->base ) 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_Stream_SeekSet( stream, off ) \ 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( (stream)->cursor = (stream)->base + (off) ) 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_ttgxvar 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** Internal Routines *****/ 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */ 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* indicates that there is a delta for every point without needing to */ 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* enumerate all of them. */ 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ensure that value `0' has the same width as a pointer */ 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ALL_POINTS (FT_UShort*)~(FT_PtrDist)0 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define GX_PT_POINTS_ARE_WORDS 0x80 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define GX_PT_POINT_RUN_COUNT_MASK 0x7F 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ft_var_readpackedpoints */ 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Read a set of points to which the following deltas will apply. */ 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Points are packed with a run length encoding. */ 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* stream :: The data stream. */ 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Output> */ 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* point_cnt :: The number of points read. A zero value means that */ 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* all points in the glyph will be affected, without */ 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* enumerating them individually. */ 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* An array of FT_UShort containing the affected points or the */ 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* special value ALL_POINTS. */ 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_UShort* 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_readpackedpoints( FT_Stream stream, 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt *point_cnt ) 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort *points = NULL; 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int n; 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int runcnt; 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int j; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int first; 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( error ); 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *point_cnt = n = FT_GET_BYTE(); 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n == 0 ) 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ALL_POINTS; 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n & GX_PT_POINTS_ARE_WORDS ) 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 ); 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( points, n ) ) 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = 0; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( i < n ) 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov runcnt = FT_GET_BYTE(); 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( runcnt & GX_PT_POINTS_ARE_WORDS ) 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK; 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = points[i++] = FT_GET_USHORT(); 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( runcnt < 1 || i + runcnt >= n ) 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first point not included in runcount */ 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < runcnt; ++j ) 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points[i++] = (FT_UShort)( first += FT_GET_USHORT() ); 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = points[i++] = FT_GET_BYTE(); 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( runcnt < 1 || i + runcnt >= n ) 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < runcnt; ++j ) 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points[i++] = (FT_UShort)( first += FT_GET_BYTE() ); 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return points; 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov enum 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_DT_DELTAS_ARE_ZERO = 0x80, 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_DT_DELTAS_ARE_WORDS = 0x40, 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_DT_DELTA_RUN_COUNT_MASK = 0x3F 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ft_var_readpackeddeltas */ 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Read a set of deltas. These are packed slightly differently than */ 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* points. In particular there is no overall count. */ 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* stream :: The data stream. */ 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* delta_cnt :: The number of to be read. */ 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* An array of FT_Short containing the deltas for the affected */ 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* points. (This only gets the deltas for one dimension. It will */ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* generally be called twice, once for x, once for y. When used in */ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cvt table, it will only be called once.) */ 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Short* 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_readpackeddeltas( FT_Stream stream, 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Offset delta_cnt ) 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short *deltas = NULL; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt runcnt; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Offset i; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt j; 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( error ); 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = 0; 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( i < delta_cnt ) 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov runcnt = FT_GET_BYTE(); 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* runcnt zeroes get added */ 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++j ) 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas[i++] = 0; 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* runcnt shorts from the stack */ 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++j ) 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas[i++] = FT_GET_SHORT(); 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* runcnt signed bytes from the stack */ 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++j ) 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas[i++] = FT_GET_CHAR(); 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) ) 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Bad format */ 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( deltas ); 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return deltas; 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ft_var_load_avar */ 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Parse the `avar' table if present. It need not be, so we return */ 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nothing. */ 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The font face. */ 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_load_avar( TT_Face face ) 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = FT_FACE_STREAM(face); 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend = face->blend; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_AVarSegment segment; 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong version; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long axisCount; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i, j; 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong table_len; 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( error ); 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->avar_checked = TRUE; 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 ) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_FRAME_ENTER( table_len ) ) 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov version = FT_GET_LONG(); 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov axisCount = FT_GET_LONG(); 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( version != 0x00010000L || 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov axisCount != (FT_Long)blend->mmvar->num_axis ) 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov segment = &blend->avar_segment[0]; 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < axisCount; ++i, ++segment ) 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov segment->pairCount = FT_GET_USHORT(); 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Failure. Free everything we have done so far. We must do */ 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* it right now since loading the `avar' table is optional. */ 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = i - 1; j >= 0; --j ) 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->avar_segment[j].correspondence ); 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->avar_segment ); 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->avar_segment = NULL; 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < segment->pairCount; ++j ) 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov segment->correspondence[j].fromCoord = 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GET_SHORT() << 2; /* convert to Fixed */ 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov segment->correspondence[j].toCoord = 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GET_SHORT()<<2; /* convert to Fixed */ 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct GX_GVar_Head_ 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long version; 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort axisCount; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort globalCoordCount; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offsetToCoord; 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort glyphCount; 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort flags; 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offsetToData; 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } GX_GVar_Head; 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ft_var_load_gvar */ 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */ 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* had better be there too. */ 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The font face. */ 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Error 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_load_gvar( TT_Face face ) 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = FT_FACE_STREAM(face); 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend = face->blend; 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, j; 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong table_len; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong gvar_start; 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offsetToData; 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_GVar_Head gvar_head; 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Frame_Field gvar_fields[] = 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_STRUCTURE 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_STRUCTURE GX_GVar_Head 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_START( 20 ), 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_LONG ( version ), 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( axisCount ), 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( globalCoordCount ), 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( offsetToCoord ), 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( glyphCount ), 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( flags ), 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( offsetToData ), 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_END 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 ) 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gvar_start = FT_STREAM_POS( ); 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) ) 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->tuplecount = gvar_head.globalCoordCount; 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->gv_glyphcnt = gvar_head.glyphCount; 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData = gvar_start + gvar_head.offsetToData; 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gvar_head.version != (FT_Long)0x00010000L || 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis ) 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Table ); 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) ) 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( gvar_head.flags & 1 ) 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* long offsets (one more offset than glyphs, to mark size of last) */ 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) ) 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i <= blend->gv_glyphcnt; ++i ) 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->glyphoffsets[i] = offsetToData + FT_GET_LONG(); 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* short offsets (one more offset than glyphs, to mark size of last) */ 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) ) 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i <= blend->gv_glyphcnt; ++i ) 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2; 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: Undocumented: `*2'! */ 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->tuplecount != 0 ) 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( blend->tuplecoords, 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gvar_head.axisCount * blend->tuplecount ) ) 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) || 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) ) 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < blend->tuplecount; ++i ) 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j ) 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->tuplecoords[i * gvar_head.axisCount + j] = 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GET_SHORT() << 2; /* convert to FT_Fixed */ 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ft_var_apply_tuple */ 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Figure out whether a given tuple (design) applies to the current */ 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* blend, and if so, what is the scaling factor. */ 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* blend :: The current blend of the font. */ 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tupleIndex :: A flag saying whether this is an intermediate */ 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tuple or not. */ 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tuple_coords :: The coordinates of the tuple in normalized axis */ 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* units. */ 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* im_start_coords :: The initial coordinates where this tuple starts */ 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to apply (for intermediate coordinates). */ 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* im_end_coords :: The final coordinates after which this tuple no */ 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* longer applies (for intermediate coordinates). */ 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* An FT_Fixed value containing the scaling factor. */ 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Fixed 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_apply_tuple( GX_Blend blend, 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort tupleIndex, 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* tuple_coords, 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_start_coords, 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_end_coords ) 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i; 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed apply = 0x10000L; 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < blend->num_axis; ++i ) 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tuple_coords[i] == 0 ) 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* It's not clear why (for intermediate tuples) we don't need */ 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to check against start/end -- the documentation says we don't. */ 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Similarly, it's unclear why we don't need to scale along the */ 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* axis. */ 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( blend->normalizedcoords[i] == 0 || 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) || 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) ) 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = 0; 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* not an intermediate tuple */ 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = FT_MulFix( apply, 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->normalizedcoords[i] > 0 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ? blend->normalizedcoords[i] 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : -blend->normalizedcoords[i] ); 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( blend->normalizedcoords[i] <= im_start_coords[i] || 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->normalizedcoords[i] >= im_end_coords[i] ) 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = 0; 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( blend->normalizedcoords[i] < tuple_coords[i] ) 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = FT_MulDiv( apply, 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->normalizedcoords[i] - im_start_coords[i], 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords[i] - im_start_coords[i] ); 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = FT_MulDiv( apply, 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords[i] - blend->normalizedcoords[i], 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords[i] - tuple_coords[i] ); 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return apply; 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/ 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct GX_FVar_Head_ 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Long version; 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort offsetToData; 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort countSizePairs; 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort axisCount; 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort axisSize; 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort instanceCount; 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort instanceSize; 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } GX_FVar_Head; 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct fvar_axis_ 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong axisTag; 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong minValue; 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong defaultValue; 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong maxValue; 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort flags; 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort nameID; 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } GX_FVar_Axis; 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TT_Get_MM_Var */ 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Check that the font's `fvar' table is valid, parse it, and return */ 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* those data. */ 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The font face. */ 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TT_Get_MM_Var initializes the blend structure. */ 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Output> */ 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* master :: The `fvar' data (must be freed by caller). */ 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Get_MM_Var( TT_Face face, 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MM_Var* *master ) 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = face->root.stream; 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong table_len; 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong fvar_start; 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i, j; 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MM_Var* mmvar = NULL; 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* next_coords; 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_String* next_name; 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Var_Axis* a; 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Var_Named_Style* ns; 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_FVar_Head fvar_head; 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Frame_Field fvar_fields[] = 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_STRUCTURE 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_STRUCTURE GX_FVar_Head 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_START( 16 ), 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_LONG ( version ), 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( offsetToData ), 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( countSizePairs ), 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( axisCount ), 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( axisSize ), 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( instanceCount ), 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( instanceSize ), 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_END 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Frame_Field fvaraxis_fields[] = 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_STRUCTURE 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_STRUCTURE GX_FVar_Axis 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_START( 20 ), 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( axisTag ), 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( minValue ), 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( defaultValue ), 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ULONG ( maxValue ), 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( flags ), 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_USHORT( nameID ), 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_END 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->blend == NULL ) 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* both `fvar' and `gvar' must be present */ 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = face->goto_table( face, TTAG_gvar, 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov stream, &table_len )) != 0 ) 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = face->goto_table( face, TTAG_fvar, 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov stream, &table_len )) != 0 ) 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_start = FT_STREAM_POS( ); 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) ) 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( fvar_head.version != (FT_Long)0x00010000L || 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.countSizePairs != 2 || 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.axisSize != 20 || 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* axisCount limit implied by 16-bit instanceSize */ 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.axisCount > 0x3FFE || 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* instanceCount limit implied by limited range of name IDs */ 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceCount > 0x7EFF || 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.offsetToData + fvar_head.axisCount * 20U + 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceCount * fvar_head.instanceSize > table_len ) 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Table ); 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW( face->blend ) ) 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cannot overflow 32-bit arithmetic because of limits above */ 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->blend->mmvar_len = 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( FT_MM_Var ) + 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.axisCount * sizeof ( FT_Var_Axis ) + 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 5 * fvar_head.axisCount; 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->blend->mmvar = mmvar; 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->num_axis = 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.axisCount; 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->num_designs = 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ~0U; /* meaningless in this context; each glyph */ 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* may have a different number of designs */ 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* (or tuples, as called by Apple) */ 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->num_namedstyles = 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fvar_head.instanceCount; 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->axis = 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Var_Axis*)&(mmvar[1]); 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->namedstyle = 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]); 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_coords = 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]); 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < fvar_head.instanceCount; ++i ) 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->namedstyle[i].coords = next_coords; 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_coords += fvar_head.axisCount; 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_name = (FT_String*)next_coords; 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < fvar_head.axisCount; ++i ) 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->axis[i].name = next_name; 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_name += 5; 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) ) 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = mmvar->axis; 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < fvar_head.axisCount; ++i ) 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_FVar_Axis axis_rec; 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) ) 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->tag = axis_rec.axisTag; 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->minimum = axis_rec.minValue; /* A Fixed */ 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->def = axis_rec.defaultValue; /* A Fixed */ 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->maximum = axis_rec.maxValue; /* A Fixed */ 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->strid = axis_rec.nameID; 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name[0] = (FT_String)( a->tag >> 24 ); 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF ); 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name[2] = (FT_String)( ( a->tag >> 8 ) & 0xFF ); 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name[3] = (FT_String)( ( a->tag ) & 0xFF ); 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name[4] = 0; 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++a; 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ns = mmvar->namedstyle; 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns ) 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) ) 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ns->strid = FT_GET_USHORT(); 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void) /* flags = */ FT_GET_USHORT(); 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < fvar_head.axisCount; ++j ) 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ns->coords[j] = FT_GET_ULONG(); /* A Fixed */ 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( master != NULL ) 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n; 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->axis = 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Var_Axis*)&(mmvar[1]); 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->namedstyle = 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]); 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_coords = 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]); 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < mmvar->num_namedstyles; ++n ) 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar->namedstyle[n].coords = next_coords; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_coords += mmvar->num_axis; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = mmvar->axis; 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_name = (FT_String*)next_coords; 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < mmvar->num_axis; ++n ) 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name = next_name; 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* standard PostScript names for some standard apple tags */ 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( a->tag == TTAG_wght ) 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name = (char *)"Weight"; 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( a->tag == TTAG_wdth ) 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name = (char *)"Width"; 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( a->tag == TTAG_opsz ) 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name = (char *)"OpticalSize"; 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( a->tag == TTAG_slnt ) 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a->name = (char *)"Slant"; 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov next_name += 5; 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++a; 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *master = mmvar; 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TT_Set_MM_Blend */ 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set the blend (normalized) coordinates for this instance of the */ 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* font. Check that the `gvar' table is reasonable and does some */ 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* initial preparation. */ 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The font. */ 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initialize the blend structure with `gvar' data. */ 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* num_coords :: Must be the axis count of the font. */ 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* coords :: An array of num_coords, each between [-1,1]. */ 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Set_MM_Blend( TT_Face face, 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_coords, 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* coords ) 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend; 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MM_Var* mmvar; 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i; 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov enum 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mcvt_retain, 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mcvt_modify, 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mcvt_load 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } manageCvt; 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->doblend = FALSE; 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->blend == NULL ) 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = TT_Get_MM_Var( face, NULL)) != 0 ) 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend = face->blend; 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar = blend->mmvar; 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_coords != mmvar->num_axis ) 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Argument ); 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < num_coords; ++i ) 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Argument ); 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->glyphoffsets == NULL ) 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = ft_var_load_gvar( face )) != 0 ) 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->normalizedcoords == NULL ) 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) ) 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov manageCvt = mcvt_modify; 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If we have not set the blend coordinates before this, then the */ 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cvt table will still be what we read from the `cvt ' table and */ 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we don't need to reload it. We may need to change it though... */ 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov manageCvt = mcvt_retain; 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < num_coords; ++i ) 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->normalizedcoords[i] != coords[i] ) 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov manageCvt = mcvt_load; 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If we don't change the blend coords then we don't need to do */ 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* anything to the cvt table. It will be correct. Otherwise we */ 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* no longer have the original cvt (it was modified when we set */ 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the blend last time), so we must reload and then modify it. */ 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->num_axis = num_coords; 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_COPY( blend->normalizedcoords, 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coords, 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_coords * sizeof ( FT_Fixed ) ); 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->doblend = TRUE; 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->cvt != NULL ) 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( manageCvt ) 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case mcvt_load: 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The cvt table has been loaded already; every time we change the */ 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* blend we may need to reload and remodify the cvt table. */ 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( face->cvt ); 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cvt = NULL; 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_face_load_cvt( face, face->root.stream ); 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case mcvt_modify: 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The original cvt table is in memory. All we need to do is */ 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* apply the `cvar' table (if any). */ 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_face_vary_cvt( face, face->root.stream ); 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case mcvt_retain: 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The cvt table is correct for this set of coordinates. */ 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TT_Set_Var_Design */ 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set the coordinates for the instance, measured in the user */ 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* coordinate system. Parse the `avar' table (if present) to convert */ 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* from user to normalized coordinates. */ 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: The font face. */ 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initialize the blend struct with `gvar' data. */ 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* num_coords :: This must be the axis count of the font. */ 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* coords :: A coordinate array with `num_coords' elements. */ 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Set_Var_Design( TT_Face face, 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt num_coords, 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* coords ) 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error = FT_Err_Ok; 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* normalized = NULL; 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend; 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MM_Var* mmvar; 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, j; 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Var_Axis* a; 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_AVarSegment av; 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = face->root.memory; 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->blend == NULL ) 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( (error = TT_Get_MM_Var( face, NULL )) != 0 ) 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend = face->blend; 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mmvar = blend->mmvar; 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_coords != mmvar->num_axis ) 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Argument ); 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Axis normalization is a two stage process. First we normalize */ 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Then, if there's an `avar' table, we renormalize this range. */ 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = mmvar->axis; 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < mmvar->num_axis; ++i, ++a ) 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coords[i] > a->maximum || coords[i] < a->minimum ) 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Argument ); 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coords[i] < a->def ) 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def ); 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( a->maximum == a->def ) 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov normalized[i] = 0; 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def ); 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !blend->avar_checked ) 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_var_load_avar( face ); 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->avar_segment != NULL ) 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av = blend->avar_segment; 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < mmvar->num_axis; ++i, ++av ) 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 1; j < (FT_UInt)av->pairCount; ++j ) 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( normalized[i] < av->correspondence[j].fromCoord ) 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov normalized[i] = 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord, 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av->correspondence[j].toCoord - 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av->correspondence[j - 1].toCoord, 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av->correspondence[j].fromCoord - 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av->correspondence[j - 1].fromCoord ) + 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov av->correspondence[j - 1].toCoord; 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = TT_Set_MM_Blend( face, num_coords, normalized ); 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( normalized ); 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** GX VAR PARSING ROUTINES *****/ 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /***** *****/ 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tt_face_vary_cvt */ 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Modify the loaded cvt table according to the `cvar' table and the */ 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* font's blend. */ 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: A handle to the target face object. */ 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* stream :: A handle to the input stream. */ 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Most errors are ignored. It is perfectly valid not to have a */ 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `cvar' table even if there is a `gvar' and `fvar' table. */ 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_face_vary_cvt( TT_Face face, 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream ) 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong table_start; 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong table_len; 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleCount; 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offsetToData; 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong here; 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, j; 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* tuple_coords = NULL; 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_start_coords = NULL; 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_end_coords = NULL; 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend = face->blend; 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt point_count; 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort* localpoints; 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short* deltas; 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE2(( "CVAR " )); 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend == NULL ) 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" )); 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( face->cvt == NULL ) 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" )); 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = face->goto_table( face, TTAG_cvar, stream, &table_len ); 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE2(( "is missing\n" )); 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_FRAME_ENTER( table_len ) ) 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov table_start = FT_Stream_FTell( stream ); 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_GET_LONG() != 0x00010000L ) 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE2(( "bad table version\n" )); 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Err_Ok; 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto FExit; 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto FExit; 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleCount = FT_GET_USHORT(); 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData = table_start + FT_GET_USHORT(); 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The documentation implies there are flags packed into the */ 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tuplecount, but John Jenkins says that shared points don't apply */ 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to `cvar', and no other flags are defined. */ 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < ( tupleCount & 0xFFF ); ++i ) 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleDataSize; 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleIndex; 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed apply; 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleDataSize = FT_GET_USHORT(); 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleIndex = FT_GET_USHORT(); 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* There is no provision here for a global tuple coordinate section, */ 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* so John says. There are no tuple indices, just embedded tuples. */ 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* short frac to fixed */ 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* skip this tuple; it makes no sense */ 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < 2 * blend->num_axis; ++j ) 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)FT_GET_SHORT(); 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData += tupleDataSize; 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_start_coords[j] = FT_GET_SHORT() << 2; 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords[j] = FT_GET_SHORT() << 2; 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = ft_var_apply_tuple( blend, 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_UShort)tupleIndex, 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords, 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_start_coords, 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords ); 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( /* tuple isn't active for our blend */ 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply == 0 || 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* global points not allowed, */ 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if they aren't local, makes no sense */ 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) ) 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData += tupleDataSize; 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov here = FT_Stream_FTell( stream ); 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, offsetToData ); 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov localpoints = ft_var_readpackedpoints( stream, &point_count ); 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas = ft_var_readpackeddeltas( stream, 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point_count == 0 ? face->cvt_size 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : point_count ); 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( localpoints == NULL || deltas == NULL ) 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* failure, ignore it */; 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( localpoints == ALL_POINTS ) 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this means that there are deltas for every entry in cvt */ 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < face->cvt_size; ++j ) 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cvt[j] = (FT_Short)( face->cvt[j] + 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MulFix( deltas[j], apply ) ); 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < point_count; ++j ) 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int pindex = localpoints[j]; 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov face->cvt[pindex] = (FT_Short)( face->cvt[pindex] + 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MulFix( deltas[j], apply ) ); 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( localpoints != ALL_POINTS ) 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( localpoints ); 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( deltas ); 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData += tupleDataSize; 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, here ); 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FExit: 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( tuple_coords ); 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( im_start_coords ); 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( im_end_coords ); 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TT_Vary_Get_Glyph_Deltas */ 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Load the appropriate deltas for the current glyph. */ 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* face :: A handle to the target face object. */ 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* glyph_index :: The index of the glyph being modified. */ 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* n_points :: The number of the points in the glyph, including */ 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* phantom points. */ 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Output> */ 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* deltas :: The array of points to change. */ 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FreeType error code. 0 means success. */ 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( FT_Error ) 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TT_Vary_Get_Glyph_Deltas( TT_Face face, 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt glyph_index, 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* *deltas, 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt n_points ) 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream stream = face->root.stream; 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = stream->memory; 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend = face->blend; 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* delta_xy = NULL; 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong glyph_start; 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleCount; 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong offsetToData; 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ULong here; 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i, j; 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* tuple_coords = NULL; 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_start_coords = NULL; 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed* im_end_coords = NULL; 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt point_count, spoint_count = 0; 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort* sharedpoints = NULL; 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort* localpoints = NULL; 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UShort* points; 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Short *deltas_x, *deltas_y; 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !face->doblend || blend == NULL ) 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to be freed by the caller */ 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( delta_xy, n_points ) ) 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *deltas = delta_xy; 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( glyph_index >= blend->gv_glyphcnt || 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->glyphoffsets[glyph_index] == 1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->glyphoffsets[glyph_index + 1] ) 1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Err_Ok; /* no variation data for this glyph */ 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] - 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->glyphoffsets[glyph_index] ) ) 1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail1; 1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_start = FT_Stream_FTell( stream ); 1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* each set of glyph variation data is formatted similarly to `cvar' */ 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* (except we get shared points and global tuples) */ 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail2; 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleCount = FT_GET_USHORT(); 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData = glyph_start + FT_GET_USHORT(); 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS ) 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov here = FT_Stream_FTell( stream ); 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, offsetToData ); 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData = FT_Stream_FTell( stream ); 1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, here ); 1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i ) 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleDataSize; 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt tupleIndex; 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed apply; 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleDataSize = FT_GET_USHORT(); 1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tupleIndex = FT_GET_USHORT(); 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* short frac to fixed */ 1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Invalid_Table ); 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Fail3; 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_COPY( 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords, 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis], 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blend->num_axis * sizeof ( FT_Fixed ) ); 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_start_coords[j] = FT_GET_SHORT() << 2; 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < blend->num_axis; ++j ) 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords[j] = FT_GET_SHORT() << 2; 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov apply = ft_var_apply_tuple( blend, 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_UShort)tupleIndex, 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tuple_coords, 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_start_coords, 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov im_end_coords ); 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( apply == 0 ) /* tuple isn't active for our blend */ 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData += tupleDataSize; 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov here = FT_Stream_FTell( stream ); 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, offsetToData ); 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov localpoints = ft_var_readpackedpoints( stream, &point_count ); 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points = localpoints; 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov points = sharedpoints; 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point_count = spoint_count; 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas_x = ft_var_readpackeddeltas( stream, 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point_count == 0 ? n_points 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : point_count ); 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov deltas_y = ft_var_readpackeddeltas( stream, 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point_count == 0 ? n_points 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : point_count ); 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( points == NULL || deltas_y == NULL || deltas_x == NULL ) 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ; /* failure, ignore it */ 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( points == ALL_POINTS ) 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this means that there are deltas for every point in the glyph */ 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < n_points; ++j ) 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta_xy[j].x += FT_MulFix( deltas_x[j], apply ); 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta_xy[j].y += FT_MulFix( deltas_y[j], apply ); 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( j = 0; j < point_count; ++j ) 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( localpoints[j] >= n_points ) 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply ); 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply ); 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( localpoints != ALL_POINTS ) 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( localpoints ); 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( deltas_x ); 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( deltas_y ); 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offsetToData += tupleDataSize; 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Stream_SeekSet( stream, here ); 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail3: 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( tuple_coords ); 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( im_start_coords ); 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( im_end_coords ); 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail2: 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FRAME_EXIT(); 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Fail1: 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( delta_xy ); 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *deltas = NULL; 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* tt_done_blend */ 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Frees the blend internal data structure. */ 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_LOCAL_DEF( void ) 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tt_done_blend( FT_Memory memory, 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov GX_Blend blend ) 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend != NULL ) 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt i; 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->normalizedcoords ); 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->mmvar ); 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( blend->avar_segment != NULL ) 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 0; i < blend->num_axis; ++i ) 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->avar_segment[i].correspondence ); 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->avar_segment ); 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->tuplecoords ); 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend->glyphoffsets ); 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( blend ); 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 1533