From e484fae8e1d0fad632bd9bdfdf1ef0b194d21572 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 27 Oct 2023 21:44:12 -0400 Subject: [PATCH] LibPDF: Don't do special subr processing for type 2 CFFs This is a subset of #21484: Type 2 CFFs never use the special subrs, so stop doing them for type 2 at least for now. Fixes an assert in 0000064.pdf in 0000.zip in the pdfa dataset (a stack underflow because a subr is supposed to push a bunch of stuff, but instead it ran one of the built-in routines instead of the subr from the font file). As discussed in #21484, this isn't right for type 1 CFFs either, but just removing the code there regresses Tests/LibPDF/type1.pdf. A slightly more involved thing is needed there; I added a FIXME for that here. --- .../LibPDF/Fonts/Type1FontProgram.cpp | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp index 04bc7d17d5..cf1902ea48 100644 --- a/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp +++ b/Userland/Libraries/LibPDF/Fonts/Type1FontProgram.cpp @@ -397,37 +397,47 @@ PDFErrorOr Type1FontProgram::parse_glyph(ReadonlyBytes if (static_cast(subr_number) >= subroutines.size()) return error("Subroutine index out of range"); - // Subroutines 0-2 handle the flex feature. - if (subr_number == 0) { - if (state.flex_index != 14) + if (!is_type2) { + // FIXME: Hardcoding subrs 0-2 here is incorrect, since some fonts don't use the flex feature. + // For the ones that do, subrs 0-2 have fixed contents that have callothersubr instructions. + // The right thing to do is to implement callothersubr for subrs 0-3 and remove the hardcoding here. + + // Subroutines 0-2 handle the flex feature. + if (subr_number == 0) { + if (state.flex_index != 14) + break; + + auto& flex = state.flex_sequence; + + path.cubic_bezier_curve_to( + { flex[2], flex[3] }, + { flex[4], flex[5] }, + { flex[6], flex[7] }); + path.cubic_bezier_curve_to( + { flex[8], flex[9] }, + { flex[10], flex[11] }, + { flex[12], flex[13] }); + + state.flex_feature = false; + state.sp = 0; break; - - auto& flex = state.flex_sequence; - - path.cubic_bezier_curve_to( - { flex[2], flex[3] }, - { flex[4], flex[5] }, - { flex[6], flex[7] }); - path.cubic_bezier_curve_to( - { flex[8], flex[9] }, - { flex[10], flex[11] }, - { flex[12], flex[13] }); - - state.flex_feature = false; - state.sp = 0; - } else if (subr_number == 1) { - state.flex_feature = true; - state.flex_index = 0; - state.sp = 0; - } else if (subr_number == 2) { - state.sp = 0; - } else { - auto const& subr = subroutines[subr_number]; - if (subr.is_empty()) - return error("Empty subroutine"); - - TRY(parse_glyph(subr, local_subroutines, global_subroutines, state, is_type2)); + } + if (subr_number == 1) { + state.flex_feature = true; + state.flex_index = 0; + state.sp = 0; + break; + } + if (subr_number == 2) { + state.sp = 0; + break; + } } + auto const& subr = subroutines[subr_number]; + if (subr.is_empty()) + return error("Empty subroutine"); + + TRY(parse_glyph(subr, local_subroutines, global_subroutines, state, is_type2)); break; }