зеркало из https://github.com/mozilla/moz-skia.git
[PDF] Subset font advance data (W array).
Patch by arthurhsu@chromium.org. Original CL: http://codereview.appspot.com/4830068 http://codereview.appspot.com/4905051/ Review URL: http://codereview.appspot.com/4911042 git-svn-id: http://skia.googlecode.com/svn/trunk@2134 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
37c472007e
Коммит
37ad8fb72f
|
@ -132,10 +132,21 @@ void finishRange(
|
|||
typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
|
||||
type);
|
||||
|
||||
/** Retrieve advance data for glyphs. Used by the PDF backend. It calls
|
||||
underlying platform dependent API getAdvance to acquire the data.
|
||||
@param num_glyphs Total number of glyphs in the given font.
|
||||
@param glyphIDs For per-glyph info, specify subset of the font by
|
||||
giving glyph ids. Each integer represents a glyph
|
||||
id. Passing NULL means all glyphs in the font.
|
||||
@param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if
|
||||
glyphIDs is NULL.
|
||||
*/
|
||||
template <typename Data, typename FontHandle>
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FontHandle fontHandle,
|
||||
int num_glyphs,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount,
|
||||
bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data));
|
||||
|
||||
} // namespace skia_advanced_typeface_metrics_utils
|
||||
|
|
|
@ -181,10 +181,17 @@ public:
|
|||
names, etc.) should be populated.
|
||||
@return The returned object has already been referenced. NULL is
|
||||
returned if the font is not found.
|
||||
@param glyphIDs For per-glyph info, specify subset of the font by
|
||||
giving glyph ids. Each integer represents a glyph
|
||||
id. Passing NULL means all glyphs in the font.
|
||||
@param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if
|
||||
glyphIDs is NULL.
|
||||
*/
|
||||
static SkAdvancedTypefaceMetrics* GetAdvancedTypefaceMetrics(
|
||||
SkFontID fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo);
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount);
|
||||
|
||||
/** Return the number of tables in the font
|
||||
*/
|
||||
|
@ -293,4 +300,3 @@ public:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -134,10 +134,17 @@ public:
|
|||
/** Retrieve detailed typeface metrics. Used by the PDF backend.
|
||||
@param perGlyphInfo Indicate what glyph specific information (advances,
|
||||
names, etc.) should be populated.
|
||||
@param glyphIDs For per-glyph info, specify subset of the font by
|
||||
giving glyph ids. Each integer represents a glyph
|
||||
id. Passing NULL means all glyphs in the font.
|
||||
@param glyphIDsCount Number of elements in subsetGlyphIds. Ignored if
|
||||
glyphIDs is NULL.
|
||||
@return The returned object has already been referenced.
|
||||
*/
|
||||
SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics(
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const;
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs = NULL,
|
||||
uint32_t glyphIDsCount = 0) const;
|
||||
|
||||
protected:
|
||||
/** uniqueID must be unique (please!) and non-zero
|
||||
|
|
|
@ -478,4 +478,3 @@ private:
|
|||
#endif /* C++ */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ protected:
|
|||
|
||||
// Accessors for subclass.
|
||||
SkAdvancedTypefaceMetrics* fontInfo();
|
||||
void setFontInfo(SkAdvancedTypefaceMetrics* info);
|
||||
uint16_t firstGlyphID() const;
|
||||
uint16_t lastGlyphID() const;
|
||||
void setLastGlyphID(uint16_t glyphID);
|
||||
|
|
|
@ -65,6 +65,8 @@ template <typename Data, typename FontHandle>
|
|||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FontHandle fontHandle,
|
||||
int num_glyphs,
|
||||
const uint32_t* subsetGlyphIDs,
|
||||
uint32_t subsetGlyphIDsLength,
|
||||
bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
|
||||
// Assuming that an ASCII representation of a width or a glyph id is,
|
||||
// on average, 3 characters long gives the following cut offs for
|
||||
|
@ -82,10 +84,17 @@ SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
|||
curRange = appendRange(&result, 0);
|
||||
Data lastAdvance = SK_MinS16;
|
||||
int repeats = 0;
|
||||
uint32_t subsetIndex = 0;
|
||||
for (int gId = 0; gId <= num_glyphs; gId++) {
|
||||
Data advance;
|
||||
Data advance = 0;
|
||||
if (gId < num_glyphs) {
|
||||
// Get glyph id only when subset is NULL, or the id is in subset.
|
||||
if (!subsetGlyphIDs ||
|
||||
(subsetIndex < subsetGlyphIDsLength &&
|
||||
static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) {
|
||||
SkAssertResult(getAdvance(fontHandle, gId, &advance));
|
||||
++subsetIndex;
|
||||
}
|
||||
} else {
|
||||
advance = SK_MinS16;
|
||||
}
|
||||
|
@ -139,16 +148,22 @@ SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
|||
template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
|
||||
HDC hdc,
|
||||
int num_glyphs,
|
||||
const uint32_t* subsetGlyphIDs,
|
||||
uint32_t subsetGlyphIDsLength,
|
||||
bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
|
||||
#elif defined(SK_BUILD_FOR_UNIX)
|
||||
template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
|
||||
FT_Face face,
|
||||
int num_glyphs,
|
||||
const uint32_t* subsetGlyphIDs,
|
||||
uint32_t subsetGlyphIDsLength,
|
||||
bool (*getAdvance)(FT_Face face, int gId, int16_t* data));
|
||||
#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
|
||||
template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
|
||||
CTFontRef ctFont,
|
||||
int num_glyphs,
|
||||
const uint32_t* subsetGlyphIDs,
|
||||
uint32_t subsetGlyphIDsLength,
|
||||
bool (*getAdvance)(CTFontRef ctFont, int gId, int16_t* data));
|
||||
#endif
|
||||
template void resetRange(
|
||||
|
|
|
@ -93,6 +93,11 @@ SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
|
|||
}
|
||||
|
||||
SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const {
|
||||
return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID, perGlyphInfo);
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount) const {
|
||||
return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID,
|
||||
perGlyphInfo,
|
||||
glyphIDs,
|
||||
glyphIDsCount);
|
||||
}
|
||||
|
|
|
@ -528,7 +528,7 @@ static void sk_delete_array(const void* ptr, size_t, void*) {
|
|||
|
||||
static int get_subset_font_stream(const char* fontName,
|
||||
const SkTypeface* typeface,
|
||||
const SkPDFGlyphSet* subset,
|
||||
const SkTDArray<uint32_t>& subset,
|
||||
SkPDFStream** fontStream) {
|
||||
SkRefPtr<SkStream> fontData =
|
||||
SkFontHost::OpenStream(SkTypeface::UniqueID(typeface));
|
||||
|
@ -537,11 +537,6 @@ static int get_subset_font_stream(const char* fontName,
|
|||
int fontSize = fontData->getLength();
|
||||
|
||||
#if defined (SK_SFNTLY_SUBSETTER)
|
||||
// Generate glyph id array.
|
||||
SkTDArray<uint32_t> glyphIDs;
|
||||
glyphIDs.push(0); // Always include glyph 0.
|
||||
subset->exportTo(&glyphIDs);
|
||||
|
||||
// Read font into buffer.
|
||||
SkPDFStream* subsetFontStream = NULL;
|
||||
SkTDArray<unsigned char> originalFont;
|
||||
|
@ -555,8 +550,8 @@ static int get_subset_font_stream(const char* fontName,
|
|||
int subsetFontSize = SfntlyWrapper::SubsetFont(fontName,
|
||||
originalFont.begin(),
|
||||
fontSize,
|
||||
glyphIDs.begin(),
|
||||
glyphIDs.count(),
|
||||
subset.begin(),
|
||||
subset.count(),
|
||||
&subsetFont);
|
||||
if (subsetFontSize > 0 && subsetFont != NULL) {
|
||||
SkAutoDataUnref data(SkData::NewWithProc(subsetFont,
|
||||
|
@ -751,13 +746,26 @@ SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) {
|
|||
relatedFontDescriptor = relatedFont->getFontDescriptor();
|
||||
} else {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo info;
|
||||
info = SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo;
|
||||
info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>(
|
||||
info, SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo);
|
||||
info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo;
|
||||
info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>(
|
||||
info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo);
|
||||
fontMetrics = SkFontHost::GetAdvancedTypefaceMetrics(fontID, info);
|
||||
#if !defined (SK_SFNTLY_SUBSETTER)
|
||||
info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>(
|
||||
info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo);
|
||||
#endif
|
||||
fontMetrics =
|
||||
SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0);
|
||||
#if defined (SK_SFNTLY_SUBSETTER)
|
||||
SkSafeUnref(fontMetrics.get()); // SkRefPtr and Get both took a ref.
|
||||
if (fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) {
|
||||
// Font does not support subsetting, get new info with advance.
|
||||
info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>(
|
||||
info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo);
|
||||
fontMetrics =
|
||||
SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0);
|
||||
SkSafeUnref(fontMetrics.get()); // SkRefPtr and Get both took a ref
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID,
|
||||
|
@ -850,6 +858,13 @@ SkAdvancedTypefaceMetrics* SkPDFFont::fontInfo() {
|
|||
return fFontInfo.get();
|
||||
}
|
||||
|
||||
void SkPDFFont::setFontInfo(SkAdvancedTypefaceMetrics* info) {
|
||||
if (info == NULL || info == fFontInfo.get()) {
|
||||
return;
|
||||
}
|
||||
fFontInfo = info;
|
||||
}
|
||||
|
||||
uint16_t SkPDFFont::firstGlyphID() const {
|
||||
return fFirstGlyphID;
|
||||
}
|
||||
|
@ -978,9 +993,10 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) {
|
|||
insertName("BaseFont", fontInfo()->fFontName);
|
||||
insertName("Encoding", "Identity-H");
|
||||
|
||||
SkPDFCIDFont* newCIDFont;
|
||||
newCIDFont = new SkPDFCIDFont(fontInfo(), typeface(), subset);
|
||||
|
||||
// Pass ref new created to fResources.
|
||||
SkPDFCIDFont* newCIDFont =
|
||||
new SkPDFCIDFont(fontInfo(), typeface(), subset);
|
||||
addResource(newCIDFont);
|
||||
SkRefPtr<SkPDFArray> descendantFonts = new SkPDFArray();
|
||||
descendantFonts->unref(); // SkRefPtr and new took a reference.
|
||||
|
@ -1006,18 +1022,19 @@ SkPDFCIDFont::SkPDFCIDFont(SkAdvancedTypefaceMetrics* info,
|
|||
SkPDFCIDFont::~SkPDFCIDFont() {}
|
||||
|
||||
bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
|
||||
const SkPDFGlyphSet* subset) {
|
||||
const SkTDArray<uint32_t>* subset) {
|
||||
SkRefPtr<SkPDFDict> descriptor = new SkPDFDict("FontDescriptor");
|
||||
descriptor->unref(); // SkRefPtr and new both took a ref.
|
||||
setFontDescriptor(descriptor.get());
|
||||
|
||||
switch (getType()) {
|
||||
case SkAdvancedTypefaceMetrics::kTrueType_Font: {
|
||||
SkASSERT(subset);
|
||||
// Font subsetting
|
||||
SkPDFStream* rawStream = NULL;
|
||||
int fontSize = get_subset_font_stream(fontInfo()->fFontName.c_str(),
|
||||
typeface(),
|
||||
subset,
|
||||
*subset,
|
||||
&rawStream);
|
||||
SkASSERT(fontSize);
|
||||
SkASSERT(rawStream);
|
||||
|
@ -1060,6 +1077,36 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
|
|||
}
|
||||
|
||||
bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
|
||||
// Generate new font metrics with advance info for true type fonts.
|
||||
if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
|
||||
// Generate glyph id array.
|
||||
SkTDArray<uint32_t> glyphIDs;
|
||||
glyphIDs.push(0); // Always include glyph 0.
|
||||
if (subset) {
|
||||
subset->exportTo(&glyphIDs);
|
||||
}
|
||||
|
||||
SkRefPtr<SkAdvancedTypefaceMetrics> fontMetrics;
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo info;
|
||||
info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo;
|
||||
info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>(
|
||||
info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo);
|
||||
uint32_t* glyphs = (glyphIDs.count() == 1) ? NULL : glyphIDs.begin();
|
||||
uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0;
|
||||
fontMetrics =
|
||||
SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
SkTypeface::UniqueID(typeface()),
|
||||
info,
|
||||
glyphs,
|
||||
glyphsCount);
|
||||
SkSafeUnref(fontMetrics.get()); // SkRefPtr and Get both took a ref
|
||||
setFontInfo(fontMetrics.get());
|
||||
addFontDescriptor(0, &glyphIDs);
|
||||
} else {
|
||||
// Other CID fonts
|
||||
addFontDescriptor(0, NULL);
|
||||
}
|
||||
|
||||
insertName("BaseFont", fontInfo()->fFontName);
|
||||
|
||||
if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) {
|
||||
|
@ -1078,8 +1125,6 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
|
|||
sysInfo->insertInt("Supplement", 0);
|
||||
insert("CIDSystemInfo", sysInfo.get());
|
||||
|
||||
addFontDescriptor(0, subset);
|
||||
|
||||
if (fontInfo()->fGlyphWidths.get()) {
|
||||
int16_t defaultWidth = 0;
|
||||
SkRefPtr<SkPDFArray> widths =
|
||||
|
|
|
@ -46,7 +46,8 @@ private:
|
|||
const SkPDFGlyphSet* subset);
|
||||
|
||||
bool populate(const SkPDFGlyphSet* subset);
|
||||
bool addFontDescriptor(int16_t defaultWidth, const SkPDFGlyphSet* subset);
|
||||
bool addFontDescriptor(int16_t defaultWidth,
|
||||
const SkTDArray<uint32_t>* subset);
|
||||
};
|
||||
|
||||
class SkPDFType1Font : public SkPDFFont {
|
||||
|
|
|
@ -408,7 +408,9 @@ static void populate_glyph_to_unicode(FT_Face& face,
|
|||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount) {
|
||||
#if defined(SK_BUILD_FOR_MAC) || defined(ANDROID)
|
||||
return NULL;
|
||||
#else
|
||||
|
@ -552,7 +554,11 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(face, face->num_glyphs, &getWidthAdvance));
|
||||
getAdvanceData(face,
|
||||
face->num_glyphs,
|
||||
glyphIDs,
|
||||
glyphIDsCount,
|
||||
&getWidthAdvance));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,6 +594,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
return info;
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool bothZero(SkScalar a, SkScalar b) {
|
||||
|
|
|
@ -476,7 +476,9 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
|||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -609,4 +611,3 @@ size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
|
|||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
|
@ -761,7 +761,9 @@ static bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) {
|
|||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount) {
|
||||
CTFontRef ctFont = GetFontRefFromFontID(fontID);
|
||||
ctFont = CTFontCreateCopyWithAttributes(ctFont, CTFontGetUnitsPerEm(ctFont),
|
||||
NULL, NULL);
|
||||
|
@ -847,7 +849,11 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
SkAdvancedTypefaceMetrics::WidthRange::kDefault);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(ctFont, glyphCount, &getWidthAdvance));
|
||||
getAdvanceData(ctFont,
|
||||
glyphCount,
|
||||
glyphIDs,
|
||||
glyphIDsCount,
|
||||
&getWidthAdvance));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1115,7 +1121,3 @@ size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
|
|||
memcpy(data, CFDataGetBytePtr(cfData) + offset, length);
|
||||
return(length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -743,7 +743,9 @@ static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
|
|||
// static
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID,
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
|
||||
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
|
||||
const uint32_t* glyphIDs,
|
||||
uint32_t glyphIDsCount) {
|
||||
LOGFONT lf;
|
||||
GetLogFontByID(fontID, &lf);
|
||||
SkAdvancedTypefaceMetrics* info = NULL;
|
||||
|
@ -863,7 +865,11 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
SkAdvancedTypefaceMetrics::WidthRange::kDefault);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(hdc, glyphCount, &getWidthAdvance));
|
||||
getAdvanceData(hdc,
|
||||
glyphCount,
|
||||
glyphIDs,
|
||||
glyphIDsCount,
|
||||
&getWidthAdvance));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче