tdf#113048: Fix PDF ascender and descender of some fonts

Use the same ascender and descender calculation for fonts with CFF
table as fonts without CFF table.

This also provides a better fix for tdf#138325 and tdf#151039.

Change-Id: I416a123199e94401fa557fce95013eb8b0590e33
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143683
Tested-by: خالد حسني <khaled@aliftype.com>
Reviewed-by: خالد حسني <khaled@aliftype.com>
diff --git a/vcl/inc/fontsubset.hxx b/vcl/inc/fontsubset.hxx
index d7e5318..a1ba31aa 100644
--- a/vcl/inc/fontsubset.hxx
+++ b/vcl/inc/fontsubset.hxx
@@ -70,6 +70,7 @@ public: // TODO: make subsetter results private and provide accessor methods ins
    int                     m_nCapHeight;
    tools::Rectangle               m_aFontBBox;
    FontType                m_nFontType;        ///< font-type of subset result
    bool                    m_bFilled;

private:
    // input-font-specific details
diff --git a/vcl/inc/sft.hxx b/vcl/inc/sft.hxx
index 29f282a..52d9c3d 100644
--- a/vcl/inc/sft.hxx
+++ b/vcl/inc/sft.hxx
@@ -616,7 +616,6 @@ class TrueTypeFont;
    VCL_DLLPUBLIC bool CreateCFFfontSubset(const unsigned char* pFontBytes,
                              int nByteLength,
                              std::vector<sal_uInt8>& rOutBuffer,
                              const OUString& rPSName,
                              const sal_GlyphId* pGlyphIds,
                              const sal_uInt8* pEncoding,
                              int nGlyphCount, FontSubsetInfo& rInfo);
diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx
index 682113c..72c0a86 100644
--- a/vcl/source/font/PhysicalFontFace.cxx
+++ b/vcl/source/font/PhysicalFontFace.cxx
@@ -358,13 +358,6 @@ bool PhysicalFontFace::CreateFontSubset(std::vector<sal_uInt8>& rOutBuffer,
                                        const sal_GlyphId* pGlyphIds, const sal_uInt8* pEncoding,
                                        const int nGlyphCount, FontSubsetInfo& rInfo) const
{
    // Shortcut for CFF-subsetting.
    auto aData = GetRawFontData(T_CFF);
    if (!aData.empty())
        return CreateCFFfontSubset(aData.data(), aData.size(), rOutBuffer,
                                   GetName(NAME_ID_POSTSCRIPT_NAME), pGlyphIds, pEncoding,
                                   nGlyphCount, rInfo);

    // Prepare data for font subsetter.
    TrueTypeFace aSftFont(RawFace(GetHbFace()), GetFontCharMap());
    if (aSftFont.initialize() != SFErrCodes::Ok)
@@ -373,6 +366,12 @@ bool PhysicalFontFace::CreateFontSubset(std::vector<sal_uInt8>& rOutBuffer,
    // Get details about the subset font.
    FillFontSubsetInfo(&aSftFont, rInfo);

    // Shortcut for CFF-subsetting.
    auto aData = GetRawFontData(T_CFF);
    if (!aData.empty())
        return CreateCFFfontSubset(aData.data(), aData.size(), rOutBuffer, pGlyphIds, pEncoding,
                                   nGlyphCount, rInfo);

    // write subset into destination file
    return CreateTTFfontSubset(aSftFont, rOutBuffer, pGlyphIds, pEncoding, nGlyphCount);
}
diff --git a/vcl/source/fontsubset/cff.cxx b/vcl/source/fontsubset/cff.cxx
index 45a8b78..76a77ec 100644
--- a/vcl/source/fontsubset/cff.cxx
+++ b/vcl/source/fontsubset/cff.cxx
@@ -2361,9 +2361,22 @@ void CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
        rEmitter.emitValVector( "/FontMatrix [", "]readonly def\n", maFontMatrix);
    else // emit default FontMatrix if needed
        rEmitter.maBuffer.append( "/FontMatrix [0.001 0 0 0.001 0 0]readonly def\n");

    // emit FontBBox
    ValType fXFactor = 1.0;
    ValType fYFactor = 1.0;
    if( maFontMatrix.size() >= 4) {
        fXFactor = 1000.0F * maFontMatrix[0];
        fYFactor = 1000.0F * maFontMatrix[3];
    }

    auto aFontBBox = maFontBBox;
    if (aFontBBox.size() != 4)
    if (rFSInfo.m_bFilled)
        aFontBBox = {
            rFSInfo.m_aFontBBox.Left() / fXFactor, rFSInfo.m_aFontBBox.Top() / fYFactor,
            rFSInfo.m_aFontBBox.Right() / fXFactor, (rFSInfo.m_aFontBBox.Bottom() + 1) / fYFactor
        };
    else if (aFontBBox.size() != 4)
        aFontBBox = { 0, 0, 999, 999 }; // emit default FontBBox if needed
    rEmitter.emitValVector( "/FontBBox {", "}readonly def\n", aFontBBox);
    // emit FONTINFO into TOPDICT
@@ -2572,12 +2585,12 @@ void CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
    // provide details to the subset requesters, TODO: move into own method?
    // note: Top and Bottom are flipped between Type1 and VCL
    // note: the rest of VCL expects the details below to be scaled like for an emUnits==1000 font
    ValType fXFactor = 1.0;
    ValType fYFactor = 1.0;
    if( maFontMatrix.size() >= 4) {
        fXFactor = 1000.0F * maFontMatrix[0];
        fYFactor = 1000.0F * maFontMatrix[3];
    }

    rFSInfo.m_nFontType = rEmitter.mbPfbSubset ? FontType::TYPE1_PFB : FontType::TYPE1_PFA;

    if (rFSInfo.m_bFilled)
        return;

    rFSInfo.m_aFontBBox = { Point(static_cast<sal_Int32>(aFontBBox[0] * fXFactor),
                                  static_cast<sal_Int32>(aFontBBox[1] * fYFactor)),
                            Point(static_cast<sal_Int32>(aFontBBox[2] * fXFactor),
@@ -2588,7 +2601,6 @@ void CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
    rFSInfo.m_nDescent = -rFSInfo.m_aFontBBox.Top();    // for all letters
    rFSInfo.m_nCapHeight = rFSInfo.m_nAscent;           // for top-flat capital letters

    rFSInfo.m_nFontType = rEmitter.mbPfbSubset ? FontType::TYPE1_PFB : FontType::TYPE1_PFA;
    rFSInfo.m_aPSName   = OUString( rEmitter.maSubsetName, strlen(rEmitter.maSubsetName), RTL_TEXTENCODING_UTF8 );
}

diff --git a/vcl/source/fontsubset/fontsubset.cxx b/vcl/source/fontsubset/fontsubset.cxx
index 1e3daa4..4e6e03c 100644
--- a/vcl/source/fontsubset/fontsubset.cxx
+++ b/vcl/source/fontsubset/fontsubset.cxx
@@ -29,6 +29,7 @@ FontSubsetInfo::FontSubsetInfo()
    , m_nDescent( 0)
    , m_nCapHeight( 0)
    , m_nFontType( FontType::NO_FONT)
    , m_bFilled(false)
    , mpInFontBytes( nullptr)
    , mnInByteLength( 0)
    , meInFontType( FontType::NO_FONT)
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx
index b0518a0..205be4f 100644
--- a/vcl/source/fontsubset/sft.cxx
+++ b/vcl/source/fontsubset/sft.cxx
@@ -1868,16 +1868,15 @@ bool CreateTTFfontSubset(vcl::AbstractTrueTypeFont& rTTF, std::vector<sal_uInt8>
}

bool CreateCFFfontSubset(const unsigned char* pFontBytes, int nByteLength,
                         std::vector<sal_uInt8>& rOutBuffer, const OUString& rPSName,
                         const sal_GlyphId* pGlyphIds, const sal_uInt8* pEncoding, int nGlyphCount,
                         FontSubsetInfo& rInfo)
                         std::vector<sal_uInt8>& rOutBuffer, const sal_GlyphId* pGlyphIds,
                         const sal_uInt8* pEncoding, int nGlyphCount, FontSubsetInfo& rInfo)
{
    utl::TempFileFast aTempFile;
    SvStream* pStream = aTempFile.GetStream(StreamMode::READWRITE);

    rInfo.LoadFont(FontType::CFF_FONT, pFontBytes, nByteLength);
    bool bRet = rInfo.CreateFontSubset(FontType::TYPE1_PFB, pStream, rPSName.toUtf8().getStr(),
                                       pGlyphIds, pEncoding, nGlyphCount);
    bool bRet = rInfo.CreateFontSubset(FontType::TYPE1_PFB, pStream, nullptr, pGlyphIds, pEncoding,
                                       nGlyphCount);

    if (bRet)
    {
@@ -2269,6 +2268,8 @@ void FillFontSubsetInfo(AbstractTrueTypeFont *ttf, FontSubsetInfo& rInfo)
        rInfo.m_nDescent = +aTTInfo.typoDescender;
    if (!rInfo.m_nDescent)
        rInfo.m_nDescent = -aTTInfo.descender;

    rInfo.m_bFilled = true;
}

std::unique_ptr<GlyphData> GetTTRawGlyphData(AbstractTrueTypeFont *ttf, sal_uInt32 glyphID)