Cleanup SkPDFTypfaceInfo and make it more generic.
Renamed to SkAdvancedTypefaceMetrics. Include Em size and return all metrics in unscaled font units. Make retrieval of advances optional. Reorder SkAdvancedTypefaceMetrics to be somewhat logical. Change the types of fields in SkAdvancedTypefaceMetrics to their minimum required size. Review URL: http://codereview.appspot.com/4121049 git-svn-id: http://skia.googlecode.com/svn/trunk@752 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
0748f217ba
commit
c48b2b330f
@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SkPDFTypefaceInfo_DEFINED
|
||||
#define SkPDFTypefaceInfo_DEFINED
|
||||
#ifndef SkAdvancedTypefaceMetrics_DEFINED
|
||||
#define SkAdvancedTypefaceMetrics_DEFINED
|
||||
|
||||
#include "SkRect.h"
|
||||
#include "SkRefCnt.h"
|
||||
@ -24,15 +24,17 @@
|
||||
#include "SkTemplates.h"
|
||||
#include "SkTScopedPtr.h"
|
||||
|
||||
/** \class SkPDFTypefaceInfo
|
||||
/** \class SkAdvancedTypefaceMetrics
|
||||
|
||||
The SkPDFTypefaceInfo is used by the PDF backend to correctly embed
|
||||
typefaces. This class is filled in with information about a given typeface
|
||||
by the SkFontHost class.
|
||||
The SkAdvancedTypefaceMetrics class is used by the PDF backend to correctly
|
||||
embed typefaces. This class is filled in with information about a given
|
||||
typeface by the SkFontHost class.
|
||||
*/
|
||||
|
||||
class SkPDFTypefaceInfo : public SkRefCnt {
|
||||
class SkAdvancedTypefaceMetrics : public SkRefCnt {
|
||||
public:
|
||||
SkString fFontName;
|
||||
|
||||
enum FontType {
|
||||
kType1_Font,
|
||||
kType1CID_Font,
|
||||
@ -43,52 +45,15 @@ public:
|
||||
};
|
||||
// The type of the underlying font program. This field determines which
|
||||
// of the following fields are valid. If it is kOther_Font or
|
||||
// kNotEmbeddable_Font, fFontName may be valid, but no other fields are
|
||||
// valid.
|
||||
// kNotEmbeddable_Font, the per glyph information will never be populated.
|
||||
FontType fType;
|
||||
|
||||
// fMultiMaster may be true for Type1_Font or CFF_Font.
|
||||
bool fMultiMaster;
|
||||
SkString fFontName;
|
||||
SkIRect fBBox; // The bounding box of all glyphs (in font units).
|
||||
uint16_t fLastGlyphID; // The last valid glyph ID in the font.
|
||||
uint16_t fEmSize; // The size of the em box (defines font units).
|
||||
|
||||
uint16_t fLastGlyphID;
|
||||
|
||||
template <typename Data>
|
||||
struct AdvanceMetric {
|
||||
enum MetricType {
|
||||
kDefault, // Default advance: fAdvance.count = 1
|
||||
kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
|
||||
kRun, // fStartID-fEndID have same advance: fAdvance.count = 1
|
||||
};
|
||||
MetricType fType;
|
||||
int fStartId;
|
||||
int fEndId;
|
||||
SkTDArray<Data> fAdvance;
|
||||
SkTScopedPtr<AdvanceMetric<Data> > fNext;
|
||||
};
|
||||
|
||||
struct VerticalMetric {
|
||||
int fVerticalAdvance;
|
||||
int fOriginXDisp; // Horizontal displacement of the secondary origin.
|
||||
int fOriginYDisp; // Vertical displacement of the secondary origin.
|
||||
};
|
||||
typedef AdvanceMetric<int> WidthRange;
|
||||
typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
|
||||
|
||||
// This is indexed by glyph id.
|
||||
SkTScopedPtr<WidthRange> fGlyphWidths;
|
||||
// Only used for Vertical CID fonts.
|
||||
SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
|
||||
|
||||
// The names of each glyph, only populated for postscript fonts.
|
||||
SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
|
||||
|
||||
// Metrics: probably used by the pdf renderer for substitution, which
|
||||
// shouldn't be needed with embedding fonts. Optional fields with a value
|
||||
// of 0 will be ignored.
|
||||
|
||||
// The enum values match the values used in the PDF file format.
|
||||
// These enum values match the values used in the PDF file format.
|
||||
enum StyleFlags {
|
||||
kFixedPitch_Style = 0x00001,
|
||||
kSerif_Style = 0x00002,
|
||||
@ -101,21 +66,45 @@ public:
|
||||
kForceBold_Style = 0x40000,
|
||||
};
|
||||
uint16_t fStyle; // Font style characteristics.
|
||||
long fItalicAngle; // Counterclockwise degrees from vertical of the
|
||||
int16_t fItalicAngle; // Counterclockwise degrees from vertical of the
|
||||
// dominant vertical stroke for an Italic face.
|
||||
SkScalar fAscent; // Max height above baseline, not including accents.
|
||||
SkScalar fDescent; // Max depth below baseline (negative).
|
||||
SkScalar fStemV; // Thickness of dominant vertical stem.
|
||||
SkScalar fCapHeight; // Height (from baseline) of top of flat capitals.
|
||||
// The following fields are all in font units.
|
||||
int16_t fAscent; // Max height above baseline, not including accents.
|
||||
int16_t fDescent; // Max depth below baseline (negative).
|
||||
int16_t fStemV; // Thickness of dominant vertical stem.
|
||||
int16_t fCapHeight; // Height (from baseline) of top of flat capitals.
|
||||
|
||||
/* Omit the optional entries. Better to let the viewer compute them, since
|
||||
* it has to be able to anyway.
|
||||
SkScalar fLeading; // Space between lines. Optional.
|
||||
SkScalar fXHeight; // Height of top of 'x'. Optional.
|
||||
SkScalar fStemH; // Thickness of dominant horizontal stem. Optional.
|
||||
SkScalar fAvgWidth; // Average width of glyphs. Optional.
|
||||
SkScalar fMaxWidth; // Max width of a glyph. Optional.
|
||||
*/
|
||||
SkIRect fBBox; // The bounding box of all glyphs (in font units).
|
||||
|
||||
template <typename Data>
|
||||
struct AdvanceMetric {
|
||||
enum MetricType {
|
||||
kDefault, // Default advance: fAdvance.count = 1
|
||||
kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
|
||||
kRun, // fStartID-fEndID have same advance: fAdvance.count = 1
|
||||
};
|
||||
MetricType fType;
|
||||
uint16_t fStartId;
|
||||
uint16_t fEndId;
|
||||
SkTDArray<Data> fAdvance;
|
||||
SkTScopedPtr<AdvanceMetric<Data> > fNext;
|
||||
};
|
||||
|
||||
struct VerticalMetric {
|
||||
int16_t fVerticalAdvance;
|
||||
int16_t fOriginXDisp; // Horiz. displacement of the secondary origin.
|
||||
int16_t fOriginYDisp; // Vert. displacement of the secondary origin.
|
||||
};
|
||||
typedef AdvanceMetric<int16_t> WidthRange;
|
||||
typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
|
||||
|
||||
// This is indexed by glyph id.
|
||||
SkTScopedPtr<WidthRange> fGlyphWidths;
|
||||
// Only used for Vertical CID fonts.
|
||||
SkTScopedPtr<VerticalAdvanceRange> fVerticalMetrics;
|
||||
|
||||
// The names of each glyph, only populated for postscript fonts.
|
||||
SkTScopedPtr<SkAutoTArray<SkString> > fGlyphNames;
|
||||
};
|
||||
|
||||
#endif
|
@ -176,10 +176,15 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Retrieve information about the typeface needed for inclusion in a
|
||||
PDF output device. Returns NULL if it is unable to find the font.
|
||||
/** Retrieve detailed typeface metrics. Used by the PDF backend.
|
||||
@param perGlyphInfo Indicate if the glyph specific information.
|
||||
@param perGlyphInfo Indicate if the glyph specific information (advances
|
||||
and names) should be populated.
|
||||
@return The returned object has already been referenced. NULL is
|
||||
returned if the font is not found.
|
||||
*/
|
||||
static SkPDFTypefaceInfo* GetPDFTypefaceInfo(SkFontID);
|
||||
static SkAdvancedTypefaceMetrics* GetAdvancedTypefaceMetrics(
|
||||
SkFontID fontID, bool perGlyphInfo);
|
||||
|
||||
/** Return the number of tables in the font
|
||||
*/
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class SkStream;
|
||||
class SkPDFTypefaceInfo;
|
||||
class SkAdvancedTypefaceMetrics;
|
||||
class SkWStream;
|
||||
|
||||
/** \class SkTypeface
|
||||
@ -131,10 +131,13 @@ public:
|
||||
*/
|
||||
static SkTypeface* Deserialize(SkStream*);
|
||||
|
||||
/** Retrieve information about the typeface needed for inclusion in a
|
||||
PDF output device.
|
||||
/** Retrieve detailed typeface metrics. Used by the PDF backend.
|
||||
@param perGlyphInfo Indicate if the glyph specific information (advances
|
||||
and names) should be populated.
|
||||
@return The returned object has already been referenced.
|
||||
*/
|
||||
SkPDFTypefaceInfo* getPDFTypefaceInfo() const;
|
||||
SkAdvancedTypefaceMetrics* getAdvancedTypefaceMetrics(
|
||||
bool perGlyphInfo) const;
|
||||
|
||||
protected:
|
||||
/** uniqueID must be unique (please!) and non-zero
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "SkThread.h"
|
||||
|
||||
class SkPaint;
|
||||
class SkPDFTypefaceInfo;
|
||||
class SkAdvancedTypefaceMetrics;
|
||||
|
||||
/** \class SkPDFFont
|
||||
A PDF Object class representing a font. The font may have resources
|
||||
@ -88,7 +88,7 @@ private:
|
||||
uint16_t fLastGlyphID;
|
||||
// The font info is only kept around after construction for large
|
||||
// Type1 (non CID) fonts that need multiple "fonts" to access all glyphs.
|
||||
SkRefPtr<SkPDFTypefaceInfo> fFontInfo;
|
||||
SkRefPtr<SkAdvancedTypefaceMetrics> fFontInfo;
|
||||
SkTDArray<SkPDFObject*> fResources;
|
||||
SkRefPtr<SkPDFDict> fDescriptor;
|
||||
|
||||
@ -120,14 +120,14 @@ private:
|
||||
* for this font, pass it in here, otherwise pass
|
||||
* NULL.
|
||||
*/
|
||||
SkPDFFont(class SkPDFTypefaceInfo* fontInfo, uint32_t fontID,
|
||||
SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, uint32_t fontID,
|
||||
uint16_t glyphID, bool descendantFont, SkPDFDict* fontDescriptor);
|
||||
|
||||
void populateType0Font();
|
||||
void populateCIDFont();
|
||||
bool populateType1Font(uint16_t firstGlyphID, uint16_t lastGlyphID);
|
||||
void populateType3Font();
|
||||
bool addFontDescriptor(int defaultWidth);
|
||||
bool addFontDescriptor(int16_t defaultWidth);
|
||||
|
||||
static bool find(uint32_t fontID, uint16_t glyphID, int* index);
|
||||
};
|
||||
|
@ -75,6 +75,7 @@ SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
|
||||
return SkFontHost::Deserialize(stream);
|
||||
}
|
||||
|
||||
SkPDFTypefaceInfo* SkTypeface::getPDFTypefaceInfo() const {
|
||||
return SkFontHost::GetPDFTypefaceInfo(fUniqueID);
|
||||
SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
|
||||
bool perGlyphInfo) const {
|
||||
return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID, perGlyphInfo);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "SkPaint.h"
|
||||
#include "SkPDFFont.h"
|
||||
#include "SkPDFStream.h"
|
||||
#include "SkPDFTypefaceInfo.h"
|
||||
#include "SkAdvancedTypefaceMetrics.h"
|
||||
#include "SkPDFTypes.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTypeface.h"
|
||||
@ -221,46 +221,58 @@ SkStream* handleType1Stream(SkStream* srcStream, size_t* headerLen,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SkPDFArray* appendWidth(const int& width, SkPDFArray* array) {
|
||||
array->append(new SkPDFInt(width))->unref();
|
||||
SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
|
||||
if (emSize == 1000)
|
||||
return SkIntToScalar(val);
|
||||
int intVal = ((int)val) * 1000;
|
||||
return SkIntToScalar(intVal) * SkScalarInvert(SkIntToScalar(emSize));
|
||||
}
|
||||
|
||||
SkPDFArray* appendWidth(const int16_t& width, uint16_t emSize,
|
||||
SkPDFArray* array) {
|
||||
array->append(new SkPDFScalar(scaleFromFontUnits(width, emSize)))->unref();
|
||||
return array;
|
||||
}
|
||||
|
||||
SkPDFArray* appendVerticalAdvance(
|
||||
const SkPDFTypefaceInfo::VerticalMetric& advance, SkPDFArray* array) {
|
||||
appendWidth(advance.fVerticalAdvance, array);
|
||||
appendWidth(advance.fOriginXDisp, array);
|
||||
appendWidth(advance.fOriginYDisp, array);
|
||||
const SkAdvancedTypefaceMetrics::VerticalMetric& advance,
|
||||
uint16_t emSize, SkPDFArray* array) {
|
||||
appendWidth(advance.fVerticalAdvance, emSize, array);
|
||||
appendWidth(advance.fOriginXDisp, emSize, array);
|
||||
appendWidth(advance.fOriginYDisp, emSize, array);
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
SkPDFArray* composeAdvanceData(
|
||||
SkPDFTypefaceInfo::AdvanceMetric<Data>* advanceInfo,
|
||||
SkPDFArray* (*appendAdvance)(const Data& advance, SkPDFArray* array),
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* advanceInfo,
|
||||
uint16_t emSize,
|
||||
SkPDFArray* (*appendAdvance)(const Data& advance, uint16_t emSize,
|
||||
SkPDFArray* array),
|
||||
Data* defaultAdvance) {
|
||||
SkPDFArray* result = new SkPDFArray();
|
||||
for (; advanceInfo != NULL; advanceInfo = advanceInfo->fNext.get()) {
|
||||
switch (advanceInfo->fType) {
|
||||
case SkPDFTypefaceInfo::WidthRange::kDefault: {
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kDefault: {
|
||||
SkASSERT(advanceInfo->fAdvance.count() == 1);
|
||||
*defaultAdvance = advanceInfo->fAdvance[0];
|
||||
break;
|
||||
}
|
||||
case SkPDFTypefaceInfo::WidthRange::kRange: {
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kRange: {
|
||||
SkRefPtr<SkPDFArray> advanceArray = new SkPDFArray();
|
||||
advanceArray->unref(); // SkRefPtr and new both took a ref.
|
||||
for (int j = 0; j < advanceInfo->fAdvance.count(); j++)
|
||||
appendAdvance(advanceInfo->fAdvance[j], advanceArray.get());
|
||||
appendAdvance(advanceInfo->fAdvance[j], emSize,
|
||||
advanceArray.get());
|
||||
result->append(new SkPDFInt(advanceInfo->fStartId))->unref();
|
||||
result->append(advanceArray.get());
|
||||
break;
|
||||
}
|
||||
case SkPDFTypefaceInfo::WidthRange::kRun: {
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kRun: {
|
||||
SkASSERT(advanceInfo->fAdvance.count() == 1);
|
||||
result->append(new SkPDFInt(advanceInfo->fStartId))->unref();
|
||||
result->append(new SkPDFInt(advanceInfo->fEndId))->unref();
|
||||
appendAdvance(advanceInfo->fAdvance[0], result);
|
||||
appendAdvance(advanceInfo->fAdvance[0], emSize, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -355,7 +367,7 @@ SkPDFFont* SkPDFFont::getFontResource(uint32_t fontID, uint16_t glyphID) {
|
||||
return canonicalFonts()[index].fFont;
|
||||
}
|
||||
|
||||
SkRefPtr<SkPDFTypefaceInfo> fontInfo;
|
||||
SkRefPtr<SkAdvancedTypefaceMetrics> fontInfo;
|
||||
SkPDFDict* fontDescriptor = NULL;
|
||||
if (index >= 0) {
|
||||
SkPDFFont* relatedFont = canonicalFonts()[index].fFont;
|
||||
@ -363,7 +375,7 @@ SkPDFFont* SkPDFFont::getFontResource(uint32_t fontID, uint16_t glyphID) {
|
||||
fontInfo = relatedFont->fFontInfo;
|
||||
fontDescriptor = relatedFont->fDescriptor.get();
|
||||
} else {
|
||||
fontInfo = SkFontHost::GetPDFTypefaceInfo(fontID);
|
||||
fontInfo = SkFontHost::GetAdvancedTypefaceMetrics(fontID, true);
|
||||
fontInfo->unref(); // SkRefPtr and get info both took a reference.
|
||||
}
|
||||
|
||||
@ -401,7 +413,7 @@ bool SkPDFFont::find(uint32_t fontID, uint16_t glyphID, int* index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkPDFFont::SkPDFFont(class SkPDFTypefaceInfo* fontInfo, uint32_t fontID,
|
||||
SkPDFFont::SkPDFFont(class SkAdvancedTypefaceMetrics* fontInfo, uint32_t fontID,
|
||||
uint16_t glyphID, bool descendantFont,
|
||||
SkPDFDict* fontDescriptor)
|
||||
: SkPDFDict("Font"),
|
||||
@ -416,17 +428,18 @@ SkPDFFont::SkPDFFont(class SkPDFTypefaceInfo* fontInfo, uint32_t fontID,
|
||||
fDescriptor(fontDescriptor) {
|
||||
|
||||
if (fontInfo->fMultiMaster) {
|
||||
SkASSERT(false); // Not supported yet.
|
||||
populateType3Font();
|
||||
} else {
|
||||
switch (fontInfo->fType) {
|
||||
case SkPDFTypefaceInfo::kType1CID_Font:
|
||||
case SkPDFTypefaceInfo::kTrueType_Font:
|
||||
case SkAdvancedTypefaceMetrics::kType1CID_Font:
|
||||
case SkAdvancedTypefaceMetrics::kTrueType_Font:
|
||||
if (descendantFont)
|
||||
populateCIDFont();
|
||||
else
|
||||
populateType0Font();
|
||||
break;
|
||||
case SkPDFTypefaceInfo::kType1_Font: {
|
||||
case SkAdvancedTypefaceMetrics::kType1_Font: {
|
||||
uint16_t firstGlyphID = glyphID - (glyphID - 1) % 255;
|
||||
uint16_t lastGlyphID = firstGlyphID + 255 - 1;
|
||||
if (lastGlyphID > fLastGlyphID)
|
||||
@ -435,17 +448,19 @@ SkPDFFont::SkPDFFont(class SkPDFTypefaceInfo* fontInfo, uint32_t fontID,
|
||||
break;
|
||||
// else, fall through.
|
||||
}
|
||||
case SkPDFTypefaceInfo::kOther_Font:
|
||||
case SkPDFTypefaceInfo::kNotEmbeddable_Font:
|
||||
case SkAdvancedTypefaceMetrics::kOther_Font:
|
||||
case SkAdvancedTypefaceMetrics::kNotEmbeddable_Font:
|
||||
populateType3Font();
|
||||
break;
|
||||
case SkPDFTypefaceInfo::kCFF_Font:
|
||||
case SkAdvancedTypefaceMetrics::kCFF_Font:
|
||||
SkASSERT(false); // Not supported yet.
|
||||
populateType3Font();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Type1 fonts may hold on to the font info, otherwise we are done with it.
|
||||
if (fontInfo->fType != SkPDFTypefaceInfo::kType1_Font)
|
||||
if (fontInfo->fType != SkAdvancedTypefaceMetrics::kType1_Font)
|
||||
fFontInfo = NULL;
|
||||
}
|
||||
|
||||
@ -468,15 +483,16 @@ void SkPDFFont::populateType0Font() {
|
||||
|
||||
void SkPDFFont::populateCIDFont() {
|
||||
fMultiByteGlyphs = true;
|
||||
|
||||
insert("BaseFont", new SkPDFName(fFontInfo.get()->fFontName))->unref();
|
||||
|
||||
if (fFontInfo.get()->fType == SkPDFTypefaceInfo::kType1CID_Font)
|
||||
if (fFontInfo.get()->fType == SkAdvancedTypefaceMetrics::kType1CID_Font) {
|
||||
insert("Subtype", new SkPDFName("CIDFontType0"))->unref();
|
||||
else if (fFontInfo.get()->fType == SkPDFTypefaceInfo::kTrueType_Font)
|
||||
} else if (fFontInfo.get()->fType ==
|
||||
SkAdvancedTypefaceMetrics::kTrueType_Font) {
|
||||
insert("Subtype", new SkPDFName("CIDFontType2"))->unref();
|
||||
else
|
||||
} else {
|
||||
SkASSERT(false);
|
||||
}
|
||||
|
||||
SkRefPtr<SkPDFDict> sysInfo = new SkPDFDict;
|
||||
sysInfo->unref(); // SkRefPtr and new both took a reference.
|
||||
@ -488,24 +504,27 @@ void SkPDFFont::populateCIDFont() {
|
||||
addFontDescriptor(0);
|
||||
|
||||
if (fFontInfo.get()->fGlyphWidths.get()) {
|
||||
int defaultWidth = 0;
|
||||
int16_t defaultWidth = 0;
|
||||
SkRefPtr<SkPDFArray> widths =
|
||||
composeAdvanceData(fFontInfo.get()->fGlyphWidths.get(),
|
||||
&appendWidth, &defaultWidth);
|
||||
fFontInfo.get()->fEmSize, &appendWidth,
|
||||
&defaultWidth);
|
||||
widths->unref(); // SkRefPtr and compose both took a reference.
|
||||
if (widths->size())
|
||||
insert("W", widths.get());
|
||||
if (defaultWidth != 0) {
|
||||
insert("DW", new SkPDFInt(defaultWidth))->unref();
|
||||
insert("DW", new SkPDFScalar(scaleFromFontUnits(
|
||||
defaultWidth, fFontInfo.get()->fEmSize)))->unref();
|
||||
}
|
||||
}
|
||||
if (fFontInfo.get()->fVerticalMetrics.get()) {
|
||||
struct SkPDFTypefaceInfo::VerticalMetric defaultAdvance;
|
||||
struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance;
|
||||
defaultAdvance.fVerticalAdvance = 0;
|
||||
defaultAdvance.fOriginXDisp = 0;
|
||||
defaultAdvance.fOriginYDisp = 0;
|
||||
SkRefPtr<SkPDFArray> advances =
|
||||
composeAdvanceData(fFontInfo.get()->fVerticalMetrics.get(),
|
||||
fFontInfo.get()->fEmSize,
|
||||
&appendVerticalAdvance, &defaultAdvance);
|
||||
advances->unref(); // SkRefPtr and compose both took a ref.
|
||||
if (advances->size())
|
||||
@ -514,6 +533,7 @@ void SkPDFFont::populateCIDFont() {
|
||||
defaultAdvance.fOriginXDisp ||
|
||||
defaultAdvance.fOriginYDisp) {
|
||||
insert("DW2", appendVerticalAdvance(defaultAdvance,
|
||||
fFontInfo.get()->fEmSize,
|
||||
new SkPDFArray))->unref();
|
||||
}
|
||||
}
|
||||
@ -523,20 +543,20 @@ bool SkPDFFont::populateType1Font(uint16_t firstGlyphID, uint16_t lastGlyphID) {
|
||||
SkASSERT(!fFontInfo.get()->fVerticalMetrics.get());
|
||||
SkASSERT(fFontInfo.get()->fGlyphWidths.get());
|
||||
|
||||
int defaultWidth = 0;
|
||||
const SkPDFTypefaceInfo::WidthRange* widthRangeEntry = NULL;
|
||||
const SkPDFTypefaceInfo::WidthRange* widthEntry;
|
||||
int16_t defaultWidth = 0;
|
||||
const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = NULL;
|
||||
const SkAdvancedTypefaceMetrics::WidthRange* widthEntry;
|
||||
for (widthEntry = fFontInfo.get()->fGlyphWidths.get();
|
||||
widthEntry != NULL;
|
||||
widthEntry = widthEntry->fNext.get()) {
|
||||
switch (widthEntry->fType) {
|
||||
case SkPDFTypefaceInfo::WidthRange::kDefault:
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kDefault:
|
||||
defaultWidth = widthEntry->fAdvance[0];
|
||||
break;
|
||||
case SkPDFTypefaceInfo::WidthRange::kRun:
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kRun:
|
||||
SkASSERT(false);
|
||||
break;
|
||||
case SkPDFTypefaceInfo::WidthRange::kRange:
|
||||
case SkAdvancedTypefaceMetrics::WidthRange::kRange:
|
||||
SkASSERT(widthRangeEntry == NULL);
|
||||
widthRangeEntry = widthEntry;
|
||||
break;
|
||||
@ -552,6 +572,7 @@ bool SkPDFFont::populateType1Font(uint16_t firstGlyphID, uint16_t lastGlyphID) {
|
||||
insert("Subtype", new SkPDFName("Type1"))->unref();
|
||||
insert("BaseFont", new SkPDFName(fFontInfo.get()->fFontName))->unref();
|
||||
|
||||
const uint16_t emSize = fFontInfo.get()->fEmSize;
|
||||
SkRefPtr<SkPDFArray> widthArray = new SkPDFArray();
|
||||
widthArray->unref(); // SkRefPtr and new both took a ref.
|
||||
int firstChar = 0;
|
||||
@ -563,14 +584,14 @@ bool SkPDFFont::populateType1Font(uint16_t firstGlyphID, uint16_t lastGlyphID) {
|
||||
if (endIndex > widthRangeEntry->fAdvance.count())
|
||||
endIndex = widthRangeEntry->fAdvance.count();
|
||||
if (widthRangeEntry->fStartId == 0) {
|
||||
appendWidth(widthRangeEntry->fAdvance[0], widthArray.get());
|
||||
appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get());
|
||||
} else {
|
||||
firstChar = startIndex + widthRangeEntry->fStartId;
|
||||
}
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
appendWidth(widthRangeEntry->fAdvance[i], widthArray.get());
|
||||
appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get());
|
||||
} else {
|
||||
appendWidth(defaultWidth, widthArray.get());
|
||||
appendWidth(defaultWidth, emSize, widthArray.get());
|
||||
}
|
||||
insert("Widths", widthArray.get());
|
||||
insert("FirstChar", new SkPDFInt(firstChar))->unref();
|
||||
@ -602,7 +623,7 @@ void SkPDFFont::populateType3Font() {
|
||||
SkASSERT(false);
|
||||
}
|
||||
|
||||
bool SkPDFFont::addFontDescriptor(int defaultWidth) {
|
||||
bool SkPDFFont::addFontDescriptor(int16_t defaultWidth) {
|
||||
if (fDescriptor.get() != NULL) {
|
||||
fResources.push(fDescriptor.get());
|
||||
fDescriptor->ref();
|
||||
@ -614,7 +635,7 @@ bool SkPDFFont::addFontDescriptor(int defaultWidth) {
|
||||
fDescriptor->unref(); // SkRefPtr and new both took a ref.
|
||||
|
||||
switch (fFontInfo.get()->fType) {
|
||||
case SkPDFTypefaceInfo::kType1_Font: {
|
||||
case SkAdvancedTypefaceMetrics::kType1_Font: {
|
||||
size_t header, data, trailer;
|
||||
SkRefPtr<SkStream> rawFontData =
|
||||
SkFontHost::OpenStream(fFontID);
|
||||
@ -633,7 +654,7 @@ bool SkPDFFont::addFontDescriptor(int defaultWidth) {
|
||||
new SkPDFObjRef(fontStream.get()))->unref();
|
||||
break;
|
||||
}
|
||||
case SkPDFTypefaceInfo::kTrueType_Font: {
|
||||
case SkAdvancedTypefaceMetrics::kTrueType_Font: {
|
||||
SkRefPtr<SkStream> fontData = SkFontHost::OpenStream(fFontID);
|
||||
fontData->unref(); // SkRefPtr and OpenStream both took a ref.
|
||||
SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get());
|
||||
@ -646,15 +667,16 @@ bool SkPDFFont::addFontDescriptor(int defaultWidth) {
|
||||
new SkPDFObjRef(fontStream.get()))->unref();
|
||||
break;
|
||||
}
|
||||
case SkPDFTypefaceInfo::kCFF_Font:
|
||||
case SkPDFTypefaceInfo::kType1CID_Font: {
|
||||
case SkAdvancedTypefaceMetrics::kCFF_Font:
|
||||
case SkAdvancedTypefaceMetrics::kType1CID_Font: {
|
||||
SkRefPtr<SkStream> fontData = SkFontHost::OpenStream(fFontID);
|
||||
fontData->unref(); // SkRefPtr and OpenStream both took a ref.
|
||||
SkRefPtr<SkPDFStream> fontStream = new SkPDFStream(fontData.get());
|
||||
// SkRefPtr and new both ref()'d fontStream, pass one.
|
||||
fResources.push(fontStream.get());
|
||||
|
||||
if (fFontInfo.get()->fType == SkPDFTypefaceInfo::kCFF_Font) {
|
||||
if (fFontInfo.get()->fType ==
|
||||
SkAdvancedTypefaceMetrics::kCFF_Font) {
|
||||
fontStream->insert("Subtype", new SkPDFName("Type1C"))->unref();
|
||||
} else {
|
||||
fontStream->insert("Subtype",
|
||||
@ -668,38 +690,43 @@ bool SkPDFFont::addFontDescriptor(int defaultWidth) {
|
||||
SkASSERT(false);
|
||||
}
|
||||
|
||||
const uint16_t emSize = fFontInfo.get()->fEmSize;
|
||||
fResources.push(fDescriptor.get());
|
||||
fDescriptor->ref();
|
||||
insert("FontDescriptor", new SkPDFObjRef(fDescriptor.get()))->unref();
|
||||
|
||||
fDescriptor->insert("FontName",
|
||||
new SkPDFName(fFontInfo.get()->fFontName))->unref();
|
||||
fDescriptor->insert("Flags",
|
||||
new SkPDFInt(fFontInfo.get()->fStyle))->unref();
|
||||
fDescriptor->insert("Ascent",
|
||||
new SkPDFScalar(fFontInfo.get()->fAscent))->unref();
|
||||
fDescriptor->insert("Descent",
|
||||
new SkPDFScalar(fFontInfo.get()->fDescent))->unref();
|
||||
fDescriptor->insert("CapHeight",
|
||||
new SkPDFScalar(fFontInfo.get()->fCapHeight))->unref();
|
||||
fDescriptor->insert("StemV",
|
||||
new SkPDFScalar(fFontInfo.get()->fStemV))->unref();
|
||||
fDescriptor->insert("ItalicAngle",
|
||||
new SkPDFInt(fFontInfo.get()->fItalicAngle))->unref();
|
||||
fDescriptor->insert("FontName", new SkPDFName(
|
||||
fFontInfo.get()->fFontName))->unref();
|
||||
fDescriptor->insert("Flags", new SkPDFInt(
|
||||
fFontInfo.get()->fStyle))->unref();
|
||||
fDescriptor->insert("Ascent", new SkPDFScalar(
|
||||
scaleFromFontUnits(fFontInfo.get()->fAscent, emSize)))->unref();
|
||||
fDescriptor->insert("Descent", new SkPDFScalar(
|
||||
scaleFromFontUnits(fFontInfo.get()->fDescent, emSize)))->unref();
|
||||
fDescriptor->insert("StemV", new SkPDFScalar(
|
||||
scaleFromFontUnits(fFontInfo.get()->fStemV, emSize)))->unref();
|
||||
fDescriptor->insert("CapHeight", new SkPDFScalar(
|
||||
scaleFromFontUnits(fFontInfo.get()->fCapHeight, emSize)))->unref();
|
||||
fDescriptor->insert("ItalicAngle", new SkPDFInt(
|
||||
fFontInfo.get()->fItalicAngle))->unref();
|
||||
|
||||
SkIRect glyphBBox = fFontInfo.get()->fBBox;
|
||||
SkRefPtr<SkPDFArray> bbox = new SkPDFArray;
|
||||
bbox->unref(); // SkRefPtr and new both took a reference.
|
||||
bbox->reserve(4);
|
||||
bbox->append(new SkPDFInt(glyphBBox.fLeft))->unref();
|
||||
bbox->append(new SkPDFInt(glyphBBox.fBottom))->unref();
|
||||
bbox->append(new SkPDFInt(glyphBBox.fRight))->unref();
|
||||
bbox->append(new SkPDFInt(glyphBBox.fTop))->unref();
|
||||
bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fLeft,
|
||||
emSize)))->unref();
|
||||
bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fBottom,
|
||||
emSize)))->unref();
|
||||
bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fRight,
|
||||
emSize)))->unref();
|
||||
bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fTop,
|
||||
emSize)))->unref();
|
||||
fDescriptor->insert("FontBBox", bbox.get());
|
||||
|
||||
if (defaultWidth > 0) {
|
||||
fDescriptor->insert("MissingWidth",
|
||||
new SkPDFInt(defaultWidth))->unref();
|
||||
fDescriptor->insert("MissingWidth", new SkPDFScalar(
|
||||
scaleFromFontUnits(defaultWidth, emSize)))->unref();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -270,7 +270,8 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
sk_throw(); // not implemented
|
||||
return NULL;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "SkFDot6.h"
|
||||
#include "SkFontHost.h"
|
||||
#include "SkMask.h"
|
||||
#include "SkPDFTypefaceInfo.h"
|
||||
#include "SkAdvancedTypefaceMetrics.h"
|
||||
#include "SkScalerContext.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkString.h"
|
||||
@ -331,38 +331,38 @@ static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int getWidthAdvance(FT_Face face, int gId, int scaleDivisor) {
|
||||
FT_Fixed unscaledAdvance = 0;
|
||||
SkAssertResult(getAdvances(face, gId, 1, FT_LOAD_NO_SCALE,
|
||||
&unscaledAdvance) == 0);
|
||||
return unscaledAdvance * 1000 / scaleDivisor;
|
||||
static int16_t getWidthAdvance(FT_Face face, int gId) {
|
||||
FT_Fixed advance = 0;
|
||||
SkAssertResult(getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance) == 0);
|
||||
return advance;
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static void resetRange(SkPDFTypefaceInfo::AdvanceMetric<Data>* range,
|
||||
static void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int startId) {
|
||||
range->fStartId = startId;
|
||||
range->fAdvance.setCount(0);
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static SkPDFTypefaceInfo::AdvanceMetric<Data>* appendRange(
|
||||
SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> >* nextSlot,
|
||||
static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
|
||||
int startId) {
|
||||
nextSlot->reset(new SkPDFTypefaceInfo::AdvanceMetric<Data>);
|
||||
nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
|
||||
resetRange(nextSlot->get(), startId);
|
||||
return nextSlot->get();
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static void finishRange(
|
||||
SkPDFTypefaceInfo::AdvanceMetric<Data>* range,
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
|
||||
int endId,
|
||||
typename SkPDFTypefaceInfo::AdvanceMetric<Data>::MetricType type) {
|
||||
typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
|
||||
type) {
|
||||
range->fEndId = endId;
|
||||
range->fType = type;
|
||||
int newLength;
|
||||
if (type == SkPDFTypefaceInfo::AdvanceMetric<Data>::kRange)
|
||||
if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange)
|
||||
newLength = endId - range->fStartId + 1;
|
||||
else
|
||||
newLength = 1;
|
||||
@ -371,10 +371,8 @@ static void finishRange(
|
||||
}
|
||||
|
||||
template <typename Data>
|
||||
static SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData(
|
||||
FT_Face face,
|
||||
int scaleDivisor,
|
||||
Data (*getAdvance)(FT_Face face, int gId, int scaleDivisor)) {
|
||||
static SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
|
||||
FT_Face face, Data (*getAdvance)(FT_Face face, int gId)) {
|
||||
// Assuming that an ASCII representation of a width or a glyph id is,
|
||||
// on average, 3 characters long gives the following cut offs for
|
||||
// using different range types:
|
||||
@ -385,13 +383,13 @@ static SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData(
|
||||
// - Removing 1 0 is a win
|
||||
// - Removing 3 repeats is a win
|
||||
|
||||
SkTScopedPtr<SkPDFTypefaceInfo::AdvanceMetric<Data> > result;
|
||||
SkPDFTypefaceInfo::AdvanceMetric<Data>* curRange;
|
||||
SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
|
||||
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
|
||||
curRange = appendRange(&result, 0);
|
||||
int lastAdvance = INT_MIN;
|
||||
Data lastAdvance = SHRT_MIN;
|
||||
int repeats = 0;
|
||||
for (FT_UInt gId = 0; gId < face->num_glyphs; gId++) {
|
||||
int advance = getAdvance(face, gId, scaleDivisor);
|
||||
for (int gId = 0; gId < face->num_glyphs; gId++) {
|
||||
Data advance = getAdvance(face, gId);
|
||||
if (advance == lastAdvance) {
|
||||
repeats++;
|
||||
} else if (curRange->fAdvance.count() == repeats + 1) {
|
||||
@ -399,22 +397,22 @@ static SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData(
|
||||
resetRange(curRange, gId);
|
||||
} else if (repeats >= 2) {
|
||||
finishRange(curRange, gId - 1,
|
||||
SkPDFTypefaceInfo::WidthRange::kRun);
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
} else {
|
||||
if (lastAdvance == 0 && repeats >= 3) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkPDFTypefaceInfo::WidthRange::kRange);
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
} else if (repeats >= 4) {
|
||||
finishRange(curRange, gId - repeats - 2,
|
||||
SkPDFTypefaceInfo::WidthRange::kRange);
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
curRange = appendRange(&curRange->fNext, gId - repeats - 1);
|
||||
curRange->fAdvance.append(1, &lastAdvance);
|
||||
finishRange(curRange, gId - 1,
|
||||
SkPDFTypefaceInfo::WidthRange::kRun);
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRun);
|
||||
curRange = appendRange(&curRange->fNext, gId);
|
||||
}
|
||||
repeats = 0;
|
||||
@ -423,12 +421,13 @@ static SkPDFTypefaceInfo::AdvanceMetric<Data>* getAdvanceData(
|
||||
lastAdvance = advance;
|
||||
}
|
||||
finishRange(curRange, face->num_glyphs - 1,
|
||||
SkPDFTypefaceInfo::WidthRange::kRange);
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
return result.release();
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
FT_Library libInit = NULL;
|
||||
if (gFTCount == 0) {
|
||||
@ -442,103 +441,83 @@ SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
return NULL;
|
||||
FT_Face face = rec->fFace;
|
||||
|
||||
SkPDFTypefaceInfo* info = new SkPDFTypefaceInfo;
|
||||
info->fMultiMaster = false;
|
||||
SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
|
||||
info->fFontName.set(FT_Get_Postscript_Name(face));
|
||||
info->fMultiMaster = FT_HAS_MULTIPLE_MASTERS(face);
|
||||
info->fLastGlyphID = face->num_glyphs - 1;
|
||||
info->fEmSize = 1000;
|
||||
|
||||
bool cid = false;
|
||||
int scaleDivisor = 1000;
|
||||
const char* fontType = FT_Get_X11_Font_Format(face);
|
||||
if (!canEmbed(face)) {
|
||||
info->fType = SkPDFTypefaceInfo::kNotEmbeddable_Font;
|
||||
} else if (FT_HAS_MULTIPLE_MASTERS(face)) {
|
||||
// PDF requires that embedded MM fonts be reduced to a simple font.
|
||||
info->fType = SkPDFTypefaceInfo::kOther_Font;
|
||||
info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
|
||||
} else if (strcmp(fontType, "Type 1") == 0) {
|
||||
info->fType = SkPDFTypefaceInfo::kType1_Font;
|
||||
info->fType = SkAdvancedTypefaceMetrics::kType1_Font;
|
||||
} else if (strcmp(fontType, "CID Type 1") == 0) {
|
||||
info->fType = SkPDFTypefaceInfo::kType1CID_Font;
|
||||
info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font;
|
||||
cid = true;
|
||||
} else if (strcmp(fontType, "CFF") == 0) {
|
||||
info->fType = SkPDFTypefaceInfo::kCFF_Font;
|
||||
info->fType = SkAdvancedTypefaceMetrics::kCFF_Font;
|
||||
} else if (strcmp(fontType, "TrueType") == 0) {
|
||||
info->fType = SkPDFTypefaceInfo::kTrueType_Font;
|
||||
info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
|
||||
cid = true;
|
||||
TT_Header* ttHeader;
|
||||
if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face,
|
||||
ft_sfnt_head)) != NULL) {
|
||||
scaleDivisor = ttHeader->Units_Per_EM;
|
||||
info->fEmSize = ttHeader->Units_Per_EM;
|
||||
}
|
||||
}
|
||||
info->fFontName.set(FT_Get_Postscript_Name(face));
|
||||
#ifdef FT_IS_CID_KEYED
|
||||
SkASSERT(FT_IS_CID_KEYED(face) ==
|
||||
(info->fType == SkPDFTypefaceInfo::kType1CID_Font));
|
||||
#endif
|
||||
|
||||
if (info->fType == SkPDFTypefaceInfo::kOther_Font ||
|
||||
info->fType == SkPDFTypefaceInfo::kNotEmbeddable_Font ||
|
||||
if (info->fType == SkAdvancedTypefaceMetrics::kOther_Font ||
|
||||
info->fType == SkAdvancedTypefaceMetrics::kNotEmbeddable_Font ||
|
||||
!FT_IS_SCALABLE(face)) {
|
||||
unref_ft_face(face);
|
||||
return info;
|
||||
perGlyphInfo = false;
|
||||
}
|
||||
|
||||
info->fLastGlyphID = face->num_glyphs - 1;
|
||||
|
||||
SkASSERT(!FT_HAS_VERTICAL(face));
|
||||
#ifdef FT_IS_CID_KEYED
|
||||
SkASSERT(FT_IS_CID_KEYED(face) ==
|
||||
(info->fType == SkAdvancedTypefaceMetrics::kType1CID_Font));
|
||||
#endif
|
||||
|
||||
if (FT_IS_FIXED_WIDTH(face)) {
|
||||
appendRange(&info->fGlyphWidths, 0);
|
||||
int advance = face->max_advance_width * 1000 / scaleDivisor;
|
||||
info->fGlyphWidths->fAdvance.append(1, &advance);
|
||||
finishRange(info->fGlyphWidths.get(), 0,
|
||||
SkPDFTypefaceInfo::WidthRange::kDefault);
|
||||
} else if(!cid) {
|
||||
appendRange(&info->fGlyphWidths, 0);
|
||||
// So as to not blow out the stack, get advances in batches.
|
||||
for (int gIDStart = 0; gIDStart < face->num_glyphs; gIDStart += 128) {
|
||||
FT_Fixed advances[128];
|
||||
int advanceCount = 128;
|
||||
if (gIDStart + advanceCount > face->num_glyphs)
|
||||
advanceCount = face->num_glyphs - gIDStart + 1;
|
||||
getAdvances(face, gIDStart, advanceCount, FT_LOAD_NO_SCALE,
|
||||
advances);
|
||||
for (int i = 0; i < advanceCount; i++) {
|
||||
int advance = advances[gIDStart + i];
|
||||
info->fGlyphWidths->fAdvance.append(1, &advance);
|
||||
}
|
||||
}
|
||||
finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
|
||||
SkPDFTypefaceInfo::WidthRange::kRange);
|
||||
} else {
|
||||
// For CID keyed fonts, an identity pdf-cmap is used, so we iterate and
|
||||
// report on glyph ids, not character ids (tt-cmap indices).
|
||||
info->fGlyphWidths.reset(getAdvanceData(face, scaleDivisor,
|
||||
&getWidthAdvance));
|
||||
}
|
||||
|
||||
if (info->fType == SkPDFTypefaceInfo::kType1_Font) {
|
||||
// Postscript fonts may contain more than 255 glyphs, so we end up
|
||||
// using multiple font descriptions with a glyph ordering. Record
|
||||
// the name of each glyph.
|
||||
info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs));
|
||||
for (FT_UInt gID = 0; gID < face->num_glyphs; gID++) {
|
||||
char glyphName[128]; // Postscript limit for names is 127 bytes.
|
||||
FT_Get_Glyph_Name(face, gID, glyphName, 128);
|
||||
info->fGlyphNames->get()[gID].set(glyphName);
|
||||
}
|
||||
}
|
||||
|
||||
info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin * 1000 / scaleDivisor,
|
||||
face->bbox.yMax * 1000 / scaleDivisor,
|
||||
face->bbox.xMax * 1000 / scaleDivisor,
|
||||
face->bbox.yMin * 1000 / scaleDivisor);
|
||||
info->fStyle = 0;
|
||||
if (FT_IS_FIXED_WIDTH(face))
|
||||
info->fStyle |= SkPDFTypefaceInfo::kFixedPitch_Style;
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
|
||||
if (face->style_flags & FT_STYLE_FLAG_ITALIC)
|
||||
info->fStyle |= SkPDFTypefaceInfo::kItalic_Style;
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
|
||||
// We should set either Symbolic or Nonsymbolic; Nonsymbolic if the font's
|
||||
// character set is a subset of 'Adobe standard Latin.'
|
||||
info->fStyle |= SkPDFTypefaceInfo::kSymbolic_Style;
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
|
||||
|
||||
PS_FontInfoRec ps_info;
|
||||
TT_Postscript* tt_info;
|
||||
if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
|
||||
info->fItalicAngle = ps_info.italic_angle;
|
||||
} else if ((tt_info =
|
||||
(TT_Postscript*)FT_Get_Sfnt_Table(face,
|
||||
ft_sfnt_post)) != NULL) {
|
||||
info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
|
||||
} else {
|
||||
info->fItalicAngle = 0;
|
||||
}
|
||||
|
||||
info->fAscent = face->ascender;
|
||||
info->fDescent = face->descender;
|
||||
|
||||
// Figure out a good guess for StemV - Min width of i, I, !, 1.
|
||||
// This probably isn't very good with an italic font.
|
||||
int16_t min_width = SHRT_MAX;
|
||||
char stem_chars[] = {'i', 'I', '!', '1'};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
|
||||
FT_BBox bbox;
|
||||
if (GetLetterCBox(face, stem_chars[i], &bbox)) {
|
||||
int16_t width = bbox.xMax - bbox.xMin;
|
||||
if (width > 0 && width < min_width) {
|
||||
min_width = width;
|
||||
info->fStemV = min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TT_PCLT* pclt_info;
|
||||
TT_OS2* os2_table;
|
||||
@ -546,9 +525,9 @@ SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
info->fCapHeight = pclt_info->CapHeight;
|
||||
uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
|
||||
if (serif_style >= 2 && serif_style <= 6)
|
||||
info->fStyle |= SkPDFTypefaceInfo::kSerif_Style;
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
|
||||
else if (serif_style >= 9 && serif_style <= 12)
|
||||
info->fStyle |= SkPDFTypefaceInfo::kScript_Style;
|
||||
info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
|
||||
} else if ((os2_table =
|
||||
(TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
|
||||
info->fCapHeight = os2_table->sCapHeight;
|
||||
@ -567,38 +546,52 @@ SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
info->fCapHeight = x_bbox.yMax - x_bbox.yMin;
|
||||
}
|
||||
}
|
||||
info->fCapHeight = info->fCapHeight * 1000 / scaleDivisor;
|
||||
|
||||
// Figure out a good guess for StemV - Min width of i, I, !, 1.
|
||||
// This probably isn't very good with an italic font.
|
||||
int min_width = INT_MAX;
|
||||
char stem_chars[] = {'i', 'I', '!', '1'};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
|
||||
FT_BBox bbox;
|
||||
if (GetLetterCBox(face, stem_chars[i], &bbox)) {
|
||||
int width = bbox.xMax - bbox.xMin;
|
||||
if (width > 0 && width < min_width) {
|
||||
min_width = width;
|
||||
info->fStemV = min_width * 1000 / scaleDivisor;
|
||||
info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
|
||||
face->bbox.xMax, face->bbox.yMin);
|
||||
|
||||
if (perGlyphInfo) {
|
||||
if (FT_IS_FIXED_WIDTH(face)) {
|
||||
appendRange(&info->fGlyphWidths, 0);
|
||||
int16_t advance = face->max_advance_width;
|
||||
info->fGlyphWidths->fAdvance.append(1, &advance);
|
||||
finishRange(info->fGlyphWidths.get(), 0,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kDefault);
|
||||
} else if(!cid) {
|
||||
appendRange(&info->fGlyphWidths, 0);
|
||||
// So as to not blow out the stack, get advances in batches.
|
||||
for (int gID = 0; gID < face->num_glyphs; gID += 128) {
|
||||
FT_Fixed advances[128];
|
||||
int advanceCount = 128;
|
||||
if (gID + advanceCount > face->num_glyphs)
|
||||
advanceCount = face->num_glyphs - gID + 1;
|
||||
getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE,
|
||||
advances);
|
||||
for (int i = 0; i < advanceCount; i++) {
|
||||
int16_t advance = advances[gID + i];
|
||||
info->fGlyphWidths->fAdvance.append(1, &advance);
|
||||
}
|
||||
}
|
||||
finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1,
|
||||
SkAdvancedTypefaceMetrics::WidthRange::kRange);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(getAdvanceData(face, &getWidthAdvance));
|
||||
}
|
||||
|
||||
if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
|
||||
// Postscript fonts may contain more than 255 glyphs, so we end up
|
||||
// using multiple font descriptions with a glyph ordering. Record
|
||||
// the name of each glyph.
|
||||
info->fGlyphNames.reset(
|
||||
new SkAutoTArray<SkString>(face->num_glyphs));
|
||||
for (int gID = 0; gID < face->num_glyphs; gID++) {
|
||||
char glyphName[128]; // PS limit for names is 127 bytes.
|
||||
FT_Get_Glyph_Name(face, gID, glyphName, 128);
|
||||
info->fGlyphNames->get()[gID].set(glyphName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PS_FontInfoRec ps_info;
|
||||
TT_Postscript* tt_info;
|
||||
if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
|
||||
info->fItalicAngle = ps_info.italic_angle;
|
||||
} else if ((tt_info =
|
||||
(TT_Postscript*)FT_Get_Sfnt_Table(face,
|
||||
ft_sfnt_post)) != NULL) {
|
||||
info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
|
||||
} else {
|
||||
info->fItalicAngle = 0;
|
||||
}
|
||||
|
||||
info->fAscent = face->ascender * 1000 / scaleDivisor;
|
||||
info->fDescent = face->descender * 1000 / scaleDivisor;
|
||||
|
||||
unref_ft_face(face);
|
||||
return info;
|
||||
}
|
||||
|
@ -585,8 +585,9 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -301,8 +301,9 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -480,8 +480,9 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -604,8 +604,9 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[])
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,9 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) {
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -583,8 +583,9 @@ SkStream* SkFontHost::OpenStream(uint32_t fontID) {
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -464,8 +464,9 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
||||
}
|
||||
|
||||
// static
|
||||
SkPDFTypefaceInfo* SkFontHost::GetPDFTypefaceInfo(uint32_t fontID) {
|
||||
SkASSERT(!"SkFontHost::GetPDFTypefaceInfo unimplemented");
|
||||
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
||||
uint32_t fontID, bool perGlyphInfo) {
|
||||
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user