diff options
-rw-r--r-- | vcl/win/gdi/salfont.cxx | 167 |
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; } |