Serialize the font index.
BUG=skia:1186
R=reed@google.com
Author: bungeman@google.com
Review URL: https://codereview.chromium.org/567013002
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
index f092e77..459ad25 100644
--- a/include/core/SkRefCnt.h
+++ b/include/core/SkRefCnt.h
@@ -234,7 +234,7 @@
BlockRefType *operator->() const {
return static_cast<BlockRefType*>(fObj);
}
- operator T*() { return fObj; }
+ operator T*() const { return fObj; }
private:
T* fObj;
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index 1df467a..cb87a6a 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -114,13 +114,13 @@
/** Return a new typeface given a file. If the file does not exist, or is
not a valid font file, returns null.
*/
- static SkTypeface* CreateFromFile(const char path[]);
+ static SkTypeface* CreateFromFile(const char path[], int index = 0);
/** Return a new typeface given a stream. If the stream is
not a valid font file, returns null. Ownership of the stream is
transferred, so the caller must not reference it again.
*/
- static SkTypeface* CreateFromStream(SkStream* stream);
+ static SkTypeface* CreateFromStream(SkStream* stream, int index = 0);
/** Write a unique signature to a stream, sufficient to reconstruct a
typeface referencing the same font when Deserialize is called.
diff --git a/src/core/SkFontDescriptor.cpp b/src/core/SkFontDescriptor.cpp
index 5088ed7..7426894 100644
--- a/src/core/SkFontDescriptor.cpp
+++ b/src/core/SkFontDescriptor.cpp
@@ -7,6 +7,7 @@
#include "SkFontDescriptor.h"
#include "SkStream.h"
+#include <SkData.h>
enum {
// these must match the sfnt 'name' enums
@@ -16,13 +17,12 @@
// These count backwards from 0xFF, so as not to collide with the SFNT
// defines for names in its 'name' table.
+ kFontIndex = 0xFD,
kFontFileName = 0xFE,
kSentinel = 0xFF,
};
-SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) {
- fStyle = style;
-}
+SkFontDescriptor::SkFontDescriptor(SkTypeface::Style style) : fFontIndex(0), fStyle(style) { }
static void read_string(SkStream* stream, SkString* string) {
const uint32_t length = SkToU32(stream->readPackedUInt());
@@ -41,11 +41,20 @@
}
}
-SkFontDescriptor::SkFontDescriptor(SkStream* stream) {
+static size_t read_uint(SkStream* stream) {
+ return stream->readPackedUInt();
+}
+
+static void write_uint(SkWStream* stream, size_t n, uint32_t id) {
+ stream->writePackedUInt(id);
+ stream->writePackedUInt(n);
+}
+
+SkFontDescriptor::SkFontDescriptor(SkStream* stream) : fFontIndex(0) {
fStyle = (SkTypeface::Style)stream->readPackedUInt();
- for (;;) {
- switch (stream->readPackedUInt()) {
+ for (size_t id; (id = stream->readPackedUInt()) != kSentinel;) {
+ switch (id) {
case kFontFamilyName:
read_string(stream, &fFamilyName);
break;
@@ -55,16 +64,25 @@
case kPostscriptName:
read_string(stream, &fPostscriptName);
break;
+ case kFontIndex:
+ fFontIndex = read_uint(stream);
+ break;
case kFontFileName:
read_string(stream, &fFontFileName);
break;
- case kSentinel:
- return;
default:
SkDEBUGFAIL("Unknown id used by a font descriptor");
return;
}
}
+
+ size_t length = stream->readPackedUInt();
+ if (length > 0) {
+ SkAutoTUnref<SkData> data(SkData::NewUninitialized(length));
+ if (stream->read(data->writable_data(), length) == length) {
+ fFontData.reset(SkNEW_ARGS(SkMemoryStream, (data)));
+ }
+ }
}
void SkFontDescriptor::serialize(SkWStream* stream) {
@@ -74,6 +92,17 @@
write_string(stream, fFullName, kFullName);
write_string(stream, fPostscriptName, kPostscriptName);
write_string(stream, fFontFileName, kFontFileName);
+ if (fFontIndex) {
+ write_uint(stream, fFontIndex, kFontIndex);
+ }
stream->writePackedUInt(kSentinel);
+
+ if (fFontData) {
+ size_t length = fFontData->getLength();
+ stream->writePackedUInt(length);
+ stream->writeStream(fFontData, length);
+ } else {
+ stream->writePackedUInt(0);
+ }
}
diff --git a/src/core/SkFontDescriptor.h b/src/core/SkFontDescriptor.h
index 5febfd8..5a6ddd5 100644
--- a/src/core/SkFontDescriptor.h
+++ b/src/core/SkFontDescriptor.h
@@ -8,10 +8,10 @@
#ifndef SkFontDescriptor_DEFINED
#define SkFontDescriptor_DEFINED
+#include "SkStream.h"
#include "SkString.h"
#include "SkTypeface.h"
-class SkStream;
class SkWStream;
class SkFontDescriptor {
@@ -24,21 +24,30 @@
SkTypeface::Style getStyle() { return fStyle; }
void setStyle(SkTypeface::Style style) { fStyle = style; }
- const char* getFamilyName() { return fFamilyName.c_str(); }
- const char* getFullName() { return fFullName.c_str(); }
- const char* getPostscriptName() { return fPostscriptName.c_str(); }
- const char* getFontFileName() { return fFontFileName.c_str(); }
+ const char* getFamilyName() const { return fFamilyName.c_str(); }
+ const char* getFullName() const { return fFullName.c_str(); }
+ const char* getPostscriptName() const { return fPostscriptName.c_str(); }
+ const char* getFontFileName() const { return fFontFileName.c_str(); }
+ SkStream* getFontData() const { return fFontData; }
+ int getFontIndex() const { return fFontIndex; }
void setFamilyName(const char* name) { fFamilyName.set(name); }
void setFullName(const char* name) { fFullName.set(name); }
void setPostscriptName(const char* name) { fPostscriptName.set(name); }
void setFontFileName(const char* name) { fFontFileName.set(name); }
+ /** Set the font data only if it is necessary for serialization.
+ * This method takes ownership of the stream (both reference and cursor).
+ */
+ void setFontData(SkStream* stream) { fFontData.reset(stream); }
+ void setFontIndex(int index) { fFontIndex = index; }
private:
SkString fFamilyName;
SkString fFullName;
SkString fPostscriptName;
SkString fFontFileName;
+ SkAutoTUnref<SkStream> fFontData;
+ int fFontIndex;
SkTypeface::Style fStyle;
};
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 1c2f8e8..88bde22 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -2308,19 +2308,15 @@
#ifndef SK_IGNORE_TO_STRING
-static SkFontDescriptor typeface_getDescriptor(const SkTypeface* face) {
- SkDynamicMemoryWStream ostream;
- face->serialize(&ostream);
- SkAutoTUnref<SkStreamAsset> istream(ostream.detachAsStream());
- return SkFontDescriptor(istream);
-}
-
void SkPaint::toString(SkString* str) const {
str->append("<dl><dt>SkPaint:</dt><dd><dl>");
SkTypeface* typeface = this->getTypeface();
if (typeface) {
- SkFontDescriptor descriptor(typeface_getDescriptor(typeface));
+ SkDynamicMemoryWStream ostream;
+ typeface->serialize(&ostream);
+ SkAutoTUnref<SkStreamAsset> istream(ostream.detachAsStream());
+ SkFontDescriptor descriptor(istream);
str->append("<dt>Font Family Name:</dt><dd>");
str->append(descriptor.getFamilyName());
diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp
index 74dd5d9..d7da131 100644
--- a/src/core/SkTypeface.cpp
+++ b/src/core/SkTypeface.cpp
@@ -147,14 +147,14 @@
return fm->matchFaceStyle(family, newStyle);
}
-SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) {
+SkTypeface* SkTypeface::CreateFromStream(SkStream* stream, int index) {
SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- return fm->createFromStream(stream);
+ return fm->createFromStream(stream, index);
}
-SkTypeface* SkTypeface::CreateFromFile(const char path[]) {
+SkTypeface* SkTypeface::CreateFromFile(const char path[], int index) {
SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
- return fm->createFromFile(path);
+ return fm->createFromFile(path, index);
}
///////////////////////////////////////////////////////////////////////////////
@@ -164,45 +164,24 @@
SkFontDescriptor desc(this->style());
this->onGetFontDescriptor(&desc, &isLocal);
- desc.serialize(wstream);
- if (isLocal) {
- int ttcIndex; // TODO: write this to the stream?
- SkAutoTUnref<SkStream> rstream(this->openStream(&ttcIndex));
- if (rstream.get()) {
- size_t length = rstream->getLength();
- wstream->writePackedUInt(length);
- wstream->writeStream(rstream, length);
- } else {
- wstream->writePackedUInt(0);
- }
- } else {
- wstream->writePackedUInt(0);
+ if (isLocal && NULL == desc.getFontData()) {
+ int ttcIndex;
+ desc.setFontData(this->onOpenStream(&ttcIndex));
+ desc.setFontIndex(ttcIndex);
}
+
+ desc.serialize(wstream);
}
SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
SkFontDescriptor desc(stream);
- size_t length = stream->readPackedUInt();
- if (length > 0) {
- void* addr = sk_malloc_flags(length, 0);
- if (addr) {
- SkAutoTUnref<SkMemoryStream> localStream(SkNEW(SkMemoryStream));
- localStream->setMemoryOwned(addr, length);
-
- if (stream->read(addr, length) == length) {
- return SkTypeface::CreateFromStream(localStream.get());
- } else {
- // Failed to read the full font data, so fall through and try to create from name.
- // If this is because of EOF, all subsequent reads from the stream will be EOF.
- // If this is because of a stream error, the stream is in an error state,
- // do not attempt to skip any remaining bytes.
- }
- } else {
- // failed to allocate, so just skip and create-from-name
- stream->skip(length);
+ SkStream* data = desc.getFontData();
+ if (data) {
+ SkTypeface* typeface = SkTypeface::CreateFromStream(data, desc.getFontIndex());
+ if (typeface) {
+ return typeface;
}
}
-
return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle());
}
diff --git a/src/ports/SkFontHost_fontconfig.cpp b/src/ports/SkFontHost_fontconfig.cpp
index 57252d0..b3a893e 100644
--- a/src/ports/SkFontHost_fontconfig.cpp
+++ b/src/ports/SkFontHost_fontconfig.cpp
@@ -169,5 +169,6 @@
void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
bool* isLocalStream) const {
desc->setFamilyName(this->getFamilyName());
+ desc->setFontIndex(this->getIdentity().fTTCIndex);
*isLocalStream = SkToBool(this->getLocalStream());
}
diff --git a/src/ports/SkFontHost_linux.cpp b/src/ports/SkFontHost_linux.cpp
index 2904cac..a4202aa 100644
--- a/src/ports/SkFontHost_linux.cpp
+++ b/src/ports/SkFontHost_linux.cpp
@@ -30,9 +30,10 @@
/** The base SkTypeface implementation for the custom font manager. */
class SkTypeface_Custom : public SkTypeface_FreeType {
public:
- SkTypeface_Custom(Style style, bool isFixedPitch, bool sysFont, const SkString familyName)
+ SkTypeface_Custom(Style style, bool isFixedPitch,
+ bool sysFont, const SkString familyName, int index)
: INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
- , fIsSysFont(sysFont), fFamilyName(familyName)
+ , fIsSysFont(sysFont), fFamilyName(familyName), fIndex(index)
{ }
bool isSysFont() const { return fIsSysFont; }
@@ -47,12 +48,16 @@
virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE {
desc->setFamilyName(fFamilyName.c_str());
desc->setFontFileName(this->getUniqueString());
+ desc->setFontIndex(fIndex);
*isLocal = !this->isSysFont();
}
+ int getIndex() const { return fIndex; }
+
private:
- bool fIsSysFont;
- SkString fFamilyName;
+ const bool fIsSysFont;
+ const SkString fFamilyName;
+ const int fIndex;
typedef SkTypeface_FreeType INHERITED;
};
@@ -62,7 +67,7 @@
*/
class SkTypeface_Empty : public SkTypeface_Custom {
public:
- SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, false, true, SkString()) {}
+ SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, false, true, SkString(), 0) {}
virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
@@ -78,21 +83,20 @@
public:
SkTypeface_Stream(Style style, bool isFixedPitch, bool sysFont, const SkString familyName,
SkStream* stream, int ttcIndex)
- : INHERITED(style, isFixedPitch, sysFont, familyName)
- , fStream(SkRef(stream)), fTtcIndex(ttcIndex)
+ : INHERITED(style, isFixedPitch, sysFont, familyName, ttcIndex)
+ , fStream(SkRef(stream))
{ }
virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
protected:
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
- *ttcIndex = 0;
+ *ttcIndex = this->getIndex();
return fStream->duplicate();
}
private:
- SkAutoTUnref<SkStream> fStream;
- int fTtcIndex;
+ const SkAutoTUnref<const SkStream> fStream;
typedef SkTypeface_Custom INHERITED;
};
@@ -101,8 +105,8 @@
class SkTypeface_File : public SkTypeface_Custom {
public:
SkTypeface_File(Style style, bool isFixedPitch, bool sysFont, const SkString familyName,
- const char path[])
- : INHERITED(style, isFixedPitch, sysFont, familyName)
+ const char path[], int index)
+ : INHERITED(style, isFixedPitch, sysFont, familyName, index)
, fPath(path)
{ }
@@ -116,7 +120,7 @@
protected:
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
- *ttcIndex = 0;
+ *ttcIndex = this->getIndex();
return SkStream::NewFromFile(fPath.c_str());
}
@@ -343,7 +347,7 @@
isFixedPitch,
true, // system-font (cannot delete)
realname,
- filename.c_str()));
+ filename.c_str(), 0));
SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
if (NULL == addTo) {
diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp
index 2fee735..5e93bf8 100644
--- a/src/ports/SkFontMgr_android.cpp
+++ b/src/ports/SkFontMgr_android.cpp
@@ -81,6 +81,7 @@
SkASSERT(serialize);
desc->setFamilyName(fFamilyName.c_str());
desc->setFontFileName(fPathName.c_str());
+ desc->setFontIndex(fIndex);
*serialize = false;
}
virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp
index f4cae23..00b962a 100644
--- a/src/ports/SkFontMgr_fontconfig.cpp
+++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -394,7 +394,7 @@
}
virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
- desc->setStyle(this->style());
+ desc->setFontIndex(fIndex);
*serialize = true;
}
@@ -425,10 +425,10 @@
virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const SK_OVERRIDE {
FCLocker lock;
desc->setFamilyName(get_string(fPattern, FC_FAMILY));
- desc->setFontFileName(get_string(fPattern, FC_FILE));
desc->setFullName(get_string(fPattern, FC_FULLNAME));
desc->setPostscriptName(get_string(fPattern, FC_POSTSCRIPT_NAME));
- desc->setStyle(this->style());
+ desc->setFontFileName(get_string(fPattern, FC_FILE));
+ desc->setFontIndex(get_int(fPattern, FC_INDEX, 0));
*serialize = false;
}
diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp
index 9c2b41d..8b9ed16 100644
--- a/src/ports/SkTypeface_win_dw.cpp
+++ b/src/ports/SkTypeface_win_dw.cpp
@@ -42,6 +42,7 @@
sk_get_locale_string(familyNames.get(), NULL/*fMgr->fLocaleName.get()*/, &utf8FamilyName);
desc->setFamilyName(utf8FamilyName.c_str());
+ desc->setFontIndex(fDWriteFontFace->GetIndex());
*isLocalStream = SkToBool(fDWriteFontFileLoader.get());
}
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index 23cc33d..b6ee978 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -301,7 +301,7 @@
return;
}
SkString filename = SkOSPath::Join(resourcePath.c_str(), "test.ttc");
- SkTypeface* typeface = SkTypeface::CreateFromFile(filename.c_str());
+ SkTypeface* typeface = SkTypeface::CreateFromFile(filename.c_str(), 1);
if (!typeface) {
SkDebugf("Could not run fontstream test because test.ttc not found.");
return;
@@ -320,7 +320,7 @@
SkIntToScalar(canvasRect.height()),
NULL, 0);
canvas->drawColor(SK_ColorWHITE);
- canvas->drawText("A", 1, 24, 32, paint);
+ canvas->drawText("A!", 2, 24, 32, paint);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
// Serlialize picture and create its clone from stream.