1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ttgxvar.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    TrueType GX Font Variation loader                                    */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2004-2013 by                                                 */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.     */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
19295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
20295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
21295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at      */
22295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
23295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*   http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html  */
24295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
25295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* The documentation for `fvar' is inconsistent.  At one point it says   */
26295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* that `countSizePairs' should be 3, at another point 2.  It should     */
27295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* be 2.                                                                 */
28295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
29295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* The documentation for `gvar' is not intelligible; `cvar' refers you   */
30295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* to `gvar' and is thus also incomprehensible.                          */
31295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
32295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* The documentation for `avar' appears correct, but Apple has no fonts  */
33295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* with an `avar' table, so it is hard to test.                          */
34295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
35295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* Many thanks to John Jenkins (at Apple) in figuring this out.          */
36295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
37295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
38295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* Apple's `kern' table has some references to tuple indices, but as     */
39295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* there is no indication where these indices are defined, nor how to    */
40295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* interpolate the kerning values (different tuples have different       */
41295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* classes) this issue is ignored.                                       */
42295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
43295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_CONFIG_CONFIG_H
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_STREAM_H
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_SFNT_H
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRUETYPE_TAGS_H
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_MULTIPLE_MASTERS_H
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttpload.h"
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttgxvar.h"
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "tterrors.h"
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_Stream_FTell( stream )  \
64a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          (FT_ULong)( (stream)->cursor - (stream)->base )
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_Stream_SeekSet( stream, off ) \
66a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          ( (stream)->cursor = (stream)->base + (off) )
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttgxvar
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                       Internal Routines                       *****/
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'.  It        */
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* indicates that there is a delta for every point without needing to    */
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* enumerate all of them.                                                */
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
94a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* ensure that value `0' has the same width as a pointer */
96a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define ALL_POINTS  (FT_UShort*)~(FT_PtrDist)0
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
99295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define GX_PT_POINTS_ARE_WORDS      0x80
100295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define GX_PT_POINT_RUN_COUNT_MASK  0x7F
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_readpackedpoints                                            */
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Read a set of points to which the following deltas will apply.     */
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Points are packed with a run length encoding.                      */
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream    :: The data stream.                                      */
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Output>                                                              */
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    point_cnt :: The number of points read.  A zero value means that   */
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                 all points in the glyph will be affected, without     */
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                 enumerating them individually.                        */
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An array of FT_UShort containing the affected points or the        */
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    special value ALL_POINTS.                                          */
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UShort*
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_readpackedpoints( FT_Stream  stream,
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_UInt   *point_cnt )
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_UShort *points = NULL;
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     n;
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     runcnt;
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     i;
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     j;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     first;
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error  = FT_Err_Ok;
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *point_cnt = n = FT_GET_BYTE();
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( n == 0 )
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ALL_POINTS;
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( n & GX_PT_POINTS_ARE_WORDS )
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 );
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( points, n ) )
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    i = 0;
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( i < n )
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      runcnt = FT_GET_BYTE();
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( runcnt & GX_PT_POINTS_ARE_WORDS )
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first  = points[i++] = FT_GET_USHORT();
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1598583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( runcnt < 1 || i + runcnt >= n )
160295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          goto Exit;
161295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* first point not included in runcount */
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < runcnt; ++j )
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          points[i++] = (FT_UShort)( first += FT_GET_USHORT() );
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = points[i++] = FT_GET_BYTE();
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1708583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( runcnt < 1 || i + runcnt >= n )
171295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          goto Exit;
172295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < runcnt; ++j )
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          points[i++] = (FT_UShort)( first += FT_GET_BYTE() );
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
178295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  Exit:
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return points;
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  enum
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_DT_DELTAS_ARE_ZERO      = 0x80,
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_DT_DELTAS_ARE_WORDS     = 0x40,
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_DT_DELTA_RUN_COUNT_MASK = 0x3F
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_readpackeddeltas                                            */
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Read a set of deltas.  These are packed slightly differently than  */
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    points.  In particular there is no overall count.                  */
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream    :: The data stream.                                      */
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    delta_cnt :: The number of to be read.                             */
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An array of FT_Short containing the deltas for the affected        */
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    points.  (This only gets the deltas for one dimension.  It will    */
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    generally be called twice, once for x, once for y.  When used in   */
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    cvt table, it will only be called once.)                           */
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Short*
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_readpackeddeltas( FT_Stream  stream,
213295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                           FT_Offset  delta_cnt )
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
215aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_Short  *deltas = NULL;
216295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    runcnt;
217295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_Offset  i;
218295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_UInt    j;
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error   error  = FT_Err_Ok;
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    i = 0;
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( i < delta_cnt )
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      runcnt = FT_GET_BYTE();
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* runcnt zeroes get added */
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0;
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              ++j )
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = 0;
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* runcnt shorts from the stack */
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0;
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              ++j )
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = FT_GET_SHORT();
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* runcnt signed bytes from the stack */
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0;
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt;
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              ++j )
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = FT_GET_CHAR();
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) )
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Bad format */
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( deltas );
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return NULL;
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return deltas;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_load_avar                                                   */
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Parse the `avar' table if present.  It need not be, so we return   */
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    nothing.                                                           */
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face :: The font face.                                             */
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_load_avar( TT_Face  face )
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream       stream = FT_FACE_STREAM(face);
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory       memory = stream->memory;
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend        blend  = face->blend;
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_AVarSegment  segment;
288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error        error = FT_Err_Ok;
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong        version;
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long         axisCount;
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int          i, j;
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong        table_len;
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend->avar_checked = TRUE;
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 )
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_ENTER( table_len ) )
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    version   = FT_GET_LONG();
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    axisCount = FT_GET_LONG();
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( version != 0x00010000L                       ||
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         axisCount != (FT_Long)blend->mmvar->num_axis )
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    segment = &blend->avar_segment[0];
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < axisCount; ++i, ++segment )
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      segment->pairCount = FT_GET_USHORT();
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Failure.  Free everything we have done so far.  We must do */
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* it right now since loading the `avar' table is optional.   */
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = i - 1; j >= 0; --j )
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_FREE( blend->avar_segment[j].correspondence );
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( blend->avar_segment );
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blend->avar_segment = NULL;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( j = 0; j < segment->pairCount; ++j )
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->correspondence[j].fromCoord =
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_GET_SHORT() << 2;    /* convert to Fixed */
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        segment->correspondence[j].toCoord =
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_GET_SHORT()<<2;    /* convert to Fixed */
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  GX_GVar_Head_
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long    version;
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisCount;
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  globalCoordCount;
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   offsetToCoord;
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  glyphCount;
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  flags;
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   offsetToData;
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_GVar_Head;
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_load_gvar                                                   */
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Parses the `gvar' table if present.  If `fvar' is there, `gvar'    */
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    had better be there too.                                           */
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face :: The font face.                                             */
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_load_gvar( TT_Face  face )
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream     stream = FT_FACE_STREAM(face);
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = stream->memory;
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend      blend  = face->blend;
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       i, j;
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      table_len;
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      gvar_start;
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      offsetToData;
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_GVar_Head  gvar_head;
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  gvar_fields[] =
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_GVar_Head
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 20 ),
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_LONG  ( version ),
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( axisCount ),
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( globalCoordCount ),
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( offsetToCoord ),
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( glyphCount ),
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( flags ),
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( offsetToData ),
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( (error = face->goto_table( face, TTAG_gvar, stream, &table_len )) != 0 )
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gvar_start = FT_STREAM_POS( );
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend->tuplecount  = gvar_head.globalCoordCount;
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend->gv_glyphcnt = gvar_head.glyphCount;
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsetToData       = gvar_start + gvar_head.offsetToData;
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( gvar_head.version   != (FT_Long)0x00010000L              ||
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
417a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Invalid_Table );
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( gvar_head.flags & 1 )
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* long offsets (one more offset than glyphs, to mark size of last) */
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i <= blend->gv_glyphcnt; ++i )
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blend->glyphoffsets[i] = offsetToData + FT_GET_LONG();
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* short offsets (one more offset than glyphs, to mark size of last) */
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i <= blend->gv_glyphcnt; ++i )
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                              /* XXX: Undocumented: `*2'! */
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend->tuplecount != 0 )
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW_ARRAY( blend->tuplecoords,
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         gvar_head.axisCount * blend->tuplecount ) )
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord )       ||
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L )                   )
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < blend->tuplecount; ++i )
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; ++j )
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blend->tuplecoords[i * gvar_head.axisCount + j] =
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_GET_SHORT() << 2;                /* convert to FT_Fixed */
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_apply_tuple                                                 */
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Figure out whether a given tuple (design) applies to the current   */
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    blend, and if so, what is the scaling factor.                      */
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    blend           :: The current blend of the font.                  */
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tupleIndex      :: A flag saying whether this is an intermediate   */
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       tuple or not.                                   */
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tuple_coords    :: The coordinates of the tuple in normalized axis */
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       units.                                          */
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    im_start_coords :: The initial coordinates where this tuple starts */
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       to apply (for intermediate coordinates).        */
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    im_end_coords   :: The final coordinates after which this tuple no */
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       longer applies (for intermediate coordinates).  */
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An FT_Fixed value containing the scaling factor.                   */
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Fixed
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_apply_tuple( GX_Blend   blend,
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UShort  tupleIndex,
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  tuple_coords,
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  im_start_coords,
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  im_end_coords )
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   i;
506a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Fixed  apply = 0x10000L;
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < blend->num_axis; ++i )
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tuple_coords[i] == 0 )
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* It's not clear why (for intermediate tuples) we don't need     */
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* to check against start/end -- the documentation says we don't. */
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* Similarly, it's unclear why we don't need to scale along the   */
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* axis.                                                          */
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( blend->normalizedcoords[i] == 0                           ||
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        apply = 0;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* not an intermediate tuple */
528a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        apply = FT_MulFix( apply,
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           blend->normalizedcoords[i] > 0
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             ? blend->normalizedcoords[i]
531a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             : -blend->normalizedcoords[i] );
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                blend->normalizedcoords[i] >= im_end_coords[i]   )
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        apply = 0;
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( blend->normalizedcoords[i] < tuple_coords[i] )
541a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        apply = FT_MulDiv( apply,
542a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           blend->normalizedcoords[i] - im_start_coords[i],
543a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           tuple_coords[i] - im_start_coords[i] );
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
546a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        apply = FT_MulDiv( apply,
547a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           im_end_coords[i] - blend->normalizedcoords[i],
548a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           im_end_coords[i] - tuple_coords[i] );
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return apply;
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****               MULTIPLE MASTERS SERVICE FUNCTIONS              *****/
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  GX_FVar_Head_
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long    version;
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  offsetToData;
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  countSizePairs;
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisCount;
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisSize;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  instanceCount;
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  instanceSize;
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_FVar_Head;
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  fvar_axis_
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   axisTag;
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   minValue;
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   defaultValue;
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   maxValue;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  flags;
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  nameID;
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_FVar_Axis;
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Get_MM_Var                                                      */
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Check that the font's `fvar' table is valid, parse it, and return  */
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    those data.                                                        */
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: The font face.                                           */
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*              TT_Get_MM_Var initializes the blend structure.           */
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Output>                                                              */
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    master :: The `fvar' data (must be freed by caller).               */
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Get_MM_Var( TT_Face      face,
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_MM_Var*  *master )
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream            stream = face->root.stream;
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory            memory = face->root.memory;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong             table_len;
615a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error             error  = FT_Err_Ok;
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong             fvar_start;
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int               i, j;
618c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_MM_Var*           mmvar = NULL;
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*            next_coords;
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_String*           next_name;
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Axis*         a;
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Named_Style*  ns;
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_FVar_Head         fvar_head;
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  fvar_fields[] =
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_FVar_Head
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 16 ),
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_LONG  ( version ),
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( offsetToData ),
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( countSizePairs ),
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( axisCount ),
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( axisSize ),
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( instanceCount ),
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( instanceSize ),
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  fvaraxis_fields[] =
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_FVar_Axis
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 20 ),
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( axisTag ),
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( minValue ),
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( defaultValue ),
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( maxValue ),
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( flags ),
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( nameID ),
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->blend == NULL )
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* both `fvar' and `gvar' must be present */
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( (error = face->goto_table( face, TTAG_gvar,
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      stream, &table_len )) != 0 )
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( (error = face->goto_table( face, TTAG_fvar,
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      stream, &table_len )) != 0 )
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      fvar_start = FT_STREAM_POS( );
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( fvar_head.version != (FT_Long)0x00010000L                      ||
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           fvar_head.countSizePairs != 2                                  ||
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           fvar_head.axisSize != 20                                       ||
678aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich           /* axisCount limit implied by 16-bit instanceSize */
679aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich           fvar_head.axisCount > 0x3FFE                                   ||
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount          ||
681aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich           /* instanceCount limit implied by limited range of name IDs */
682aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich           fvar_head.instanceCount > 0x7EFF                               ||
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           fvar_head.offsetToData + fvar_head.axisCount * 20U +
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project             fvar_head.instanceCount * fvar_head.instanceSize > table_len )
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
686a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Table );
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW( face->blend ) )
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
693aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      /* cannot overflow 32-bit arithmetic because of limits above */
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->blend->mmvar_len =
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sizeof ( FT_MM_Var ) +
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        5 * fvar_head.axisCount;
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->blend->mmvar = mmvar;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_axis =
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.axisCount;
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_designs =
708a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        ~0U;                   /* meaningless in this context; each glyph */
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               /* may have a different number of designs  */
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               /* (or tuples, as called by Apple)         */
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_namedstyles =
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount;
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->axis =
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Var_Axis*)&(mmvar[1]);
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->namedstyle =
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]);
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_coords =
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]);
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < fvar_head.instanceCount; ++i )
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->namedstyle[i].coords  = next_coords;
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_coords                 += fvar_head.axisCount;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_name = (FT_String*)next_coords;
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < fvar_head.axisCount; ++i )
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->axis[i].name  = next_name;
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_name           += 5;
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a = mmvar->axis;
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < fvar_head.axisCount; ++i )
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        GX_FVar_Axis  axis_rec;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->tag     = axis_rec.axisTag;
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->minimum = axis_rec.minValue;     /* A Fixed */
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->def     = axis_rec.defaultValue; /* A Fixed */
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->maximum = axis_rec.maxValue;     /* A Fixed */
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->strid   = axis_rec.nameID;
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[0] = (FT_String)(   a->tag >> 24 );
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[2] = (FT_String)( ( a->tag >>  8 ) & 0xFF );
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[3] = (FT_String)( ( a->tag       ) & 0xFF );
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[4] = 0;
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ++a;
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ns = mmvar->namedstyle;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < fvar_head.instanceCount; ++i, ++ns )
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) )
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ns->strid       =    FT_GET_USHORT();
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (void) /* flags = */ FT_GET_USHORT();
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < fvar_head.axisCount; ++j )
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ns->coords[j] = FT_GET_ULONG();     /* A Fixed */
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_EXIT();
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( master != NULL )
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  n;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->axis =
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Var_Axis*)&(mmvar[1]);
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->namedstyle =
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]);
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_coords =
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]);
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < mmvar->num_namedstyles; ++n )
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->namedstyle[n].coords  = next_coords;
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_coords                 += mmvar->num_axis;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a = mmvar->axis;
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_name = (FT_String*)next_coords;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( n = 0; n < mmvar->num_axis; ++n )
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name = next_name;
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* standard PostScript names for some standard apple tags */
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( a->tag == TTAG_wght )
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          a->name = (char *)"Weight";
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_wdth )
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          a->name = (char *)"Width";
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_opsz )
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          a->name = (char *)"OpticalSize";
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_slnt )
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          a->name = (char *)"Slant";
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_name += 5;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ++a;
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *master = mmvar;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Set_MM_Blend                                                    */
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Set the blend (normalized) coordinates for this instance of the    */
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    font.  Check that the `gvar' table is reasonable and does some     */
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    initial preparation.                                               */
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face       :: The font.                                            */
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                  Initialize the blend structure with `gvar' data.     */
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    num_coords :: Must be the axis count of the font.                  */
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    coords     :: An array of num_coords, each between [-1,1].         */
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Set_MM_Blend( TT_Face    face,
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_UInt    num_coords,
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Fixed*  coords )
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
852a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error    error = FT_Err_Ok;
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend;
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MM_Var*  mmvar;
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = face->root.memory;
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    enum
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_retain,
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_modify,
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_load
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } manageCvt;
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->doblend = FALSE;
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->blend == NULL )
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( (error = TT_Get_MM_Var( face, NULL)) != 0 )
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend = face->blend;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mmvar = blend->mmvar;
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_coords != mmvar->num_axis )
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
880a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Invalid_Argument );
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < num_coords; ++i )
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
887a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Argument );
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend->glyphoffsets == NULL )
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( (error = ft_var_load_gvar( face )) != 0 )
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend->normalizedcoords == NULL )
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) )
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      manageCvt = mcvt_modify;
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* If we have not set the blend coordinates before this, then the  */
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* cvt table will still be what we read from the `cvt ' table and  */
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we don't need to reload it.  We may need to change it though... */
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
9080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      manageCvt = mcvt_retain;
9090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      for ( i = 0; i < num_coords; ++i )
9100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      {
9110a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        if ( blend->normalizedcoords[i] != coords[i] )
9120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        {
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          manageCvt = mcvt_load;
9140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          break;
9150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        }
9160a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      }
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* If we don't change the blend coords then we don't need to do  */
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* anything to the cvt table.  It will be correct.  Otherwise we */
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no longer have the original cvt (it was modified when we set  */
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the blend last time), so we must reload and then modify it.   */
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend->num_axis = num_coords;
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MEM_COPY( blend->normalizedcoords,
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 coords,
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 num_coords * sizeof ( FT_Fixed ) );
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->doblend = TRUE;
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->cvt != NULL )
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      switch ( manageCvt )
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_load:
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The cvt table has been loaded already; every time we change the */
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* blend we may need to reload and remodify the cvt table.         */
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( face->cvt );
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        face->cvt = NULL;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_face_load_cvt( face, face->root.stream );
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_modify:
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The original cvt table is in memory.  All we need to do is */
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* apply the `cvar' table (if any).                           */
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tt_face_vary_cvt( face, face->root.stream );
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_retain:
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The cvt table is correct for this set of coordinates. */
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Set_Var_Design                                                  */
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Set the coordinates for the instance, measured in the user         */
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    coordinate system.  Parse the `avar' table (if present) to convert */
969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    from user to normalized coordinates.                               */
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face       :: The font face.                                       */
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                  Initialize the blend struct with `gvar' data.        */
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    num_coords :: This must be the axis count of the font.             */
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    coords     :: A coordinate array with `num_coords' elements.       */
979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Set_Var_Design( TT_Face    face,
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_UInt    num_coords,
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Fixed*  coords )
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
988a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error        error      = FT_Err_Ok;
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*       normalized = NULL;
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend        blend;
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MM_Var*      mmvar;
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         i, j;
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Axis*    a;
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_AVarSegment  av;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory       memory = face->root.memory;
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->blend == NULL )
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( (error = TT_Get_MM_Var( face, NULL )) != 0 )
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend = face->blend;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mmvar = blend->mmvar;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( num_coords != mmvar->num_axis )
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1009a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Invalid_Argument );
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Axis normalization is a two stage process.  First we normalize */
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on the [min,def,max] values for the axis to be [-1,0,1]. */
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Then, if there's an `avar' table, we renormalize this range.   */
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = mmvar->axis;
1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < mmvar->num_axis; ++i, ++a )
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coords[i] > a->maximum || coords[i] < a->minimum )
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1025a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Argument );
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coords[i] < a->def )
1030a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def );
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( a->maximum == a->def )
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        normalized[i] = 0;
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1034a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def );
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !blend->avar_checked )
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_var_load_avar( face );
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend->avar_segment != NULL )
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      av = blend->avar_segment;
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( i = 0; i < mmvar->num_axis; ++i, ++av )
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 1; j < (FT_UInt)av->pairCount; ++j )
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( normalized[i] < av->correspondence[j].fromCoord )
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            normalized[i] =
1049a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
1050a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         av->correspondence[j].toCoord -
1051a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           av->correspondence[j - 1].toCoord,
1052a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         av->correspondence[j].fromCoord -
1053a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                           av->correspondence[j - 1].fromCoord ) +
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              av->correspondence[j - 1].toCoord;
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = TT_Set_MM_Blend( face, num_coords, normalized );
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( normalized );
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                     GX VAR PARSING ROUTINES                   *****/
1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_vary_cvt                                                   */
1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Modify the loaded cvt table according to the `cvar' table and the  */
1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    font's blend.                                                      */
1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Most errors are ignored.  It is perfectly valid not to have a      */
1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    `cvar' table even if there is a `gvar' and `fvar' table.           */
1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_vary_cvt( TT_Face    face,
1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Stream  stream )
1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = stream->memory;
1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    table_start;
1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    table_len;
1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     tupleCount;
1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    offsetToData;
1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    here;
1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i, j;
1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   tuple_coords    = NULL;
1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_start_coords = NULL;
1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_end_coords   = NULL;
1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend           = face->blend;
1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     point_count;
1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  localpoints;
1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short*   deltas;
1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "CVAR " ));
1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend == NULL )
1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1123295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_Err_Ok;
1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( face->cvt == NULL )
1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1131295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_Err_Ok;
1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_cvar, stream, &table_len );
1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1140295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "is missing\n" ));
1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_Err_Ok;
1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_ENTER( table_len ) )
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_Err_Ok;
1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table_start = FT_Stream_FTell( stream );
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_GET_LONG() != 0x00010000L )
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1155295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "bad table version\n" ));
1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_Err_Ok;
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto FExit;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto FExit;
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tupleCount   = FT_GET_USHORT();
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsetToData = table_start + FT_GET_USHORT();
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* The documentation implies there are flags packed into the        */
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* tuplecount, but John Jenkins says that shared points don't apply */
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* to `cvar', and no other flags are defined.                       */
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleDataSize;
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleIndex;
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  apply;
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleDataSize = FT_GET_USHORT();
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleIndex    = FT_GET_USHORT();
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* There is no provision here for a global tuple coordinate section, */
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* so John says.  There are no tuple indices, just embedded tuples.  */
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from        */
1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 /* short frac to fixed */
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip this tuple; it makes no sense */
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( j = 0; j < 2 * blend->num_axis; ++j )
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            (void)FT_GET_SHORT();
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          im_start_coords[j] = FT_GET_SHORT() << 2;
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          im_end_coords[j] = FT_GET_SHORT() << 2;
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      apply = ft_var_apply_tuple( blend,
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  (FT_UShort)tupleIndex,
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  tuple_coords,
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_start_coords,
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_end_coords );
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( /* tuple isn't active for our blend */
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           apply == 0                                    ||
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* global points not allowed,           */
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* if they aren't local, makes no sense */
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, offsetToData );
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      localpoints = ft_var_readpackedpoints( stream, &point_count );
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas      = ft_var_readpackeddeltas( stream,
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             point_count == 0 ? face->cvt_size
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                              : point_count );
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( localpoints == NULL || deltas == NULL )
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* failure, ignore it */;
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( localpoints == ALL_POINTS )
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* this means that there are deltas for every entry in cvt */
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < face->cvt_size; ++j )
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          face->cvt[j] = (FT_Short)( face->cvt[j] +
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_MulFix( deltas[j], apply ) );
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < point_count; ++j )
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          int  pindex = localpoints[j];
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          FT_MulFix( deltas[j], apply ) );
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( localpoints != ALL_POINTS )
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( localpoints );
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas );
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData += tupleDataSize;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FExit:
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( tuple_coords );
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_start_coords );
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_end_coords );
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Vary_Get_Glyph_Deltas                                           */
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Load the appropriate deltas for the current glyph.                 */
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face        :: A handle to the target face object.                 */
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    glyph_index :: The index of the glyph being modified.              */
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    n_points    :: The number of the points in the glyph, including    */
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                   phantom points.                                     */
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Output>                                                              */
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    deltas      :: The array of points to change.                      */
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Vary_Get_Glyph_Deltas( TT_Face      face,
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_UInt      glyph_index,
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_Vector*  *deltas,
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            FT_UInt      n_points )
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream   stream = face->root.stream;
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = stream->memory;
1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend  = face->blend;
1309c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    FT_Vector*  delta_xy = NULL;
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    glyph_start;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     tupleCount;
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    offsetToData;
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    here;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i, j;
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   tuple_coords    = NULL;
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_start_coords = NULL;
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_end_coords   = NULL;
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     point_count, spoint_count = 0;
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  sharedpoints = NULL;
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  localpoints  = NULL;
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  points;
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short    *deltas_x, *deltas_y;
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !face->doblend || blend == NULL )
1328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* to be freed by the caller */
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( delta_xy, n_points ) )
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *deltas = delta_xy;
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_index >= blend->gv_glyphcnt      ||
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         blend->glyphoffsets[glyph_index] ==
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           blend->glyphoffsets[glyph_index + 1] )
1338a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_Err_Ok;               /* no variation data for this glyph */
1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] )   ||
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           blend->glyphoffsets[glyph_index] ) )
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail1;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_start = FT_Stream_FTell( stream );
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* each set of glyph variation data is formatted similarly to `cvar' */
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* (except we get shared points and global tuples)                   */
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail2;
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tupleCount   = FT_GET_USHORT();
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offsetToData = glyph_start + FT_GET_USHORT();
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, offsetToData );
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData = FT_Stream_FTell( stream );
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleDataSize;
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleIndex;
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  apply;
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleDataSize = FT_GET_USHORT();
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleIndex    = FT_GET_USHORT();
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tuple_coords[j] = FT_GET_SHORT() << 2;  /* convert from        */
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                  /* short frac to fixed */
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        error = FT_THROW( Invalid_Table );
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Fail3;
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_MEM_COPY(
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tuple_coords,
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blend->num_axis * sizeof ( FT_Fixed ) );
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          im_start_coords[j] = FT_GET_SHORT() << 2;
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < blend->num_axis; ++j )
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          im_end_coords[j] = FT_GET_SHORT() << 2;
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      apply = ft_var_apply_tuple( blend,
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  (FT_UShort)tupleIndex,
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  tuple_coords,
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_start_coords,
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_end_coords );
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( apply == 0 )              /* tuple isn't active for our blend */
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_Stream_SeekSet( stream, offsetToData );
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        localpoints = ft_var_readpackedpoints( stream, &point_count );
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = localpoints;
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = sharedpoints;
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point_count = spoint_count;
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas_x = ft_var_readpackeddeltas( stream,
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          point_count == 0 ? n_points
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                           : point_count );
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas_y = ft_var_readpackeddeltas( stream,
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          point_count == 0 ? n_points
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                           : point_count );
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ; /* failure, ignore it */
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( points == ALL_POINTS )
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* this means that there are deltas for every point in the glyph */
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < n_points; ++j )
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( j = 0; j < point_count; ++j )
1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1458e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang          if ( localpoints[j] >= n_points )
1459e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang            continue;
1460e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( localpoints != ALL_POINTS )
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( localpoints );
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas_x );
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas_y );
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData += tupleDataSize;
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail3:
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( tuple_coords );
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_start_coords );
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_end_coords );
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail2:
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail1:
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( delta_xy );
1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *deltas = NULL;
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_done_blend                                                      */
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Frees the blend internal data structure.                           */
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_done_blend( FT_Memory  memory,
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 GX_Blend   blend )
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend != NULL )
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  i;
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->normalizedcoords );
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->mmvar );
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( blend->avar_segment != NULL )
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for ( i = 0; i < blend->num_axis; ++i )
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_FREE( blend->avar_segment[i].correspondence );
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( blend->avar_segment );
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->tuplecoords );
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->glyphoffsets );
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend );
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
1533