summaryrefslogtreecommitdiff
path: root/vcl/win
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2019-07-04 19:27:31 +0200
committerJan-Marek Glogowski <glogow@fbihome.de>2019-07-05 19:39:55 +0200
commit5111baa39117f6e16909566e28a8663a32e25269 (patch)
tree92168974ad78f787fbc5d2cc7c62c3e11e3fa33b /vcl/win
parent8e63934c398dd5065f3589c8a7d1b3008f5514d1 (diff)
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 <glogow@fbihome.de>
Diffstat (limited to 'vcl/win')
-rw-r--r--vcl/win/gdi/salfont.cxx167
1 files changed, 64 insertions, 103 deletions
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;
}