summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/psaux/t1decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/psaux/t1decode.c')
-rw-r--r--src/3rdparty/freetype/src/psaux/t1decode.c246
1 files changed, 197 insertions, 49 deletions
diff --git a/src/3rdparty/freetype/src/psaux/t1decode.c b/src/3rdparty/freetype/src/psaux/t1decode.c
index c2b3729b53..4b6b969bcb 100644
--- a/src/3rdparty/freetype/src/psaux/t1decode.c
+++ b/src/3rdparty/freetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (body).
*
- * Copyright (C) 2000-2019 by
+ * Copyright (C) 2000-2023 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -16,20 +16,22 @@
*/
-#include <ft2build.h>
-#include FT_INTERNAL_CALC_H
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
-#include FT_INTERNAL_HASH_H
-#include FT_OUTLINE_H
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/pshints.h>
+#include <freetype/internal/fthash.h>
+#include <freetype/ftoutln.h>
#include "t1decode.h"
#include "psobjs.h"
#include "psauxerr.h"
+
/* ensure proper sign extension */
-#define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) )
+#define Fix2Int( f ) ( (FT_Int) (FT_Short)( (f) >> 16 ) )
+#define Fix2UInt( f ) ( (FT_UInt)(FT_Short)( (f) >> 16 ) )
+
/**************************************************************************
*
@@ -367,6 +369,12 @@
FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+ /* save the left bearing and width of the SEAC */
+ /* glyph as they will be erased by the next load */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
/* the seac operator must not be nested */
decoder->seac = TRUE;
error = t1_decoder_parse_glyph( decoder, (FT_UInt)bchar_index );
@@ -374,11 +382,14 @@
if ( error )
goto Exit;
- /* save the left bearing and width of the base character */
- /* as they will be erased by the next load. */
+ /* If the SEAC glyph doesn't have a (H)SBW of its */
+ /* own use the values from the base glyph. */
- left_bearing = decoder->builder.left_bearing;
- advance = decoder->builder.advance;
+ if ( decoder->builder.parse_state != T1_Parse_Have_Width )
+ {
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+ }
decoder->builder.left_bearing.x = 0;
decoder->builder.left_bearing.y = 0;
@@ -396,8 +407,8 @@
if ( error )
goto Exit;
- /* restore the left side bearing and */
- /* advance width of the base character */
+ /* restore the left side bearing and advance width */
+ /* of the SEAC glyph or base character (saved above) */
decoder->builder.left_bearing = left_bearing;
decoder->builder.advance = advance;
@@ -509,7 +520,7 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( bol )
{
- FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
+ FT_TRACE5(( " (%td)", decoder->top - decoder->stack ));
bol = FALSE;
}
#endif
@@ -650,10 +661,8 @@
if ( value > 32000 || value < -32000 )
{
if ( large_int )
- {
FT_ERROR(( "t1_decoder_parse_charstrings:"
" no `div' after large integer\n" ));
- }
else
large_int = TRUE;
}
@@ -1019,16 +1028,16 @@
/* <val> <idx> 2 24 callothersubr */
/* ==> set BuildCharArray[cvi( <idx> )] = <val> */
{
- FT_Int idx;
+ FT_UInt idx;
PS_Blend blend = decoder->blend;
if ( arg_cnt != 2 || !blend )
goto Unexpected_OtherSubr;
- idx = Fix2Int( top[1] );
+ idx = Fix2UInt( top[1] );
- if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ if ( idx >= decoder->len_buildchar )
goto Unexpected_OtherSubr;
decoder->buildchar[idx] = top[0];
@@ -1040,16 +1049,16 @@
/* ==> push BuildCharArray[cvi( idx )] */
/* onto T1 stack */
{
- FT_Int idx;
+ FT_UInt idx;
PS_Blend blend = decoder->blend;
if ( arg_cnt != 1 || !blend )
goto Unexpected_OtherSubr;
- idx = Fix2Int( top[0] );
+ idx = Fix2UInt( top[0] );
- if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+ if ( idx >= decoder->len_buildchar )
goto Unexpected_OtherSubr;
top[0] = decoder->buildchar[idx];
@@ -1156,9 +1165,9 @@
if ( top - decoder->stack != num_args )
FT_TRACE0(( "t1_decoder_parse_charstrings:"
" too much operands on the stack"
- " (seen %d, expected %d)\n",
+ " (seen %td, expected %d)\n",
top - decoder->stack, num_args ));
- break;
+ break;
}
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1203,7 +1212,7 @@
FT_TRACE4(( "BuildCharArray = [ " ));
for ( i = 0; i < decoder->len_buildchar; i++ )
- FT_TRACE4(( "%d ", decoder->buildchar[i] ));
+ FT_TRACE4(( "%ld ", decoder->buildchar[i] ));
FT_TRACE4(( "]\n" ));
}
@@ -1231,8 +1240,8 @@
FT_UNUSED( orig_y );
- /* the `metrics_only' indicates that we only want to compute */
- /* the glyph's metrics (lsb + advance width), not load the */
+ /* `metrics_only' indicates that we only want to compute the */
+ /* glyph's metrics (lsb + advance width) without loading the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
{
@@ -1266,8 +1275,8 @@
x = ADD_LONG( builder->pos_x, top[0] );
y = ADD_LONG( builder->pos_y, top[1] );
- /* the `metrics_only' indicates that we only want to compute */
- /* the glyph's metrics (lsb + advance width), not load the */
+ /* `metrics_only' indicates that we only want to compute the */
+ /* glyph's metrics (lsb + advance width) without loading the */
/* rest of it; so exit immediately */
if ( builder->metrics_only )
{
@@ -1644,7 +1653,8 @@
} /* while ip < limit */
- FT_TRACE4(( "..end..\n\n" ));
+ FT_TRACE4(( "..end..\n" ));
+ FT_TRACE4(( "\n" ));
Fail:
return error;
@@ -1690,6 +1700,7 @@
FT_Byte* ip;
FT_Byte* limit;
T1_Builder builder = &decoder->builder;
+ FT_Bool large_int;
#ifdef FT_DEBUG_LEVEL_TRACE
FT_Bool bol = TRUE;
@@ -1707,6 +1718,8 @@
limit = zone->limit = charstring_base + charstring_len;
ip = zone->cursor = zone->base;
+ large_int = FALSE;
+
/* now, execute loop */
while ( ip < limit )
{
@@ -1718,7 +1731,7 @@
#ifdef FT_DEBUG_LEVEL_TRACE
if ( bol )
{
- FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
+ FT_TRACE5(( " (%ld)", decoder->top - decoder->stack ));
bol = FALSE;
}
#endif
@@ -1740,8 +1753,6 @@
case 7:
case 8:
case 9:
- case 10:
- case 11:
case 14:
case 15:
case 21:
@@ -1750,6 +1761,13 @@
case 31:
goto No_Width;
+ case 10:
+ op = op_callsubr;
+ break;
+ case 11:
+ op = op_return;
+ break;
+
case 13:
op = op_hsbw;
break;
@@ -1767,6 +1785,9 @@
case 7:
op = op_sbw;
break;
+ case 12:
+ op = op_div;
+ break;
default:
goto No_Width;
@@ -1796,13 +1817,19 @@
/* anyway. */
if ( value > 32000 || value < -32000 )
{
- FT_ERROR(( "t1_decoder_parse_metrics:"
- " large integer found for width\n" ));
- goto Syntax_Error;
+ if ( large_int )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " no `div' after large integer\n" ));
+ goto Syntax_Error;
+ }
+ else
+ large_int = TRUE;
}
else
{
- value = (FT_Int32)( (FT_UInt32)value << 16 );
+ if ( !large_int )
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
}
break;
@@ -1827,7 +1854,8 @@
value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
}
- value = (FT_Int32)( (FT_UInt32)value << 16 );
+ if ( !large_int )
+ value = (FT_Int32)( (FT_UInt32)value << 16 );
}
else
{
@@ -1837,6 +1865,13 @@
}
}
+ if ( large_int && !( op == op_none || op == op_div ) )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " no `div' after large integer\n" ));
+ goto Syntax_Error;
+ }
+
/**********************************************************************
*
* Push value on stack, or process operator
@@ -1851,6 +1886,9 @@
}
#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( large_int )
+ FT_TRACE4(( " %d", value ));
+ else
FT_TRACE4(( " %d", value / 65536 ));
#endif
@@ -1869,11 +1907,21 @@
#ifdef FT_DEBUG_LEVEL_TRACE
- if ( top - decoder->stack != num_args )
- FT_TRACE0(( "t1_decoder_parse_metrics:"
- " too much operands on the stack"
- " (seen %d, expected %d)\n",
- top - decoder->stack, num_args ));
+ switch ( op )
+ {
+ case op_callsubr:
+ case op_div:
+ case op_return:
+ break;
+
+ default:
+ if ( top - decoder->stack != num_args )
+ FT_TRACE0(( "t1_decoder_parse_metrics:"
+ " too much operands on the stack"
+ " (seen %ld, expected %d)\n",
+ top - decoder->stack, num_args ));
+ break;
+ }
#endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1893,8 +1941,8 @@
builder->advance.y = 0;
/* we only want to compute the glyph's metrics */
- /* (lsb + advance width), not load the rest of */
- /* it; so exit immediately */
+ /* (lsb + advance width) without loading the */
+ /* rest of it; so exit immediately */
FT_TRACE4(( "\n" ));
return FT_Err_Ok;
@@ -1912,22 +1960,122 @@
builder->advance.y = top[3];
/* we only want to compute the glyph's metrics */
- /* (lsb + advance width), not load the rest of */
- /* it; so exit immediately */
+ /* (lsb + advance width), without loading the */
+ /* rest of it; so exit immediately */
FT_TRACE4(( "\n" ));
return FT_Err_Ok;
+ case op_div:
+ FT_TRACE4(( " div" ));
+
+ /* if `large_int' is set, we divide unscaled numbers; */
+ /* otherwise, we divide numbers in 16.16 format -- */
+ /* in both cases, it is the same operation */
+ *top = FT_DivFix( top[0], top[1] );
+ top++;
+
+ large_int = FALSE;
+ break;
+
+ case op_callsubr:
+ {
+ FT_Int idx;
+
+
+ FT_TRACE4(( " callsubr" ));
+
+ idx = Fix2Int( top[0] );
+
+ if ( decoder->subrs_hash )
+ {
+ size_t* val = ft_hash_num_lookup( idx,
+ decoder->subrs_hash );
+
+
+ if ( val )
+ idx = *val;
+ else
+ idx = -1;
+ }
+
+ if ( idx < 0 || idx >= decoder->num_subrs )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+
+ /* The Type 1 driver stores subroutines without the seed bytes. */
+ /* The CID driver stores subroutines with seed bytes. This */
+ /* case is taken care of when decoder->subrs_len == 0. */
+ zone->base = decoder->subrs[idx];
+
+ if ( decoder->subrs_len )
+ zone->limit = zone->base + decoder->subrs_len[idx];
+ else
+ {
+ /* We are using subroutines from a CID font. We must adjust */
+ /* for the seed bytes. */
+ zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
+ zone->limit = decoder->subrs[idx + 1];
+ }
+
+ zone->cursor = zone->base;
+
+ if ( !zone->base )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " invoking empty subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ break;
+ }
+
+ case op_return:
+ FT_TRACE4(( " return" ));
+
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "t1_decoder_parse_metrics:"
+ " unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+ break;
+
default:
FT_ERROR(( "t1_decoder_parse_metrics:"
" unhandled opcode %d\n", op ));
goto Syntax_Error;
}
+ decoder->top = top;
+
} /* general operator processing */
} /* while ip < limit */
- FT_TRACE4(( "..end..\n\n" ));
+ FT_TRACE4(( "..end..\n" ));
+ FT_TRACE4(( "\n" ));
No_Width:
FT_ERROR(( "t1_decoder_parse_metrics:"