2018-06-03 09:01:17 +02:00
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* cffparse.c
|
|
|
|
*
|
|
|
|
* CFF token stream parser (body)
|
|
|
|
*
|
2024-01-27 17:11:22 +01:00
|
|
|
* Copyright (C) 1996-2024 by
|
2018-06-03 09:01:17 +02:00
|
|
|
* David Turner, Robert Wilhelm, and Werner Lemberg.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
|
2001-03-20 12:14:24 +01:00
|
|
|
#include "cffparse.h"
|
2020-06-08 13:31:55 +02:00
|
|
|
#include <freetype/internal/ftstream.h>
|
|
|
|
#include <freetype/internal/ftdebug.h>
|
|
|
|
#include <freetype/internal/ftcalc.h>
|
|
|
|
#include <freetype/internal/psaux.h>
|
|
|
|
#include <freetype/ftlist.h>
|
2000-12-08 03:42:29 +01:00
|
|
|
|
Complete redesign of error codes. Please check ftmoderr.h for more
details.
* include/freetype/internal/cfferrs.h,
include/freetype/internal/tterrors.h,
include/freetype/internal/t1errors.h: Removed. Replaced with files
local to the module. All extra error codes have been moved to
`fterrors.h'.
* src/sfnt/ttpost.h: Move error codes to `fterrors.h'.
* src/autohint/aherrors.h, src/cache/ftcerror.h, src/cff/cfferrs.h,
src/cid/ciderrs.h, src/pcf/pcferror.h, src/psaux/psauxerr.h,
src/psnames/psnamerr.h, src/raster/rasterrs.h, src/sfnt/sferrors.h,
src/smooth/ftsmerrs.h, src/truetype/tterrors.h,
src/type1/t1errors.h, src/winfonts/fnterrs.h: New files defining the
error names for the module it belongs to.
* include/freetype/ftmoderr.h: New file, defining the module error
offsets. Its structure is similar to `fterrors.h'.
* include/freetype/fterrors.h (FT_NOERRORDEF): New macro.
(FT_ERRORDEF): Redefined to use module error offsets.
All internal error codes are now public; unused error codes have
been removed, some are new.
* include/freetype/config/ftheader.h (FT_MODULE_ERRORS_H): New
macro.
* include/freetype/config/ftoption.h
(FT_CONFIG_OPTION_USE_MODULE_ERRORS): New macro.
All other source files have been updated to use the new error codes;
some already existing (internal) error codes local to a module have
been renamed to give them the same name as in the base module.
All make files have been updated to include the local error files.
* src/cid/cidtokens.h: Replaced with...
* src/cid/cidtoken.h: This file for 8+3 consistency.
* src/raster/ftraster.c: Use macros for header file names.
2001-06-06 19:30:41 +02:00
|
|
|
#include "cfferrs.h"
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
#include "cffload.h"
|
Complete redesign of error codes. Please check ftmoderr.h for more
details.
* include/freetype/internal/cfferrs.h,
include/freetype/internal/tterrors.h,
include/freetype/internal/t1errors.h: Removed. Replaced with files
local to the module. All extra error codes have been moved to
`fterrors.h'.
* src/sfnt/ttpost.h: Move error codes to `fterrors.h'.
* src/autohint/aherrors.h, src/cache/ftcerror.h, src/cff/cfferrs.h,
src/cid/ciderrs.h, src/pcf/pcferror.h, src/psaux/psauxerr.h,
src/psnames/psnamerr.h, src/raster/rasterrs.h, src/sfnt/sferrors.h,
src/smooth/ftsmerrs.h, src/truetype/tterrors.h,
src/type1/t1errors.h, src/winfonts/fnterrs.h: New files defining the
error names for the module it belongs to.
* include/freetype/ftmoderr.h: New file, defining the module error
offsets. Its structure is similar to `fterrors.h'.
* include/freetype/fterrors.h (FT_NOERRORDEF): New macro.
(FT_ERRORDEF): Redefined to use module error offsets.
All internal error codes are now public; unused error codes have
been removed, some are new.
* include/freetype/config/ftheader.h (FT_MODULE_ERRORS_H): New
macro.
* include/freetype/config/ftoption.h
(FT_CONFIG_OPTION_USE_MODULE_ERRORS): New macro.
All other source files have been updated to use the new error codes;
some already existing (internal) error codes local to a module have
been renamed to give them the same name as in the base module.
All make files have been updated to include the local error files.
* src/cid/cidtokens.h: Replaced with...
* src/cid/cidtoken.h: This file for 8+3 consistency.
* src/raster/ftraster.c: Use macros for header file names.
2001-06-06 19:30:41 +02:00
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
|
2018-06-03 09:01:17 +02:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2000-12-08 03:42:29 +01:00
|
|
|
#undef FT_COMPONENT
|
2018-08-15 18:13:17 +02:00
|
|
|
#define FT_COMPONENT cffparse
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
|
2016-12-15 11:22:15 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
* src/cff/cffcmap.c, src/cff/cffcmap.h, Jamfile, rules.mk: new files added
to support charmaps for CFF fonts
* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffobjs.c,
src/cff/cffobjs.h, src/cff/cffparse.c, src/cffparse.h, src/cff/cffgload.c,
src/cff/cffgload.h: adding support for CFF charmaps, reformatting the
sources, and removing some bugs in the Encoding and Charset loaders
2002-07-10 18:52:06 +02:00
|
|
|
cff_parser_init( CFF_Parser parser,
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_UInt code,
|
2009-04-05 16:34:40 +02:00
|
|
|
void* object,
|
2016-02-14 16:03:15 +01:00
|
|
|
FT_Library library,
|
2016-12-15 11:22:15 +01:00
|
|
|
FT_UInt stackSize,
|
2016-02-15 20:41:58 +01:00
|
|
|
FT_UShort num_designs,
|
|
|
|
FT_UShort num_axes )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2016-12-15 11:22:15 +01:00
|
|
|
FT_Memory memory = library->memory; /* for FT_NEW_ARRAY */
|
|
|
|
FT_Error error; /* for FT_NEW_ARRAY */
|
|
|
|
|
|
|
|
|
2016-09-28 19:06:21 +02:00
|
|
|
FT_ZERO( parser );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2016-12-15 11:22:15 +01:00
|
|
|
#if 0
|
2000-12-08 03:42:29 +01:00
|
|
|
parser->top = parser->stack;
|
2016-12-15 11:22:15 +01:00
|
|
|
#endif
|
2000-12-08 03:42:29 +01:00
|
|
|
parser->object_code = code;
|
|
|
|
parser->object = object;
|
2009-04-05 16:34:40 +02:00
|
|
|
parser->library = library;
|
2016-02-14 16:03:15 +01:00
|
|
|
parser->num_designs = num_designs;
|
2016-02-15 20:41:58 +01:00
|
|
|
parser->num_axes = num_axes;
|
2016-12-15 11:22:15 +01:00
|
|
|
|
|
|
|
/* allocate the stack buffer */
|
2021-04-26 23:21:51 +02:00
|
|
|
if ( FT_QNEW_ARRAY( parser->stack, stackSize ) )
|
2016-12-15 11:22:15 +01:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
parser->stackSize = stackSize;
|
|
|
|
parser->top = parser->stack; /* empty stack */
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FT_LOCAL_DEF( void )
|
|
|
|
cff_parser_done( CFF_Parser parser )
|
|
|
|
{
|
|
|
|
FT_Memory memory = parser->library->memory; /* for FT_FREE */
|
|
|
|
|
|
|
|
|
|
|
|
FT_FREE( parser->stack );
|
2019-03-31 12:08:49 +02:00
|
|
|
|
|
|
|
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
|
2023-03-20 21:53:51 +01:00
|
|
|
FT_List_Finalize( &parser->t2_strings, NULL, memory, NULL );
|
2019-03-31 12:08:49 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-03-19 15:13:52 +01:00
|
|
|
/* The parser limit checks in the next two functions are supposed */
|
|
|
|
/* to detect the immediate crossing of the stream boundary. They */
|
|
|
|
/* shall not be triggered from the distant t2_strings buffers. */
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
/* read an integer */
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Long
|
2023-03-19 15:13:52 +01:00
|
|
|
cff_parse_integer( FT_Byte* start,
|
|
|
|
FT_Byte* limit )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
|
|
|
FT_Byte* p = start;
|
|
|
|
FT_Int v = *p++;
|
|
|
|
FT_Long val = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if ( v == 28 )
|
|
|
|
{
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 2 > limit && limit >= p )
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Bad;
|
|
|
|
|
2013-05-04 18:57:56 +02:00
|
|
|
val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] );
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
else if ( v == 29 )
|
|
|
|
{
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 4 > limit && limit >= p )
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Bad;
|
|
|
|
|
2013-05-04 18:57:56 +02:00
|
|
|
val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) |
|
|
|
|
( (FT_ULong)p[1] << 16 ) |
|
|
|
|
( (FT_ULong)p[2] << 8 ) |
|
|
|
|
(FT_ULong)p[3] );
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
else if ( v < 247 )
|
|
|
|
{
|
|
|
|
val = v - 139;
|
|
|
|
}
|
|
|
|
else if ( v < 251 )
|
|
|
|
{
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 1 > limit && limit >= p )
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Bad;
|
|
|
|
|
|
|
|
val = ( v - 247 ) * 256 + p[0] + 108;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 1 > limit && limit >= p )
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Bad;
|
|
|
|
|
|
|
|
val = -( v - 251 ) * 256 - p[0] - 108;
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return val;
|
|
|
|
|
|
|
|
Bad:
|
|
|
|
val = 0;
|
2012-10-19 09:06:53 +02:00
|
|
|
FT_TRACE4(( "!!!END OF DATA:!!!" ));
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
static const FT_Long power_tens[] =
|
|
|
|
{
|
|
|
|
1L,
|
|
|
|
10L,
|
|
|
|
100L,
|
|
|
|
1000L,
|
|
|
|
10000L,
|
|
|
|
100000L,
|
|
|
|
1000000L,
|
|
|
|
10000000L,
|
|
|
|
100000000L,
|
|
|
|
1000000000L
|
|
|
|
};
|
|
|
|
|
2017-05-30 22:35:41 +02:00
|
|
|
/* maximum values allowed for multiplying */
|
|
|
|
/* with the corresponding `power_tens' element */
|
|
|
|
static const FT_Long power_ten_limits[] =
|
|
|
|
{
|
|
|
|
FT_LONG_MAX / 1L,
|
|
|
|
FT_LONG_MAX / 10L,
|
|
|
|
FT_LONG_MAX / 100L,
|
|
|
|
FT_LONG_MAX / 1000L,
|
|
|
|
FT_LONG_MAX / 10000L,
|
|
|
|
FT_LONG_MAX / 100000L,
|
|
|
|
FT_LONG_MAX / 1000000L,
|
|
|
|
FT_LONG_MAX / 10000000L,
|
|
|
|
FT_LONG_MAX / 100000000L,
|
|
|
|
FT_LONG_MAX / 1000000000L,
|
|
|
|
};
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
/* read a real */
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Fixed
|
2023-03-19 15:13:52 +01:00
|
|
|
cff_parse_real( FT_Byte* start,
|
|
|
|
FT_Byte* limit,
|
|
|
|
FT_Long power_ten,
|
|
|
|
FT_Long* scaling )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2008-05-04 15:37:38 +02:00
|
|
|
FT_Byte* p = start;
|
2015-02-20 08:35:32 +01:00
|
|
|
FT_Int nib;
|
2001-06-19 10:28:24 +02:00
|
|
|
FT_UInt phase;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2010-03-09 17:01:21 +01:00
|
|
|
FT_Long result, number, exponent;
|
2012-10-20 21:27:17 +02:00
|
|
|
FT_Int sign = 0, exponent_sign = 0, have_overflow = 0;
|
2009-07-31 17:32:08 +02:00
|
|
|
FT_Long exponent_add, integer_length, fraction_length;
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
if ( scaling )
|
2010-03-09 17:01:21 +01:00
|
|
|
*scaling = 0;
|
2008-05-04 15:37:38 +02:00
|
|
|
|
|
|
|
result = 0;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
number = 0;
|
|
|
|
exponent = 0;
|
|
|
|
|
|
|
|
exponent_add = 0;
|
|
|
|
integer_length = 0;
|
|
|
|
fraction_length = 0;
|
|
|
|
|
|
|
|
/* First of all, read the integer part. */
|
2000-12-08 03:42:29 +01:00
|
|
|
phase = 4;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* If we entered this iteration with phase == 4, we need to */
|
2007-01-26 23:18:56 +01:00
|
|
|
/* read a new byte. This also skips past the initial 0x1E. */
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( phase )
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
|
|
|
|
/* Make sure we don't read past the end. */
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 1 > limit && limit >= p )
|
2012-10-19 09:06:53 +02:00
|
|
|
goto Bad;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the nibble. */
|
2015-02-20 08:35:32 +01:00
|
|
|
nib = (FT_Int)( p[0] >> phase ) & 0xF;
|
2000-12-08 03:42:29 +01:00
|
|
|
phase = 4 - phase;
|
|
|
|
|
|
|
|
if ( nib == 0xE )
|
|
|
|
sign = 1;
|
|
|
|
else if ( nib > 9 )
|
|
|
|
break;
|
|
|
|
else
|
2008-05-04 15:37:38 +02:00
|
|
|
{
|
|
|
|
/* Increase exponent if we can't add the digit. */
|
|
|
|
if ( number >= 0xCCCCCCCL )
|
|
|
|
exponent_add++;
|
|
|
|
/* Skip leading zeros. */
|
|
|
|
else if ( nib || number )
|
|
|
|
{
|
|
|
|
integer_length++;
|
|
|
|
number = number * 10 + nib;
|
|
|
|
}
|
|
|
|
}
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Read fraction part, if any. */
|
2014-12-07 11:03:57 +01:00
|
|
|
if ( nib == 0xA )
|
2000-12-08 03:42:29 +01:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* If we entered this iteration with phase == 4, we need */
|
|
|
|
/* to read a new byte. */
|
|
|
|
if ( phase )
|
2000-12-08 17:17:16 +01:00
|
|
|
{
|
2000-12-08 03:42:29 +01:00
|
|
|
p++;
|
|
|
|
|
|
|
|
/* Make sure we don't read past the end. */
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 1 > limit && limit >= p )
|
2012-10-19 09:06:53 +02:00
|
|
|
goto Bad;
|
2000-12-08 17:17:16 +01:00
|
|
|
}
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
/* Get the nibble. */
|
|
|
|
nib = ( p[0] >> phase ) & 0xF;
|
|
|
|
phase = 4 - phase;
|
|
|
|
if ( nib >= 10 )
|
|
|
|
break;
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Skip leading zeros if possible. */
|
|
|
|
if ( !nib && !number )
|
|
|
|
exponent_add--;
|
|
|
|
/* Only add digit if we don't overflow. */
|
2009-03-11 11:20:51 +01:00
|
|
|
else if ( number < 0xCCCCCCCL && fraction_length < 9 )
|
2008-04-01 07:55:48 +02:00
|
|
|
{
|
2008-05-04 15:37:38 +02:00
|
|
|
fraction_length++;
|
|
|
|
number = number * 10 + nib;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Read exponent, if any. */
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( nib == 12 )
|
|
|
|
{
|
2004-08-29 18:50:09 +02:00
|
|
|
exponent_sign = 1;
|
|
|
|
nib = 11;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( nib == 11 )
|
|
|
|
{
|
|
|
|
for (;;)
|
|
|
|
{
|
2008-05-04 15:37:38 +02:00
|
|
|
/* If we entered this iteration with phase == 4, */
|
|
|
|
/* we need to read a new byte. */
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( phase )
|
2000-12-08 17:17:16 +01:00
|
|
|
{
|
2000-12-08 03:42:29 +01:00
|
|
|
p++;
|
|
|
|
|
|
|
|
/* Make sure we don't read past the end. */
|
2023-03-19 15:13:52 +01:00
|
|
|
if ( p + 1 > limit && limit >= p )
|
2012-10-19 09:06:53 +02:00
|
|
|
goto Bad;
|
2000-12-08 17:17:16 +01:00
|
|
|
}
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
/* Get the nibble. */
|
|
|
|
nib = ( p[0] >> phase ) & 0xF;
|
|
|
|
phase = 4 - phase;
|
|
|
|
if ( nib >= 10 )
|
|
|
|
break;
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Arbitrarily limit exponent. */
|
|
|
|
if ( exponent > 1000 )
|
2012-10-20 21:27:17 +02:00
|
|
|
have_overflow = 1;
|
|
|
|
else
|
|
|
|
exponent = exponent * 10 + nib;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
2004-08-29 18:50:09 +02:00
|
|
|
if ( exponent_sign )
|
|
|
|
exponent = -exponent;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
2012-10-19 09:06:53 +02:00
|
|
|
if ( !number )
|
|
|
|
goto Exit;
|
|
|
|
|
2012-10-20 21:27:17 +02:00
|
|
|
if ( have_overflow )
|
|
|
|
{
|
|
|
|
if ( exponent_sign )
|
|
|
|
goto Underflow;
|
|
|
|
else
|
|
|
|
goto Overflow;
|
|
|
|
}
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* We don't check `power_ten' and `exponent_add'. */
|
|
|
|
exponent += power_ten + exponent_add;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
if ( scaling )
|
2007-12-14 08:48:32 +01:00
|
|
|
{
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Only use `fraction_length'. */
|
|
|
|
fraction_length += integer_length;
|
|
|
|
exponent += integer_length;
|
|
|
|
|
|
|
|
if ( fraction_length <= 5 )
|
|
|
|
{
|
|
|
|
if ( number > 0x7FFFL )
|
|
|
|
{
|
|
|
|
result = FT_DivFix( number, 10 );
|
|
|
|
*scaling = exponent - fraction_length + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( exponent > 0 )
|
|
|
|
{
|
2009-07-31 17:32:08 +02:00
|
|
|
FT_Long new_fraction_length, shift;
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2007-12-14 08:48:32 +01:00
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Make `scaling' as small as possible. */
|
|
|
|
new_fraction_length = FT_MIN( exponent, 5 );
|
|
|
|
shift = new_fraction_length - fraction_length;
|
|
|
|
|
2012-06-25 10:58:20 +02:00
|
|
|
if ( shift > 0 )
|
2008-05-04 15:37:38 +02:00
|
|
|
{
|
2012-06-25 10:58:20 +02:00
|
|
|
exponent -= new_fraction_length;
|
|
|
|
number *= power_tens[shift];
|
|
|
|
if ( number > 0x7FFFL )
|
|
|
|
{
|
|
|
|
number /= 10;
|
|
|
|
exponent += 1;
|
|
|
|
}
|
2008-05-04 15:37:38 +02:00
|
|
|
}
|
2012-06-25 10:58:20 +02:00
|
|
|
else
|
|
|
|
exponent -= fraction_length;
|
2008-05-04 15:37:38 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
exponent -= fraction_length;
|
|
|
|
|
2013-05-04 16:40:12 +02:00
|
|
|
result = (FT_Long)( (FT_ULong)number << 16 );
|
2008-05-04 15:37:38 +02:00
|
|
|
*scaling = exponent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )
|
|
|
|
{
|
|
|
|
result = FT_DivFix( number, power_tens[fraction_length - 4] );
|
|
|
|
*scaling = exponent - 4;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = FT_DivFix( number, power_tens[fraction_length - 5] );
|
|
|
|
*scaling = exponent - 5;
|
|
|
|
}
|
|
|
|
}
|
2007-12-14 08:48:32 +01:00
|
|
|
}
|
2008-05-04 15:37:38 +02:00
|
|
|
else
|
2007-12-14 08:48:32 +01:00
|
|
|
{
|
2008-05-04 15:37:38 +02:00
|
|
|
integer_length += exponent;
|
|
|
|
fraction_length -= exponent;
|
2007-12-14 08:48:32 +01:00
|
|
|
|
2012-10-20 21:27:17 +02:00
|
|
|
if ( integer_length > 5 )
|
2012-10-19 09:06:53 +02:00
|
|
|
goto Overflow;
|
2012-10-20 21:27:17 +02:00
|
|
|
if ( integer_length < -5 )
|
|
|
|
goto Underflow;
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2008-11-27 22:55:20 +01:00
|
|
|
/* Remove non-significant digits. */
|
2010-06-08 08:37:11 +02:00
|
|
|
if ( integer_length < 0 )
|
|
|
|
{
|
2008-11-27 22:55:20 +01:00
|
|
|
number /= power_tens[-integer_length];
|
|
|
|
fraction_length += integer_length;
|
|
|
|
}
|
|
|
|
|
2010-06-08 09:21:39 +02:00
|
|
|
/* this can only happen if exponent was non-zero */
|
|
|
|
if ( fraction_length == 10 )
|
|
|
|
{
|
|
|
|
number /= 10;
|
|
|
|
fraction_length -= 1;
|
|
|
|
}
|
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
/* Convert into 16.16 format. */
|
|
|
|
if ( fraction_length > 0 )
|
|
|
|
{
|
|
|
|
if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
result = FT_DivFix( number, power_tens[fraction_length] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
number *= power_tens[-fraction_length];
|
|
|
|
|
|
|
|
if ( number > 0x7FFFL )
|
2012-10-19 09:06:53 +02:00
|
|
|
goto Overflow;
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2013-05-04 16:40:12 +02:00
|
|
|
result = (FT_Long)( (FT_ULong)number << 16 );
|
2008-05-04 15:37:38 +02:00
|
|
|
}
|
2007-12-14 08:48:32 +01:00
|
|
|
}
|
|
|
|
|
2012-10-19 09:06:53 +02:00
|
|
|
Exit:
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( sign )
|
|
|
|
result = -result;
|
|
|
|
|
|
|
|
return result;
|
2012-10-19 09:06:53 +02:00
|
|
|
|
|
|
|
Overflow:
|
|
|
|
result = 0x7FFFFFFFL;
|
|
|
|
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
Underflow:
|
|
|
|
result = 0;
|
|
|
|
FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
Bad:
|
|
|
|
result = 0;
|
|
|
|
FT_TRACE4(( "!!!END OF DATA:!!!" ));
|
|
|
|
goto Exit;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* read a number, either integer or real */
|
2016-12-15 12:17:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Long )
|
|
|
|
cff_parse_num( CFF_Parser parser,
|
|
|
|
FT_Byte** d )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
if ( **d == 30 )
|
|
|
|
{
|
|
|
|
/* binary-coded decimal is truncated to integer */
|
2023-03-19 15:13:52 +01:00
|
|
|
return cff_parse_real( *d, parser->limit, 0, NULL ) >> 16;
|
2016-12-15 12:17:22 +01:00
|
|
|
}
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
|
|
|
|
else if ( **d == 255 )
|
|
|
|
{
|
2022-06-21 17:08:04 +02:00
|
|
|
/* 16.16 fixed-point is used internally for CFF2 blend results. */
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
/* Since these are trusted values, a limit check is not needed. */
|
|
|
|
|
2017-01-03 06:53:13 +01:00
|
|
|
/* After the 255, 4 bytes give the number. */
|
|
|
|
/* The blend value is converted to integer, with rounding; */
|
|
|
|
/* due to the right-shift we don't need the lowest byte. */
|
|
|
|
#if 0
|
|
|
|
return (FT_Short)(
|
|
|
|
( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
|
|
|
|
( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
|
|
|
|
( (FT_UInt32)*( d[0] + 3 ) << 8 ) |
|
|
|
|
(FT_UInt32)*( d[0] + 4 ) ) + 0x8000U ) >> 16 );
|
|
|
|
#else
|
2017-01-03 00:27:07 +01:00
|
|
|
return (FT_Short)(
|
2017-01-03 06:53:13 +01:00
|
|
|
( ( ( (FT_UInt32)*( d[0] + 1 ) << 16 ) |
|
|
|
|
( (FT_UInt32)*( d[0] + 2 ) << 8 ) |
|
|
|
|
(FT_UInt32)*( d[0] + 3 ) ) + 0x80U ) >> 8 );
|
|
|
|
#endif
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-15 12:17:22 +01:00
|
|
|
else
|
2023-03-19 15:13:52 +01:00
|
|
|
return cff_parse_integer( *d, parser->limit );
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
/* read a floating point number, either integer or real */
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Fixed
|
2016-12-15 12:17:22 +01:00
|
|
|
do_fixed( CFF_Parser parser,
|
|
|
|
FT_Byte** d,
|
|
|
|
FT_Long scaling )
|
2001-02-07 02:11:54 +01:00
|
|
|
{
|
2012-10-17 19:55:20 +02:00
|
|
|
if ( **d == 30 )
|
2023-03-19 15:13:52 +01:00
|
|
|
return cff_parse_real( *d, parser->limit, scaling, NULL );
|
2023-07-11 10:40:25 +02:00
|
|
|
else if ( **d == 255 )
|
|
|
|
{
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
|
|
|
|
( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
|
|
|
|
( (FT_UInt32)*( d[0] + 3 ) << 8 ) |
|
|
|
|
(FT_UInt32)*( d[0] + 4 ) ) );
|
2023-07-11 10:40:25 +02:00
|
|
|
|
|
|
|
if ( scaling )
|
|
|
|
{
|
|
|
|
if ( FT_ABS( val ) > power_ten_limits[scaling] )
|
|
|
|
{
|
|
|
|
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
|
|
|
return val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
|
|
|
|
}
|
|
|
|
val *= power_tens[scaling];
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
2012-10-17 19:55:20 +02:00
|
|
|
else
|
|
|
|
{
|
2023-03-19 15:13:52 +01:00
|
|
|
FT_Long val = cff_parse_integer( *d, parser->limit );
|
2012-10-19 09:06:53 +02:00
|
|
|
|
2012-10-17 19:55:20 +02:00
|
|
|
|
2012-10-19 09:06:53 +02:00
|
|
|
if ( scaling )
|
2017-05-30 22:35:41 +02:00
|
|
|
{
|
2023-07-11 10:40:25 +02:00
|
|
|
if ( ( FT_ABS( val ) << 16 ) > power_ten_limits[scaling] )
|
2017-05-30 22:35:41 +02:00
|
|
|
{
|
2017-06-27 16:56:38 +02:00
|
|
|
val = val > 0 ? 0x7FFFFFFFL : -0x7FFFFFFFL;
|
2017-05-30 22:35:41 +02:00
|
|
|
goto Overflow;
|
|
|
|
}
|
|
|
|
|
2012-10-19 09:06:53 +02:00
|
|
|
val *= power_tens[scaling];
|
2017-05-30 22:35:41 +02:00
|
|
|
}
|
2012-10-17 19:55:20 +02:00
|
|
|
|
|
|
|
if ( val > 0x7FFF )
|
2012-10-19 09:06:53 +02:00
|
|
|
{
|
|
|
|
val = 0x7FFFFFFFL;
|
|
|
|
goto Overflow;
|
|
|
|
}
|
2012-10-17 19:55:20 +02:00
|
|
|
else if ( val < -0x7FFF )
|
2012-10-19 09:06:53 +02:00
|
|
|
{
|
|
|
|
val = -0x7FFFFFFFL;
|
|
|
|
goto Overflow;
|
|
|
|
}
|
2012-10-17 19:55:20 +02:00
|
|
|
|
2013-05-04 16:40:12 +02:00
|
|
|
return (FT_Long)( (FT_ULong)val << 16 );
|
2012-10-19 09:06:53 +02:00
|
|
|
|
|
|
|
Overflow:
|
|
|
|
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
|
|
|
return val;
|
2012-10-17 19:55:20 +02:00
|
|
|
}
|
2001-02-07 02:11:54 +01:00
|
|
|
}
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2008-05-04 15:37:38 +02:00
|
|
|
|
2012-10-19 09:06:53 +02:00
|
|
|
/* read a floating point number, either integer or real */
|
2023-07-14 18:58:55 +02:00
|
|
|
FT_LOCAL_DEF( FT_Fixed )
|
2016-12-15 12:17:22 +01:00
|
|
|
cff_parse_fixed( CFF_Parser parser,
|
|
|
|
FT_Byte** d )
|
2012-10-19 09:06:53 +02:00
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
return do_fixed( parser, d, 0 );
|
2012-10-19 09:06:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* read a floating point number, either integer or real, */
|
|
|
|
/* but return `10^scaling' times the number read in */
|
|
|
|
static FT_Fixed
|
2016-12-15 12:17:22 +01:00
|
|
|
cff_parse_fixed_scaled( CFF_Parser parser,
|
|
|
|
FT_Byte** d,
|
|
|
|
FT_Long scaling )
|
2012-10-19 09:06:53 +02:00
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
return do_fixed( parser, d, scaling );
|
2012-10-19 09:06:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-15 01:05:38 +02:00
|
|
|
/* read a floating point number, either integer or real, */
|
|
|
|
/* and return it as precise as possible -- `scaling' returns */
|
|
|
|
/* the scaling factor (as a power of 10) */
|
|
|
|
static FT_Fixed
|
2016-12-15 12:17:22 +01:00
|
|
|
cff_parse_fixed_dynamic( CFF_Parser parser,
|
|
|
|
FT_Byte** d,
|
|
|
|
FT_Long* scaling )
|
2008-05-15 01:05:38 +02:00
|
|
|
{
|
|
|
|
FT_ASSERT( scaling );
|
|
|
|
|
|
|
|
if ( **d == 30 )
|
2023-03-19 15:13:52 +01:00
|
|
|
return cff_parse_real( *d, parser->limit, 0, scaling );
|
2008-05-15 01:05:38 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
FT_Long number;
|
|
|
|
FT_Int integer_length;
|
|
|
|
|
|
|
|
|
2023-03-19 15:13:52 +01:00
|
|
|
number = cff_parse_integer( *d, parser->limit );
|
2008-05-15 01:05:38 +02:00
|
|
|
|
|
|
|
if ( number > 0x7FFFL )
|
|
|
|
{
|
|
|
|
for ( integer_length = 5; integer_length < 10; integer_length++ )
|
|
|
|
if ( number < power_tens[integer_length] )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )
|
|
|
|
{
|
|
|
|
*scaling = integer_length - 4;
|
|
|
|
return FT_DivFix( number, power_tens[integer_length - 4] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*scaling = integer_length - 5;
|
|
|
|
return FT_DivFix( number, power_tens[integer_length - 5] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*scaling = 0;
|
2013-05-04 16:40:12 +02:00
|
|
|
return (FT_Long)( (FT_ULong)number << 16 );
|
2008-05-15 01:05:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Error
|
2002-03-30 17:41:09 +01:00
|
|
|
cff_parse_font_matrix( CFF_Parser parser )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2002-03-14 09:57:10 +01:00
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_Matrix* matrix = &dict->font_matrix;
|
|
|
|
FT_Vector* offset = &dict->font_offset;
|
2008-05-15 01:05:38 +02:00
|
|
|
FT_ULong* upm = &dict->units_per_em;
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_Byte** data = parser->stack;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2000-12-30 23:14:58 +01:00
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( parser->top >= parser->stack + 6 )
|
|
|
|
{
|
2016-05-17 19:54:09 +02:00
|
|
|
FT_Fixed values[6];
|
|
|
|
FT_Long scalings[6];
|
|
|
|
|
|
|
|
FT_Long min_scaling, max_scaling;
|
|
|
|
int i;
|
2000-12-24 10:57:28 +01:00
|
|
|
|
|
|
|
|
2011-09-07 15:01:20 +02:00
|
|
|
dict->has_font_matrix = TRUE;
|
|
|
|
|
2023-04-26 13:15:57 +02:00
|
|
|
/* We expect a well-formed font matrix, that is, the matrix elements */
|
2008-05-15 01:05:38 +02:00
|
|
|
/* `xx' and `yy' are of approximately the same magnitude. To avoid */
|
2016-05-17 19:54:09 +02:00
|
|
|
/* loss of precision, we use the magnitude of the largest matrix */
|
|
|
|
/* element to scale all other elements. The scaling factor is then */
|
|
|
|
/* contained in the `units_per_em' value. */
|
2008-04-01 07:55:48 +02:00
|
|
|
|
2016-05-17 19:54:09 +02:00
|
|
|
max_scaling = FT_LONG_MIN;
|
|
|
|
min_scaling = FT_LONG_MAX;
|
2001-02-07 02:11:54 +01:00
|
|
|
|
2016-05-17 19:54:09 +02:00
|
|
|
for ( i = 0; i < 6; i++ )
|
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
values[i] = cff_parse_fixed_dynamic( parser, data++, &scalings[i] );
|
2016-05-17 19:54:09 +02:00
|
|
|
if ( values[i] )
|
|
|
|
{
|
|
|
|
if ( scalings[i] > max_scaling )
|
|
|
|
max_scaling = scalings[i];
|
|
|
|
if ( scalings[i] < min_scaling )
|
|
|
|
min_scaling = scalings[i];
|
|
|
|
}
|
|
|
|
}
|
2008-05-15 01:05:38 +02:00
|
|
|
|
2016-05-17 19:54:09 +02:00
|
|
|
if ( max_scaling < -9 ||
|
|
|
|
max_scaling > 0 ||
|
|
|
|
( max_scaling - min_scaling ) < 0 ||
|
|
|
|
( max_scaling - min_scaling ) > 9 )
|
2000-12-24 10:57:28 +01:00
|
|
|
{
|
2011-07-29 06:15:20 +02:00
|
|
|
FT_TRACE1(( "cff_parse_font_matrix:"
|
2021-02-04 07:44:06 +01:00
|
|
|
" strange scaling values (minimum %ld, maximum %ld),\n",
|
|
|
|
min_scaling, max_scaling ));
|
|
|
|
FT_TRACE1(( " "
|
|
|
|
" using default matrix\n" ));
|
2018-06-24 06:22:48 +02:00
|
|
|
goto Unlikely;
|
2000-12-24 10:57:28 +01:00
|
|
|
}
|
|
|
|
|
2016-05-17 19:54:09 +02:00
|
|
|
for ( i = 0; i < 6; i++ )
|
|
|
|
{
|
|
|
|
FT_Fixed value = values[i];
|
|
|
|
FT_Long divisor, half_divisor;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !value )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
divisor = power_tens[max_scaling - scalings[i]];
|
|
|
|
half_divisor = divisor >> 1;
|
|
|
|
|
|
|
|
if ( value < 0 )
|
|
|
|
{
|
|
|
|
if ( FT_LONG_MIN + half_divisor < value )
|
|
|
|
values[i] = ( value - half_divisor ) / divisor;
|
|
|
|
else
|
|
|
|
values[i] = FT_LONG_MIN / divisor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( FT_LONG_MAX - half_divisor > value )
|
|
|
|
values[i] = ( value + half_divisor ) / divisor;
|
|
|
|
else
|
|
|
|
values[i] = FT_LONG_MAX / divisor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
matrix->xx = values[0];
|
|
|
|
matrix->yx = values[1];
|
|
|
|
matrix->xy = values[2];
|
|
|
|
matrix->yy = values[3];
|
|
|
|
offset->x = values[4];
|
|
|
|
offset->y = values[5];
|
2000-12-24 10:57:28 +01:00
|
|
|
|
2016-05-17 19:54:09 +02:00
|
|
|
*upm = (FT_ULong)power_tens[-max_scaling];
|
2011-07-29 06:15:20 +02:00
|
|
|
|
2011-09-07 15:01:20 +02:00
|
|
|
FT_TRACE4(( " [%f %f %f %f %f %f]\n",
|
For debugging, avoid implicit conversion from integer to double.
Otherwise we get zillions of clang 15 warnings.
* src/autofit/afcjk.c, src/autofit/afhints.c, src/autofit/aflatin.c,
src/base/ftobjs.c, src/base/ftoutln.c, src/cff/cffparse.c,
src/raster/ftraster.c, src/sfnt/pngshim.c, src/truetype/ttgload.c,
src/truetype/ttgxvar.c, src/truetype/ttobjs.c, src/type1/t1gload.c: Use
`double` cast in debugging and tracing macros.
2023-02-07 22:24:53 +01:00
|
|
|
(double)matrix->xx / (double)*upm / 65536,
|
|
|
|
(double)matrix->xy / (double)*upm / 65536,
|
|
|
|
(double)matrix->yx / (double)*upm / 65536,
|
|
|
|
(double)matrix->yy / (double)*upm / 65536,
|
|
|
|
(double)offset->x / (double)*upm / 65536,
|
|
|
|
(double)offset->y / (double)*upm / 65536 ));
|
2018-06-24 06:22:48 +02:00
|
|
|
|
|
|
|
if ( !FT_Matrix_Check( matrix ) )
|
|
|
|
{
|
|
|
|
FT_TRACE1(( "cff_parse_font_matrix:"
|
|
|
|
" degenerate values, using default matrix\n" ));
|
|
|
|
goto Unlikely;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FT_Err_Ok;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
2018-06-24 06:22:48 +02:00
|
|
|
else
|
|
|
|
return FT_THROW( Stack_Underflow );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2018-06-24 06:22:48 +02:00
|
|
|
Unlikely:
|
|
|
|
/* Return default matrix in case of unlikely values. */
|
|
|
|
|
|
|
|
matrix->xx = 0x10000L;
|
|
|
|
matrix->yx = 0;
|
|
|
|
matrix->xy = 0;
|
|
|
|
matrix->yy = 0x10000L;
|
|
|
|
offset->x = 0;
|
|
|
|
offset->y = 0;
|
|
|
|
*upm = 1;
|
|
|
|
|
|
|
|
return FT_Err_Ok;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Error
|
2002-03-30 17:41:09 +01:00
|
|
|
cff_parse_font_bbox( CFF_Parser parser )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2002-03-14 09:57:10 +01:00
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_BBox* bbox = &dict->font_bbox;
|
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
FT_Error error;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
|
2013-03-14 17:50:49 +01:00
|
|
|
error = FT_ERR( Stack_Underflow );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 4 )
|
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
bbox->xMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
|
|
|
|
bbox->yMin = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
|
|
|
|
bbox->xMax = FT_RoundFix( cff_parse_fixed( parser, data++ ) );
|
|
|
|
bbox->yMax = FT_RoundFix( cff_parse_fixed( parser, data ) );
|
2013-03-14 11:21:17 +01:00
|
|
|
error = FT_Err_Ok;
|
2011-07-29 06:15:20 +02:00
|
|
|
|
2020-07-28 07:33:40 +02:00
|
|
|
FT_TRACE4(( " [%ld %ld %ld %ld]\n",
|
2011-07-29 06:15:20 +02:00
|
|
|
bbox->xMin / 65536,
|
|
|
|
bbox->yMin / 65536,
|
|
|
|
bbox->xMax / 65536,
|
|
|
|
bbox->yMax / 65536 ));
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Error
|
2002-03-30 17:41:09 +01:00
|
|
|
cff_parse_private_dict( CFF_Parser parser )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2002-03-14 09:57:10 +01:00
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
FT_Error error;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
|
2013-03-14 17:50:49 +01:00
|
|
|
error = FT_ERR( Stack_Underflow );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 2 )
|
|
|
|
{
|
2015-02-19 14:11:16 +01:00
|
|
|
FT_Long tmp;
|
|
|
|
|
|
|
|
|
2016-12-15 12:17:22 +01:00
|
|
|
tmp = cff_parse_num( parser, data++ );
|
2015-02-19 14:11:16 +01:00
|
|
|
if ( tmp < 0 )
|
|
|
|
{
|
|
|
|
FT_ERROR(( "cff_parse_private_dict: Invalid dictionary size\n" ));
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Fail;
|
|
|
|
}
|
|
|
|
dict->private_size = (FT_ULong)tmp;
|
|
|
|
|
2016-12-15 12:17:22 +01:00
|
|
|
tmp = cff_parse_num( parser, data );
|
2015-02-19 14:11:16 +01:00
|
|
|
if ( tmp < 0 )
|
|
|
|
{
|
|
|
|
FT_ERROR(( "cff_parse_private_dict: Invalid dictionary offset\n" ));
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Fail;
|
|
|
|
}
|
|
|
|
dict->private_offset = (FT_ULong)tmp;
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
FT_TRACE4(( " %lu %lu\n",
|
|
|
|
dict->private_size, dict->private_offset ));
|
|
|
|
|
2013-03-14 11:21:17 +01:00
|
|
|
error = FT_Err_Ok;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
2015-02-19 14:11:16 +01:00
|
|
|
Fail:
|
2000-12-08 03:42:29 +01:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-15 08:48:50 +01:00
|
|
|
/* The `MultipleMaster' operator comes before any */
|
|
|
|
/* top DICT operators that contain T2 charstrings. */
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
static FT_Error
|
|
|
|
cff_parse_multiple_master( CFF_Parser parser )
|
|
|
|
{
|
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
|
|
|
FT_Error error;
|
|
|
|
|
|
|
|
|
2016-02-15 22:21:01 +01:00
|
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
|
|
/* beautify tracing message */
|
2018-08-15 18:13:17 +02:00
|
|
|
if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] < 4 )
|
2016-02-15 22:21:01 +01:00
|
|
|
FT_TRACE1(( "Multiple Master CFFs not supported yet,"
|
|
|
|
" handling first master design only\n" ));
|
|
|
|
else
|
|
|
|
FT_TRACE1(( " (not supported yet,"
|
|
|
|
" handling first master design only)\n" ));
|
|
|
|
#endif
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
error = FT_ERR( Stack_Underflow );
|
|
|
|
|
|
|
|
/* currently, we handle only the first argument */
|
|
|
|
if ( parser->top >= parser->stack + 5 )
|
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
FT_Long num_designs = cff_parse_num( parser, parser->stack );
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
if ( num_designs > 16 || num_designs < 2 )
|
|
|
|
{
|
|
|
|
FT_ERROR(( "cff_parse_multiple_master:"
|
|
|
|
" Invalid number of designs\n" ));
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dict->num_designs = (FT_UShort)num_designs;
|
2016-02-15 20:41:58 +01:00
|
|
|
dict->num_axes = (FT_UShort)( parser->top - parser->stack - 4 );
|
|
|
|
|
2016-02-14 16:03:15 +01:00
|
|
|
parser->num_designs = dict->num_designs;
|
2016-02-15 20:41:58 +01:00
|
|
|
parser->num_axes = dict->num_axes;
|
|
|
|
|
2016-02-14 16:03:15 +01:00
|
|
|
error = FT_Err_Ok;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-27 21:46:12 +02:00
|
|
|
static FT_Error
|
2002-03-30 17:41:09 +01:00
|
|
|
cff_parse_cid_ros( CFF_Parser parser )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2002-03-14 09:57:10 +01:00
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
FT_Error error;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
|
2013-03-14 17:50:49 +01:00
|
|
|
error = FT_ERR( Stack_Underflow );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
if ( parser->top >= parser->stack + 3 )
|
|
|
|
{
|
2016-12-15 12:17:22 +01:00
|
|
|
dict->cid_registry = (FT_UInt)cff_parse_num( parser, data++ );
|
|
|
|
dict->cid_ordering = (FT_UInt)cff_parse_num( parser, data++ );
|
2009-07-31 17:32:06 +02:00
|
|
|
if ( **data == 30 )
|
|
|
|
FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
|
2016-12-15 12:17:22 +01:00
|
|
|
dict->cid_supplement = cff_parse_num( parser, data );
|
2009-07-31 17:32:06 +02:00
|
|
|
if ( dict->cid_supplement < 0 )
|
2020-07-28 07:33:40 +02:00
|
|
|
FT_TRACE1(( "cff_parse_cid_ros: negative supplement %ld is found\n",
|
2009-07-31 17:32:06 +02:00
|
|
|
dict->cid_supplement ));
|
2013-03-14 11:21:17 +01:00
|
|
|
error = FT_Err_Ok;
|
2011-07-29 06:15:20 +02:00
|
|
|
|
2020-07-28 07:33:40 +02:00
|
|
|
FT_TRACE4(( " %d %d %ld\n",
|
2011-07-29 06:15:20 +02:00
|
|
|
dict->cid_registry,
|
|
|
|
dict->cid_ordering,
|
|
|
|
dict->cid_supplement ));
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
static FT_Error
|
|
|
|
cff_parse_vsindex( CFF_Parser parser )
|
|
|
|
{
|
|
|
|
/* vsindex operator can only be used in a Private DICT */
|
|
|
|
CFF_Private priv = (CFF_Private)parser->object;
|
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
CFF_Blend blend;
|
|
|
|
FT_Error error;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !priv || !priv->subfont )
|
|
|
|
{
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
blend = &priv->subfont->blend;
|
|
|
|
|
|
|
|
if ( blend->usedBV )
|
|
|
|
{
|
|
|
|
FT_ERROR(( " cff_parse_vsindex: vsindex not allowed after blend\n" ));
|
|
|
|
error = FT_THROW( Syntax_Error );
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->vsindex = (FT_UInt)cff_parse_num( parser, data++ );
|
|
|
|
|
|
|
|
FT_TRACE4(( " %d\n", priv->vsindex ));
|
|
|
|
|
|
|
|
error = FT_Err_Ok;
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error
|
|
|
|
cff_parse_blend( CFF_Parser parser )
|
|
|
|
{
|
|
|
|
/* blend operator can only be used in a Private DICT */
|
|
|
|
CFF_Private priv = (CFF_Private)parser->object;
|
|
|
|
CFF_SubFont subFont;
|
|
|
|
CFF_Blend blend;
|
|
|
|
FT_UInt numBlends;
|
|
|
|
FT_Error error;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !priv || !priv->subfont )
|
|
|
|
{
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
subFont = priv->subfont;
|
|
|
|
blend = &subFont->blend;
|
|
|
|
|
|
|
|
if ( cff_blend_check_vector( blend,
|
|
|
|
priv->vsindex,
|
|
|
|
subFont->lenNDV,
|
|
|
|
subFont->NDV ) )
|
|
|
|
{
|
|
|
|
error = cff_blend_build_vector( blend,
|
|
|
|
priv->vsindex,
|
|
|
|
subFont->lenNDV,
|
|
|
|
subFont->NDV );
|
2016-12-17 21:05:54 +01:00
|
|
|
if ( error )
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
numBlends = (FT_UInt)cff_parse_num( parser, parser->top - 1 );
|
2016-12-28 08:33:35 +01:00
|
|
|
if ( numBlends > parser->stackSize )
|
|
|
|
{
|
|
|
|
FT_ERROR(( "cff_parse_blend: Invalid number of blends\n" ));
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Exit;
|
|
|
|
}
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
|
2017-12-05 12:06:29 +01:00
|
|
|
FT_TRACE4(( " %d value%s blended\n",
|
|
|
|
numBlends,
|
|
|
|
numBlends == 1 ? "" : "s" ));
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
|
|
|
|
error = cff_blend_doBlend( subFont, parser, numBlends );
|
|
|
|
|
|
|
|
blend->usedBV = TRUE;
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
[cff] Implement CFF2 support (1/2).
This commit does not contain the blend code for font variation
support, which follows in another commit.
You should ignore whitespace while inspecting this commit.
* include/freetype/internal/tttypes.h (TT_Face): Add `isCFF2'
member.
* src/cff/cf2font.h (CF2_Font): Add `isCFF2' member.
* src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Handle `isCFF2'
flag.
(cf2_getMaxstack): New function.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c (cf2_escRESERVED_38): New enum.
(cf2_interpT2CharString): Handle CFF2 differences.
Add tracing message for errors.
* src/cff/cffdrivr.c (cff_get_glyph_name, cff_get_name_index):
Update for CFF2.
* src/cff/cffload.c (FT_FIXED_ONE): New macro.
(cff_index_init, cff_index_load_offsets, cff_index_access_element,
cff_index_get_name, cff_ft_select_get, cff_load_private_dict,
cff_subfont_load, cff_font_load): Handle CFF2.
* src/cff/cffload.h: Updated.
* src/cff/cffobjs.c (cff_face_init): Handle CFF2.
* src/cff/cffparse.c (cff_parse_maxstack): New function.
(CFFCODE_TOPDICT, CFFCODE_PRIVATE): Removed
* src/cff/cffparse.h (CFF2_MAX_STACK, CFF2_DEFAULT_STACK): New
macros.
(CFF2_CODE_TOPDICT, CFF2_CODE_FONTDICT, CFF2_CODE_PRIVATE): New
macros.
* src/cff/cfftoken.h: Add fields for CFF2 dictionaries (but no blend
stuff).
* src/cff/cfftypes.h (CFF_Index): Add `hdr_size' field.
(CFF_FontRecDict): Add `maxstack' field.
(CFF_Private): Add `subfont' field.
(CFF_Font): Add `top_dict_length' and `cff2' fields.
* src/sfnt/sfobjs.c (sfnt_load_face): Handle `CFF2' table.
2016-12-15 20:27:47 +01:00
|
|
|
/* maxstack operator increases parser and operand stacks for CFF2 */
|
|
|
|
static FT_Error
|
|
|
|
cff_parse_maxstack( CFF_Parser parser )
|
|
|
|
{
|
|
|
|
/* maxstack operator can only be used in a Top DICT */
|
|
|
|
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
|
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
FT_Error error = FT_Err_Ok;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !dict )
|
|
|
|
{
|
|
|
|
error = FT_THROW( Invalid_File_Format );
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
dict->maxstack = (FT_UInt)cff_parse_num( parser, data++ );
|
|
|
|
if ( dict->maxstack > CFF2_MAX_STACK )
|
|
|
|
dict->maxstack = CFF2_MAX_STACK;
|
|
|
|
if ( dict->maxstack < CFF2_DEFAULT_STACK )
|
|
|
|
dict->maxstack = CFF2_DEFAULT_STACK;
|
|
|
|
|
|
|
|
FT_TRACE4(( " %d\n", dict->maxstack ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#define CFF_FIELD_NUM( code, name, id ) \
|
|
|
|
CFF_FIELD( code, name, id, cff_kind_num )
|
|
|
|
#define CFF_FIELD_FIXED( code, name, id ) \
|
|
|
|
CFF_FIELD( code, name, id, cff_kind_fixed )
|
|
|
|
#define CFF_FIELD_FIXED_1000( code, name, id ) \
|
|
|
|
CFF_FIELD( code, name, id, cff_kind_fixed_thousand )
|
|
|
|
#define CFF_FIELD_STRING( code, name, id ) \
|
|
|
|
CFF_FIELD( code, name, id, cff_kind_string )
|
|
|
|
#define CFF_FIELD_BOOL( code, name, id ) \
|
|
|
|
CFF_FIELD( code, name, id, cff_kind_bool )
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
#define CFF_FIELD_DELTA( code, name, max, id ) \
|
|
|
|
CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta )
|
|
|
|
#define CFF_FIELD_DELTA_FIXED( code, name, max, id ) \
|
|
|
|
CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed )
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2011-08-24 20:50:25 +02:00
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#undef CFF_FIELD
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
#undef CFF_FIELD_DELTA_KIND
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
#ifndef FT_DEBUG_LEVEL_TRACE
|
|
|
|
|
|
|
|
|
|
|
|
#define CFF_FIELD_CALLBACK( code, name, id ) \
|
|
|
|
{ \
|
|
|
|
cff_kind_callback, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
0, 0, \
|
|
|
|
cff_parse_ ## name, \
|
|
|
|
0, 0 \
|
2000-12-08 03:42:29 +01:00
|
|
|
},
|
|
|
|
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
#define CFF_FIELD_BLEND( code, id ) \
|
|
|
|
{ \
|
|
|
|
cff_kind_blend, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
0, 0, \
|
|
|
|
cff_parse_blend, \
|
|
|
|
0, 0 \
|
|
|
|
},
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#define CFF_FIELD( code, name, id, kind ) \
|
|
|
|
{ \
|
|
|
|
kind, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
FT_FIELD_OFFSET( name ), \
|
|
|
|
FT_FIELD_SIZE( name ), \
|
2023-09-10 05:01:13 +02:00
|
|
|
NULL, 0, 0 \
|
2000-12-08 03:42:29 +01:00
|
|
|
},
|
|
|
|
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
|
|
|
|
{ \
|
|
|
|
kind, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
FT_FIELD_OFFSET( name ), \
|
|
|
|
FT_FIELD_SIZE_DELTA( name ), \
|
|
|
|
NULL, \
|
|
|
|
max, \
|
|
|
|
FT_FIELD_OFFSET( num_ ## name ) \
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
},
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
static const CFF_Field_Handler cff_field_handlers[] =
|
|
|
|
{
|
|
|
|
|
2001-03-20 12:14:24 +01:00
|
|
|
#include "cfftoken.h"
|
2000-12-08 03:42:29 +01:00
|
|
|
|
2023-09-10 05:01:13 +02:00
|
|
|
{ 0, 0, 0, 0, NULL, 0, 0 }
|
2000-12-08 03:42:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#else /* FT_DEBUG_LEVEL_TRACE */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CFF_FIELD_CALLBACK( code, name, id ) \
|
|
|
|
{ \
|
|
|
|
cff_kind_callback, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
0, 0, \
|
|
|
|
cff_parse_ ## name, \
|
|
|
|
0, 0, \
|
|
|
|
id \
|
|
|
|
},
|
|
|
|
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
#define CFF_FIELD_BLEND( code, id ) \
|
|
|
|
{ \
|
|
|
|
cff_kind_blend, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
0, 0, \
|
|
|
|
cff_parse_blend, \
|
|
|
|
0, 0, \
|
|
|
|
id \
|
|
|
|
},
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#define CFF_FIELD( code, name, id, kind ) \
|
|
|
|
{ \
|
|
|
|
kind, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
FT_FIELD_OFFSET( name ), \
|
|
|
|
FT_FIELD_SIZE( name ), \
|
2023-09-10 05:01:13 +02:00
|
|
|
NULL, 0, 0, \
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
id \
|
|
|
|
},
|
|
|
|
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
|
|
|
|
{ \
|
|
|
|
kind, \
|
|
|
|
code | CFFCODE, \
|
|
|
|
FT_FIELD_OFFSET( name ), \
|
|
|
|
FT_FIELD_SIZE_DELTA( name ), \
|
|
|
|
NULL, \
|
|
|
|
max, \
|
|
|
|
FT_FIELD_OFFSET( num_ ## name ), \
|
|
|
|
id \
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
static const CFF_Field_Handler cff_field_handlers[] =
|
|
|
|
{
|
|
|
|
|
|
|
|
#include "cfftoken.h"
|
|
|
|
|
2023-09-10 05:01:13 +02:00
|
|
|
{ 0, 0, 0, 0, NULL, 0, 0, NULL }
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* FT_DEBUG_LEVEL_TRACE */
|
|
|
|
|
|
|
|
|
2002-03-01 03:26:22 +01:00
|
|
|
FT_LOCAL_DEF( FT_Error )
|
* src/cff/cffcmap.c, src/cff/cffcmap.h, Jamfile, rules.mk: new files added
to support charmaps for CFF fonts
* src/cff/cffload.c, src/cff/cffload.h, src/cff/cffobjs.c,
src/cff/cffobjs.h, src/cff/cffparse.c, src/cffparse.h, src/cff/cffgload.c,
src/cff/cffgload.h: adding support for CFF charmaps, reformatting the
sources, and removing some bugs in the Encoding and Charset loaders
2002-07-10 18:52:06 +02:00
|
|
|
cff_parser_run( CFF_Parser parser,
|
2002-03-30 17:41:09 +01:00
|
|
|
FT_Byte* start,
|
|
|
|
FT_Byte* limit )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
2018-11-22 11:29:35 +01:00
|
|
|
FT_Byte* p = start;
|
|
|
|
FT_Error error = FT_Err_Ok;
|
|
|
|
|
2017-09-25 06:10:20 +02:00
|
|
|
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
|
|
|
|
PSAux_Service psaux;
|
|
|
|
|
2009-04-05 17:12:03 +02:00
|
|
|
FT_Library library = parser->library;
|
2018-11-22 11:29:35 +01:00
|
|
|
FT_Memory memory = library->memory;
|
|
|
|
#endif
|
2017-09-24 21:56:54 +02:00
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
parser->top = parser->stack;
|
|
|
|
parser->start = start;
|
|
|
|
parser->limit = limit;
|
|
|
|
parser->cursor = start;
|
|
|
|
|
|
|
|
while ( p < limit )
|
|
|
|
{
|
2001-06-19 10:28:24 +02:00
|
|
|
FT_UInt v = *p;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
[psaux, type1] Trace PostScript dictionaries and other things.
The tracing of /Encoding, /Subrs, and /Charstrings is rudimentary
right now.
* src/psaux/psobjs.c (ps_parser_load_field,
ps_parser_load_field_table): Add tracing calls.
* src/psaux/t1decode.c (t1_decoder_parse_charstrings): Make tracing
output more compact.
* src/type1/t1gload.c (T1_Compute_Max_Advance, T1_Get_Advances): Add
tracing messages.
* src/type1/t1load.c (parse_blend_axis_types,
parse_blend_design_positions, parse_blend_design_map,
parse_weight_vector, t1_load_keyword, t1_parse_font_matrix,
parse_encoding, parse_subrs, parse_charstrings, T1_Open_Face): Add
tracing calls.
* src/type1/t1objs.c (T1_Face_Init): Add tracing call.
* src/sfnt/sfobjs.c (sfnt_init_face): Make tracing message more
verbose.
2018-07-25 22:07:22 +02:00
|
|
|
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
/* Opcode 31 is legacy MM T2 operator, not a number. */
|
|
|
|
/* Opcode 255 is reserved and should not appear in fonts; */
|
|
|
|
/* it is used internally for CFF2 blends. */
|
|
|
|
if ( v >= 27 && v != 31 && v != 255 )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
|
|
|
/* it's a number; we will push its position on the stack */
|
2016-12-15 11:22:15 +01:00
|
|
|
if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Stack_Overflow;
|
|
|
|
|
2016-02-14 16:03:15 +01:00
|
|
|
*parser->top++ = p;
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
/* now, skip it */
|
|
|
|
if ( v == 30 )
|
|
|
|
{
|
|
|
|
/* skip real number */
|
|
|
|
p++;
|
|
|
|
for (;;)
|
|
|
|
{
|
2009-12-18 07:13:22 +01:00
|
|
|
/* An unterminated floating point number at the */
|
|
|
|
/* end of a dictionary is invalid but harmless. */
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( p >= limit )
|
2009-12-18 07:13:22 +01:00
|
|
|
goto Exit;
|
2000-12-08 03:42:29 +01:00
|
|
|
v = p[0] >> 4;
|
|
|
|
if ( v == 15 )
|
|
|
|
break;
|
|
|
|
v = p[0] & 0xF;
|
|
|
|
if ( v == 15 )
|
|
|
|
break;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( v == 28 )
|
|
|
|
p += 2;
|
|
|
|
else if ( v == 29 )
|
|
|
|
p += 4;
|
|
|
|
else if ( v > 246 )
|
|
|
|
p += 1;
|
|
|
|
}
|
2016-02-15 20:53:22 +01:00
|
|
|
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
|
2016-02-14 16:03:15 +01:00
|
|
|
else if ( v == 31 )
|
|
|
|
{
|
|
|
|
/* a Type 2 charstring */
|
|
|
|
|
|
|
|
CFF_Decoder decoder;
|
|
|
|
CFF_FontRec cff_rec;
|
|
|
|
FT_Byte* charstring_base;
|
|
|
|
FT_ULong charstring_len;
|
|
|
|
|
2023-05-08 07:22:59 +02:00
|
|
|
FT_Fixed* stack;
|
|
|
|
FT_Byte* q = NULL;
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
charstring_base = ++p;
|
|
|
|
|
|
|
|
/* search `endchar' operator */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if ( p >= limit )
|
|
|
|
goto Exit;
|
|
|
|
if ( *p == 14 )
|
|
|
|
break;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
charstring_len = (FT_ULong)( p - charstring_base ) + 1;
|
|
|
|
|
|
|
|
/* construct CFF_Decoder object */
|
2016-09-28 19:06:21 +02:00
|
|
|
FT_ZERO( &decoder );
|
|
|
|
FT_ZERO( &cff_rec );
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
cff_rec.top_font.font_dict.num_designs = parser->num_designs;
|
2016-02-15 20:41:58 +01:00
|
|
|
cff_rec.top_font.font_dict.num_axes = parser->num_axes;
|
2016-02-14 16:03:15 +01:00
|
|
|
decoder.cff = &cff_rec;
|
|
|
|
|
2017-09-30 16:36:28 +02:00
|
|
|
psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
|
2017-09-24 21:56:54 +02:00
|
|
|
if ( !psaux )
|
|
|
|
{
|
|
|
|
FT_ERROR(( "cff_parser_run: cannot access `psaux' module\n" ));
|
|
|
|
error = FT_THROW( Missing_Module );
|
|
|
|
goto Exit;
|
|
|
|
}
|
2017-09-25 06:10:20 +02:00
|
|
|
|
2017-09-30 16:36:28 +02:00
|
|
|
error = psaux->cff_decoder_funcs->parse_charstrings_old(
|
|
|
|
&decoder, charstring_base, charstring_len, 1 );
|
2018-08-14 07:54:25 +02:00
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
/* Now copy the stack data in the temporary decoder object, */
|
|
|
|
/* converting it back to charstring number representations */
|
|
|
|
/* (this is ugly, I know). */
|
2023-03-20 21:53:51 +01:00
|
|
|
/* The maximum required size is 5 bytes per stack element. */
|
2023-05-08 07:22:59 +02:00
|
|
|
if ( FT_QALLOC( q, (FT_Long)( 2 * sizeof ( FT_ListNode ) ) +
|
2023-03-20 21:53:51 +01:00
|
|
|
5 * ( decoder.top - decoder.stack ) ) )
|
2023-03-04 20:00:52 +01:00
|
|
|
goto Exit;
|
2018-11-22 11:29:35 +01:00
|
|
|
|
2023-03-20 21:53:51 +01:00
|
|
|
FT_List_Add( &parser->t2_strings, (FT_ListNode)q );
|
2018-11-22 11:29:35 +01:00
|
|
|
|
2023-03-20 21:53:51 +01:00
|
|
|
q += 2 * sizeof ( FT_ListNode );
|
2016-02-14 16:03:15 +01:00
|
|
|
|
2023-03-20 21:53:51 +01:00
|
|
|
for ( stack = decoder.stack; stack < decoder.top; stack++ )
|
2016-02-14 16:03:15 +01:00
|
|
|
{
|
2023-03-05 05:49:49 +01:00
|
|
|
FT_Long num = *stack;
|
2016-02-14 16:03:15 +01:00
|
|
|
|
|
|
|
|
2016-12-15 11:22:15 +01:00
|
|
|
if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
|
2016-02-14 16:03:15 +01:00
|
|
|
goto Stack_Overflow;
|
|
|
|
|
|
|
|
*parser->top++ = q;
|
|
|
|
|
|
|
|
if ( num & 0xFFFFU )
|
|
|
|
{
|
|
|
|
*q++ = 255;
|
2023-03-05 05:49:49 +01:00
|
|
|
*q++ = (FT_Byte)( ( num >> 24 ) & 0xFF );
|
|
|
|
*q++ = (FT_Byte)( ( num >> 16 ) & 0xFF );
|
|
|
|
*q++ = (FT_Byte)( ( num >> 8 ) & 0xFF );
|
|
|
|
*q++ = (FT_Byte)( ( num ) & 0xFF );
|
2016-02-14 16:03:15 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
num >>= 16;
|
|
|
|
|
2023-03-05 05:49:49 +01:00
|
|
|
if ( -107 <= num && num <= 107 )
|
|
|
|
*q++ = (FT_Byte)( num + 139 );
|
|
|
|
else if ( 108 <= num && num <= 1131 )
|
2016-02-14 16:03:15 +01:00
|
|
|
{
|
2023-03-05 05:49:49 +01:00
|
|
|
*q++ = (FT_Byte)( ( ( num - 108 ) >> 8 ) + 247 );
|
|
|
|
*q++ = (FT_Byte)( ( num - 108 ) & 0xFF );
|
|
|
|
}
|
|
|
|
else if ( -1131 <= num && num <= -108 )
|
|
|
|
{
|
2023-03-05 06:31:58 +01:00
|
|
|
*q++ = (FT_Byte)( ( ( -num - 108 ) >> 8 ) + 251 );
|
|
|
|
*q++ = (FT_Byte)( ( -num - 108) & 0xFF );
|
2016-02-14 16:03:15 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-03-05 05:49:49 +01:00
|
|
|
*q++ = 28;
|
|
|
|
*q++ = (FT_Byte)( num >> 8 );
|
|
|
|
*q++ = (FT_Byte)( num & 0xFF );
|
2016-02-14 16:03:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-02-15 20:53:22 +01:00
|
|
|
#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
|
2000-12-08 03:42:29 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* This is not a number, hence it's an operator. Compute its code */
|
|
|
|
/* and look for it in our current list. */
|
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
FT_UInt code;
|
2016-12-16 08:52:03 +01:00
|
|
|
FT_UInt num_args;
|
2000-12-08 03:42:29 +01:00
|
|
|
const CFF_Field_Handler* field;
|
|
|
|
|
|
|
|
|
2016-12-16 08:52:03 +01:00
|
|
|
if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
|
|
|
|
goto Stack_Overflow;
|
|
|
|
|
|
|
|
num_args = (FT_UInt)( parser->top - parser->stack );
|
2000-12-08 03:42:29 +01:00
|
|
|
*parser->top = p;
|
2016-12-16 08:52:03 +01:00
|
|
|
code = v;
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
if ( v == 12 )
|
|
|
|
{
|
|
|
|
/* two byte operator */
|
|
|
|
p++;
|
2002-09-10 01:45:29 +02:00
|
|
|
if ( p >= limit )
|
|
|
|
goto Syntax_Error;
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
code = 0x100 | p[0];
|
|
|
|
}
|
|
|
|
code = code | parser->object_code;
|
|
|
|
|
Remove FT_CONFIG_OPTION_PIC and related code.
*/* [FT_CONFIG_OPTION_PIC]: Remove all code guarded by this
preprocessor symbol.
*/*: Replace `XXX_GET' macros (which could be either a function in
PIC mode or an array in non-PIC mode) with `xxx' arrays.
* include/freetype/internal/ftpic.h, src/autofit/afpic.c,
src/autofit/afpic.h, src/base/basepic.c, src/base/basepic.h,
src/base/ftpic.c, src/cff/cffpic.c, src/cff/cffpic.h,
src/pshinter/pshpic.c, src/pshinter/pshpic.h, src/psnames/pspic.c,
src/psnames/pspic.h, src/raster/rastpic.c, src/raster/rastpic.h,
src/sfnt/sfntpic.c, src/sfnt/sfntpic.h, src/smooth/ftspic.c,
src/smooth/ftspic.h, src/truetype/ttpic.c, src/truetype/ttpic.h:
Removed.
2018-05-02 20:27:48 +02:00
|
|
|
for ( field = cff_field_handlers; field->kind; field++ )
|
2000-12-08 03:42:29 +01:00
|
|
|
{
|
|
|
|
if ( field->code == (FT_Int)code )
|
|
|
|
{
|
|
|
|
/* we found our field's handler; read it */
|
|
|
|
FT_Long val;
|
|
|
|
FT_Byte* q = (FT_Byte*)parser->object + field->offset;
|
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
|
|
FT_TRACE4(( " %s", field->id ));
|
|
|
|
#endif
|
|
|
|
|
2002-09-10 01:45:29 +02:00
|
|
|
/* check that we have enough arguments -- except for */
|
|
|
|
/* delta encoded arrays, which can be empty */
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
if ( field->kind != cff_kind_delta &&
|
|
|
|
field->kind != cff_kind_delta_fixed && num_args < 1 )
|
2002-09-10 01:45:29 +02:00
|
|
|
goto Stack_Underflow;
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
switch ( field->kind )
|
|
|
|
{
|
|
|
|
case cff_kind_bool:
|
|
|
|
case cff_kind_string:
|
|
|
|
case cff_kind_num:
|
2016-12-15 12:17:22 +01:00
|
|
|
val = cff_parse_num( parser, parser->stack );
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Store_Number;
|
|
|
|
|
|
|
|
case cff_kind_fixed:
|
2016-12-15 12:17:22 +01:00
|
|
|
val = cff_parse_fixed( parser, parser->stack );
|
2003-06-06 07:07:53 +02:00
|
|
|
goto Store_Number;
|
|
|
|
|
|
|
|
case cff_kind_fixed_thousand:
|
2016-12-15 12:17:22 +01:00
|
|
|
val = cff_parse_fixed_scaled( parser, parser->stack, 3 );
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
Store_Number:
|
|
|
|
switch ( field->size )
|
|
|
|
{
|
2004-04-24 08:06:39 +02:00
|
|
|
case (8 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Byte*)q = (FT_Byte)val;
|
|
|
|
break;
|
|
|
|
|
2004-04-24 08:06:39 +02:00
|
|
|
case (16 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Short*)q = (FT_Short)val;
|
|
|
|
break;
|
|
|
|
|
2004-04-24 08:06:39 +02:00
|
|
|
case (32 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Int32*)q = (FT_Int)val;
|
|
|
|
break;
|
|
|
|
|
2004-04-24 08:06:39 +02:00
|
|
|
default: /* for 64-bit systems */
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Long*)q = val;
|
|
|
|
}
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
|
|
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
|
|
|
switch ( field->kind )
|
|
|
|
{
|
|
|
|
case cff_kind_bool:
|
|
|
|
FT_TRACE4(( " %s\n", val ? "true" : "false" ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cff_kind_string:
|
2011-09-26 08:59:21 +02:00
|
|
|
FT_TRACE4(( " %ld (SID)\n", val ));
|
|
|
|
break;
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
case cff_kind_num:
|
|
|
|
FT_TRACE4(( " %ld\n", val ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cff_kind_fixed:
|
|
|
|
FT_TRACE4(( " %f\n", (double)val / 65536 ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cff_kind_fixed_thousand:
|
|
|
|
FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 ));
|
2021-05-29 09:50:29 +02:00
|
|
|
break;
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
; /* never reached */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case cff_kind_delta:
|
|
|
|
{
|
|
|
|
FT_Byte* qcount = (FT_Byte*)parser->object +
|
|
|
|
field->count_offset;
|
|
|
|
|
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
|
|
|
|
|
|
|
|
if ( num_args > field->array_max )
|
|
|
|
num_args = field->array_max;
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
FT_TRACE4(( " [" ));
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
/* store count */
|
|
|
|
*qcount = (FT_Byte)num_args;
|
|
|
|
|
|
|
|
val = 0;
|
|
|
|
while ( num_args > 0 )
|
|
|
|
{
|
2017-06-09 11:21:58 +02:00
|
|
|
val = ADD_LONG( val, cff_parse_num( parser, data++ ) );
|
2000-12-08 03:42:29 +01:00
|
|
|
switch ( field->size )
|
|
|
|
{
|
2004-04-24 08:06:39 +02:00
|
|
|
case (8 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Byte*)q = (FT_Byte)val;
|
|
|
|
break;
|
|
|
|
|
2004-04-24 08:06:39 +02:00
|
|
|
case (16 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Short*)q = (FT_Short)val;
|
|
|
|
break;
|
|
|
|
|
2004-04-24 08:06:39 +02:00
|
|
|
case (32 / FT_CHAR_BIT):
|
2000-12-08 03:42:29 +01:00
|
|
|
*(FT_Int32*)q = (FT_Int)val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* for 64-bit systems */
|
|
|
|
*(FT_Long*)q = val;
|
|
|
|
}
|
|
|
|
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
FT_TRACE4(( " %ld", val ));
|
|
|
|
|
2000-12-08 03:42:29 +01:00
|
|
|
q += field->size;
|
[CFF] Extract `BlueValues` as `Fixed` rather than `Int`.
This is a follow-up to commit 26a7f047,
[cff] Make blend operator work with floats in private dicts.
which addressed the 'party baseline' bug. However, the reporting user
indicated that the default location and some other points in design space
rendered OK, but other points in design space still had problems. The most
obvious issue being that the x-heights of lower-case letters did not align;
see
https://github.com/adobe-fonts/source-serif/issues/121#issuecomment-1773794136
After some analysis we determined that this was due to an interaction
between `BlueValue` rounding and the zone-based algorithm. In short, for a
point to be considered in a zone it must fall within the bounds of the zone.
(There is a slop factor in some cases, but only a very small one.) In the
Adobe-contributed side of the code, point values are not integer-rounded,
instead they're kept as (some form of) fixed. Rounding just the `BlueValues`
means that points that need to be considered within a zone will fall outside
of it at some points in design space.
The majority of this patch changes the storage and parsing of `BlueValues`
to keep them as `FT_Fixed`. No significant code changes were needed because
the values are converted to `Fixed` anyway when stored in `CF_BlueRec`. No
attempt was made to address problems in the older pshinter code beyond
converting the values from `FT_Fixed` to `FT_Short` when copying the private
dictionary. (However, as the point values are also rounded in that code,
the problem is much less likely to occur, although inconsistency between
rounding and truncation could cause an analogous problem.)
* include/freetype/internal/cfftypes.h (CFF_PrivateRec): Use `FT_Fixed` for
`blue_values`, `other_blues`, `family_blues`, and `family_other_blues`.
* src/cff/cffload.c (cff_blend_doBlend): Updated.
* src/cff/cffobjs.c (CFF_fixedToInt): New macro.
(cff_make_private_dict): Use it.
* src/cff/cffparse.h (cff_kind_delta_fixed): New enum value.
* src/cff/cffparse.c (do_fixed): Updated.
(CFF_FIELD_DELTA, CFF_FIELD_DELTA_FIXED, CFF_DELTA_KIND): New set of macros,
replacing `CFF_FIELD_DELTA`.
(cff_parser_run): Updated to handle fixed-float deltas.
* src/cff/cfftoken.h: Updated to use `CFF_FIELD_DELTA_FIXED` for blue
values.
* src/psaux/psblues.c (cf2_blueToFixed): Removed, no longer needed.
(cf2_blues_init): Updated.
* src/pxaux/psft.c, src/pxaux/psft.h (cf2_getBlueValues, cf2_getOtherBlues,
cf2_getFamilyBlues, cf2_getFamilyOtherBlues): Updated signatures.
* src/psaux/psobjs.c (t1_make_subfont): Updated.
2023-12-14 06:59:05 +01:00
|
|
|
num_args--;
|
|
|
|
}
|
|
|
|
|
|
|
|
FT_TRACE4(( "]\n" ));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case cff_kind_delta_fixed:
|
|
|
|
{
|
|
|
|
FT_Byte* qcount = (FT_Byte*)parser->object +
|
|
|
|
field->count_offset;
|
|
|
|
|
|
|
|
FT_Byte** data = parser->stack;
|
|
|
|
|
|
|
|
|
|
|
|
if ( num_args > field->array_max )
|
|
|
|
num_args = field->array_max;
|
|
|
|
|
|
|
|
FT_TRACE4(( " [" ));
|
|
|
|
|
|
|
|
/* store count */
|
|
|
|
*qcount = (FT_Byte)num_args;
|
|
|
|
|
|
|
|
val = 0;
|
|
|
|
while ( num_args > 0 )
|
|
|
|
{
|
|
|
|
val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) );
|
|
|
|
*(FT_Long*)q = val;
|
|
|
|
|
|
|
|
FT_TRACE4(( " %f\n", (double)val / 65536 ));
|
|
|
|
|
|
|
|
q += field->size;
|
2000-12-08 03:42:29 +01:00
|
|
|
num_args--;
|
|
|
|
}
|
[cff] Better tracing of the parsing process.
* src/cff/cffload.c (cff_subfont_load, cff_font_load): Decorate with
FT_TRACE.
* src/cff/cffparse.c (cff_parse_font_matrix, cff_parse_font_bbox,
cff_parse_private_dict, cff_parse_cid_ros): Updated.
(CFF_FIELD_NUM, CFF_FIELD_FIXED, CFF_FIELD_FIXED_1000,
CFF_FIELD_STRING, CFF_FIELD_BOOL, CFF_FIELD_CALLBACK, CFF_FIELD,
CFF_FIELD_DELTA): Add argument for ID.
(cff_parser_run): Decorate with FT_TRACE.
* src/cff/cffparse.h (CFF_Field_Handler) [FT_DEBUG_LEVEL_TRACE]: Add
`id' member.
* src/cff/cfftoken.h: Add IDs to all fields.
2011-08-25 13:41:16 +02:00
|
|
|
|
|
|
|
FT_TRACE4(( "]\n" ));
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
default: /* callback or blend */
|
2000-12-08 03:42:29 +01:00
|
|
|
error = field->reader( parser );
|
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
goto Found;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this is an unknown operator, or it is unsupported; */
|
|
|
|
/* we will ignore it for now. */
|
|
|
|
|
|
|
|
Found:
|
|
|
|
/* clear stack */
|
[cff] Implement CFF2 support (2/2).
The font variation code. All parts dependent on the GX code in the
`truetype' module are guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
In other words, you can still compile the `cff' module without
defining TT_CONFIG_OPTION_GX_VAR_SUPPORT (which brings you CFF2
support without font variation).
* src/cff/cf2font.c (cf2_font_setup): Add support for font
variation.
* src/cff/cf2font.h (CF2_Font): Add fields for variation data.
* src/cff/cf2ft.c (cf2_free_instance): Free blend data.
(cf2_getVStore, cf2_getNormalizedVector): New functions.
* src/cff/cf2ft.h: Updated.
* src/cff/cf2intrp.c: Include `cffload.h'.
(cf2_cmdRESERVED_15, cf2_cmdRESERVED_16): Replace with...
(cf2_cmdVSINDEX, cf2_cmdBLEND): ... this new enum values.
(cf2_doBlend): New function.
(cf2_interpT2CharString): Handle `vsindex' and `blend' opcodes.
* src/cff/cffload.c (FT_fdot14ToFixed): New macro.
(cff_vstore_done, cff_vstore_load): New functions.
(cff_blend_clear, cff_blend_doBlend, cff_blend_build_vector,
cff_blend_check_vector): New functions.
(cff_load_private_dict): Add arguments for blend vector.
Handle blend data.
(cff_subfont_load, cff_subfont_done): Updated.
(cff_font_load): Handle CFF2 variation store data.
(cff_font_done): Updated.
* src/cff/cffload.h: Include `cffparse.h'.
Updated.
* src/cff/cffobjs.c (cff_face_done): Updated.
* src/cff/cffparse.c: Include `cffload.h'.
(cff_parse_num): Handle internal value 255.
(cff_parse_vsindex, cff_parse_blend): New functions.
(CFF_FIELD_BLEND): New macro.
(cff_parser_run): Updated.
* src/cff/cffparse.h (cff_kind_blend): New enum value.
* src/cff/cfftoken.h: Handle `vstore', `vsindex', and `blend'
dictionary values.
* src/cff/cfftypes.h (CFF_VarData, CFF_AxisCoords, CFF_VarRegion,
CFF_VStore, CFF_Blend): New structures.
(CFF_FontRecDict): Add `vstore_offset' field.
(CFF_Private): Add `vsindex' field.
(CFF_SubFont): Add fields for blend data.
(CFF_Font): Add `vstore' field.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): `CFF2' is equal to `gvar',
since glyph variation data is directly embedded.
(TT_Set_MM_Blend): Don't load `gvar' table for CFF2 fonts.
2016-12-15 21:56:44 +01:00
|
|
|
/* TODO: could clear blend stack here, */
|
|
|
|
/* but we don't have access to subFont */
|
|
|
|
if ( field->kind != cff_kind_blend )
|
|
|
|
parser->top = parser->stack;
|
2000-12-08 03:42:29 +01:00
|
|
|
}
|
|
|
|
p++;
|
2018-11-22 11:29:35 +01:00
|
|
|
} /* while ( p < limit ) */
|
2000-12-08 03:42:29 +01:00
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
|
|
|
|
Stack_Overflow:
|
2013-03-14 10:27:35 +01:00
|
|
|
error = FT_THROW( Invalid_Argument );
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
Stack_Underflow:
|
2013-03-14 10:27:35 +01:00
|
|
|
error = FT_THROW( Invalid_Argument );
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
Syntax_Error:
|
2013-03-14 10:27:35 +01:00
|
|
|
error = FT_THROW( Invalid_Argument );
|
2000-12-08 03:42:29 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* END */
|