[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:
vandebo@chromium.org 2011-08-18 02:38:50 +00:00
Родитель 37c472007e
Коммит 37ad8fb72f
13 изменённых файлов: 199 добавлений и 93 удалений

Просмотреть файл

@ -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));
}
}