vcl/win/gdi/salfont.cxx |  167 ++++++++++++++++++------------------------------
 1 file changed, 64 insertions(+), 103 deletions(-)

New commits:
commit 5111baa39117f6e16909566e28a8663a32e25269
Author:     Jan-Marek Glogowski <glo...@fbihome.de>
AuthorDate: Thu Jul 4 19:27:31 2019 +0200
Commit:     Jan-Marek Glogowski <glo...@fbihome.de>
CommitDate: Fri Jul 5 19:39:55 2019 +0200

    WIN get embedded font info from EnumFontFamiliesEx
    
    Instead of some manual decoding of the .fot file, this extracts
    all the relevant information of the registered font using the
    default routines already used when enumerating the system fonts.
    
    We still have to extract the font family from the .fot file to
    know the registered family name of the embedded font.
    
    And it uses the OSL functions to create the temporary font resource
    file name and generally adds more SAL_WARNs when some part of the
    private font registration fails.
    
    Change-Id: I5e118bf1f3bc1fb7bbf4c68a383a45892dffaf98
    Reviewed-on: https://gerrit.libreoffice.org/75102
    Tested-by: Jenkins
    Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de>

diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 0dfd4fdc62a1..56685cda8eb9 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -40,6 +40,7 @@
 #include <o3tl/char16_t2wchar_t.hxx>
 #include <tools/helpers.hxx>
 #include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
 #include <unotools/fontcfg.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/sysdata.hxx>
@@ -1105,111 +1106,71 @@ void ImplReleaseTempFonts(SalData& rSalData, bool bAll)
     }
 }
 
-static bool ImplGetFontAttrFromFile( const OUString& rFontFileURL,
-    FontAttributes& rDFA )
+static OUString lcl_GetFontFamilyName(const OUString& rFontFileURL)
 {
-    OUString aUSytemPath;
-    OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, 
aUSytemPath ) );
-
-    // get FontAttributes from a *fot file
-    // TODO: use GetTTGlobalFontInfo() to access the font directly
-    rDFA.SetQuality( 1000 );
-    rDFA.SetFamilyType(FAMILY_DONTKNOW);
-    rDFA.SetWidthType(WIDTH_DONTKNOW);
-    rDFA.SetWeight(WEIGHT_DONTKNOW);
-    rDFA.SetItalic(ITALIC_DONTKNOW);
-    rDFA.SetPitch(PITCH_DONTKNOW);
-
     // Create temporary file name
-    wchar_t aResourceName[512];
-    int nMaxLen = SAL_N_ELEMENTS(aResourceName) - 16;
-    int nLen = GetTempPathW( nMaxLen, aResourceName );
-    wcsncpy( aResourceName + nLen, L"soAAT.fot", std::max( 0, nMaxLen - nLen 
));
-    DeleteFileW( aResourceName );
-
-    // Create font resource file (typically with a .fot file name extension).
-    CreateScalableFontResourceW( 0, aResourceName, 
o3tl::toW(aUSytemPath.getStr()), nullptr );
+    OUString aTempFileURL;
+    if (osl::File::E_None != osl::File::createTempFile(nullptr, nullptr, 
&aTempFileURL))
+        return OUString();
+    osl::File::remove(aTempFileURL);
+    OUString aResSystemPath;
+    osl::FileBase::getSystemPathFromFileURL(aTempFileURL, aResSystemPath);
+
+    // Create font resource file (.fot)
+    // There is a limit of 127 characters for the full path passed via 
lpszFile, so we have to
+    // split the font URL and pass it as two parameters. As a result we can't 
use
+    // CreateScalableFontResource for renaming, as it now expects the font in 
the system path.
+    // But it's still good to use it for family name extraction, we're 
currently after.
+    // BTW: it doesn't help to prefix the lpszFile with \\?\ to support larger 
paths.
+    // TODO: use TTLoadEmbeddedFont (needs an EOT as input, so we have to add 
a header to the TTF)
+    // TODO: forward the EOT from the AddTempDevFont call side, if VCL 
supports it
+    INetURLObject aTTFUrl(rFontFileURL);
+    // GetBase() stripts the extension
+    OUString aFilename = 
aTTFUrl.GetLastName(INetURLObject::DecodeMechanism::WithCharset);
+    if (!CreateScalableFontResourceW(0, o3tl::toW(aResSystemPath.getStr()),
+            o3tl::toW(aFilename.getStr()), 
o3tl::toW(aTTFUrl.GetPath().getStr())))
+    {
+        sal_uInt32 nError = GetLastError();
+        SAL_WARN("vcl.fonts", "CreateScalableFontResource failed for " << 
aResSystemPath << " "
+                              << aFilename << " " << aTTFUrl.GetPath() << " " 
<< nError);
+        return OUString();
+    }
 
     // Open and read the font resource file
-    OUString aFotFileName = o3tl::toU( aResourceName );
-    osl::FileBase::getFileURLFromSystemPath( aFotFileName, aFotFileName );
-    osl::File aFotFile( aFotFileName );
-    osl::FileBase::RC aError = aFotFile.open( osl_File_OpenFlag_Read );
-    if( aError != osl::FileBase::E_None )
-        return false;
+    osl::File aFotFile(aTempFileURL);
+    if (osl::FileBase::E_None != aFotFile.open(osl_File_OpenFlag_Read))
+        return OUString();
 
     sal_uInt64  nBytesRead = 0;
     char        aBuffer[4096];
     aFotFile.read( aBuffer, sizeof( aBuffer ), nBytesRead );
     // clean up temporary resource file
     aFotFile.close();
-    DeleteFileW( aResourceName );
+    osl::File::remove(aTempFileURL);
 
     // retrieve font family name from byte offset 0x4F6
-    sal_uInt64 i = 0x4F6;
-    sal_uInt64 nNameOfs = i;
-    while( (i < nBytesRead) && (aBuffer[i++] != 0) );
-    // skip full name
-    while( (i < nBytesRead) && (aBuffer[i++] != 0) );
-    // retrieve font style name
-    int nStyleOfs = i;
-    while( (i < nBytesRead) && (aBuffer[i++] != 0) );
-    if( i >= nBytesRead )
-        return false;
+    static const sal_uInt64 nNameOfs = 0x4F6;
+    sal_uInt64 nPos = nNameOfs;
+    for (; (nPos < nBytesRead) && (aBuffer[nPos] != 0); nPos++);
+    if (nPos >= nBytesRead || (nPos == nNameOfs))
+        return OUString();
 
-    // convert byte strings to unicode
-    char *pName = aBuffer + nNameOfs;
-    rDFA.SetFamilyName(OUString(pName, strlen(pName), 
osl_getThreadTextEncoding()));
-    char *pStyle = aBuffer + nStyleOfs;
-    rDFA.SetStyleName(OUString(pStyle, strlen(pStyle), 
osl_getThreadTextEncoding() ));
-
-    // byte offset 0x4C7: OS2_fsSelection
-    const char nFSS = aBuffer[ 0x4C7 ];
-    if( nFSS & 0x01 )   // italic
-        rDFA.SetItalic(ITALIC_NORMAL);
-    //if( nFSS & 0x20 )   // bold
-    //   rDFA.meWeight = WEIGHT_BOLD;
-    if( nFSS & 0x40 )   // regular
-    {
-        rDFA.SetWeight(WEIGHT_NORMAL);
-        rDFA.SetItalic(ITALIC_NONE);
-    }
-
-    // byte offsets 0x4D7/0x4D8: wingdi's FW_WEIGHT
-    int nWinWeight = (aBuffer[0x4D7] & 0xFF) + ((aBuffer[0x4D8] & 0xFF) << 8);
-    rDFA.SetWeight(ImplWeightToSal( nWinWeight ));
-
-    rDFA.SetSymbolFlag(false);          // TODO
-    rDFA.SetPitch(PITCH_DONTKNOW); // TODO
-
-    // byte offset 0x4DE: pitch&family
-    rDFA.SetFamilyType(ImplFamilyToSal( aBuffer[0x4DE] ));
-
-    // byte offsets 0x4C8/0x4C9: emunits
-    // byte offsets 0x4CE/0x4CF: winascent
-    // byte offsets 0x4D0/0x4D1: winascent+windescent-emunits
-    // byte offsets 0x4DF/0x4E0: avgwidth
-
-    return true;
+    return OUString(aBuffer + nNameOfs, nPos - nNameOfs, 
osl_getThreadTextEncoding());
 }
 
 bool WinSalGraphics::AddTempDevFont(PhysicalFontCollection* pFontCollection,
                                     const OUString& rFontFileURL, const 
OUString& rFontName)
 {
-
-    FontAttributes aDFA;
-    aDFA.SetFamilyName(rFontName);
-    aDFA.SetQuality( 1000 );
-
-    // Retrieve font name from font resource
-    if( aDFA.GetFamilyName().isEmpty() )
+    OUString aFontFamily = lcl_GetFontFamilyName(rFontFileURL);
+    if (aFontFamily.isEmpty())
     {
-        ImplGetFontAttrFromFile( rFontFileURL, aDFA );
+        SAL_WARN("vcl.fonts", "error extracting font family from " << 
rFontFileURL);
+        return false;
     }
 
-    if ( aDFA.GetFamilyName().isEmpty() )
+    if (rFontName != aFontFamily)
     {
-        SAL_WARN("vcl.fonts", "error extracting font family from " << 
rFontFileURL);
+        SAL_WARN("vcl.fonts", "font family renaming not implemented; skipping 
embedded " << rFontName);
         return false;
     }
 
@@ -1217,26 +1178,26 @@ bool 
WinSalGraphics::AddTempDevFont(PhysicalFontCollection* pFontCollection,
     if (nFonts <= 0)
         return false;
 
-    // create matching FontData struct
-    aDFA.SetSymbolFlag(false); // TODO: how to know it without accessing the 
font?
-    aDFA.SetFamilyType(FAMILY_DONTKNOW);
-    aDFA.SetWidthType(WIDTH_DONTKNOW);
-    aDFA.SetWeight(WEIGHT_DONTKNOW);
-    aDFA.SetItalic(ITALIC_DONTKNOW);
-    aDFA.SetPitch(PITCH_DONTKNOW);
-
-    /*
-    // TODO: improve FontAttributes using the "font resource file"
-    aDFS.maName = // using "FONTRES:" from file
-    if( rFontName != aDFS.maName )
-        aDFS.maMapName = aFontName;
-    */
-
-    rtl::Reference<WinFontFace> pFontData = new WinFontFace(aDFA,
-        sal::static_int_cast<BYTE>(DEFAULT_CHARSET),
-        sal::static_int_cast<BYTE>(TMPF_VECTOR|TMPF_TRUETYPE) );
-    pFontData->SetFontId( reinterpret_cast<sal_IntPtr>(pFontData.get()) );
-    pFontCollection->Add( pFontData.get() );
+    ImplEnumInfo aInfo;
+    aInfo.mhDC = getHDC();
+    aInfo.mpList = pFontCollection;
+    aInfo.mpName = &aFontFamily;
+    aInfo.mbPrinter = mbPrinter;
+    aInfo.mnFontCount = pFontCollection->Count();
+    const int nExpectedFontCount = aInfo.mnFontCount + nFonts;
+
+    LOGFONTW aLogFont;
+    memset(&aLogFont, 0, sizeof(aLogFont));
+    aLogFont.lfCharSet = DEFAULT_CHARSET;
+    aInfo.mpLogFont = &aLogFont;
+
+    // add the font to the PhysicalFontCollection
+    EnumFontFamiliesExW(getHDC(), &aLogFont,
+        SalEnumFontsProcExW, reinterpret_cast<LPARAM>(&aInfo), 0);
+
+    SAL_WARN_IF(nExpectedFontCount != pFontCollection->Count(), "vcl.fonts",
+        "temp font was registered but is not in enumeration: " << 
rFontFileURL);
+
     return true;
 }
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to