tdf#162002 DOCX import, font embed: only discard subset fonts with few glyphs
Commit a9f3c11375525a7708378dd3648febc40db1ad20 (tdf#162002 DOCX import: ignore subsetted embedded fonts for editing, 2024-07-12) decided to ignore all subsetted fonts for editing, improve this a little so we only ignore subsetted fonts when they can't even provide an English alphabet in any form (lowercase, uppercase). This avoids the possible problem that a font is marked as subsetted but it's good enough in practice and we would still throw it away for editing. Change-Id: I0bc0e14ffc0c039f029220991bd16d9e3254f059 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170570 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
This commit is contained in:
parent
828b26bdc2
commit
09da7fd9ce
@ -66,7 +66,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool addEmbeddedFont( const css::uno::Reference< css::io::XInputStream >& stream,
|
bool addEmbeddedFont( const css::uno::Reference< css::io::XInputStream >& stream,
|
||||||
const OUString& fontName, std::u16string_view extra,
|
const OUString& fontName, std::u16string_view extra,
|
||||||
std::vector< unsigned char > const & key, bool eot = false);
|
std::vector< unsigned char > const & key, bool eot = false,
|
||||||
|
bool bSubsetted = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns a URL for a file where to store contents of a given temporary font.
|
Returns a URL for a file where to store contents of a given temporary font.
|
||||||
|
@ -39,6 +39,24 @@ CPPUNIT_TEST_FIXTURE(Test, testSubsettedEmbeddedFont)
|
|||||||
// during editing may be missing from the subsetted font:
|
// during editing may be missing from the subsetted font:
|
||||||
CPPUNIT_ASSERT(aUrl.isEmpty());
|
CPPUNIT_ASSERT(aUrl.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPPUNIT_TEST_FIXTURE(Test, testSubsettedFullEmbeddedFont)
|
||||||
|
{
|
||||||
|
#if !defined(MACOSX) // FIXME fails on macOS
|
||||||
|
// Given a document with an embedded font (marked as subsetted, but otherwise full in practice),
|
||||||
|
// loaded for editing:
|
||||||
|
loadFromFile(u"subsetted-full-embedded-font.docx");
|
||||||
|
|
||||||
|
// When checking if the font is available:
|
||||||
|
OUString aUrl = EmbeddedFontsHelper::fontFileUrl(
|
||||||
|
u"IBM Plex Serif Light", FAMILY_ROMAN, ITALIC_NONE, WEIGHT_NORMAL, PITCH_VARIABLE,
|
||||||
|
EmbeddedFontsHelper::FontRights::ViewingAllowed);
|
||||||
|
|
||||||
|
// Then make sure the subsetted font is available, given that it has the reasonable amount of
|
||||||
|
// glyphs:
|
||||||
|
CPPUNIT_ASSERT(!aUrl.isEmpty());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||||
|
Binary file not shown.
@ -236,11 +236,13 @@ bool FontTable::IsReadOnly() const
|
|||||||
|
|
||||||
void FontTable::addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& stream,
|
void FontTable::addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& stream,
|
||||||
const OUString& fontName, std::u16string_view extra,
|
const OUString& fontName, std::u16string_view extra,
|
||||||
std::vector<unsigned char> const & key)
|
std::vector<unsigned char> const & key,
|
||||||
|
bool bSubsetted)
|
||||||
{
|
{
|
||||||
if (!m_pImpl->xEmbeddedFontHelper)
|
if (!m_pImpl->xEmbeddedFontHelper)
|
||||||
m_pImpl->xEmbeddedFontHelper.reset(new EmbeddedFontsHelper);
|
m_pImpl->xEmbeddedFontHelper.reset(new EmbeddedFontsHelper);
|
||||||
m_pImpl->xEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key);
|
m_pImpl->xEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key,
|
||||||
|
/*eot=*/false, bSubsetted);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmbeddedFontHandler::EmbeddedFontHandler(FontTable& rFontTable, OUString _fontName, std::u16string_view style )
|
EmbeddedFontHandler::EmbeddedFontHandler(FontTable& rFontTable, OUString _fontName, std::u16string_view style )
|
||||||
@ -256,11 +258,6 @@ EmbeddedFontHandler::~EmbeddedFontHandler()
|
|||||||
if( !m_inputStream.is())
|
if( !m_inputStream.is())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_bSubsetted && !m_fontTable.IsReadOnly())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector< unsigned char > key( 32 );
|
std::vector< unsigned char > key( 32 );
|
||||||
if( !m_fontKey.isEmpty())
|
if( !m_fontKey.isEmpty())
|
||||||
{ // key for unobfuscating
|
{ // key for unobfuscating
|
||||||
@ -280,7 +277,9 @@ EmbeddedFontHandler::~EmbeddedFontHandler()
|
|||||||
key[ i + 16 ] = val;
|
key[ i + 16 ] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_fontTable.addEmbeddedFont( m_inputStream, m_fontName, m_style, key );
|
// Ignore the "subsetted" flag if we're not editing anyway.
|
||||||
|
bool bSubsetted = m_bSubsetted && !m_fontTable.IsReadOnly();
|
||||||
|
m_fontTable.addEmbeddedFont( m_inputStream, m_fontName, m_style, key, bSubsetted );
|
||||||
m_inputStream->closeInput();
|
m_inputStream->closeInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ class FontTable : public LoggedProperties, public LoggedTable
|
|||||||
|
|
||||||
void addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& stream,
|
void addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& stream,
|
||||||
const OUString& fontName, std::u16string_view extra,
|
const OUString& fontName, std::u16string_view extra,
|
||||||
std::vector<unsigned char> const & key);
|
std::vector<unsigned char> const & key,
|
||||||
|
bool bSubsetted);
|
||||||
bool IsReadOnly() const;
|
bool IsReadOnly() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -66,7 +66,8 @@ void EmbeddedFontsHelper::clearTemporaryFontFiles()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EmbeddedFontsHelper::addEmbeddedFont( const uno::Reference< io::XInputStream >& stream, const OUString& fontName,
|
bool EmbeddedFontsHelper::addEmbeddedFont( const uno::Reference< io::XInputStream >& stream, const OUString& fontName,
|
||||||
std::u16string_view extra, std::vector< unsigned char > const & key, bool eot )
|
std::u16string_view extra, std::vector< unsigned char > const & key, bool eot,
|
||||||
|
bool bSubsetted )
|
||||||
{
|
{
|
||||||
OUString fileUrl = EmbeddedFontsHelper::fileUrlForTemporaryFont( fontName, extra );
|
OUString fileUrl = EmbeddedFontsHelper::fileUrlForTemporaryFont( fontName, extra );
|
||||||
osl::File file( fileUrl );
|
osl::File file( fileUrl );
|
||||||
@ -159,6 +160,37 @@ bool EmbeddedFontsHelper::addEmbeddedFont( const uno::Reference< io::XInputStrea
|
|||||||
osl::File::remove( fileUrl );
|
osl::File::remove( fileUrl );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bSubsetted)
|
||||||
|
{
|
||||||
|
TrueTypeFont* font;
|
||||||
|
sal_uInt32 nGlyphs = 0;
|
||||||
|
if (OpenTTFontBuffer(fontData.data(), fontData.size(), 0, &font) == SFErrCodes::Ok)
|
||||||
|
{
|
||||||
|
sal_uInt32 nGlyphCount = font->glyphCount();
|
||||||
|
for (sal_uInt32 i = 0; i < nGlyphCount; ++i)
|
||||||
|
{
|
||||||
|
sal_uInt32 nOffset = font->glyphOffset(i);
|
||||||
|
sal_uInt32 nNextOffset = font->glyphOffset(i + 1);
|
||||||
|
if (nOffset == nNextOffset)
|
||||||
|
{
|
||||||
|
// GetTTGlyphComponents() says this is an empty glyph, ignore it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++nGlyphs;
|
||||||
|
}
|
||||||
|
CloseTTFont(font);
|
||||||
|
}
|
||||||
|
// Check if it has reasonable amount of glyphs, set the limit to the number of glyphs in the
|
||||||
|
// English alphabet (not differentiating lowercase and uppercase).
|
||||||
|
if (nGlyphs < 26)
|
||||||
|
{
|
||||||
|
SAL_INFO("vcl.fonts", "Ignoring embedded font that only provides " << nGlyphs << " non-empty glyphs");
|
||||||
|
osl::File::remove(fileUrl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_aAccumulatedFonts.emplace_back(std::make_pair(fontName, fileUrl));
|
m_aAccumulatedFonts.emplace_back(std::make_pair(fontName, fileUrl));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user