Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ from Tavmjong Bah. For further information, contact: tavmjong @ free

The GUST font license applies to the following fonts:
- fonts/LatinModernRoman-Regular.otf
- fonts/EndcharInSubroutine_1.otf (derived from LatinModernRoman-Regular.otf)
- fonts/NewCMMath-Regular.otf

% This is version 1.0, dated 22 June 2009, of the GUST Font License.
Expand Down
Binary file added fonts/EndcharInSubroutine.otf
Binary file not shown.
29 changes: 22 additions & 7 deletions src/cff/charstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ pub struct Decompiler<'a> {
hint_mask_bytes: u16,
}

enum CharStringEnd {
Return,
EndChar,
}

impl<'a> Decompiler<'a> {
/// Create a new charstring decompiler.
pub fn new(
Expand Down Expand Up @@ -48,7 +53,7 @@ impl<'a> Decompiler<'a> {
charstring: CharString<'a>,
program: &mut Program<'a>,
depth: u8,
) -> Result<()> {
) -> Result<CharStringEnd> {
if depth > 64 {
return Err(CFFError);
}
Expand Down Expand Up @@ -94,9 +99,7 @@ impl<'a> Decompiler<'a> {
self.stack.pop_all();
program.push(Instruction::Operator(operator));
}
RETURN => {
// Don't do anything for return, since we desubroutinize.
}
RETURN => return Ok(CharStringEnd::Return),
CALL_GLOBAL_SUBROUTINE => {
// Pop the subroutine index from the program.
program.0.pop();
Expand All @@ -107,7 +110,12 @@ impl<'a> Decompiler<'a> {
.gsubr_handler
.get_with_biased(biased_index)
.ok_or(CFFError)?;
self.decompile_inner(gsubr, program, depth + 1)?;
if matches!(
self.decompile_inner(gsubr, program, depth + 1)?,
CharStringEnd::EndChar
) {
return Ok(CharStringEnd::EndChar);
}
}
CALL_LOCAL_SUBROUTINE => {
// Pop the subroutine index from the program.
Expand All @@ -119,7 +127,12 @@ impl<'a> Decompiler<'a> {
.lsubr_handler
.get_with_biased(biased_index)
.ok_or(CFFError)?;
self.decompile_inner(lsubr, program, depth + 1)?;
if matches!(
self.decompile_inner(lsubr, program, depth + 1)?,
CharStringEnd::EndChar
) {
return Ok(CharStringEnd::EndChar);
}
}
HINT_MASK | COUNTER_MASK => {
program.push(Instruction::Operator(operator));
Expand All @@ -141,14 +154,16 @@ impl<'a> Decompiler<'a> {
}

program.push(Instruction::Operator(operator));

return Ok(CharStringEnd::EndChar);
}
_ => {
return Err(CFFError);
}
}
}

Ok(())
Ok(CharStringEnd::Return)
}

fn count_hints(&mut self) {
Expand Down
1 change: 1 addition & 0 deletions tests/data/fonttools.tests
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ NotoSans-Regular.ttf;567-570,2345-2350
Roboto-Regular.ttf;456,460-463
NewCMMath-Regular.otf;803-806,950-952,5600-5602
NotoSansCJKsc-Bold-subset1.otf;1
EndcharInSubroutine.otf;1
NotoSans-Regular_var.ttf;10,40,58,201-205;wght=400
NotoSans-Regular_var.ttf;10,40,58,201-205;wght=900
NotoSans-Regular_var.ttf;10,40,58,201-205;wght=800,wdth=70.0
Expand Down
1 change: 1 addition & 0 deletions tests/src/font_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::*;
#[test] fn roboto_regular_1() {test_font_tools("Roboto-Regular.ttf", "456,460-463", "", 1)}
#[test] fn new_c_m_math_regular_1() {test_font_tools("NewCMMath-Regular.otf", "803-806,950-952,5600-5602", "", 1)}
#[test] fn noto_sans_c_j_ksc_boldsubset1_1() {test_font_tools("NotoSansCJKsc-Bold-subset1.otf", "1", "", 1)}
#[test] fn endchar_in_subroutine_1() {test_font_tools("EndcharInSubroutine.otf", "1", "", 1)}
#[test] #[cfg(feature = "variable-fonts")] fn noto_sans_regular_var_1() {test_font_tools("NotoSans-Regular_var.ttf", "10,40,58,201-205", "wght=400", 1)}
#[test] #[cfg(feature = "variable-fonts")] fn noto_sans_regular_var_2() {test_font_tools("NotoSans-Regular_var.ttf", "10,40,58,201-205", "wght=900", 2)}
#[test] #[cfg(feature = "variable-fonts")] fn noto_sans_regular_var_3() {test_font_tools("NotoSans-Regular_var.ttf", "10,40,58,201-205", "wght=800,wdth=70.0", 3)}
Expand Down
154 changes: 154 additions & 0 deletions tests/ttx/EndcharInSubroutine_1.ttx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.62">

<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="cid00001"/>
</GlyphOrder>

<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.004"/>
<checkSumAdjustment value="0x59e8be78"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Oct 8 09:58:12 2009"/>
<modified value="Fri May 1 12:01:06 2026"/>
<xMin value="-430"/>
<yMin value="-290"/>
<xMax value="1417"/>
<yMax value="1127"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>

<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1127"/>
<descent value="-290"/>
<lineGap value="0"/>
<advanceWidthMax value="1457"/>
<minLeftSideBearing value="-430"/>
<minRightSideBearing value="-260"/>
<xMaxExtent value="1417"/>
<caretSlopeRise value="1"/>
<caretSlopeRun value="0"/>
<caretOffset value="0"/>
<reserved0 value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<metricDataFormat value="0"/>
<numberOfHMetrics value="2"/>
</hhea>

<maxp>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>

<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
Copyright 2003, 2009 B. Jackowski and J. M. Nowacki (on behalf of TeX users groups). This work is released under the GUST Font License -- see http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt for details.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
LM Roman 10
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
2.004;UKWN;LMRoman10-Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
LMRoman10-Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.004;PS 2.004;hotconv 1.0.49;makeotf.lib2.0.14853
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
LMRoman10-Regular
</namerecord>
</name>

<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-126"/>
<underlineThickness value="40"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>

<CFF>
<major value="1"/>
<minor value="0"/>
<CFFFont name="LMRoman10-Regular">
<ROS Registry="Adobe" Order="Identity" Supplement="0"/>
<Notice value="Copyright 2003, 2009 B. Jackowski and J. M. Nowacki (on behalf of TeX users groups). This work is released under the GUST Font License -- see http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt for details."/>
<isFixedPitch value="0"/>
<ItalicAngle value="0"/>
<UnderlinePosition value="-100"/>
<UnderlineThickness value="50"/>
<PaintType value="0"/>
<CharstringType value="2"/>
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FontBBox value="-430 -290 1417 1127"/>
<StrokeWidth value="0"/>
<CIDFontVersion value="0"/>
<CIDFontRevision value="0"/>
<CIDFontType value="0"/>
<CIDCount value="65535"/>
<!-- charset is dumped separately as the 'GlyphOrder' element -->
<FDSelect format="3"/>
<FDArray>
<FontDict index="0">
<FontMatrix value="1 0 0 1 0 0"/>
<Private>
<BlueValues value="-22 0 431 448 666 677 683 705"/>
<BlueScale value="0.04546"/>
<BlueShift value="7"/>
<BlueFuzz value="0"/>
<StdHW value="31"/>
<StdVW value="69"/>
<StemSnapH value="22 23 25 26 28 30 31 38 40 42 45 106"/>
<StemSnapV value="25 66 69 75 77 83 86 89 92 97 103 107"/>
<ForceBold value="0"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
<initialRandomSeed value="0"/>
<defaultWidthX value="0"/>
<nominalWidthX value="0"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef" fdSelectIndex="0">
280 endchar
</CharString>
<CharString name="cid00001" fdSelectIndex="0">
333 endchar
</CharString>
</CharStrings>
</CFFFont>

<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF>

<hmtx>
<mtx name=".notdef" width="280" lsb="0"/>
<mtx name="cid00001" width="333" lsb="0"/>
</hmtx>

</ttFont>
Loading