зеркало из 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
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef uint32_t SkFontTableTag;
|
|||
This class is ported to each environment. It is responsible for bridging
|
||||
the gap between the (sort of) abstract class SkTypeface and the
|
||||
platform-specific implementation that provides access to font files.
|
||||
|
||||
|
||||
One basic task is for each create (subclass of) SkTypeface, the FontHost is
|
||||
resonsible for assigning a uniqueID. The ID should be unique for the
|
||||
underlying font file/data, not unique per typeface instance. Thus it is
|
||||
|
@ -36,7 +36,7 @@ typedef uint32_t SkFontTableTag;
|
|||
returned). Either way, the fontID for those instance(s) will be the same.
|
||||
In addition, the fontID should never be set to 0. That value is used as a
|
||||
sentinel to indicate no-font-id.
|
||||
|
||||
|
||||
The major aspects are:
|
||||
1) Given either a name/style, return a subclass of SkTypeface that
|
||||
references the closest matching font available on the host system.
|
||||
|
@ -65,17 +65,17 @@ public:
|
|||
|
||||
/** Return a new typeface given the data buffer. If the data does not
|
||||
represent a valid font, returns null.
|
||||
|
||||
|
||||
If a typeface instance is returned, the caller is responsible for
|
||||
calling unref() on the typeface when they are finished with it.
|
||||
|
||||
|
||||
The returned typeface may or may not have called ref() on the stream
|
||||
parameter. If the typeface has not called ref(), then it may have made
|
||||
a copy of the releveant data. In either case, the caller is still
|
||||
responsible for its refcnt ownership of the stream.
|
||||
responsible for its refcnt ownership of the stream.
|
||||
*/
|
||||
static SkTypeface* CreateTypefaceFromStream(SkStream*);
|
||||
|
||||
|
||||
/** Return a new typeface from the specified file path. If the file does not
|
||||
represent a valid font, this returns null. If a typeface is returned,
|
||||
the caller is responsible for calling unref() when it is no longer used.
|
||||
|
@ -83,13 +83,13 @@ public:
|
|||
static SkTypeface* CreateTypefaceFromFile(const char path[]);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/** Returns true if the specified unique ID matches an existing font.
|
||||
Returning false is similar to calling OpenStream with an invalid ID,
|
||||
which will return NULL in that case.
|
||||
*/
|
||||
static bool ValidFontID(SkFontID uniqueID);
|
||||
|
||||
|
||||
/** Return a new stream to read the font data, or null if the uniqueID does
|
||||
not match an existing typeface. .The caller must call stream->unref()
|
||||
when it is finished reading the data.
|
||||
|
@ -138,7 +138,7 @@ public:
|
|||
static SkTypeface* Deserialize(SkStream*);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/** Return a subclass of SkScalarContext
|
||||
*/
|
||||
static SkScalerContext* CreateScalerContext(const SkDescriptor* desc);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -199,7 +206,7 @@ public:
|
|||
/** Given a table tag, return the size of its contents, or 0 if not present
|
||||
*/
|
||||
static size_t GetTableSize(SkFontID, SkFontTableTag);
|
||||
|
||||
|
||||
/** Copy the contents of a table into data (allocated by the caller). Note
|
||||
that the contents of the table will be in their native endian order
|
||||
(which for most truetype tables is big endian). If the table tag is
|
||||
|
@ -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) {
|
||||
SkAssertResult(getAdvance(fontHandle, gId, &advance));
|
||||
// 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(
|
||||
|
|
|
@ -43,7 +43,7 @@ uint32_t SkTypeface::UniqueID(const SkTypeface* face) {
|
|||
// The initial value of 0 is fine, since a typeface's uniqueID should not
|
||||
// be zero.
|
||||
static uint32_t gDefaultFontID;
|
||||
|
||||
|
||||
if (0 == gDefaultFontID) {
|
||||
SkTypeface* defaultFace =
|
||||
SkFontHost::CreateTypeface(NULL, NULL, NULL, 0,
|
||||
|
@ -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
|
||||
|
@ -521,7 +523,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax,
|
||||
face->bbox.xMax, face->bbox.yMin);
|
||||
|
||||
if (!canEmbed(face) || !FT_IS_SCALABLE(face) ||
|
||||
if (!canEmbed(face) || !FT_IS_SCALABLE(face) ||
|
||||
info->fType == SkAdvancedTypefaceMetrics::kOther_Font) {
|
||||
perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -622,7 +629,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
|
|||
// to do subpixel, we must have at most slight hinting
|
||||
h = SkPaint::kSlight_Hinting;
|
||||
}
|
||||
#ifndef SK_IGNORE_ROTATED_FREETYPE_FIX
|
||||
#ifndef SK_IGNORE_ROTATED_FREETYPE_FIX
|
||||
// rotated text looks bad with hinting, so we disable it as needed
|
||||
if (!isAxisAligned(*rec)) {
|
||||
h = SkPaint::kNo_Hinting;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
static uint32_t find_from_name(const char name[]) {
|
||||
CFStringRef str = CFStringCreateWithCString(NULL, name,
|
||||
kCFStringEncodingUTF8);
|
||||
kCFStringEncodingUTF8);
|
||||
uint32_t fontID = ::ATSFontFindFromName(str, kATSOptionFlagsDefault);
|
||||
CFRelease(str);
|
||||
return fontID;
|
||||
|
@ -93,7 +93,7 @@ private:
|
|||
ATSUStyle fStyle;
|
||||
CGColorSpaceRef fGrayColorSpace;
|
||||
CGAffineTransform fTransform;
|
||||
|
||||
|
||||
static OSStatus MoveTo(const Float32Point *pt, void *cb);
|
||||
static OSStatus Line(const Float32Point *pt, void *cb);
|
||||
static OSStatus Curve(const Float32Point *pt1, const Float32Point *pt2, const Float32Point *pt3, void *cb);
|
||||
|
@ -122,20 +122,20 @@ SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
|
|||
{
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
OSStatus err;
|
||||
|
||||
|
||||
err = ::ATSUCreateStyle(&fStyle);
|
||||
SkASSERT(0 == err);
|
||||
|
||||
|
||||
SkMatrix m;
|
||||
fRec.getSingleMatrix(&m);
|
||||
|
||||
|
||||
fTransform = CGAffineTransformMake(SkScalarToFloat(m[SkMatrix::kMScaleX]),
|
||||
SkScalarToFloat(m[SkMatrix::kMSkewX]),
|
||||
SkScalarToFloat(m[SkMatrix::kMSkewY]),
|
||||
SkScalarToFloat(m[SkMatrix::kMScaleY]),
|
||||
SkScalarToFloat(m[SkMatrix::kMTransX]),
|
||||
SkScalarToFloat(m[SkMatrix::kMTransY]));
|
||||
|
||||
|
||||
ATSStyleRenderingOptions renderOpts = kATSStyleApplyAntiAliasing;
|
||||
switch (fRec.getHinting()) {
|
||||
case SkPaint::kNo_Hinting:
|
||||
|
@ -192,16 +192,16 @@ unsigned SkScalerContext_Mac::generateGlyphCount() {
|
|||
uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni)
|
||||
{
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
|
||||
|
||||
OSStatus err;
|
||||
UniChar achar = uni;
|
||||
err = ::ATSUSetTextPointerLocation(fLayout,&achar,0,1,1);
|
||||
err = ::ATSUSetRunStyle(fLayout,fStyle,kATSUFromTextBeginning,kATSUToTextEnd);
|
||||
|
||||
|
||||
ATSLayoutRecord *layoutPtr;
|
||||
ItemCount count;
|
||||
ATSGlyphRef glyph;
|
||||
|
||||
|
||||
err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(fLayout,0,kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,(void**)&layoutPtr,&count);
|
||||
glyph = layoutPtr->glyphID;
|
||||
::ATSUDirectReleaseLayoutDataArrayPtr(NULL,kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,(void**)&layoutPtr);
|
||||
|
@ -260,7 +260,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
|
|||
{
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
SkASSERT(fLayout);
|
||||
|
||||
|
||||
sk_bzero(glyph.fImage, glyph.fHeight * glyph.rowBytes());
|
||||
CGContextRef contextRef = ::CGBitmapContextCreate(glyph.fImage,
|
||||
glyph.fWidth, glyph.fHeight, 8,
|
||||
|
@ -270,10 +270,10 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
|
|||
SkASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
::CGContextSetGrayFillColor(contextRef, 1.0, 1.0);
|
||||
::CGContextSetTextDrawingMode(contextRef, kCGTextFill);
|
||||
|
||||
|
||||
CGGlyph glyphID = glyph.getGlyphID(fBaseGlyphCount);
|
||||
CGFontRef fontRef = CGFontCreateWithPlatformFont(&fRec.fFontID);
|
||||
CGContextSetFont(contextRef, fontRef);
|
||||
|
@ -281,7 +281,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
|
|||
CGContextSetTextMatrix(contextRef, fTransform);
|
||||
CGContextShowGlyphsAtPoint(contextRef, -glyph.fLeft,
|
||||
glyph.fTop + glyph.fHeight, &glyphID, 1);
|
||||
|
||||
|
||||
::CGContextRelease(contextRef);
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ static bool init_vertical_metrics(ATSFontRef font, SkPoint pts[5]) {
|
|||
for (int i = 0; i < 5; i++) {
|
||||
pts[i].set(0, SkIntToScalar(ys[i]) / upem);
|
||||
}
|
||||
|
||||
|
||||
sk_free(hhea);
|
||||
sk_free(head);
|
||||
return true;
|
||||
|
@ -368,7 +368,7 @@ static bool init_vertical_metrics(ATSFontRef font, SkPoint pts[5]) {
|
|||
void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx,
|
||||
SkPaint::FontMetrics* my) {
|
||||
SkPoint pts[5];
|
||||
|
||||
|
||||
if (!init_vertical_metrics(fRec.fFontID, pts)) {
|
||||
// these are not as accurate as init_vertical_metrics :(
|
||||
ATSFontMetrics metrics;
|
||||
|
@ -380,7 +380,7 @@ void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx,
|
|||
pts[3].set(0, -SkFloatToScalar(metrics.descent));
|
||||
pts[4].set(0, SkFloatToScalar(metrics.leading)); //+ or -?
|
||||
}
|
||||
|
||||
|
||||
SkMatrix m;
|
||||
fRec.getSingleMatrix(&m);
|
||||
m.mapPoints(pts, 5);
|
||||
|
@ -415,7 +415,7 @@ void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path)
|
|||
{
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
OSStatus err,result;
|
||||
|
||||
|
||||
err = ::ATSUGlyphGetCubicPaths(
|
||||
fStyle,glyph.fID,
|
||||
&SkScalerContext_Mac::MoveTo,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -545,33 +547,33 @@ struct SfntHeader {
|
|||
if (ATSFontGetTableDirectory(fontID, 0, NULL, &size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SkAutoMalloc storage(size);
|
||||
SkSFNTHeader* header = reinterpret_cast<SkSFNTHeader*>(storage.get());
|
||||
if (ATSFontGetTableDirectory(fontID, size, header, &size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fCount = SkEndian_SwapBE16(header->fNumTables);
|
||||
fData = header;
|
||||
storage.detach();
|
||||
}
|
||||
|
||||
|
||||
~SfntHeader() {
|
||||
sk_free(fData);
|
||||
}
|
||||
|
||||
|
||||
int count() const { return fCount; }
|
||||
const SkSFNTDirEntry* entries() const {
|
||||
return reinterpret_cast<const SkSFNTDirEntry*>
|
||||
(reinterpret_cast<char*>(fData) + sizeof(SkSFNTHeader));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int fCount;
|
||||
void* fData;
|
||||
};
|
||||
|
||||
|
||||
int SkFontHost::CountTables(SkFontID fontID) {
|
||||
SfntHeader header(fontID, false);
|
||||
return header.count();
|
||||
|
@ -609,4 +611,3 @@ size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
|
|||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,13 +129,13 @@ static SkTypeface* NewFromName(const char familyName[],
|
|||
CTFontDescriptorRef ctFontDesc;
|
||||
CFStringRef cfFontName;
|
||||
CTFontRef ctFont;
|
||||
|
||||
|
||||
|
||||
|
||||
// Get the state we need
|
||||
ctFontDesc = NULL;
|
||||
ctFont = NULL;
|
||||
ctFontTraits = 0;
|
||||
|
||||
|
||||
if (theStyle & SkTypeface::kBold) {
|
||||
ctFontTraits |= kCTFontBoldTrait;
|
||||
}
|
||||
|
@ -143,27 +143,27 @@ static SkTypeface* NewFromName(const char familyName[],
|
|||
if (theStyle & SkTypeface::kItalic) {
|
||||
ctFontTraits |= kCTFontItalicTrait;
|
||||
}
|
||||
|
||||
|
||||
// Create the font info
|
||||
cfFontName = CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8);
|
||||
cfFontTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits);
|
||||
cfAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
cfTraits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
|
||||
|
||||
|
||||
// Create the font
|
||||
if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) {
|
||||
CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
|
||||
|
||||
|
||||
CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
|
||||
CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
|
||||
|
||||
|
||||
ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
|
||||
if (ctFontDesc != NULL) {
|
||||
ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CFSafeRelease(cfFontName);
|
||||
CFSafeRelease(cfFontTraits);
|
||||
CFSafeRelease(cfAttributes);
|
||||
|
@ -233,7 +233,7 @@ static bool FindByNameStyle(SkTypeface* face, SkTypeface::Style style,
|
|||
void* ctx) {
|
||||
const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face);
|
||||
const NameStyleRec* rec = reinterpret_cast<const NameStyleRec*>(ctx);
|
||||
|
||||
|
||||
return rec->fStyle == style && mface->fName.equals(rec->fName);
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ static const char* map_css_names(const char* name) {
|
|||
{ "serif", "Times" },
|
||||
{ "monospace", "Courier" }
|
||||
};
|
||||
|
||||
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
|
||||
if (strcmp(name, gPairs[i].fFrom) == 0) {
|
||||
return gPairs[i].fTo;
|
||||
|
@ -262,18 +262,18 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||
if (familyName) {
|
||||
familyName = map_css_names(familyName);
|
||||
}
|
||||
|
||||
|
||||
// Clone an existing typeface
|
||||
// TODO: only clone if style matches the familyFace's style...
|
||||
if (familyName == NULL && familyFace != NULL) {
|
||||
familyFace->ref();
|
||||
return const_cast<SkTypeface*>(familyFace);
|
||||
}
|
||||
|
||||
|
||||
if (!familyName || !*familyName) {
|
||||
familyName = FONT_DEFAULT_NAME;
|
||||
}
|
||||
|
||||
|
||||
NameStyleRec rec = { familyName, style };
|
||||
SkTypeface* face = SkTypefaceCache::FindByProc(FindByNameStyle, &rec);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -771,11 +773,11 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
// plus 1 byte for the trailing null.
|
||||
int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(
|
||||
fontName), kCFStringEncodingUTF8) + 1;
|
||||
info->fFontName.resize(length);
|
||||
info->fFontName.resize(length);
|
||||
CFStringGetCString(fontName, info->fFontName.writable_str(), length,
|
||||
kCFStringEncodingUTF8);
|
||||
// Resize to the actual UTF-8 length used, stripping the null character.
|
||||
info->fFontName.resize(strlen(info->fFontName.c_str()));
|
||||
info->fFontName.resize(strlen(info->fFontName.c_str()));
|
||||
info->fMultiMaster = false;
|
||||
CFIndex glyphCount = CTFontGetGlyphCount(ctFont);
|
||||
info->fLastGlyphID = SkToU16(glyphCount - 1);
|
||||
|
@ -824,7 +826,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
CGGlyph glyphs[count];
|
||||
CGRect boundingRects[count];
|
||||
if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) {
|
||||
CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation,
|
||||
CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation,
|
||||
glyphs, boundingRects, count);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
int16_t width = boundingRects[i].size.width;
|
||||
|
@ -847,7 +849,11 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
|
|||
SkAdvancedTypefaceMetrics::WidthRange::kDefault);
|
||||
} else {
|
||||
info->fGlyphWidths.reset(
|
||||
getAdvanceData(ctFont, glyphCount, &getWidthAdvance));
|
||||
getAdvanceData(ctFont,
|
||||
glyphCount,
|
||||
glyphIDs,
|
||||
glyphIDsCount,
|
||||
&getWidthAdvance));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -989,7 +995,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
|
|||
SkScalerContext::kAutohinting_Flag;
|
||||
|
||||
rec->fFlags &= ~flagsWeDontSupport;
|
||||
|
||||
|
||||
// we only support 2 levels of hinting
|
||||
SkPaint::Hinting h = rec->getHinting();
|
||||
if (SkPaint::kSlight_Hinting == h) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче