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)

Reply via email to