vcl/source/fontsubset/cff.cxx | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
New commits: commit 81fe821cc30a6746636350d78b4fdd88839dc21c Author: Khaled Hosny <kha...@aliftype.com> AuthorDate: Tue Sep 13 12:34:35 2022 +0200 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Sat Oct 15 22:39:03 2022 +0200 tdf#126242: Handle fractional values when subsetting CFF Instead of truncating the values, write the fraction using “div” operator. Change-Id: Ideff4ed3c9922a3ddd6c8aa0ec2733722ae722f6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139854 Tested-by: Jenkins Reviewed-by: خالد حسني <kha...@aliftype.com> (cherry picked from commit a387f39de8e59d7542b74962242504b798af1362) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141397 Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx index fdc210e040a7..d417c7fe1a42 100644 --- a/vcl/source/fontsubset/cff.cxx +++ b/vcl/source/fontsubset/cff.cxx @@ -582,7 +582,30 @@ void CffSubsetterContext::writeType1Val( ValType aVal) { U8* pOut = mpWritePtr; - int nInt = static_cast<int>(aVal); + // tdf#126242 + // Type2 has 16.16 fixed numbers, but Type1 does not. To represent values + // with fractions we multiply it by a factor then use “div” operator to + // divide it back and keep the fractions. + // Code Adapted from: + // https://github.com/fontforge/fontforge/blob/f152f12e567ea5bd737a2907c318ae26cfaabd08/fontforge/splinesave.c#L378 + int nDiv = 0; + aVal = rint(aVal * 1024) / 1024; + if (aVal != floor(aVal)) + { + if (aVal == rint(aVal * 64) / 64) + nDiv = 64; + else + nDiv = 1024; + aVal *= nDiv; + } + + int nInt = static_cast<int>(rint(aVal)); + if (nDiv && floor(nInt) / nDiv == floor(nInt / nDiv)) + { + nInt = rint(nInt / nDiv); + nDiv = 0; + } + if( (nInt >= -107) && (nInt <= +107)) { *(pOut++) = static_cast<U8>(nInt + 139); // -107..+107 } else if( (nInt >= -1131) && (nInt <= +1131)) { @@ -602,6 +625,12 @@ void CffSubsetterContext::writeType1Val( ValType aVal) } mpWritePtr = pOut; + + if (nDiv) + { + writeType1Val(nDiv); + writeTypeEsc(TYPE1OP::DIV); + } } inline void CffSubsetterContext::writeTypeOp( int nTypeOp)