📄 ttgxvar.c
字号:
/***************************************************************************//* *//* ttgxvar.c *//* *//* TrueType GX Font Variation loader *//* *//* Copyright 2004, 2005, 2006, 2007 by *//* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. *//* *//* This file is part of the FreeType project, and may only be used, *//* modified, and distributed under the terms of the FreeType project *//* license, LICENSE.TXT. By continuing to use, modify, or distribute *//* this file you indicate that you have read the license and *//* understand and accept it fully. *//* *//***************************************************************************//***************************************************************************//* *//* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at *//* *//* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html *//* *//* The documentation for `fvar' is inconsistent. At one point it says *//* that `countSizePairs' should be 3, at another point 2. It should be 2. *//* *//* The documentation for `gvar' is not intelligible; `cvar' refers you to *//* `gvar' and is thus also incomprehensible. *//* *//* The documentation for `avar' appears correct, but Apple has no fonts *//* with an `avar' table, so it is hard to test. *//* *//* Many thanks to John Jenkins (at Apple) in figuring this out. *//* *//* *//* Apple's `kern' table has some references to tuple indices, but as there *//* is no indication where these indices are defined, nor how to *//* interpolate the kerning values (different tuples have different *//* classes) this issue is ignored. *//* *//***************************************************************************/#include <ft2build.h>#include FT_INTERNAL_DEBUG_H#include FT_CONFIG_CONFIG_H#include FT_INTERNAL_STREAM_H#include FT_INTERNAL_SFNT_H#include FT_TRUETYPE_IDS_H#include FT_TRUETYPE_TAGS_H#include FT_MULTIPLE_MASTERS_H#include "ttdriver.h"#include "ttpload.h"#include "ttgxvar.h"#include "tterrors.h"#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT#define FT_Stream_FTell( stream ) \ ( (stream)->cursor - (stream)->base )#define FT_Stream_SeekSet( stream, off ) \ ( (stream)->cursor = (stream)->base+(off) ) /*************************************************************************/ /* */ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ /* messages during execution. */ /* */#undef FT_COMPONENT#define FT_COMPONENT trace_ttgxvar /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** Internal Routines *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */ /* indicates that there is a delta for every point without needing to */ /* enumerate all of them. */ /* */#define ALL_POINTS (FT_UShort*)( -1 ) enum { GX_PT_POINTS_ARE_WORDS = 0x80, GX_PT_POINT_RUN_COUNT_MASK = 0x7F }; /*************************************************************************/ /* */ /* <Function> */ /* ft_var_readpackedpoints */ /* */ /* <Description> */ /* Read a set of points to which the following deltas will apply. */ /* Points are packed with a run length encoding. */ /* */ /* <Input> */ /* stream :: The data stream. */ /* */ /* <Output> */ /* point_cnt :: The number of points read. A zero value means that */ /* all points in the glyph will be affected, without */ /* enumerating them individually. */ /* */ /* <Return> */ /* An array of FT_UShort containing the affected points or the */ /* special value ALL_POINTS. */ /* */ static FT_UShort* ft_var_readpackedpoints( FT_Stream stream, FT_UInt *point_cnt ) { FT_UShort *points; FT_Int n; FT_Int runcnt; FT_Int i; FT_Int j; FT_Int first; FT_Memory memory = stream->memory; FT_Error error = TT_Err_Ok; FT_UNUSED( error ); *point_cnt = n = FT_GET_BYTE(); if ( n == 0 ) return ALL_POINTS; if ( n & GX_PT_POINTS_ARE_WORDS ) n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 ); if ( FT_NEW_ARRAY( points, n ) ) return NULL; i = 0; while ( i < n ) { runcnt = FT_GET_BYTE(); if ( runcnt & GX_PT_POINTS_ARE_WORDS ) { runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK; first = points[i++] = FT_GET_USHORT(); /* first point not included in runcount */ for ( j = 0; j < runcnt; ++j ) points[i++] = (FT_UShort)( first += FT_GET_USHORT() ); } else { first = points[i++] = FT_GET_BYTE(); for ( j = 0; j < runcnt; ++j ) points[i++] = (FT_UShort)( first += FT_GET_BYTE() ); } } return points; } enum { GX_DT_DELTAS_ARE_ZERO = 0x80, GX_DT_DELTAS_ARE_WORDS = 0x40, GX_DT_DELTA_RUN_COUNT_MASK = 0x3F }; /*************************************************************************/ /* */ /* <Function> */ /* ft_var_readpackeddeltas */ /* */ /* <Description> */ /* Read a set of deltas. These are packed slightly differently than */ /* points. In particular there is no overall count. */ /* */ /* <Input> */ /* stream :: The data stream. */ /* */ /* delta_cnt :: The number of to be read. */ /* */ /* <Return> */ /* An array of FT_Short containing the deltas for the affected */ /* points. (This only gets the deltas for one dimension. It will */ /* generally be called twice, once for x, once for y. When used in */ /* cvt table, it will only be called once.) */ /* */ static FT_Short* ft_var_readpackeddeltas( FT_Stream stream, FT_Int delta_cnt ) { FT_Short *deltas; FT_Int runcnt; FT_Int i; FT_Int j; FT_Memory memory = stream->memory; FT_Error error = TT_Err_Ok; FT_UNUSED( error ); if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) return NULL; i = 0; while ( i < delta_cnt ) { runcnt = FT_GET_BYTE(); if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) { /* runcnt zeroes get added */ for ( j = 0; j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; ++j ) deltas[i++] = 0; } else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) { /* runcnt shorts from the stack */ for ( j = 0; j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; ++j ) deltas[i++] = FT_GET_SHORT(); } else { /* runcnt signed bytes from the stack */ for ( j = 0; j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; ++j ) deltas[i++] = FT_GET_CHAR(); } if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) ) { /* Bad format */ FT_FREE( deltas ); return NULL; } } return deltas; } /*************************************************************************/ /* */ /* <Function> */ /* ft_var_load_avar */ /* */ /* <Description> */ /* Parse the `avar' table if present. It need not be, so we return */ /* nothing. */ /* */ /* <InOut> */ /* face :: The font face. */ /* */ static void ft_var_load_avar( TT_Face face ) { FT_Stream stream = FT_FACE_STREAM(face); FT_Memory memory = stream->memory; GX_Blend blend = face->blend; GX_AVarSegment segment; FT_Error error = TT_Err_Ok; FT_ULong version; FT_Long axisCount; FT_Int i, j; FT_ULong table_len; FT_UNUSED( error ); blend->avar_checked = TRUE; if ( (error = face->goto_table( face, TTAG_avar, stream, &table_len )) != 0 ) return; if ( FT_FRAME_ENTER( table_len ) ) return; version = FT_GET_LONG(); axisCount = FT_GET_LONG(); if ( version != 0x00010000L || axisCount != (FT_Long)blend->mmvar->num_axis ) goto Exit; if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) goto Exit; segment = &blend->avar_segment[0]; for ( i = 0; i < axisCount; ++i, ++segment ) { segment->pairCount = FT_GET_USHORT(); if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) { /* Failure. Free everything we have done so far. We must do */ /* it right now since loading the `avar' table is optional. */ for ( j = i - 1; j >= 0; --j ) FT_FREE( blend->avar_segment[j].correspondence ); FT_FREE( blend->avar_segment ); blend->avar_segment = NULL; goto Exit; } for ( j = 0; j < segment->pairCount; ++j ) { segment->correspondence[j].fromCoord = FT_GET_SHORT() << 2; /* convert to Fixed */ segment->correspondence[j].toCoord = FT_GET_SHORT()<<2; /* convert to Fixed */ } } Exit: FT_FRAME_EXIT(); } typedef struct GX_GVar_Head_ { FT_Long version; FT_UShort axisCount; FT_UShort globalCoordCount; FT_ULong offsetToCoord; FT_UShort glyphCount; FT_UShort flags; FT_ULong offsetToData; } GX_GVar_Head; /*************************************************************************/ /* */ /* <Function> */ /* ft_var_load_gvar */ /* */ /* <Description> */ /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */ /* had better be there too. */ /* */ /* <InOut> */ /* face :: The font face. */ /* */ /* <Return> */ /* FreeType error code. 0 means success. */ /* */ static FT_Error ft_var_load_gvar( TT_Face face ) { FT_Stream stream = FT_FACE_STREAM(face); FT_Memory memory = stream->memory; GX_Blend blend = face->blend; FT_Error error; FT_UInt i, j; FT_ULong table_len; FT_ULong gvar_start; FT_ULong offsetToData; GX_GVar_Head gvar_head; static const FT_Frame_Field gvar_fields[] = {#undef FT_STRUCTURE#define FT_STRUCTURE GX_GVar_Head
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -