Let PDF know when TrueType isn't TrueType.

FreeType reports that the type of a font is TrueType when the font is
logically TrueType. However, the underlying data may not be TrueType and
may be encoded in woff or woff2. The raw woff or woff2 data should not
be embedded in the PDF. If the tables are accessed individually it is
possible to subset them into a TrueType font. However, the subsetters
are not currently capable of handling a font as tables so fall back to
Type3 for now.

Change-Id: I5235ad02fd73fd88759dc30adfcf80aa0e4d2feb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/543921
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2022-05-25 14:00:11 -04:00 committed by SkCQ
parent 48cfc92ec8
commit 2bc5447527
3 changed files with 39 additions and 3 deletions

View File

@ -48,9 +48,10 @@ struct SkAdvancedTypefaceMetrics {
FontType fType = kOther_Font;
enum FontFlags : uint8_t {
kVariable_FontFlag = 0x01, //!<May be true for Type1, CFF, or TrueType fonts.
kNotEmbeddable_FontFlag = 0x02, //!<May not be embedded.
kNotSubsettable_FontFlag = 0x04, //!<May not be subset.
kVariable_FontFlag = 1 << 0, //!<May be true for Type1, CFF, or TrueType fonts.
kNotEmbeddable_FontFlag = 1 << 1, //!<May not be embedded.
kNotSubsettable_FontFlag = 1 << 2, //!<May not be subset.
kAltDataFormat_FontFlag = 1 << 3, //!<Data compressed. Table access may still work.
};
FontFlags fFlags = (FontFlags)0; // Global font flags.

View File

@ -171,6 +171,12 @@ const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typefac
SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkTypeface& typeface,
const SkAdvancedTypefaceMetrics& metrics) {
if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kVariable_FontFlag) ||
// PDF is actually interested in the encoding of the data, not just the logical format.
// If the TrueType is actually wOFF or wOF2 then it should not be directly embedded in PDF.
// For now export these as Type3 until the subsetter can handle table based fonts.
// See https://github.com/harfbuzz/harfbuzz/issues/3609 and
// https://skia-review.googlesource.com/c/skia/+/543485
SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kAltDataFormat_FontFlag) ||
SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) {
// force Type3 fallback.
return SkAdvancedTypefaceMetrics::kOther_Font;

View File

@ -33,6 +33,8 @@
#include "src/core/SkTSearch.h"
#include "src/ports/SkFontHost_FreeType_common.h"
#include "src/sfnt/SkOTUtils.h"
#include "src/sfnt/SkSFNTHeader.h"
#include "src/sfnt/SkTTCFHeader.h"
#include "src/utils/SkCallableTraits.h"
#include "src/utils/SkMatrix22.h"
@ -513,6 +515,27 @@ static SkAdvancedTypefaceMetrics::FontType get_font_type(FT_Face face) {
return SkAdvancedTypefaceMetrics::kOther_Font;
}
static bool is_opentype_font_data_standard_format(const SkTypeface& typeface) {
// FreeType reports TrueType for any data that can be decoded to TrueType or OpenType.
// However, there are alternate data formats for OpenType, like wOFF and wOF2.
std::unique_ptr<SkStreamAsset> stream = typeface.openStream(nullptr);
if (!stream) {
return false;
}
char buffer[4];
if (stream->read(buffer, 4) < 4) {
return false;
}
SkFourByteTag tag = SkSetFourByteTag(buffer[0], buffer[1], buffer[2], buffer[3]);
SK_OT_ULONG otTag = SkEndian_SwapBE32(tag);
return otTag == SkSFNTHeader::fontType_WindowsTrueType::TAG ||
otTag == SkSFNTHeader::fontType_MacTrueType::TAG ||
otTag == SkSFNTHeader::fontType_PostScript::TAG ||
otTag == SkSFNTHeader::fontType_OpenTypeCFF::TAG ||
otTag == SkTTCFHeader::TAG;
}
std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMetrics() const {
AutoFTAccess fta(this);
FT_Face face = fta.face();
@ -535,6 +558,12 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMet
}
info->fType = get_font_type(face);
if (info->fType == SkAdvancedTypefaceMetrics::kTrueType_Font &&
!is_opentype_font_data_standard_format(*this))
{
info->fFlags |= SkAdvancedTypefaceMetrics::kAltDataFormat_FontFlag;
}
info->fStyle = (SkAdvancedTypefaceMetrics::StyleFlags)0;
if (FT_IS_FIXED_WIDTH(face)) {
info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;