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/*                                                                         */
7a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin/*  Copyright 2004-2017 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  /*                                                                       */
23fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*   https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6[fgca]var.html */
24295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
25295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* The documentation for `gvar' is not intelligible; `cvar' refers you   */
26295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* to `gvar' and is thus also incomprehensible.                          */
27295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
28295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* The documentation for `avar' appears correct, but Apple has no fonts  */
29295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* with an `avar' table, so it is hard to test.                          */
30295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
31295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* Many thanks to John Jenkins (at Apple) in figuring this out.          */
32295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
33295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
34295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* Apple's `kern' table has some references to tuple indices, but as     */
35295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* there is no indication where these indices are defined, nor how to    */
36295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* interpolate the kerning values (different tuples have different       */
37295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /* classes) this issue is ignored.                                       */
38295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*                                                                       */
39295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  /*************************************************************************/
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_CONFIG_CONFIG_H
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_STREAM_H
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_SFNT_H
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRUETYPE_TAGS_H
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_MULTIPLE_MASTERS_H
49a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin#include FT_LIST_H
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttpload.h"
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ttgxvar.h"
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "tterrors.h"
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
60fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_Stream_FTell( stream )                         \
61727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          (FT_ULong)( (stream)->cursor - (stream)->base )
62fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_Stream_SeekSet( stream, off )                  \
63727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          ( (stream)->cursor = (stream)->base + (off) )
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_ttgxvar
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                       Internal Routines                       *****/
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
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  /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'.  It        */
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* indicates that there is a delta for every point without needing to    */
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* enumerate all of them.                                                */
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
91727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
92727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* ensure that value `0' has the same width as a pointer */
93727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define ALL_POINTS  (FT_UShort*)~(FT_PtrDist)0
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define GX_PT_POINTS_ARE_WORDS      0x80U
97fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define GX_PT_POINT_RUN_COUNT_MASK  0x7FU
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_readpackedpoints                                            */
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Read a set of points to which the following deltas will apply.     */
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Points are packed with a run length encoding.                      */
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream    :: The data stream.                                      */
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
112055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*    size      :: The size of the table holding the data.               */
113055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*                                                                       */
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Output>                                                              */
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    point_cnt :: The number of points read.  A zero value means that   */
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                 all points in the glyph will be affected, without     */
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                 enumerating them individually.                        */
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An array of FT_UShort containing the affected points or the        */
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    special value ALL_POINTS.                                          */
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_UShort*
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_readpackedpoints( FT_Stream  stream,
125055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                           FT_ULong   size,
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           FT_UInt   *point_cnt )
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
128aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_UShort *points = NULL;
129fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    n;
130fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    runcnt;
131fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    i, j;
132fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UShort  first;
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
134727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error  = FT_Err_Ok;
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
139fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    *point_cnt = 0;
140fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
141fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    n = FT_GET_BYTE();
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( n == 0 )
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return ALL_POINTS;
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( n & GX_PT_POINTS_ARE_WORDS )
146fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
147fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      n  &= GX_PT_POINT_RUN_COUNT_MASK;
148fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      n <<= 8;
149fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      n  |= FT_GET_BYTE();
150fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
152055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( n > size )
153055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
154055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
155055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return NULL;
156055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
157055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
158055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* in the nested loops below we increase `i' twice; */
159055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* it is faster to simply allocate one more slot    */
160055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* than to add another test within the loop         */
161055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( FT_NEW_ARRAY( points, n + 1 ) )
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
164fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    *point_cnt = n;
165fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
166055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    first = 0;
167055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    i     = 0;
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( i < n )
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      runcnt = FT_GET_BYTE();
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( runcnt & GX_PT_POINTS_ARE_WORDS )
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
173fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
174055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        first      += FT_GET_USHORT();
175fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        points[i++] = first;
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
177fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* first point not included in run count */
178fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < runcnt; j++ )
179fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
180fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          first      += FT_GET_USHORT();
181fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          points[i++] = first;
182055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( i >= n )
183055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
184fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
188055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        first      += FT_GET_BYTE();
189fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        points[i++] = first;
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
191fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < runcnt; j++ )
192fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
193fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          first      += FT_GET_BYTE();
194fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          points[i++] = first;
195055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( i >= n )
196055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            break;
197fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return points;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define GX_DT_DELTAS_ARE_ZERO       0x80U
206fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define GX_DT_DELTAS_ARE_WORDS      0x40U
207fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define GX_DT_DELTA_RUN_COUNT_MASK  0x3FU
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_readpackeddeltas                                            */
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Read a set of deltas.  These are packed slightly differently than  */
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    points.  In particular there is no overall count.                  */
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream    :: The data stream.                                      */
221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
222055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*    size      :: The size of the table holding the data.               */
223055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*                                                                       */
224fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    delta_cnt :: The number of deltas to be read.                      */
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An array of FT_Short containing the deltas for the affected        */
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    points.  (This only gets the deltas for one dimension.  It will    */
229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    generally be called twice, once for x, once for y.  When used in   */
230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    cvt table, it will only be called once.)                           */
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Short*
233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_readpackeddeltas( FT_Stream  stream,
234055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                           FT_ULong   size,
235fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                           FT_UInt    delta_cnt )
236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
237aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    FT_Short  *deltas = NULL;
238fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    runcnt, cnt;
239fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UInt    i, j;
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory  memory = stream->memory;
241727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error   error  = FT_Err_Ok;
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
246055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( delta_cnt > size )
247055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
248055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
249055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      return NULL;
250055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
251055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return NULL;
254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    i = 0;
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    while ( i < delta_cnt )
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      runcnt = FT_GET_BYTE();
259fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
260fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
263fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* `runcnt' zeroes get added */
264fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = 0;
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
269fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* `runcnt' shorts from the stack */
270fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = FT_GET_SHORT();
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
275fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* `runcnt' signed bytes from the stack */
276fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          deltas[i++] = FT_GET_CHAR();
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
280fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( j <= cnt )
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
282fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* bad format */
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( deltas );
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return NULL;
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return deltas;
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_load_avar                                                   */
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Parse the `avar' table if present.  It need not be, so we return   */
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    nothing.                                                           */
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face :: The font face.                                             */
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_load_avar( TT_Face  face )
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
307fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Stream       stream = FT_FACE_STREAM( face );
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory       memory = stream->memory;
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend        blend  = face->blend;
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_AVarSegment  segment;
311727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error        error = FT_Err_Ok;
312fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Long         version;
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long         axisCount;
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int          i, j;
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong        table_len;
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( error );
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE2(( "AVAR " ));
321fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
322a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    blend->avar_checked = TRUE;
323a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    error = face->goto_table( face, TTAG_avar, stream, &table_len );
324a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
325a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
326a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "is missing\n" ));
327a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
328a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
329a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
330a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_FRAME_ENTER( table_len ) )
331a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
332a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
333a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    version   = FT_GET_LONG();
334a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    axisCount = FT_GET_LONG();
335a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
336a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( version != 0x00010000L )
337a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
338a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "bad table version\n" ));
339a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
340a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
341a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
342a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE2(( "loaded\n" ));
343a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
344a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( axisCount != (FT_Long)blend->mmvar->num_axis )
345a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
346a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `fvar'\n"
347a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  "                  table are different\n" ));
348a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
349a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
350a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
351a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
352a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
353a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
354a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    segment = &blend->avar_segment[0];
355a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < axisCount; i++, segment++ )
356a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
357a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE5(( "  axis %d:\n", i ));
358a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
359a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      segment->pairCount = FT_GET_USHORT();
360a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( (FT_ULong)segment->pairCount * 4 > table_len                ||
361a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
362a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
363a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* Failure.  Free everything we have done so far.  We must do */
364a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* it right now since loading the `avar' table is optional.   */
365a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
366a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( j = i - 1; j >= 0; j-- )
367a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_FREE( blend->avar_segment[j].correspondence );
368a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
369a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->avar_segment );
370a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        blend->avar_segment = NULL;
371a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
372a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
373a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
374a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < segment->pairCount; j++ )
375a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
376a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* convert to Fixed */
377a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        segment->correspondence[j].fromCoord = FT_GET_SHORT() * 4;
378a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        segment->correspondence[j].toCoord   = FT_GET_SHORT() * 4;
379a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
380a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE5(( "    mapping %.5f to %.5f\n",
381a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    segment->correspondence[j].fromCoord / 65536.0,
382a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    segment->correspondence[j].toCoord / 65536.0 ));
383a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
384a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
385a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE5(( "\n" ));
386a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
387a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
388a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  Exit:
389a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_FRAME_EXIT();
390a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
391a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
392a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
393a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* some macros we need */
394a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  #define FT_FIXED_ONE  ( (FT_Fixed)0x10000 )
395a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
396a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  #define FT_fdot14ToFixed( x )                \
397a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
398a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  #define FT_intToFixed( i )                    \
399a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
400a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  #define FT_fixedToInt( x )                                   \
401a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
402a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
403a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
404a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Error
405a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_load_item_variation_store( TT_Face          face,
406a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                    FT_ULong         offset,
407a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                    GX_ItemVarStore  itemStore )
408a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
409a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Stream  stream = FT_FACE_STREAM( face );
410a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = stream->memory;
411a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
412a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error   error;
413a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UShort  format;
414a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   region_offset;
415a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    i, j, k;
416a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    shortDeltaCount;
417a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
418a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend        blend = face->blend;
419a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_ItemVarData  varData;
420a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
421a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong*  dataOffsetArray = NULL;
422a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
423a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
424a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_STREAM_SEEK( offset ) ||
425a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( format ) )
426a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
427a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
428a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( format != 1 )
429a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
430a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "ft_var_load_item_variation_store: bad store format %d\n",
431a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  format ));
432a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = FT_THROW( Invalid_Table );
433a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
434a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
435a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
436a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* read top level fields */
437a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_READ_ULONG( region_offset )         ||
438a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( itemStore->dataCount ) )
439a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
440a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
441a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* we need at least one entry in `itemStore->varData' */
442a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !itemStore->dataCount )
443a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
444a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "ft_var_load_item_variation_store: missing varData\n" ));
445a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = FT_THROW( Invalid_Table );
446a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
447a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
448a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
449a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* make temporary copy of item variation data offsets; */
450a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* we will parse region list first, then come back     */
451a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
452a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
453a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
454a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < itemStore->dataCount; i++ )
455a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
456a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_READ_ULONG( dataOffsetArray[i] ) )
457a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
458a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
459a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
460a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* parse array of region records (region list) */
461a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_STREAM_SEEK( offset + region_offset ) )
462a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
463a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
464a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_READ_USHORT( itemStore->axisCount )   ||
465a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( itemStore->regionCount ) )
466a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
467a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
468a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis )
469a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
470a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "ft_var_load_item_variation_store:"
471a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  " number of axes in item variation store\n"
472a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  "                                 "
473a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  " and `fvar' table are different\n" ));
474a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = FT_THROW( Invalid_Table );
475a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
476a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
477a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
478a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) )
479a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
480a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
481a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < itemStore->regionCount; i++ )
482a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
483a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_AxisCoords  axisCoords;
484a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
485a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
486a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList,
487a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         itemStore->axisCount ) )
488a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
489a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
490a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      axisCoords = itemStore->varRegionList[i].axisList;
491a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
492a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < itemStore->axisCount; j++ )
493a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
494a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_Short  start, peak, end;
495a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
496a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
497a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( FT_READ_SHORT( start ) ||
498a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin             FT_READ_SHORT( peak )  ||
499a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin             FT_READ_SHORT( end )   )
500a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
501a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
502a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        axisCoords[j].startCoord = FT_fdot14ToFixed( start );
503a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
504a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
505a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
506a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
507a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
508a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* end of region list parse */
509a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
510a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* use dataOffsetArray now to parse varData items */
511a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) )
512a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
513a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
514a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < itemStore->dataCount; i++ )
515a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
516a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      varData = &itemStore->varData[i];
517a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
518a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) )
519a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
520a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
521a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_READ_USHORT( varData->itemCount )      ||
522a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           FT_READ_USHORT( shortDeltaCount )         ||
523a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           FT_READ_USHORT( varData->regionIdxCount ) )
524a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
525a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
526a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* check some data consistency */
527a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( shortDeltaCount > varData->regionIdxCount )
528a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
529a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE2(( "bad short count %d or region count %d\n",
530a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    shortDeltaCount,
531a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    varData->regionIdxCount ));
532a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Table );
533a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
534a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
535a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
536a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( varData->regionIdxCount > itemStore->regionCount )
537a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
538a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n",
539a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    varData->regionIdxCount,
540a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    i ));
541a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Table );
542a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
543a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
544a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
545a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* parse region indices */
546a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_NEW_ARRAY( varData->regionIndices,
547a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         varData->regionIdxCount ) )
548a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
549a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
550a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < varData->regionIdxCount; j++ )
551a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
552a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( FT_READ_USHORT( varData->regionIndices[j] ) )
553a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
554a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
555a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( varData->regionIndices[j] >= itemStore->regionCount )
556a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
557a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE2(( "bad region index %d\n",
558a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      varData->regionIndices[j] ));
559a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          error = FT_THROW( Invalid_Table );
560a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
561a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
562a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
563a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
564a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* Parse delta set.                                                */
565a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /*                                                                 */
566a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes   */
567a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* each; on output, deltas are expanded to `regionIdxCount' shorts */
568a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* each.                                                           */
569a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_NEW_ARRAY( varData->deltaSet,
570a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         varData->regionIdxCount * varData->itemCount ) )
571a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
572a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
573a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* the delta set is stored as a 2-dimensional array of shorts; */
574a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* sign-extend signed bytes to signed shorts                   */
575a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
576a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
577a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( k = 0; k < shortDeltaCount; k++, j++ )
578a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
579a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          /* read the short deltas */
580a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_Short  delta;
581a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
582a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
583a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( FT_READ_SHORT( delta ) )
584a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            goto Exit;
585a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
586a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          varData->deltaSet[j] = delta;
587a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
588a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
589a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( ; k < varData->regionIdxCount; k++, j++ )
590a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
591a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          /* read the (signed) byte deltas */
592a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_Char  delta;
593a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
594a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
595a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( FT_READ_CHAR( delta ) )
596a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            goto Exit;
597a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
598a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          varData->deltaSet[j] = delta;
599a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
600a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
601a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
602a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
603a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  Exit:
604a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_FREE( dataOffsetArray );
605a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
606a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return error;
607a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
608a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
609a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
610a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Error
611a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_load_delta_set_index_mapping( TT_Face            face,
612a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                       FT_ULong           offset,
613a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                       GX_DeltaSetIdxMap  map,
614a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                       GX_ItemVarStore    itemStore )
615a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
616a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Stream  stream = FT_FACE_STREAM( face );
617a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = stream->memory;
618a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
619a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error   error;
620a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
621a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UShort  format;
622a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    entrySize;
623a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    innerBitCount;
624a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    innerIndexMask;
625a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    i, j;
626a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
627a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
628a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_STREAM_SEEK( offset )        ||
629a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( format )        ||
630a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( map->mapCount ) )
631a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
632a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
633a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( format & 0xFFC0 )
634a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
635a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "bad map format %d\n", format ));
636a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = FT_THROW( Invalid_Table );
637a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
638a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
639a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
640a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* bytes per entry: 1, 2, 3, or 4 */
641a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    entrySize      = ( ( format & 0x0030 ) >> 4 ) + 1;
642a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    innerBitCount  = ( format & 0x000F ) + 1;
643a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    innerIndexMask = ( 1 << innerBitCount ) - 1;
644a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
645a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) )
646a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
647a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
648a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( map->outerIndex, map->mapCount ) )
649a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
650a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
651a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < map->mapCount; i++ )
652a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
653a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_UInt  mapData = 0;
654a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_UInt  outerIndex, innerIndex;
655a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
656a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
657a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* read map data one unsigned byte at a time, big endian */
658a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < entrySize; j++ )
659a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
660a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_Byte  data;
661a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
662a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
663a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( FT_READ_BYTE( data ) )
664a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
665a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
666a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        mapData = ( mapData << 8 ) | data;
667a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
668a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
669a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      outerIndex = mapData >> innerBitCount;
670a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
671a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( outerIndex >= itemStore->dataCount )
672a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
673a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE2(( "outerIndex[%d] == %d out of range\n",
674a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    i,
675a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    outerIndex ));
676a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Table );
677a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
678a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
679a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
680a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      map->outerIndex[i] = outerIndex;
681a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
682a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      innerIndex = mapData & innerIndexMask;
683a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
684a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( innerIndex >= itemStore->varData[outerIndex].itemCount )
685a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
686a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE2(( "innerIndex[%d] == %d out of range\n",
687a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    i,
688a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    innerIndex ));
689a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Table );
690a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
691a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
692a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
693a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      map->innerIndex[i] = innerIndex;
694a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
695a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
696a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  Exit:
697a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return error;
698a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
699a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
700a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
701a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
702a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
703a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
704a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    ft_var_load_hvvar                                                  */
705a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
706a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
707a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    If `vertical' is zero, parse the `HVAR' table and set              */
708a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    `blend->hvar_loaded' to TRUE.  On success, `blend->hvar_checked'   */
709a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    is set to TRUE.                                                    */
710a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
711a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    If `vertical' is not zero, parse the `VVAR' table and set          */
712a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    `blend->vvar_loaded' to TRUE.  On success, `blend->vvar_checked'   */
713a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    is set to TRUE.                                                    */
714a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
715a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Some memory may remain allocated on error; it is always freed in   */
716a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    `tt_done_blend', however.                                          */
717a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
718a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <InOut>                                                               */
719a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face :: The font face.                                             */
720a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
721a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Return>                                                              */
722a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    FreeType error code.  0 means success.                             */
723a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
724a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Error
725a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_load_hvvar( TT_Face  face,
726a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                     FT_Bool  vertical )
727a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
728a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Stream  stream = FT_FACE_STREAM( face );
729a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = stream->memory;
730a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
731a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend  blend = face->blend;
732a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
733a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_HVVarTable  table;
734a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
735a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error   error;
736a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UShort  majorVersion;
737a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   table_len;
738a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   table_offset;
739a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   store_offset;
740a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   widthMap_offset;
741a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
742a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
743a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( vertical )
744a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
745a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      blend->vvar_loaded = TRUE;
746a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
747a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "VVAR " ));
748a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
749a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = face->goto_table( face, TTAG_VVAR, stream, &table_len );
750a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
751a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
752a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
753a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      blend->hvar_loaded = TRUE;
754a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
755a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "HVAR " ));
756a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
757a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = face->goto_table( face, TTAG_HVAR, stream, &table_len );
758a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
759a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
760a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
761a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
762a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "is missing\n" ));
763a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
764a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
765a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
766a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    table_offset = FT_STREAM_POS();
767a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
768a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* skip minor version */
769a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_READ_USHORT( majorVersion ) ||
770a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_STREAM_SKIP( 2 )            )
771a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
772a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
773a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( majorVersion != 1 )
774a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
775a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "bad table version %d\n", majorVersion ));
776a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = FT_THROW( Invalid_Table );
777a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
778a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
779a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
780a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_READ_ULONG( store_offset )    ||
781a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_ULONG( widthMap_offset ) )
782a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
783a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
784a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( vertical )
785a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
786a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_NEW( blend->vvar_table ) )
787a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
788a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      table = blend->vvar_table;
789a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
790a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
791a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
792a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_NEW( blend->hvar_table ) )
793a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
794a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      table = blend->hvar_table;
795a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
796a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
797a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    error = ft_var_load_item_variation_store(
798a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              face,
799a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              table_offset + store_offset,
800a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              &table->itemStore );
801a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
802a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
803a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
804a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( widthMap_offset )
805a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
806a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      error = ft_var_load_delta_set_index_mapping(
807a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                face,
808a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                table_offset + widthMap_offset,
809a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                &table->widthMap,
810a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                &table->itemStore );
811a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( error )
812a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
813a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
814a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
815a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE2(( "loaded\n" ));
816a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    error = FT_Err_Ok;
817a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
818a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  Exit:
819a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !error )
820a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
821a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( vertical )
822a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
823a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        blend->vvar_checked = TRUE;
824a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
825a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* FreeType doesn't provide functions to quickly retrieve    */
826a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* TSB, BSB, or VORG values; we thus don't have to implement */
827a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* support for those three item variation stores.            */
828a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
829a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        face->variation_support |= TT_FACE_FLAG_VAR_VADVANCE;
830a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
831a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      else
832a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
833a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        blend->hvar_checked = TRUE;
834a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
835a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* FreeType doesn't provide functions to quickly retrieve */
836a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* LSB or RSB values; we thus don't have to implement     */
837a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* support for those two item variation stores.           */
838a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
839a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        face->variation_support |= TT_FACE_FLAG_VAR_HADVANCE;
840a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
841a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
842a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
843a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return error;
844a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
845a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
846a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
847a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Int
848a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_get_item_delta( TT_Face          face,
849a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         GX_ItemVarStore  itemStore,
850a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         FT_UInt          outerIndex,
851a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         FT_UInt          innerIndex )
852a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
853a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_ItemVarData  varData;
854a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Short*       deltaSet;
855a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
856a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt   master, j;
857a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Fixed  netAdjustment = 0;     /* accumulated adjustment */
858a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Fixed  scaledDelta;
859a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Fixed  delta;
860a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
861a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
862a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* See pseudo code from `Font Variations Overview' */
863a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* in the OpenType specification.                  */
864a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
865a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    varData  = &itemStore->varData[outerIndex];
866a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex];
867a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
868a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* outer loop steps through master designs to be blended */
869a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( master = 0; master < varData->regionIdxCount; master++ )
870a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
871a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Fixed  scalar      = FT_FIXED_ONE;
872a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_UInt   regionIndex = varData->regionIndices[master];
873a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
874a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_AxisCoords  axis = itemStore->varRegionList[regionIndex].axisList;
875a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
876a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
877a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* inner loop steps through axes in this region */
878a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( j = 0; j < itemStore->axisCount; j++, axis++ )
879a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
880a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_Fixed  axisScalar;
881a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
882a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
883a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* compute the scalar contribution of this axis; */
884a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* ignore invalid ranges                         */
885a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( axis->startCoord > axis->peakCoord ||
886a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin             axis->peakCoord > axis->endCoord   )
887a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          axisScalar = FT_FIXED_ONE;
888a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
889a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else if ( axis->startCoord < 0 &&
890a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  axis->endCoord > 0   &&
891a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  axis->peakCoord != 0 )
892a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          axisScalar = FT_FIXED_ONE;
893a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
894a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* peak of 0 means ignore this axis */
895a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else if ( axis->peakCoord == 0 )
896a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          axisScalar = FT_FIXED_ONE;
897a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
898a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* ignore this region if coords are out of range */
899a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else if ( face->blend->normalizedcoords[j] < axis->startCoord ||
900a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  face->blend->normalizedcoords[j] > axis->endCoord   )
901a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          axisScalar = 0;
902a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
903a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* calculate a proportional factor */
904a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else
905a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
906a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( face->blend->normalizedcoords[j] == axis->peakCoord )
907a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            axisScalar = FT_FIXED_ONE;
908a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          else if ( face->blend->normalizedcoords[j] < axis->peakCoord )
909a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            axisScalar =
910a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              FT_DivFix( face->blend->normalizedcoords[j] - axis->startCoord,
911a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         axis->peakCoord - axis->startCoord );
912a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          else
913a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            axisScalar =
914a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              FT_DivFix( axis->endCoord - face->blend->normalizedcoords[j],
915a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         axis->endCoord - axis->peakCoord );
916a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
917a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
918a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* take product of all the axis scalars */
919a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        scalar = FT_MulFix( scalar, axisScalar );
920a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
921a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      } /* per-axis loop */
922a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
923a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* get the scaled delta for this region */
924a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      delta       = FT_intToFixed( deltaSet[master] );
925a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      scaledDelta = FT_MulFix( scalar, delta );
926a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
927a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* accumulate the adjustments from each region */
928a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      netAdjustment = netAdjustment + scaledDelta;
929a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
930a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    } /* per-region loop */
931a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
932a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return FT_fixedToInt( netAdjustment );
933a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
934a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
935a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
936a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
937a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
938a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
939a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    tt_hvadvance_adjust                                                */
940a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
941a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
942a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Apply `HVAR' advance width or `VVAR' advance height adjustment of  */
943a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    a given glyph.                                                     */
944a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
945a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Input>                                                               */
946a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    gindex   :: The glyph index.                                       */
947a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
948a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    vertical :: If set, handle `VVAR' table.                           */
949a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
950a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <InOut>                                                               */
951a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face     :: The font face.                                         */
952a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
953a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    adelta   :: Points to width or height value that gets modified.    */
954a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
955a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Error
956a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_hvadvance_adjust( TT_Face  face,
957a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       FT_UInt  gindex,
958a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       FT_Int  *avalue,
959a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       FT_Bool  vertical )
960a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
961a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error  error = FT_Err_Ok;
962a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt   innerIndex, outerIndex;
963a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Int    delta;
964a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
965a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_HVVarTable  table;
966a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
967a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
968a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->doblend || !face->blend )
969a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      goto Exit;
970a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
971a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( vertical )
972a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
973a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !face->blend->vvar_loaded )
974a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
975a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* initialize vvar table */
976a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        face->blend->vvar_error = ft_var_load_hvvar( face, 1 );
977a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
978a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
979a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !face->blend->vvar_checked )
980a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
981a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = face->blend->vvar_error;
982a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
983a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
984a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
985a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      table = face->blend->vvar_table;
986a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
987a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
988a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
989a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !face->blend->hvar_loaded )
990a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
991a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* initialize hvar table */
992a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        face->blend->hvar_error = ft_var_load_hvvar( face, 0 );
993a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
994a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
995a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !face->blend->hvar_checked )
996a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
997a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = face->blend->hvar_error;
998a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
999a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
1000a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1001a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      table = face->blend->hvar_table;
1002a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1003a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1004a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* advance width or height adjustments are always present in an */
1005a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* `HVAR' or `VVAR' table; no need to test for this capability  */
1006a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1007a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( table->widthMap.innerIndex )
1008a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
10092357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin      FT_UInt  idx = gindex;
10102357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin
10112357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin
10122357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin      if ( idx >= table->widthMap.mapCount )
10132357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin        idx = table->widthMap.mapCount - 1;
1014a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1015a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* trust that HVAR parser has checked indices */
10162357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin      outerIndex = table->widthMap.outerIndex[idx];
10172357eb4d408bd48fb7ad5641c6967f4d50ecc4a8Jungshik Shin      innerIndex = table->widthMap.innerIndex[idx];
1018a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1019a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
1020a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1021a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_ItemVarData  varData;
1022a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1023a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1024a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* no widthMap data */
1025a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      outerIndex = 0;
1026a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      innerIndex = gindex;
1027a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1028a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      varData = &table->itemStore.varData[outerIndex];
1029a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( gindex >= varData->itemCount )
1030a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
1031a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE2(( "gindex %d out of range\n", gindex ));
1032a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Argument );
1033a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        goto Exit;
1034a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
1035a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1036a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1037a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    delta = ft_var_get_item_delta( face,
1038a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                   &table->itemStore,
1039a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                   outerIndex,
1040a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                   innerIndex );
1041a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1042a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE5(( "%s value %d adjusted by %d units (%s)\n",
1043a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                vertical ? "vertical height" : "horizontal width",
1044a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                *avalue,
1045a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                delta,
1046a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                vertical ? "VVAR" : "HVAR" ));
1047a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1048a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    *avalue += delta;
1049a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1050a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  Exit:
1051a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return error;
1052a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1053a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1054a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1055a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( FT_Error )
1056a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_hadvance_adjust( TT_Face  face,
1057a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      FT_UInt  gindex,
1058a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      FT_Int  *avalue )
1059a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1060a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return tt_hvadvance_adjust( face, gindex, avalue, 0 );
1061a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1062a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1063a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1064a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( FT_Error )
1065a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_vadvance_adjust( TT_Face  face,
1066a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      FT_UInt  gindex,
1067a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      FT_Int  *avalue )
1068a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1069a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return tt_hvadvance_adjust( face, gindex, avalue, 1 );
1070a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1071a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1072a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1073a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin#define GX_VALUE_SIZE  8
1074a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1075a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* all values are FT_Short or FT_UShort entities; */
1076a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* we treat them consistently as FT_Short         */
1077a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin#define GX_VALUE_CASE( tag, dflt )      \
1078a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          case MVAR_TAG_ ## tag :       \
1079a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            p = (FT_Short*)&face->dflt; \
1080a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            break
1081a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1082a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin#define GX_GASP_CASE( idx )                                       \
1083a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          case MVAR_TAG_GASP_ ## idx :                            \
1084a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            if ( idx < face->gasp.numRanges - 1 )                 \
1085a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              p = (FT_Short*)&face->gasp.gaspRanges[idx].maxPPEM; \
1086a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            else                                                  \
1087a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              p = NULL;                                           \
1088a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            break
1089a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1090a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1091a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Short*
1092a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_get_value_pointer( TT_Face   face,
1093a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                            FT_ULong  mvar_tag )
1094a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1095a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Short*  p;
1096a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1097a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1098a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    switch ( mvar_tag )
1099a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1100a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 0 );
1101a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 1 );
1102a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 2 );
1103a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 3 );
1104a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 4 );
1105a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 5 );
1106a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 6 );
1107a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 7 );
1108a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 8 );
1109a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_GASP_CASE( 9 );
1110a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1111a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( CPHT, os2.sCapHeight );
1112a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HASC, os2.sTypoAscender );
1113a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HCLA, os2.usWinAscent );
1114a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HCLD, os2.usWinDescent );
1115a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HCOF, horizontal.caret_Offset );
1116a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HCRN, horizontal.caret_Slope_Run );
1117a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HCRS, horizontal.caret_Slope_Rise );
1118a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HDSC, os2.sTypoDescender );
1119a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( HLGP, os2.sTypoLineGap );
1120a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SBXO, os2.ySubscriptXOffset);
1121a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SBXS, os2.ySubscriptXSize );
1122a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SBYO, os2.ySubscriptYOffset );
1123a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SBYS, os2.ySubscriptYSize );
1124a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SPXO, os2.ySuperscriptXOffset );
1125a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SPXS, os2.ySuperscriptXSize );
1126a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SPYO, os2.ySuperscriptYOffset );
1127a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( SPYS, os2.ySuperscriptYSize );
1128a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( STRO, os2.yStrikeoutPosition );
1129a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( STRS, os2.yStrikeoutSize );
1130a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( UNDO, postscript.underlinePosition );
1131a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( UNDS, postscript.underlineThickness );
1132a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VASC, vertical.Ascender );
1133a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VCOF, vertical.caret_Offset );
1134a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VCRN, vertical.caret_Slope_Run );
1135a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VCRS, vertical.caret_Slope_Rise );
1136a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VDSC, vertical.Descender );
1137a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( VLGP, vertical.Line_Gap );
1138a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_VALUE_CASE( XHGT, os2.sxHeight );
1139a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1140a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    default:
1141a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* ignore unknown tag */
1142a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      p = NULL;
1143a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1144a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1145a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return p;
1146a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1147a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1148a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1149a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
1150a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1151a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
1152a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    ft_var_load_mvar                                                   */
1153a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1154a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
1155a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Parse the `MVAR' table.                                            */
1156a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1157a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Some memory may remain allocated on error; it is always freed in   */
1158a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    `tt_done_blend', however.                                          */
1159a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1160a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <InOut>                                                               */
1161a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face :: The font face.                                             */
1162a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1163a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static void
1164a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_load_mvar( TT_Face  face )
1165a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1166a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Stream  stream = FT_FACE_STREAM( face );
1167a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = stream->memory;
1168a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1169a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend         blend = face->blend;
1170a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_ItemVarStore  itemStore;
1171a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Value         value, limit;
1172a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1173a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error   error;
1174a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UShort  majorVersion;
1175a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   table_len;
1176a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   table_offset;
1177a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UShort  store_offset;
1178a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_ULong   records_offset;
1179a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1180a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1181a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE2(( "MVAR " ));
1182a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1183a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    error = face->goto_table( face, TTAG_MVAR, stream, &table_len );
1184a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
1185a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1186a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "is missing\n" ));
1187a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1188a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1189a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1190a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    table_offset = FT_STREAM_POS();
1191a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1192a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* skip minor version */
1193a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_READ_USHORT( majorVersion ) ||
1194a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_STREAM_SKIP( 2 )            )
1195a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1196a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1197a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( majorVersion != 1 )
1198a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1199a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "bad table version %d\n", majorVersion ));
1200a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1201a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1202a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1203a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW( blend->mvar_table ) )
1204a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1205a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1206a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* skip reserved entry and value record size */
1207a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_STREAM_SKIP( 4 )                             ||
1208a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( blend->mvar_table->valueCount ) ||
1209a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_READ_USHORT( store_offset )                  )
1210a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1211a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1212a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    records_offset = FT_STREAM_POS();
1213a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1214a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    error = ft_var_load_item_variation_store(
1215a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              face,
1216a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              table_offset + store_offset,
1217a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              &blend->mvar_table->itemStore );
1218a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
1219a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1220a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1221a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_NEW_ARRAY( blend->mvar_table->values,
1222a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       blend->mvar_table->valueCount ) )
1223a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1224a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1225a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_STREAM_SEEK( records_offset )                                ||
1226a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin         FT_FRAME_ENTER( blend->mvar_table->valueCount * GX_VALUE_SIZE ) )
1227a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1228a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1229a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    value     = blend->mvar_table->values;
1230a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    limit     = value + blend->mvar_table->valueCount;
1231a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    itemStore = &blend->mvar_table->itemStore;
1232a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1233a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( ; value < limit; value++ )
1234a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1235a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      value->tag        = FT_GET_ULONG();
1236a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      value->outerIndex = FT_GET_USHORT();
1237a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      value->innerIndex = FT_GET_USHORT();
1238a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1239a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( value->outerIndex >= itemStore->dataCount                  ||
1240a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           value->innerIndex >= itemStore->varData[value->outerIndex]
1241a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                                  .itemCount          )
1242a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
1243a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        error = FT_THROW( Invalid_Table );
1244a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        break;
1245a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
1246a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1247a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1248a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_FRAME_EXIT();
1249a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1250a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( error )
1251a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      return;
1252a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1253a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE2(( "loaded\n" ));
1254a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1255a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    value = blend->mvar_table->values;
1256a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    limit = value + blend->mvar_table->valueCount;
1257a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1258a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* save original values of the data MVAR is going to modify */
1259a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( ; value < limit; value++ )
1260a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
1261a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Short*  p = ft_var_get_value_pointer( face, value->tag );
12629888dce90e659608e20790214fac16d921322077Jungshik Shin      if ( p )
12639888dce90e659608e20790214fac16d921322077Jungshik Shin        value->unmodified = *p;
12649888dce90e659608e20790214fac16d921322077Jungshik Shin#ifdef FT_DEBUG_LEVEL_TRACE
12659888dce90e659608e20790214fac16d921322077Jungshik Shin      else
12669888dce90e659608e20790214fac16d921322077Jungshik Shin        FT_TRACE1(( "ft_var_load_mvar: Ignoring unknown tag `%c%c%c%c'\n",
12679888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 24 ),
12689888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 16 ),
12699888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 8 ),
12709888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag ) ));
12719888dce90e659608e20790214fac16d921322077Jungshik Shin#endif
1272a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
1273a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1274a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    face->variation_support |= TT_FACE_FLAG_VAR_MVAR;
1275a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1276a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1277a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1278a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static FT_Error
1279a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_size_reset_iterator( FT_ListNode  node,
1280a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                          void*        user )
1281a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1282a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    TT_Size  size = (TT_Size)node->data;
1283a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1284a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UNUSED( user );
1285a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1286a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1287a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    tt_size_reset( size, 1 );
1288a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1289a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return FT_Err_Ok;
1290a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
1291a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1292a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1293a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
1294a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1295a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
1296a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    tt_apply_mvar                                                      */
1297a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1298a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
1299a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Apply `MVAR' table adjustments.                                    */
1300a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1301a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <InOut>                                                               */
1302a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face :: The font face.                                             */
1303a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
1304a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( void )
1305a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_apply_mvar( TT_Face  face )
1306a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
1307a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend  blend = face->blend;
1308a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Value  value, limit;
1309a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1311a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !( face->variation_support & TT_FACE_FLAG_VAR_MVAR ) )
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1314a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    value = blend->mvar_table->values;
1315a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    limit = value + blend->mvar_table->valueCount;
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1317a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( ; value < limit; value++ )
1318fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
1319a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Short*  p = ft_var_get_value_pointer( face, value->tag );
1320a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Int     delta;
1321a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1322a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1323a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      delta = ft_var_get_item_delta( face,
1324a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                     &blend->mvar_table->itemStore,
1325a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                     value->outerIndex,
1326a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                     value->innerIndex );
1327a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
13289888dce90e659608e20790214fac16d921322077Jungshik Shin      if ( p )
13299888dce90e659608e20790214fac16d921322077Jungshik Shin      {
13309888dce90e659608e20790214fac16d921322077Jungshik Shin        FT_TRACE5(( "value %c%c%c%c (%d units) adjusted by %d units (MVAR)\n",
13319888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 24 ),
13329888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 16 ),
13339888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag >> 8 ),
13349888dce90e659608e20790214fac16d921322077Jungshik Shin                    (FT_Char)( value->tag ),
13359888dce90e659608e20790214fac16d921322077Jungshik Shin                    value->unmodified,
13369888dce90e659608e20790214fac16d921322077Jungshik Shin                    delta ));
13379888dce90e659608e20790214fac16d921322077Jungshik Shin
13389888dce90e659608e20790214fac16d921322077Jungshik Shin        /* since we handle both signed and unsigned values as FT_Short, */
13399888dce90e659608e20790214fac16d921322077Jungshik Shin        /* ensure proper overflow arithmetic                            */
13409888dce90e659608e20790214fac16d921322077Jungshik Shin        *p = (FT_Short)( value->unmodified + (FT_Short)delta );
13419888dce90e659608e20790214fac16d921322077Jungshik Shin      }
1342fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
1343fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1344a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* adjust all derived values */
1345fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
1346a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Face  root = &face->root;
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1348fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1349a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( face->os2.version != 0xFFFFU )
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1351a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( face->os2.sTypoAscender || face->os2.sTypoDescender )
1352a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
1353a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->ascender  = face->os2.sTypoAscender;
1354a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->descender = face->os2.sTypoDescender;
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1356a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->height = root->ascender - root->descender +
1357a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         face->os2.sTypoLineGap;
1358a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
1359a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else
1360a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
1361a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->ascender  =  (FT_Short)face->os2.usWinAscent;
1362a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->descender = -(FT_Short)face->os2.usWinDescent;
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          root->height = root->ascender - root->descender;
1365a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1368a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      root->underline_position  = face->postscript.underlinePosition -
1369a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                  face->postscript.underlineThickness / 2;
1370a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      root->underline_thickness = face->postscript.underlineThickness;
1371fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1372a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* iterate over all FT_Size objects and call `tt_size_reset' */
1373a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* to propagate the metrics changes                          */
1374a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_List_Iterate( &root->sizes_list,
1375a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       tt_size_reset_iterator,
1376a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                       NULL );
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  GX_GVar_Head_
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long    version;
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisCount;
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  globalCoordCount;
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   offsetToCoord;
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  glyphCount;
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  flags;
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   offsetToData;
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_GVar_Head;
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_load_gvar                                                   */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1400fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    Parse the `gvar' table if present.  If `fvar' is there, `gvar' had */
1401fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    better be there too.                                               */
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face :: The font face.                                             */
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Error
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_load_gvar( TT_Face  face )
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1412fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Stream     stream = FT_FACE_STREAM( face );
1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory     memory = stream->memory;
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend      blend  = face->blend;
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error      error;
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt       i, j;
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      table_len;
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      gvar_start;
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong      offsetToData;
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_GVar_Head  gvar_head;
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  gvar_fields[] =
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_GVar_Head
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 20 ),
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_LONG  ( version ),
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( axisCount ),
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( globalCoordCount ),
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( offsetToCoord ),
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( glyphCount ),
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( flags ),
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( offsetToData ),
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1439fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1440fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE2(( "GVAR " ));
1441fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1442a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( FT_SET_ERROR( face->goto_table( face,
1443a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                         TTAG_gvar,
1444a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                         stream,
1445a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                         &table_len ) ) )
1446fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
1447fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "is missing\n" ));
1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1449fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gvar_start = FT_STREAM_POS( );
1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1455fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( gvar_head.version != 0x00010000L )
1456fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
1457fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE1(( "bad table version\n" ));
1458fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      error = FT_THROW( Invalid_Table );
1459fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      goto Exit;
1460fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
1461fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1462fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1464fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
1465fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  "                  table are different\n" ));
1466727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Invalid_Table );
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1470055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* rough sanity check, ignoring offsets */
1471055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( (FT_ULong)gvar_head.globalCoordCount * gvar_head.axisCount >
1472055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin           table_len / 2 )
1473055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
1474055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE1(( "ft_var_load_gvar:"
1475055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  " invalid number of global coordinates\n" ));
1476055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      error = FT_THROW( Invalid_Table );
1477055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      goto Exit;
1478055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
1479055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1480a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* rough sanity check: offsets can be either 2 or 4 bytes */
1481055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( (FT_ULong)gvar_head.glyphCount *
1482a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len )
1483055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
1484055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
1485055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      error = FT_THROW( Invalid_Table );
1486055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      goto Exit;
1487055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
1488055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1489055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_TRACE2(( "loaded\n" ));
1490055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1491055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    blend->gvar_size   = table_len;
1492055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    blend->tuplecount  = gvar_head.globalCoordCount;
1493055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    blend->gv_glyphcnt = gvar_head.glyphCount;
1494055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    offsetToData       = gvar_start + gvar_head.offsetToData;
1495055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1496fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
1497fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                blend->tuplecount ));
1498fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( gvar_head.flags & 1 )
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* long offsets (one more offset than glyphs, to mark size of last) */
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) )
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1508fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i <= blend->gv_glyphcnt; i++ )
1509fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* short offsets (one more offset than glyphs, to mark size of last) */
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) )
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1519fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i <= blend->gv_glyphcnt; i++ )
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
1521fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                               /* XXX: Undocumented: `*2'! */
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( blend->tuplecount != 0 )
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW_ARRAY( blend->tuplecoords,
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         gvar_head.axisCount * blend->tuplecount ) )
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1532fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord )         ||
1533fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki           FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) )
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1536fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < blend->tuplecount; i++ )
1537fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1538fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE5(( "  [ " ));
1539055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
1540fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blend->tuplecoords[i * gvar_head.axisCount + j] =
1542055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin            FT_GET_SHORT() * 4;                 /* convert to FT_Fixed */
1543a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE5(( "%.5f ",
1544fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
1545fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
1546fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE5(( "]\n" ));
1547fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1548fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1549fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE5(( "\n" ));
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_EXIT();
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    ft_var_apply_tuple                                                 */
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Figure out whether a given tuple (design) applies to the current   */
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    blend, and if so, what is the scaling factor.                      */
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    blend           :: The current blend of the font.                  */
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tupleIndex      :: A flag saying whether this is an intermediate   */
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       tuple or not.                                   */
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tuple_coords    :: The coordinates of the tuple in normalized axis */
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       units.                                          */
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    im_start_coords :: The initial coordinates where this tuple starts */
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       to apply (for intermediate coordinates).        */
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    im_end_coords   :: The final coordinates after which this tuple no */
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                       longer applies (for intermediate coordinates).  */
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    An FT_Fixed value containing the scaling factor.                   */
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Fixed
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_var_apply_tuple( GX_Blend   blend,
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_UShort  tupleIndex,
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  tuple_coords,
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  im_start_coords,
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed*  im_end_coords )
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt   i;
1594727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Fixed  apply = 0x10000L;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1597fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i < blend->num_axis; i++ )
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1599a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE6(( "    axis coordinate %d (%.5f):\n",
1600fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  i, blend->normalizedcoords[i] / 65536.0 ));
1601055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
1602a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE6(( "      intermediate coordinates %d (%.5f, %.5f):\n",
1603055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    i,
1604055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    im_start_coords[i] / 65536.0,
1605055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    im_end_coords[i] / 65536.0 ));
1606fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1607fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* It's not clear why (for intermediate tuples) we don't need     */
1608fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* to check against start/end -- the documentation says we don't. */
1609fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* Similarly, it's unclear why we don't need to scale along the   */
1610fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* axis.                                                          */
1611fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tuple_coords[i] == 0 )
1613fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1614fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE6(( "      tuple coordinate is zero, ignored\n", i ));
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1616fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1617fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1618055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( blend->normalizedcoords[i] == 0 )
1619fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1620fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
1621fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        apply = 0;
1622fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        break;
1623fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1625055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( blend->normalizedcoords[i] == tuple_coords[i] )
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1627a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE6(( "      tuple coordinate value %.5f fits perfectly\n",
1628fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    tuple_coords[i] / 65536.0 ));
1629055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* `apply' does not change */
1630055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        continue;
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1633055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
1634fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* not an intermediate tuple */
1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1637055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
1638055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
1639055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1640a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE6(( "      tuple coordinate value %.5f is exceeded, stop\n",
1641055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      tuple_coords[i] / 65536.0 ));
1642055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          apply = 0;
1643055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          break;
1644055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1646a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE6(( "      tuple coordinate value %.5f fits\n",
1647055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    tuple_coords[i] / 65536.0 ));
1648727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        apply = FT_MulDiv( apply,
1649055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                           blend->normalizedcoords[i],
1650055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                           tuple_coords[i] );
1651fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1653fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1654055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        /* intermediate tuple */
1655055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1656055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        if ( blend->normalizedcoords[i] < im_start_coords[i] ||
1657055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin             blend->normalizedcoords[i] > im_end_coords[i]   )
1658055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1659a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] is exceeded,"
1660055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      " stop\n",
1661055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_start_coords[i] / 65536.0,
1662055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_end_coords[i] / 65536.0 ));
1663055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          apply = 0;
1664055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          break;
1665055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1666055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1667055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        else if ( blend->normalizedcoords[i] < tuple_coords[i] )
1668055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1669a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] fits\n",
1670055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_start_coords[i] / 65536.0,
1671055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_end_coords[i] / 65536.0 ));
1672055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          apply = FT_MulDiv( apply,
1673055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                             blend->normalizedcoords[i] - im_start_coords[i],
1674055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                             tuple_coords[i] - im_start_coords[i] );
1675055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1676055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
1677055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        else
1678055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        {
1679a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE6(( "      intermediate tuple range [%.5f;%.5f] fits\n",
1680055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_start_coords[i] / 65536.0,
1681055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                      im_end_coords[i] / 65536.0 ));
1682055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          apply = FT_MulDiv( apply,
1683055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                             im_end_coords[i] - blend->normalizedcoords[i],
1684055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                             im_end_coords[i] - tuple_coords[i] );
1685055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        }
1686fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1689a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_TRACE6(( "    apply factor is %.5f\n", apply / 65536.0 ));
1690fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return apply;
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****               MULTIPLE MASTERS SERVICE FUNCTIONS              *****/
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  GX_FVar_Head_
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Long    version;
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  offsetToData;
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisCount;
1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  axisSize;
1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  instanceCount;
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  instanceSize;
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_FVar_Head;
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  fvar_axis_
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong   axisTag;
1719fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Fixed   minValue;
1720fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Fixed   defaultValue;
1721fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Fixed   maxValue;
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  flags;
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort  nameID;
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } GX_FVar_Axis;
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Get_MM_Var                                                      */
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Check that the font's `fvar' table is valid, parse it, and return  */
1735a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    those data.  It also loads (and parses) the `MVAR' table, if       */
1736a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    possible.                                                          */
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: The font face.                                           */
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*              TT_Get_MM_Var initializes the blend structure.           */
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Output>                                                              */
1743055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*    master :: The `fvar' data (must be freed by caller).  Can be NULL, */
1744055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  /*              which makes this function simply load MM support.        */
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Get_MM_Var( TT_Face      face,
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_MM_Var*  *master )
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream            stream = face->root.stream;
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory            memory = face->root.memory;
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong             table_len;
1756727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error             error  = FT_Err_Ok;
1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong             fvar_start;
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int               i, j;
1759aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    FT_MM_Var*           mmvar = NULL;
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*            next_coords;
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_String*           next_name;
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Axis*         a;
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Named_Style*  ns;
1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_FVar_Head         fvar_head;
1765a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Bool              usePsName;
1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  fvar_fields[] =
1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_FVar_Head
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 16 ),
1774a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_LONG      ( version ),
1775a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_USHORT    ( offsetToData ),
1776a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_SKIP_SHORT,
1777a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_USHORT    ( axisCount ),
1778a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_USHORT    ( axisSize ),
1779a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_USHORT    ( instanceCount ),
1780a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FRAME_USHORT    ( instanceSize ),
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    static const FT_Frame_Field  fvaraxis_fields[] =
1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_STRUCTURE
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_STRUCTURE  GX_FVar_Axis
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_START( 20 ),
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_ULONG ( axisTag ),
1792fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FRAME_LONG  ( minValue ),
1793fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FRAME_LONG  ( defaultValue ),
1794fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_FRAME_LONG  ( maxValue ),
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( flags ),
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_USHORT( nameID ),
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FRAME_END
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    };
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1801fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* read the font data and set up the internal representation */
1802fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* if not already done                                       */
1803fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1804a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->blend )
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1806fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "FVAR " ));
1807fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* both `fvar' and `gvar' must be present */
1809a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( face->goto_table( face, TTAG_gvar,
1810a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                           stream, &table_len ) ) )
1811fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1812a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* CFF2 is an alternate to gvar here */
1813a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( FT_SET_ERROR( face->goto_table( face, TTAG_CFF2,
1814a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                             stream, &table_len ) ) )
1815a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
1816a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE1(( "\n"
1817a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" ));
1818a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          goto Exit;
1819a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
1820fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1822a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( face->goto_table( face, TTAG_fvar,
1823a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                           stream, &table_len ) ) )
1824fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
1825fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE1(( "is missing\n" ));
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1827fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      fvar_start = FT_STREAM_POS( );
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1831a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* the validity of the `fvar' header data was already checked */
1832a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* in function `sfnt_init_face'                               */
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) )
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1836a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      usePsName = FT_BOOL( fvar_head.instanceSize ==
1837a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                           6 + 4 * fvar_head.axisCount );
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1839fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "loaded\n" ));
1840fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1841fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
1842fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_NEW( face->blend ) )
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1846aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      /* cannot overflow 32-bit arithmetic because of limits above */
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->blend->mmvar_len =
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        sizeof ( FT_MM_Var ) +
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.axisCount * sizeof ( FT_Var_Axis ) +
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) +
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) +
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        5 * fvar_head.axisCount;
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      face->blend->mmvar = mmvar;
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1858fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* set up pointers and offsets into the `mmvar' array; */
1859fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* the data gets filled in later on                    */
1860fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_axis =
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.axisCount;
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_designs =
1864727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        ~0U;                   /* meaningless in this context; each glyph */
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               /* may have a different number of designs  */
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                               /* (or tuples, as called by Apple)         */
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->num_namedstyles =
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        fvar_head.instanceCount;
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->axis =
1870fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Var_Axis*)&( mmvar[1] );
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->namedstyle =
1872fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Var_Named_Style*)&( mmvar->axis[fvar_head.axisCount] );
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_coords =
1875fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Fixed*)&( mmvar->namedstyle[fvar_head.instanceCount] );
1876fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < fvar_head.instanceCount; i++ )
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->namedstyle[i].coords  = next_coords;
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_coords                 += fvar_head.axisCount;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_name = (FT_String*)next_coords;
1883fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < fvar_head.axisCount; i++ )
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->axis[i].name  = next_name;
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_name           += 5;
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1889fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* now fill in the data */
1890fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) )
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      a = mmvar->axis;
1895fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < fvar_head.axisCount; i++ )
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        GX_FVar_Axis  axis_rec;
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) )
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->tag     = axis_rec.axisTag;
1903fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a->minimum = axis_rec.minValue;
1904fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a->def     = axis_rec.defaultValue;
1905fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a->maximum = axis_rec.maxValue;
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->strid   = axis_rec.nameID;
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[0] = (FT_String)(   a->tag >> 24 );
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[1] = (FT_String)( ( a->tag >> 16 ) & 0xFF );
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[2] = (FT_String)( ( a->tag >>  8 ) & 0xFF );
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name[3] = (FT_String)( ( a->tag       ) & 0xFF );
1912fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a->name[4] = '\0';
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1914a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( a->minimum > a->def ||
1915a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin             a->def > a->maximum )
1916a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
1917a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_TRACE2(( "TT_Get_MM_Var:"
1918a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      " invalid \"%s\" axis record; disabling\n",
1919a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      a->name ));
1920a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1921a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          a->minimum = a->def;
1922a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          a->maximum = a->def;
1923a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
1924a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1925a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE5(( "  \"%s\": minimum=%.5f, default=%.5f, maximum=%.5f\n",
1926fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    a->name,
1927fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    a->minimum / 65536.0,
1928fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    a->def / 65536.0,
1929fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    a->maximum / 65536.0 ));
1930fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1931fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a++;
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1934fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE5(( "\n" ));
1935fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ns = mmvar->namedstyle;
1937fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1939a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        /* PostScript names add 2 bytes to the instance record size */
1940a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( FT_FRAME_ENTER( ( usePsName ? 6L : 4L ) +
1941a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                             4L * fvar_head.axisCount ) )
1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          goto Exit;
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ns->strid       =    FT_GET_USHORT();
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (void) /* flags = */ FT_GET_USHORT();
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1947fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < fvar_head.axisCount; j++ )
1948fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          ns->coords[j] = FT_GET_LONG();
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1950a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( usePsName )
1951a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          ns->psid = FT_GET_USHORT();
1952a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FRAME_EXIT();
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1955a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
1956a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      ft_var_load_mvar( face );
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1959fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* fill the output array if requested */
1960fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1961a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( master )
1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt  n;
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) )
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len );
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->axis =
1971fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Var_Axis*)&( mmvar[1] );
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mmvar->namedstyle =
1973fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Var_Named_Style*)&( mmvar->axis[mmvar->num_axis] );
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_coords =
1975fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        (FT_Fixed*)&( mmvar->namedstyle[mmvar->num_namedstyles] );
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1977fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( n = 0; n < mmvar->num_namedstyles; n++ )
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mmvar->namedstyle[n].coords  = next_coords;
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_coords                 += mmvar->num_axis;
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1983fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      a         = mmvar->axis;
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      next_name = (FT_String*)next_coords;
1985fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( n = 0; n < mmvar->num_axis; n++ )
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        a->name = next_name;
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* standard PostScript names for some standard apple tags */
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( a->tag == TTAG_wght )
1991fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          a->name = (char*)"Weight";
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_wdth )
1993fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          a->name = (char*)"Width";
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_opsz )
1995fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          a->name = (char*)"OpticalSize";
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( a->tag == TTAG_slnt )
1997fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          a->name = (char*)"Slant";
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        next_name += 5;
2000fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        a++;
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      *master = mmvar;
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Set_MM_Blend                                                    */
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Set the blend (normalized) coordinates for this instance of the    */
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    font.  Check that the `gvar' table is reasonable and does some     */
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    initial preparation.                                               */
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face       :: The font.                                            */
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                  Initialize the blend structure with `gvar' data.     */
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
2026fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    num_coords :: The number of available coordinates.  If it is       */
2027fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  larger than the number of axes, ignore the excess    */
2028fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  values.  If it is smaller than the number of axes,   */
2029fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  use the default value (0) for the remaining axes.    */
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2031fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    coords     :: An array of `num_coords', each between [-1,1].       */
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Set_MM_Blend( TT_Face    face,
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_UInt    num_coords,
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Fixed*  coords )
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2041727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error    error = FT_Err_Ok;
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend;
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MM_Var*  mmvar;
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i;
2045a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Bool     is_default_instance = 1;
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = face->root.memory;
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    enum
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_retain,
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_modify,
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mcvt_load
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    } manageCvt;
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->doblend = FALSE;
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2059a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->blend )
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2061a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend = face->blend;
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mmvar = blend->mmvar;
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( num_coords > mmvar->num_axis )
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2070fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n",
2071fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  mmvar->num_axis, num_coords ));
2072fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      num_coords = mmvar->num_axis;
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "normalized design coordinates:\n" ));
2076fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2077fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i < num_coords; i++ )
2078fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
2079a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE5(( "  %.5f\n", coords[i] / 65536.0 ));
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2082a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n"
2083fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    "                 is out of range [-1;1]\n",
2084fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                    coords[i] / 65536.0 ));
2085727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Invalid_Argument );
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2088a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2089a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coords[i] != 0 )
2090a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        is_default_instance = 0;
2091fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
2092fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2093fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "\n" ));
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2095a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->isCFF2 && !blend->glyphoffsets )
2096a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( ft_var_load_gvar( face ) ) )
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2099a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !blend->normalizedcoords )
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2101fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( FT_NEW_ARRAY( blend->normalizedcoords, mmvar->num_axis ) )
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      manageCvt = mcvt_modify;
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* If we have not set the blend coordinates before this, then the  */
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* cvt table will still be what we read from the `cvt ' table and  */
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* we don't need to reload it.  We may need to change it though... */
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
21120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      manageCvt = mcvt_retain;
2113fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2114fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < num_coords; i++ )
21150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      {
21160a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        if ( blend->normalizedcoords[i] != coords[i] )
21170a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        {
2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          manageCvt = mcvt_load;
21190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          break;
21200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        }
21210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      }
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2123fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( ; i < mmvar->num_axis; i++ )
2124fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
2125fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( blend->normalizedcoords[i] != 0 )
2126fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2127fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          manageCvt = mcvt_load;
2128fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          break;
2129fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2130fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
2131fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* If we don't change the blend coords then we don't need to do  */
2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* anything to the cvt table.  It will be correct.  Otherwise we */
2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* no longer have the original cvt (it was modified when we set  */
2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* the blend last time), so we must reload and then modify it.   */
2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2138fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    blend->num_axis = mmvar->num_axis;
2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MEM_COPY( blend->normalizedcoords,
2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 coords,
2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 num_coords * sizeof ( FT_Fixed ) );
2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    face->doblend = TRUE;
2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2145a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( face->cvt )
2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      switch ( manageCvt )
2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_load:
2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The cvt table has been loaded already; every time we change the */
2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* blend we may need to reload and remodify the cvt table.         */
2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( face->cvt );
2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        face->cvt = NULL;
2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2155fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        error = tt_face_load_cvt( face, face->root.stream );
2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_modify:
2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The original cvt table is in memory.  All we need to do is */
2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* apply the `cvar' table (if any).                           */
2161fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        error = tt_face_vary_cvt( face, face->root.stream );
2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      case mcvt_retain:
2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* The cvt table is correct for this set of coordinates. */
2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2170a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    face->is_default_instance = is_default_instance;
2171a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
2180a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    TT_Get_MM_Blend                                                    */
2181a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2182a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
2183a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Get the blend (normalized) coordinates for this instance of the    */
2184a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    font.                                                              */
2185a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2186a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <InOut>                                                               */
2187a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face       :: The font.                                            */
2188a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                  Initialize the blend structure with `gvar' data.     */
2189a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2190a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Input>                                                               */
2191a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    num_coords :: The number of available coordinates.  If it is       */
2192a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                  larger than the number of axes, set the excess       */
2193a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                  values to 0.                                         */
2194a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2195a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    coords     :: An array of `num_coords', each between [-1,1].       */
2196a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2197a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Return>                                                              */
2198a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    FreeType error code.  0 means success.                             */
2199a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2200a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( FT_Error )
2201a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  TT_Get_MM_Blend( TT_Face    face,
2202a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                   FT_UInt    num_coords,
2203a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                   FT_Fixed*  coords )
2204a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
2205a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error  error = FT_Err_Ok;
2206a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend  blend;
2207a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt   i, nc;
2208a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2209a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2210a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->blend )
2211a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2212a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
2213a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        return error;
2214a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2215a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2216a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    blend = face->blend;
2217a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2218a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    nc = num_coords;
2219a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( num_coords > blend->num_axis )
2220a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2221a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "TT_Get_MM_Blend: only using first %d of %d coordinates\n",
2222a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  blend->num_axis, num_coords ));
2223a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      nc = blend->num_axis;
2224a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2225a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2226a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( face->doblend )
2227a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2228a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < nc; i++ )
2229a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = blend->normalizedcoords[i];
2230a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2231a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
2232a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2233a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < nc; i++ )
2234a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = 0;
2235a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2236a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2237a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( ; i < num_coords; i++ )
2238a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      coords[i] = 0;
2239a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2240a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return FT_Err_Ok;
2241a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
2242a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2243a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2244a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
2245a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2246a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    TT_Set_Var_Design                                                  */
2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Set the coordinates for the instance, measured in the user         */
2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    coordinate system.  Parse the `avar' table (if present) to convert */
2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    from user to normalized coordinates.                               */
2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face       :: The font face.                                       */
2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                  Initialize the blend struct with `gvar' data.        */
2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
2259fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    num_coords :: The number of available coordinates.  If it is       */
2260fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  larger than the number of axes, ignore the excess    */
2261fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  values.  If it is smaller than the number of axes,   */
2262fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*                  use the default values for the remaining axes.       */
2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    coords     :: A coordinate array with `num_coords' elements.       */
2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  TT_Set_Var_Design( TT_Face    face,
2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_UInt    num_coords,
2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     FT_Fixed*  coords )
2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2274727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Error        error      = FT_Err_Ok;
2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*       normalized = NULL;
2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend        blend;
2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MM_Var*      mmvar;
2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt         i, j;
2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Var_Axis*    a;
2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_AVarSegment  av;
2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory       memory = face->root.memory;
2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2284a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->blend )
2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2286a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    blend = face->blend;
2291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mmvar = blend->mmvar;
2292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2293fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( num_coords > mmvar->num_axis )
2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2295fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "TT_Set_Var_Design:"
2296fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  " only using first %d of %d coordinates\n",
2297fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  mmvar->num_axis, num_coords ));
2298fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      num_coords = mmvar->num_axis;
2299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2301a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    /* Axis normalization is a two-stage process.  First we normalize */
2302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* based on the [min,def,max] values for the axis to be [-1,0,1]. */
2303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Then, if there's an `avar' table, we renormalize this range.   */
2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
2306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2308fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "design coordinates:\n" ));
2309fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = mmvar->axis;
2311fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i < num_coords; i++, a++ )
2312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2313a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_Fixed  coord = coords[i];
2314a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2315a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2316a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE5(( "  %.5f\n", coord / 65536.0 ));
2317a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coord > a->maximum || coord < a->minimum )
2318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2319a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_TRACE1((
2320a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          "TT_Set_Var_Design: design coordinate %.5f\n"
2321a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          "                   is out of range [%.5f;%.5f]; clamping\n",
2322a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          coord / 65536.0,
2323a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          a->minimum / 65536.0,
2324a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          a->maximum / 65536.0 ));
2325a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2326a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        if ( coord > a->maximum)
2327a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          coord = a->maximum;
2328a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        else
2329a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          coord = a->minimum;
2330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2332a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coord < a->def )
2333fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        normalized[i] = -FT_DivFix( coords[i] - a->def,
2334fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                    a->minimum - a->def );
2335a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      else if ( coord > a->def )
2336fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        normalized[i] = FT_DivFix( coords[i] - a->def,
2337fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                   a->maximum - a->def );
2338a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      else
2339a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        normalized[i] = 0;
2340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2342fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "\n" ));
2343fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2344fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( ; i < mmvar->num_axis; i++ )
2345fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      normalized[i] = 0;
2346fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !blend->avar_checked )
2348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_var_load_avar( face );
2349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2350a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( blend->avar_segment )
2351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2352fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE5(( "normalized design coordinates"
2353fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  " before applying `avar' data:\n" ));
2354fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      av = blend->avar_segment;
2356fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      for ( i = 0; i < mmvar->num_axis; i++, av++ )
2357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2358fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
2359fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( normalized[i] < av->correspondence[j].fromCoord )
2361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
2362a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            FT_TRACE5(( "  %.5f\n", normalized[i] / 65536.0 ));
2363a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            normalized[i] =
2365727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease              FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
2366727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                         av->correspondence[j].toCoord -
2367727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                           av->correspondence[j - 1].toCoord,
2368727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                         av->correspondence[j].fromCoord -
2369727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                           av->correspondence[j - 1].fromCoord ) +
2370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              av->correspondence[j - 1].toCoord;
2371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break;
2372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
2373fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2377fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    error = TT_Set_MM_Blend( face, mmvar->num_axis, normalized );
2378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( normalized );
2381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2386a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2387a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
2388a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    TT_Get_Var_Design                                                  */
2389a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2390a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
2391a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    Get the design coordinates of the currently selected interpolated  */
2392a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    font.                                                              */
2393a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2394a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Input>                                                               */
2395a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    face       :: A handle to the source face.                         */
2396a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2397a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    num_coords :: The number of design coordinates to retrieve.  If it */
2398a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                  is larger than the number of axes, set the excess    */
2399a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                  values to~0.                                         */
2400a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2401a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Output>                                                              */
2402a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    coords     :: The design coordinates array.                        */
2403a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2404a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Return>                                                              */
2405a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    FreeType error code.  0~means success.                             */
2406a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
2407a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( FT_Error )
2408a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  TT_Get_Var_Design( TT_Face    face,
2409a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                     FT_UInt    num_coords,
2410a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                     FT_Fixed*  coords )
2411a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
2412a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Error  error = FT_Err_Ok;
2413a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2414a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend      blend;
2415a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_MM_Var*    mmvar;
2416a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Var_Axis*  a;
2417a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2418a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt  i, j, nc;
2419a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2420a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2421a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->blend )
2422a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2423a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( FT_SET_ERROR( TT_Get_MM_Var( face, NULL ) ) )
2424a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        return error;
2425a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2426a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2427a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    blend = face->blend;
2428a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2429a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    nc = num_coords;
2430a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( num_coords > blend->num_axis )
2431a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2432a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE2(( "TT_Get_Var_Design: only using first %d of %d coordinates\n",
2433a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  blend->num_axis, num_coords ));
2434a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      nc = blend->num_axis;
2435a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2436a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2437a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( face->doblend )
2438a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2439a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < nc; i++ )
2440a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = blend->normalizedcoords[i];
2441a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2442a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
2443a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2444a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < nc; i++ )
2445a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = 0;
2446a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2447a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2448a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( ; i < num_coords; i++ )
2449a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      coords[i] = 0;
2450a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2451a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !blend->avar_checked )
2452a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      ft_var_load_avar( face );
2453a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2454a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( blend->avar_segment )
2455a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2456a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      GX_AVarSegment  av = blend->avar_segment;
2457a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2458a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2459a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_TRACE5(( "design coordinates"
2460a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                  " after removing `avar' distortion:\n" ));
2461a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2462a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < nc; i++, av++ )
2463a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
2464a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
2465a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        {
2466a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( coords[i] < av->correspondence[j].toCoord )
2467a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          {
2468a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            coords[i] =
2469a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              FT_MulDiv( coords[i] - av->correspondence[j - 1].toCoord,
2470a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         av->correspondence[j].fromCoord -
2471a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                           av->correspondence[j - 1].fromCoord,
2472a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         av->correspondence[j].toCoord -
2473a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                           av->correspondence[j - 1].toCoord ) +
2474a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              av->correspondence[j - 1].fromCoord;
2475a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2476a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            FT_TRACE5(( "  %.5f\n", coords[i] / 65536.0 ));
2477a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            break;
2478a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          }
2479a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        }
2480a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
2481a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2482a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2483a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    mmvar = blend->mmvar;
2484a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    a     = mmvar->axis;
2485a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2486a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    for ( i = 0; i < nc; i++, a++ )
2487a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
2488a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coords[i] < 0 )
2489a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = a->def + FT_MulFix( coords[i],
2490a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                        a->def - a->minimum );
2491a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      else if ( coords[i] > 0 )
2492a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = a->def + FT_MulFix( coords[i],
2493a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                        a->maximum - a->def );
2494a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      else
2495a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        coords[i] = a->def;
2496a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
2497a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2498a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return FT_Err_Ok;
2499a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
2500a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2501a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2502a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
2503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                     GX VAR PARSING ROUTINES                   *****/
2506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*****                                                               *****/
2507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
2512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
2514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_face_vary_cvt                                                   */
2515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
2517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Modify the loaded cvt table according to the `cvar' table and the  */
2518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    font's blend.                                                      */
2519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <InOut>                                                               */
2521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face   :: A handle to the target face object.                      */
2522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
2524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    stream :: A handle to the input stream.                            */
2525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
2527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
2528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Most errors are ignored.  It is perfectly valid not to have a      */
2530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    `cvar' table even if there is a `gvar' and `fvar' table.           */
2531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
2532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
2533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  tt_face_vary_cvt( TT_Face    face,
2534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Stream  stream )
2535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
2537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = stream->memory;
2538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    table_start;
2539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    table_len;
2540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     tupleCount;
2541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    offsetToData;
2542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    here;
2543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i, j;
2544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   tuple_coords    = NULL;
2545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_start_coords = NULL;
2546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_end_coords   = NULL;
2547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend           = face->blend;
2548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     point_count;
2549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  localpoints;
2550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short*   deltas;
2551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_TRACE2(( "CVAR " ));
2554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2555a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !blend )
2556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2557fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "\n"
2558fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  "tt_face_vary_cvt: no blend specified\n" ));
2559727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_Err_Ok;
2560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2563a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->cvt )
2564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2565fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "\n"
2566fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  "tt_face_vary_cvt: no `cvt ' table\n" ));
2567727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_Err_Ok;
2568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    error = face->goto_table( face, TTAG_cvar, stream, &table_len );
2572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( error )
2573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2574295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "is missing\n" ));
2575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2576727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_Err_Ok;
2577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_FRAME_ENTER( table_len ) )
2581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2582727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_Err_Ok;
2583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Exit;
2584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    table_start = FT_Stream_FTell( stream );
2587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_GET_LONG() != 0x00010000L )
2588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2589295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_TRACE2(( "bad table version\n" ));
2590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2591727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_Err_Ok;
2592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto FExit;
2593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2595fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE2(( "loaded\n" ));
2596fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
2598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
2599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
2600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto FExit;
2601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tupleCount   = FT_GET_USHORT();
2603055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    offsetToData = FT_GET_USHORT();
2604055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2605055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* rough sanity test */
2606a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 >
2607a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin           table_len )
2608055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
2609055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE2(( "tt_face_vary_cvt:"
2610055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  " invalid CVT variation array header\n" ));
2611055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2612055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      error = FT_THROW( Invalid_Table );
2613055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      goto FExit;
2614055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
2615055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
2616055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    offsetToData += table_start;
2617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2618055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* The documentation implies there are flags packed into              */
2619055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* `tupleCount', but John Jenkins says that shared points don't apply */
2620055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* to `cvar', and no other flags are defined.                         */
2621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2622055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount & 0xFFF ));
2623fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2624fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
2625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleDataSize;
2627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleIndex;
2628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  apply;
2629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2631fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE6(( "  tuple %d:\n", i ));
2632fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleDataSize = FT_GET_USHORT();
2634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleIndex    = FT_GET_USHORT();
2635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* There is no provision here for a global tuple coordinate section, */
2637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* so John says.  There are no tuple indices, just embedded tuples.  */
2638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
2640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2641fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
2642055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          tuple_coords[j] = FT_GET_SHORT() * 4;  /* convert from        */
2643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                 /* short frac to fixed */
2644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* skip this tuple; it makes no sense */
2648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
2650fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          for ( j = 0; j < 2 * blend->num_axis; j++ )
2651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            (void)FT_GET_SHORT();
2652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
2654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
2658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2659fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
2660055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          im_start_coords[j] = FT_GET_SHORT() * 4;
2661fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
2662055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          im_end_coords[j] = FT_GET_SHORT() * 4;
2663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      apply = ft_var_apply_tuple( blend,
2666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  (FT_UShort)tupleIndex,
2667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  tuple_coords,
2668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_start_coords,
2669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_end_coords );
2670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( /* tuple isn't active for our blend */
2671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           apply == 0                                    ||
2672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* global points not allowed,           */
2673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           /* if they aren't local, makes no sense */
2674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
2675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
2677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
2678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
2681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, offsetToData );
2683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2684055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      localpoints = ft_var_readpackedpoints( stream,
2685055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                             table_len,
2686055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                             &point_count );
2687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas      = ft_var_readpackeddeltas( stream,
2688055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                             table_len,
2689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                             point_count == 0 ? face->cvt_size
2690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                              : point_count );
2691a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !localpoints || !deltas )
2692fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ; /* failure, ignore it */
2693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( localpoints == ALL_POINTS )
2695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2696fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2697fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        int  count = 0;
2698fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2699fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2700fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2701fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE7(( "    CVT deltas:\n" ));
2702fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* this means that there are deltas for every entry in cvt */
2704fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < face->cvt_size; j++ )
2705fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2706fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_Long  orig_cvt = face->cvt[j];
2707fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2708fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2709fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          face->cvt[j] = (FT_Short)( orig_cvt +
2710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     FT_MulFix( deltas[j], apply ) );
2711fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2712fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2713fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( orig_cvt != face->cvt[j] )
2714fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          {
2715fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            FT_TRACE7(( "      %d: %d -> %d\n",
2716fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        j, orig_cvt, face->cvt[j] ));
2717fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            count++;
2718fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          }
2719fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2720fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2721fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2722fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2723fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( !count )
2724fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_TRACE7(( "      none\n" ));
2725fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2730fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2731fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        int  count = 0;
2732fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2733fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2734fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2735fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE7(( "    CVT deltas:\n" ));
2736fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2737fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < point_count; j++ )
2738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
2739a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          int      pindex;
2740a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          FT_Long  orig_cvt;
2741a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
2742fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2743a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          pindex = localpoints[j];
2744a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( (FT_ULong)pindex >= face->cvt_size )
2745a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            continue;
2746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2747a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          orig_cvt          = face->cvt[pindex];
2748fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          face->cvt[pindex] = (FT_Short)( orig_cvt +
2749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          FT_MulFix( deltas[j], apply ) );
2750fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2751fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2752fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( orig_cvt != face->cvt[pindex] )
2753fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          {
2754fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            FT_TRACE7(( "      %d: %d -> %d\n",
2755fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        pindex, orig_cvt, face->cvt[pindex] ));
2756fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            count++;
2757fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          }
2758fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
2760fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2761fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
2762fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( !count )
2763fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_TRACE7(( "      none\n" ));
2764fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
2765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( localpoints != ALL_POINTS )
2768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( localpoints );
2769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas );
2770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData += tupleDataSize;
2772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
2774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2776fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "\n" ));
2777fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FExit:
2779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
2780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
2782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( tuple_coords );
2783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_start_coords );
2784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_end_coords );
2785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2790fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* Shift the original coordinates of all points between indices `p1' */
2791fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* and `p2', using the same difference as given by index `ref'.      */
2792fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2793fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* modeled after `af_iup_shift' */
2794fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2795fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  static void
2796fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  tt_delta_shift( int         p1,
2797fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  int         p2,
2798fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  int         ref,
2799fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  FT_Vector*  in_points,
2800fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  FT_Vector*  out_points )
2801fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  {
2802fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    int        p;
2803fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Vector  delta;
2804fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2805fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2806fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    delta.x = out_points[ref].x - in_points[ref].x;
2807fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    delta.y = out_points[ref].y - in_points[ref].y;
2808fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2809fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( delta.x == 0 && delta.y == 0 )
2810fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      return;
2811fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2812fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( p = p1; p < ref; p++ )
2813fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
2814fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out_points[p].x += delta.x;
2815fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out_points[p].y += delta.y;
2816fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
2817fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2818fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( p = ref + 1; p <= p2; p++ )
2819fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
2820fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out_points[p].x += delta.x;
2821fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out_points[p].y += delta.y;
2822fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
2823fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  }
2824fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2825fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2826fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* Interpolate the original coordinates of all points with indices */
2827fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* between `p1' and `p2', using `ref1' and `ref2' as the reference */
2828fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* point indices.                                                  */
2829fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2830fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* modeled after `af_iup_interp', `_iup_worker_interpolate', and */
2831fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* `Ins_IUP'                                                     */
2832fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2833fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  static void
2834fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  tt_delta_interpolate( int         p1,
2835fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        int         p2,
2836fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        int         ref1,
2837fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        int         ref2,
2838fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        FT_Vector*  in_points,
2839fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        FT_Vector*  out_points )
2840fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  {
2841fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    int  p, i;
2842fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2843fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Pos  out, in1, in2, out1, out2, d1, d2;
2844fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2845fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2846fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( p1 > p2 )
2847fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      return;
2848fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2849fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* handle both horizontal and vertical coordinates */
2850fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i <= 1; i++ )
2851fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
2852fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* shift array pointers so that we can access `foo.y' as `foo.x' */
2853fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      in_points  = (FT_Vector*)( (FT_Pos*)in_points + i );
2854fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out_points = (FT_Vector*)( (FT_Pos*)out_points + i );
2855fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2856fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( in_points[ref1].x > in_points[ref2].x )
2857fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
2858fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        p    = ref1;
2859fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ref1 = ref2;
2860fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        ref2 = p;
2861fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
2862fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2863fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      in1  = in_points[ref1].x;
2864fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      in2  = in_points[ref2].x;
2865fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out1 = out_points[ref1].x;
2866fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      out2 = out_points[ref2].x;
2867fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      d1   = out1 - in1;
2868fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      d2   = out2 - in2;
2869fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2870fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( out1 == out2 || in1 == in2 )
2871fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
2872fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( p = p1; p <= p2; p++ )
2873fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2874fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          out = in_points[p].x;
2875fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2876fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( out <= in1 )
2877fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out += d1;
2878fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          else if ( out >= in2 )
2879fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out += d2;
2880fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          else
2881fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out = out1;
2882fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2883fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          out_points[p].x = out;
2884fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2885fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
2886fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      else
2887fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
2888fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_Fixed  scale = FT_DivFix( out2 - out1, in2 - in1 );
2889fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2890fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2891fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( p = p1; p <= p2; p++ )
2892fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2893fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          out = in_points[p].x;
2894fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2895fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( out <= in1 )
2896fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out += d1;
2897fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          else if ( out >= in2 )
2898fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out += d2;
2899fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          else
2900fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            out = out1 + FT_MulFix( out - in1, scale );
2901fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2902fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          out_points[p].x = out;
2903fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2904fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
2905fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
2906fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  }
2907fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2908fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2909fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* Interpolate points without delta values, similar to */
2910fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* the `IUP' hinting instruction.                      */
2911fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2912fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* modeled after `Ins_IUP */
2913fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2914fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  static void
2915055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin  tt_interpolate_deltas( FT_Outline*  outline,
2916055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                         FT_Vector*   out_points,
2917055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                         FT_Vector*   in_points,
2918055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                         FT_Bool*     has_delta )
2919fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  {
2920055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Int  first_point;
2921055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Int  end_point;
2922fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2923055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Int  first_delta;
2924055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Int  cur_delta;
2925fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2926055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Int    point;
2927fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Short  contour;
2928fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2929fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2930fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    /* ignore empty outlines */
2931fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( !outline->n_contours )
2932fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      return;
2933fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2934fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    contour = 0;
2935fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    point   = 0;
2936fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2937fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    do
2938fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
2939fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      end_point   = outline->contours[contour];
2940fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      first_point = point;
2941fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2942fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      /* search first point that has a delta */
2943fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      while ( point <= end_point && !has_delta[point] )
2944fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        point++;
2945fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2946fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      if ( point <= end_point )
2947fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      {
2948fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        first_delta = point;
2949fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        cur_delta   = point;
2950fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2951fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        point++;
2952fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2953fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        while ( point <= end_point )
2954fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2955fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* search next point that has a delta  */
2956fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* and interpolate intermediate points */
2957fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( has_delta[point] )
2958fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          {
2959fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            tt_delta_interpolate( cur_delta + 1,
2960fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  point - 1,
2961fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  cur_delta,
2962fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  point,
2963fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  in_points,
2964fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  out_points );
2965fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            cur_delta = point;
2966fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          }
2967fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2968fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          point++;
2969fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2970fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2971fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* shift contour if we only have a single delta */
2972fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( cur_delta == first_delta )
2973fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          tt_delta_shift( first_point,
2974fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                          end_point,
2975fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                          cur_delta,
2976fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                          in_points,
2977fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                          out_points );
2978fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        else
2979fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
2980fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* otherwise handle remaining points       */
2981fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          /* at the end and beginning of the contour */
2982fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          tt_delta_interpolate( cur_delta + 1,
2983fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                end_point,
2984fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                cur_delta,
2985fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                first_delta,
2986fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                in_points,
2987fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                out_points );
2988fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2989fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( first_delta > 0 )
2990fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            tt_delta_interpolate( first_point,
2991fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  first_delta - 1,
2992fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  cur_delta,
2993fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  first_delta,
2994fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  in_points,
2995fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  out_points );
2996fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
2997fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      }
2998fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      contour++;
2999fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3000fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    } while ( contour < outline->n_contours );
3001fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  }
3002fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3003fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
3005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
3007fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    TT_Vary_Apply_Glyph_Deltas                                         */
3008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
3010fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    Apply the appropriate deltas to the current glyph.                 */
3011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
3013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    face        :: A handle to the target face object.                 */
3014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    glyph_index :: The index of the glyph being modified.              */
3016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    n_points    :: The number of the points in the glyph, including    */
3018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                   phantom points.                                     */
3019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3020fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* <InOut>                                                               */
3021fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    outline     :: The outline to change.                              */
3022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
3024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FreeType error code.  0 means success.                             */
3025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( FT_Error )
3027fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  TT_Vary_Apply_Glyph_Deltas( TT_Face      face,
3028fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                              FT_UInt      glyph_index,
3029fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                              FT_Outline*  outline,
3030fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                              FT_UInt      n_points )
3031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Stream   stream = face->root.stream;
3033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Memory   memory = stream->memory;
3034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    GX_Blend    blend  = face->blend;
3035fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3036fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Vector*  points_org = NULL;
3037055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_Vector*  points_out = NULL;
3038fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_Bool*    has_delta  = NULL;
3039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Error    error;
3041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    glyph_start;
3042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     tupleCount;
3043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    offsetToData;
3044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_ULong    here;
3045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     i, j;
3046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   tuple_coords    = NULL;
3047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_start_coords = NULL;
3048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Fixed*   im_end_coords   = NULL;
3049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UInt     point_count, spoint_count = 0;
3050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  sharedpoints = NULL;
3051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  localpoints  = NULL;
3052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UShort*  points;
3053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Short    *deltas_x, *deltas_y;
3054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3056a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( !face->doblend || !blend )
3057727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
3058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( glyph_index >= blend->gv_glyphcnt      ||
3060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         blend->glyphoffsets[glyph_index] ==
3061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           blend->glyphoffsets[glyph_index + 1] )
3062fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    {
3063fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
3064fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  " no variation data for this glyph\n" ));
3065fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      return FT_Err_Ok;
3066fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    }
3067fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3068fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( FT_NEW_ARRAY( points_org, n_points ) ||
3069055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin         FT_NEW_ARRAY( points_out, n_points ) ||
3070fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki         FT_NEW_ARRAY( has_delta, n_points )  )
3071fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      goto Fail1;
3072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] )   ||
3074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
3075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           blend->glyphoffsets[glyph_index] ) )
3076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail1;
3077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    glyph_start = FT_Stream_FTell( stream );
3079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* each set of glyph variation data is formatted similarly to `cvar' */
3081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* (except we get shared points and global tuples)                   */
3082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
3084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
3085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
3086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto Fail2;
3087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tupleCount   = FT_GET_USHORT();
3089055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    offsetToData = FT_GET_USHORT();
3090055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3091055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    /* rough sanity test */
3092055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 >
3093055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin           blend->gvar_size )
3094055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    {
3095055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
3096055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                  " invalid glyph variation array header\n" ));
3097055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3098055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      error = FT_THROW( Invalid_Table );
3099055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      goto Fail2;
3100055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    }
3101055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3102055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    offsetToData += glyph_start;
3103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
3105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
3107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, offsetToData );
3109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3110055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      sharedpoints = ft_var_readpackedpoints( stream,
3111055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                              blend->gvar_size,
3112055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                              &spoint_count );
3113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData = FT_Stream_FTell( stream );
3114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
3116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3118055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_TRACE5(( "gvar: there are %d tuples:\n",
3119055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                tupleCount & GX_TC_TUPLE_COUNT_MASK ));
3120055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3121055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    for ( j = 0; j < n_points; j++ )
3122055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      points_org[j] = outline->points[j];
3123fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3124fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
3125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleDataSize;
3127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_UInt   tupleIndex;
3128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Fixed  apply;
3129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3131fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      FT_TRACE6(( "  tuple %d:\n", i ));
3132fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleDataSize = FT_GET_USHORT();
3134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tupleIndex    = FT_GET_USHORT();
3135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
3137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3138fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
3139055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          tuple_coords[j] = FT_GET_SHORT() * 4;   /* convert from        */
3140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                  /* short frac to fixed */
3141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
3143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3144055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
3145055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                    " invalid tuple index\n" ));
3146055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3147727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        error = FT_THROW( Invalid_Table );
3148fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        goto Fail2;
3149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_MEM_COPY(
3152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          tuple_coords,
3153fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          &blend->tuplecoords[( tupleIndex & 0xFFF ) * blend->num_axis],
3154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          blend->num_axis * sizeof ( FT_Fixed ) );
3155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
3157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3158fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
3159055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          im_start_coords[j] = FT_GET_SHORT() * 4;
3160fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < blend->num_axis; j++ )
3161055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          im_end_coords[j] = FT_GET_SHORT() * 4;
3162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      apply = ft_var_apply_tuple( blend,
3165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  (FT_UShort)tupleIndex,
3166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  tuple_coords,
3167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_start_coords,
3168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  im_end_coords );
3169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( apply == 0 )              /* tuple isn't active for our blend */
3171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        offsetToData += tupleDataSize;
3173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
3174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      here = FT_Stream_FTell( stream );
3177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3178055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_Stream_SeekSet( stream, offsetToData );
3179055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
3181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3182055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        localpoints = ft_var_readpackedpoints( stream,
3183055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                               blend->gvar_size,
3184055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                               &point_count );
3185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = localpoints;
3186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        points      = sharedpoints;
3190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point_count = spoint_count;
3191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas_x = ft_var_readpackeddeltas( stream,
3194055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                          blend->gvar_size,
3195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          point_count == 0 ? n_points
3196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                           : point_count );
3197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      deltas_y = ft_var_readpackeddeltas( stream,
3198055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                                          blend->gvar_size,
3199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                          point_count == 0 ? n_points
3200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                           : point_count );
3201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3202a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( !points || !deltas_y || !deltas_x )
3203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ; /* failure, ignore it */
3204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( points == ALL_POINTS )
3206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3207fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
3208fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        int  count = 0;
3209fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
3210fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3211fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3212fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE7(( "    point deltas:\n" ));
3213fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* this means that there are deltas for every point in the glyph */
3215fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < n_points; j++ )
3216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3217055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Pos  delta_x = FT_MulFix( deltas_x[j], apply );
3218055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Pos  delta_y = FT_MulFix( deltas_y[j], apply );
3219fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3220fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3221a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          if ( j < n_points - 3 )
3222a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          {
3223a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            outline->points[j].x += delta_x;
3224a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            outline->points[j].y += delta_y;
3225a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          }
3226a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          else
3227a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          {
3228a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            /* To avoid double adjustment of advance width or height, */
3229a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            /* adjust phantom points only if there is no HVAR or VVAR */
3230a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            /* support, respectively.                                 */
3231a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            if ( j == ( n_points - 3 )          &&
3232a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                 !( face->variation_support   &
3233a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    TT_FACE_FLAG_VAR_HADVANCE ) )
3234a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              outline->points[j].x += delta_x;
3235a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3236a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            else if ( j == ( n_points - 2 )        &&
3237a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      !( face->variation_support &
3238a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         TT_FACE_FLAG_VAR_LSB    ) )
3239a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              outline->points[j].x += delta_x;
3240a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3241a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            else if ( j == ( n_points - 1 )          &&
3242a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      !( face->variation_support   &
3243a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         TT_FACE_FLAG_VAR_VADVANCE ) )
3244a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              outline->points[j].y += delta_y;
3245a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3246a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin            else if ( j == ( n_points - 0 )        &&
3247a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                      !( face->variation_support &
3248a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                         TT_FACE_FLAG_VAR_TSB    ) )
3249a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin              outline->points[j].y += delta_y;
3250a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin          }
3251fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3252fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
3253055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( delta_x || delta_y )
3254fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          {
3255fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            FT_TRACE7(( "      %d: (%d, %d) -> (%d, %d)\n",
3256fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        j,
3257055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        outline->points[j].x - delta_x,
3258055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        outline->points[j].y - delta_y,
3259fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        outline->points[j].x,
3260fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        outline->points[j].y ));
3261fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            count++;
3262fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          }
3263fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
3264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3265fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3266fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
3267fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( !count )
3268fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_TRACE7(( "      none\n" ));
3269fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
3270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
3273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3274fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef FT_DEBUG_LEVEL_TRACE
3275fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        int  count = 0;
3276fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
3277fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3278fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3279fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* we have to interpolate the missing deltas similar to the */
3280fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* IUP bytecode instruction                                 */
3281fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < n_points; j++ )
3282fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
3283fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          has_delta[j]  = FALSE;
3284055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          points_out[j] = points_org[j];
3285fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
3286fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3287fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        for ( j = 0; j < point_count; j++ )
3288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
3289055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_UShort  idx = points[j];
3290fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3291fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3292fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          if ( idx >= n_points )
3293bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly            continue;
3294bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
3295fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          has_delta[idx] = TRUE;
3296fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3297055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          points_out[idx].x += FT_MulFix( deltas_x[j], apply );
3298055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          points_out[idx].y += FT_MulFix( deltas_y[j], apply );
3299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
3300fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3301fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* no need to handle phantom points here,      */
3302fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        /* since solitary points can't be interpolated */
3303055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        tt_interpolate_deltas( outline,
3304055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                               points_out,
3305055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                               points_org,
3306055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                               has_delta );
3307fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3308fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        FT_TRACE7(( "    point deltas:\n" ));
3309fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3310055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin        for ( j = 0; j < n_points; j++ )
3311fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        {
3312055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Pos  delta_x = points_out[j].x - points_org[j].x;
3313055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          FT_Pos  delta_y = points_out[j].y - points_org[j].y;
3314055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3315055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3316055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          outline->points[j].x += delta_x;
3317055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          outline->points[j].y += delta_y;
3318055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin
3319055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin#ifdef FT_DEBUG_LEVEL_TRACE
3320055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin          if ( delta_x || delta_y )
3321fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          {
3322fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            FT_TRACE7(( "      %d: (%d, %d) -> (%d, %d)\n",
3323fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        j,
3324055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        outline->points[j].x - delta_x,
3325055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin                        outline->points[j].y - delta_y,
3326fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        outline->points[j].x,
3327fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        outline->points[j].y ));
3328fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            count++;
3329fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          }
3330055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin#endif
3331fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        }
3332fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3333055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin#ifdef FT_DEBUG_LEVEL_TRACE
3334fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        if ( !count )
3335fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          FT_TRACE7(( "      none\n" ));
3336fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif
3337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( localpoints != ALL_POINTS )
3340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( localpoints );
3341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas_x );
3342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( deltas_y );
3343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      offsetToData += tupleDataSize;
3345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_Stream_SeekSet( stream, here );
3347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3349fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_TRACE5(( "\n" ));
3350fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
3351fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  Fail2:
3352055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    if ( sharedpoints != ALL_POINTS )
3353055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin      FT_FREE( sharedpoints );
3354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( tuple_coords );
3355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_start_coords );
3356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( im_end_coords );
3357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FRAME_EXIT();
3359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Fail1:
3361fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_FREE( points_org );
3362055aee28cedc3631434b2636fc6093c0d4d818abJungshik Shin    FT_FREE( points_out );
3363fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_FREE( has_delta );
3364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
3366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
3370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
3372a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    tt_get_var_blend                                                   */
3373a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
3374a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Description>                                                         */
3375a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    An extended internal version of `TT_Get_MM_Blend' that returns     */
3376a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    pointers instead of copying data, without any initialization of    */
3377a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*    the MM machinery in case it isn't loaded yet.                      */
3378a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
3379a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  FT_LOCAL_DEF( FT_Error )
3380a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_get_var_blend( TT_Face      face,
3381a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    FT_UInt     *num_coords,
3382a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    FT_Fixed*   *coords,
3383a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                    FT_MM_Var*  *mm_var )
3384a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
3385a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( face->blend )
3386a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
3387a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( num_coords )
3388a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *num_coords = face->blend->num_axis;
3389a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coords )
3390a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *coords     = face->blend->normalizedcoords;
3391a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( mm_var )
3392a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *mm_var     = face->blend->mmvar;
3393a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
3394a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    else
3395a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
3396a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( num_coords )
3397a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *num_coords = 0;
3398a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( coords )
3399a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *coords     = NULL;
3400a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( mm_var )
3401a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        *mm_var     = NULL;
3402a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
3403a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3404a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    return FT_Err_Ok;
3405a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
3406a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3407a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3408a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  static void
3409a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  ft_var_done_item_variation_store( TT_Face          face,
3410a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                    GX_ItemVarStore  itemStore )
3411a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  {
3412a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = FT_FACE_MEMORY( face );
3413a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_UInt    i;
3414a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3415a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3416a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( itemStore->varData )
3417a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
3418a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < itemStore->dataCount; i++ )
3419a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
3420a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( itemStore->varData[i].regionIndices );
3421a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( itemStore->varData[i].deltaSet );
3422a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
3423a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3424a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_FREE( itemStore->varData );
3425a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
3426a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3427a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( itemStore->varRegionList )
3428a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    {
3429a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      for ( i = 0; i < itemStore->regionCount; i++ )
3430a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( itemStore->varRegionList[i].axisList );
3431a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3432a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_FREE( itemStore->varRegionList );
3433a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    }
3434a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  }
3435a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3436a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3437a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*************************************************************************/
3438a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /*                                                                       */
3439a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  /* <Function>                                                            */
3440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    tt_done_blend                                                      */
3441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
3443fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*    Free the blend internal data structure.                            */
3444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
3445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_LOCAL_DEF( void )
3446a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin  tt_done_blend( TT_Face  face )
3447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
3448a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    FT_Memory  memory = FT_FACE_MEMORY( face );
3449a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    GX_Blend   blend  = face->blend;
3450a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3451a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3452a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin    if ( blend )
3453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
3454a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      FT_UInt  i, num_axes;
3455a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3457a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      /* blend->num_axis might not be set up yet */
3458a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      num_axes = blend->mmvar->num_axis;
3459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->normalizedcoords );
3461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->mmvar );
3462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3463a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( blend->avar_segment )
3464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
3465a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        for ( i = 0; i < num_axes; i++ )
3466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_FREE( blend->avar_segment[i].correspondence );
3467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        FT_FREE( blend->avar_segment );
3468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
3469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3470a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( blend->hvar_table )
3471a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
3472a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        ft_var_done_item_variation_store( face,
3473a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                          &blend->hvar_table->itemStore );
3474a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3475a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->hvar_table->widthMap.innerIndex );
3476a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->hvar_table->widthMap.outerIndex );
3477a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->hvar_table );
3478a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
3479a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3480a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      if ( blend->mvar_table )
3481a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      {
3482a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        ft_var_done_item_variation_store( face,
3483a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin                                          &blend->mvar_table->itemStore );
3484a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3485a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->mvar_table->values );
3486a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin        FT_FREE( blend->mvar_table );
3487a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin      }
3488a2527749993cb7f25560e4b1266787f1874435d4Jungshik Shin
3489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->tuplecoords );
3490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend->glyphoffsets );
3491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      FT_FREE( blend );
3492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
3493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
3494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
3496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
3498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
3499