summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Behrens <Thorsten.Behrens@CIB.de>2019-03-14 00:36:37 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2019-03-22 08:06:39 +0100
commitd3f21588d3d1402bee42d5374ed060a7e26b7b91 (patch)
tree921d64326a796b23155977f59b3cfde825fb76ab
parent6c30df1a30566877761bb926121836ada62d6fad (diff)
Fix pdf validation error 'glyph width in dict and font inconsistent'
Previous code was writing hard-coded '1000' as glyph width for any type1 font subsetting - since actual type2 width info only became available during subsequent convertOneTypeOp() parsing. Catch was, that loop sometimes already modifies the output buffer (whenever glyph path info was given), so we fix that by first padding out 5 bytes for the width (size of integers are sadly variable), then parsing Type2 glyph code, and in the end putting in the actual width value we then know. Can't put hsbw type1 op last, since standard requires that to be first (and can only be given _once_). Could be re-done nicer by buffering Type2 glyph data, then writing it. Left as an exercise for the reader. Conflicts: vcl/source/fontsubset/cff.cxx Change-Id: I64ffaa32ded2f0a7c06311d1e0426cf358308a0a
-rw-r--r--vcl/source/fontsubset/cff.cxx46
1 files changed, 29 insertions, 17 deletions
diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx
index 13ed076d1ff6..aa6d09f8d992 100644
--- a/vcl/source/fontsubset/cff.cxx
+++ b/vcl/source/fontsubset/cff.cxx
@@ -1099,29 +1099,41 @@ int CffSubsetterContext::convert2Type1Ops( CffLocal* pCffLocal, const U8* const
*(mpWritePtr++) = 0x44;
*(mpWritePtr++) = 0x55;
*(mpWritePtr++) = ' ';
-#if 1 // convert the Type2 charstring to Type1
+
+ // convert the Type2 charstring to Type1
mpReadPtr = pT2Ops;
mpReadEnd = pT2Ops + nT2Len;
// prepend "hsbw" or "sbw"
// TODO: only emit hsbw when charwidth is known
- // TODO: remove charwidth from T2 stack
- writeType1Val( 0); // TODO: aSubsetterContext.getLeftSideBearing();
- writeType1Val( 1000/*###getCharWidth()###*/);
- writeTypeOp( TYPE1OP::HSBW);
-mbNeedClose = false;
-mbIgnoreHints = false;
-mnHintSize=mnHorzHintSize=mnStackIdx=0; maCharWidth=-1;//#######
-mnCntrMask = 0;
+ writeType1Val(0); // TODO: aSubsetterContext.getLeftSideBearing();
+ U8* pCharWidthPtr=mpWritePtr; // need to overwrite that later
+ // pad out 5 bytes for the char width with default val 1000 (to be
+ // filled with the actual value below)
+ *(mpWritePtr++) = 255;
+ *(mpWritePtr++) = static_cast<U8>(0);
+ *(mpWritePtr++) = static_cast<U8>(0);
+ *(mpWritePtr++) = static_cast<U8>(250);
+ *(mpWritePtr++) = static_cast<U8>(124);
+ writeTypeOp(TYPE1OP::HSBW);
+ mbNeedClose = false;
+ mbIgnoreHints = false;
+ mnHintSize=mnHorzHintSize=mnStackIdx=0; maCharWidth=-1;//#######
+ mnCntrMask = 0;
while( mpReadPtr < mpReadEnd)
convertOneTypeOp();
-// if( bActivePath)
-// writeTypeOp( TYPE1OP::CLOSEPATH);
-// if( bSubRoutine)
-// writeTypeOp( TYPE1OP::RETURN);
-#else // useful for manually encoding charstrings
- mpWritePtr = pT1Ops;
- mpWritePtr += sprintf( (char*)mpWritePtr, "OOo_\x8b\x8c\x0c\x10\x0b");
-#endif
+ if( maCharWidth != -1 )
+ {
+ // overwrite earlier charWidth value, which we only now have
+ // parsed out of mpReadPtr buffer (by way of
+ // convertOneTypeOp()s above)
+ const int nInt = static_cast<int>(maCharWidth);
+ *(pCharWidthPtr++) = 255;
+ *(pCharWidthPtr++) = static_cast<U8>(nInt >> 24);
+ *(pCharWidthPtr++) = static_cast<U8>(nInt >> 16);
+ *(pCharWidthPtr++) = static_cast<U8>(nInt >> 8);
+ *(pCharWidthPtr++) = static_cast<U8>(nInt);
+ }
+
const int nType1Len = mpWritePtr - pT1Ops;
// encrypt the Type1 charstring