Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkTypeface.cpp
index cd3953b..c537d4a 100644 (file)
@@ -6,32 +6,18 @@
  */
 
 #include "SkAdvancedTypefaceMetrics.h"
+#include "SkEndian.h"
 #include "SkFontDescriptor.h"
-#include "SkFontHost.h"
-#include "SkOnce.h"
+#include "SkFontMgr.h"
+#include "SkLazyPtr.h"
+#include "SkOTTable_OS_2.h"
 #include "SkStream.h"
 #include "SkTypeface.h"
 
-//#define TRACE_LIFECYCLE
+SkTypeface::SkTypeface(const SkFontStyle& style, SkFontID fontID, bool isFixedPitch)
+    : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) { }
 
-#ifdef TRACE_LIFECYCLE
-    static int32_t gTypefaceCounter;
-#endif
-
-SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedPitch)
-    : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) {
-#ifdef TRACE_LIFECYCLE
-    SkDebugf("SkTypeface: create  %p fontID %d total %d\n",
-             this, fontID, ++gTypefaceCounter);
-#endif
-}
-
-SkTypeface::~SkTypeface() {
-#ifdef TRACE_LIFECYCLE
-    SkDebugf("SkTypeface: destroy %p fontID %d total %d\n",
-             this, fUniqueID, --gTypefaceCounter);
-#endif
-}
+SkTypeface::~SkTypeface() { }
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -41,7 +27,7 @@ public:
         return SkNEW(SkEmptyTypeface);
     }
 protected:
-    SkEmptyTypeface() : SkTypeface(SkTypeface::kNormal, 0, true) { }
+    SkEmptyTypeface() : SkTypeface(SkFontStyle(), 0, true) { }
 
     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { return NULL; }
     virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE {
@@ -65,6 +51,9 @@ protected:
     public:
         virtual bool next(SkTypeface::LocalizedString*) SK_OVERRIDE { return false; }
     };
+    virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
+        familyName->reset();
+    }
     virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE {
         return SkNEW(EmptyLocalizedStrings);
     };
@@ -74,34 +63,33 @@ protected:
     }
 };
 
-static SkTypeface* gDefaultTypefaces[] = { NULL, NULL, NULL, NULL };
-static const size_t FONT_STYLE_COUNT = SK_ARRAY_COUNT(gDefaultTypefaces);
-static SkOnceFlag gDefaultTypefaceOnce[FONT_STYLE_COUNT] = {
-    SK_ONCE_INIT, SK_ONCE_INIT, SK_ONCE_INIT, SK_ONCE_INIT
-};
-template <uintmax_t N> struct SkTIsPow2 {
-    static const bool value = (N & (N - 1)) == 0;
-};
-SK_COMPILE_ASSERT(SkTIsPow2<FONT_STYLE_COUNT>::value, FONT_STYLE_COUNT_not_power_of_2);
+namespace {
 
-void SkTypeface::create_default_typeface(Style style) {
-    if (NULL == gDefaultTypefaces[style]) {
-        gDefaultTypefaces[style] = SkFontHost::CreateTypeface(NULL, NULL, style);
-    }
-    if (NULL == gDefaultTypefaces[style]) {
-        // FIXME: Use a singleton for SkEmptyTypeface.
-        gDefaultTypefaces[style] = SkEmptyTypeface::Create();
-    }
+SK_DECLARE_STATIC_MUTEX(gCreateDefaultMutex);
+
+// As a template arguments, these must have external linkage.
+SkTypeface* sk_create_default_typeface(int style) {
+    // If backed by fontconfig, it's not safe to call SkFontHost::CreateTypeface concurrently.
+    // To be safe, we serialize here with a mutex so only one call to
+    // CreateTypeface is happening at any given time.
+    // TODO(bungeman, mtklein): This is sad.  Make our fontconfig code safe?
+    SkAutoMutexAcquire lock(&gCreateDefaultMutex);
+
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    SkTypeface* t = fm->legacyCreateTypeface(NULL, style);;
+    return t ? t : SkEmptyTypeface::Create();
 }
 
-SkTypeface* SkTypeface::GetDefaultTypeface(Style style) {
-    SkASSERT((size_t)style < FONT_STYLE_COUNT);
+void sk_unref_typeface(SkTypeface* ptr) { SkSafeUnref(ptr); }
 
-    // mask off any other bits to avoid a crash in SK_RELEASE
-    style = (Style)(style & (FONT_STYLE_COUNT - 1));
+}  // namespace
 
-    SkOnce(&gDefaultTypefaceOnce[style], SkTypeface::create_default_typeface, style);
-    return gDefaultTypefaces[style];
+SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkTypeface, defaults, 4,
+                                 sk_create_default_typeface, sk_unref_typeface);
+
+SkTypeface* SkTypeface::GetDefaultTypeface(Style style) {
+    SkASSERT((int)style < 4);
+    return defaults[style];
 }
 
 SkTypeface* SkTypeface::RefDefault(Style style) {
@@ -125,23 +113,39 @@ SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) {
     if (NULL == name) {
         return RefDefault(style);
     }
-    return SkFontHost::CreateTypeface(NULL, name, style);
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    return fm->legacyCreateTypeface(name, style);
 }
 
 SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) {
-    if (family && family->style() == s) {
+    if (!family) {
+        return SkTypeface::RefDefault(s);
+    }
+
+    if (family->style() == s) {
         family->ref();
         return const_cast<SkTypeface*>(family);
     }
-    return SkFontHost::CreateTypeface(family, NULL, s);
+
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    bool bold = s & SkTypeface::kBold;
+    bool italic = s & SkTypeface::kItalic;
+    SkFontStyle newStyle = SkFontStyle(bold ? SkFontStyle::kBold_Weight
+                                            : SkFontStyle::kNormal_Weight,
+                                       SkFontStyle::kNormal_Width,
+                                       italic ? SkFontStyle::kItalic_Slant
+                                              : SkFontStyle::kUpright_Slant);
+    return fm->matchFaceStyle(family, newStyle);
 }
 
-SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) {
-    return SkFontHost::CreateTypefaceFromStream(stream);
+SkTypeface* SkTypeface::CreateFromStream(SkStream* stream, int index) {
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    return fm->createFromStream(stream, index);
 }
 
-SkTypeface* SkTypeface::CreateFromFile(const char path[]) {
-    return SkFontHost::CreateTypefaceFromFile(path);
+SkTypeface* SkTypeface::CreateFromFile(const char path[], int index) {
+    SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+    return fm->createFromFile(path, index);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -151,45 +155,24 @@ void SkTypeface::serialize(SkWStream* wstream) const {
     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());
 }
 
@@ -263,22 +246,93 @@ SkTypeface::LocalizedStrings* SkTypeface::createFamilyNameIterator() const {
 }
 
 void SkTypeface::getFamilyName(SkString* name) const {
-    bool isLocal = false;
-    SkFontDescriptor desc(this->style());
-    this->onGetFontDescriptor(&desc, &isLocal);
-    name->set(desc.getFamilyName());
+    SkASSERT(name);
+    this->onGetFamilyName(name);
 }
 
 SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
                                 SkAdvancedTypefaceMetrics::PerGlyphInfo info,
                                 const uint32_t* glyphIDs,
                                 uint32_t glyphIDsCount) const {
-    return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
+    SkAdvancedTypefaceMetrics* result =
+            this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
+    if (result && result->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
+        struct SkOTTableOS2 os2table;
+        if (this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG), 0,
+                               sizeof(os2table), &os2table) > 0) {
+            if (os2table.version.v2.fsType.field.Bitmap ||
+                (os2table.version.v2.fsType.field.Restricted &&
+                 !(os2table.version.v2.fsType.field.PreviewPrint ||
+                   os2table.version.v2.fsType.field.Editable))) {
+                result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+                        result->fFlags,
+                        SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
+            }
+            if (os2table.version.v2.fsType.field.NoSubsetting) {
+                result->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
+                        result->fFlags,
+                        SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
+            }
+        }
+    }
+    return result;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
 bool SkTypeface::onGetKerningPairAdjustments(const uint16_t glyphs[], int count,
                                              int32_t adjustments[]) const {
     return false;
 }
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkDescriptor.h"
+#include "SkPaint.h"
+
+struct SkTypeface::BoundsComputer {
+    const SkTypeface& fTypeface;
+
+    BoundsComputer(const SkTypeface& tf) : fTypeface(tf) {}
+
+    SkRect* operator()() const {
+        SkRect* rect = SkNEW(SkRect);
+        if (!fTypeface.onComputeBounds(rect)) {
+            rect->setEmpty();
+        }
+        return rect;
+    }
+};
+
+SkRect SkTypeface::getBounds() const {
+    return *fLazyBounds.get(BoundsComputer(*this));
+}
+
+bool SkTypeface::onComputeBounds(SkRect* bounds) const {
+    // we use a big size to ensure lots of significant bits from the scalercontext.
+    // then we scale back down to return our final answer (at 1-pt)
+    const SkScalar textSize = 2048;
+    const SkScalar invTextSize = 1 / textSize;
+
+    SkPaint paint;
+    paint.setTypeface(const_cast<SkTypeface*>(this));
+    paint.setTextSize(textSize);
+    paint.setLinearText(true);
+
+    SkScalerContext::Rec rec;
+    SkScalerContext::MakeRec(paint, NULL, NULL, &rec);
+
+    SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
+    SkDescriptor*    desc = ad.getDesc();
+    desc->init();
+    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
+
+    SkAutoTDelete<SkScalerContext> ctx(this->createScalerContext(desc, true));
+    if (ctx.get()) {
+        SkPaint::FontMetrics fm;
+        ctx->getFontMetrics(&fm);
+        bounds->set(fm.fXMin * invTextSize, fm.fTop * invTextSize,
+                    fm.fXMax * invTextSize, fm.fBottom * invTextSize);
+        return true;
+    }
+    return false;
+}
+