API modifications needed to upstream Android font changes.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 9 May 2013 20:54:20 +0000 (20:54 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 9 May 2013 20:54:20 +0000 (20:54 +0000)
R=reed@google.com

Author: djsollen@google.com

Review URL: https://chromiumcodereview.appspot.com/14761003

git-svn-id: http://skia.googlecode.com/svn/trunk@9083 2bbb7eff-a529-9590-31e7-b0007b416f81

gyp/core.gyp
include/core/SkPaint.h
include/core/SkPaintOptionsAndroid.h [new file with mode: 0644]
include/ports/SkTypeface_android.h
src/core/SkPaint.cpp
src/core/SkPaintOptionsAndroid.cpp [new file with mode: 0644]
src/core/SkScalerContext.cpp
src/core/SkScalerContext.h
src/ports/SkFontHost_android.cpp

index 7d9c9d774cb68455f23633dfceb191679146f177..9e0792b7734be1dfced1715b21bf3fe93838eef6 100644 (file)
@@ -79,6 +79,7 @@
         [ 'skia_os == "android" and skia_arch_type == "arm" and armv7 == 1', {
           # The code in SkUtilsArm.cpp can be used on an ARM-based Linux system, not only Android.
           'sources': [
+            '../src/core/SkPaintOptionsAndroid.cpp',
             '../src/core/SkUtilsArm.cpp',
             '../src/core/SkUtilsArm.h',
           ],
index a73a46a2c6d3b6e612cdbb0eb67fe826d2cce104..35a502d6b82ee09a3b3cb63096e0b567fedb91ac 100644 (file)
@@ -14,6 +14,9 @@
 #include "SkColor.h"
 #include "SkDrawLooper.h"
 #include "SkXfermode.h"
+#ifdef SK_BUILD_FOR_ANDROID
+#include "SkPaintOptionsAndroid.h"
+#endif
 
 class SkAnnotation;
 class SkAutoGlyphCache;
@@ -860,6 +863,11 @@ public:
     /** Returns the base glyph count for the strike associated with this paint
     */
     unsigned getBaseGlyphCount(SkUnichar text) const;
+
+    const SkPaintOptionsAndroid& getPaintOptionsAndroid() const {
+        return fPaintOptionsAndroid;
+    }
+    void setPaintOptionsAndroid(const SkPaintOptionsAndroid& options);
 #endif
 
     // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
@@ -990,6 +998,8 @@ private:
     friend class SkTextToPathIter;
 
 #ifdef SK_BUILD_FOR_ANDROID
+    SkPaintOptionsAndroid fPaintOptionsAndroid;
+
     // In order for the == operator to work properly this must be the last field
     // in the struct so that we can do a memcmp to this field's offset.
     uint32_t        fGenerationID;
diff --git a/include/core/SkPaintOptionsAndroid.h b/include/core/SkPaintOptionsAndroid.h
new file mode 100644 (file)
index 0000000..235cae9
--- /dev/null
@@ -0,0 +1,118 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkPaintOptionsAndroid_DEFINED
+#define SkPaintOptionsAndroid_DEFINED
+
+#ifdef SK_BUILD_FOR_ANDROID
+
+#include "SkString.h"
+#include "SkTypes.h"
+
+class SkFlattenableReadBuffer;
+class SkFlattenableWriteBuffer;
+
+struct SkLanguageInfo {
+    SkLanguageInfo(const char* tag) : fTag(tag) { }
+    SkString fTag; //! BCP 47 language identifier
+};
+
+/** \class SkLanguage
+
+    The SkLanguage class represents a human written language, and is used by
+    text draw operations to determine which glyph to draw when drawing
+    characters with variants (ie Han-derived characters).
+*/
+class SkLanguage {
+public:
+    SkLanguage() : fInfo(getInfo("")) { }
+    SkLanguage(const char* tag) : fInfo(getInfo(tag)) { }
+    SkLanguage(const SkLanguage& b) : fInfo(b.fInfo) { }
+
+    /** Gets a BCP 47 language identifier for this SkLanguage.
+        @return a BCP 47 language identifier representing this language
+    */
+    const SkString& getTag() const { return fInfo->fTag; }
+
+    /** Performs BCP 47 fallback to return an SkLanguage one step more general.
+        @return an SkLanguage one step more general
+    */
+    SkLanguage getParent() const;
+
+    bool operator==(const SkLanguage& b) const {
+        return fInfo == b.fInfo;
+    }
+    bool operator!=(const SkLanguage& b) const {
+        return fInfo != b.fInfo;
+    }
+    bool operator<(const SkLanguage& b) const {
+        return fInfo < b.fInfo;
+    }
+    bool operator>(const SkLanguage& b) const {
+        return fInfo > b.fInfo;
+    }
+    SkLanguage& operator=(const SkLanguage& b) {
+        fInfo = b.fInfo;
+        return *this;
+    }
+
+private:
+    const SkLanguageInfo* fInfo;
+
+    static const SkLanguageInfo* getInfo(const char* tag);
+};
+
+class SkPaintOptionsAndroid {
+public:
+    SkPaintOptionsAndroid() {
+        fFontVariant = kDefault_Variant;
+    }
+
+    /** Return the paint's language value used for drawing text.
+        @return the paint's language value used for drawing text.
+    */
+    const SkLanguage& getLanguage() const { return fLanguage; }
+
+    /** Set the paint's language value used for drawing text.
+        @param language set the paint's language value for drawing text.
+    */
+    void setLanguage(const SkLanguage& language) { fLanguage = language; }
+    void setLanguage(const char* languageTag) { fLanguage = SkLanguage(languageTag); }
+
+
+    enum FontVariant {
+       kDefault_Variant, // Currently setting yourself to Default gives you Compact Variant
+       kCompact_Variant,
+       kElegant_Variant,
+       kLast_Variant = kElegant_Variant,
+    };
+
+    /** Return the font variant
+        @return the font variant used by this paint object
+    */
+    FontVariant getFontVariant() const { return fFontVariant; }
+
+    /** Set the font variant
+      @param fontVariant set the paint's font variant for choosing fonts
+    */
+    void setFontVariant(FontVariant fontVariant) {
+        SkASSERT((unsigned)fontVariant <= kLast_Variant);
+        fFontVariant = fontVariant;
+    }
+
+    void flatten(SkFlattenableWriteBuffer&) const;
+    void unflatten(SkFlattenableReadBuffer&);
+
+private:
+    SkLanguage fLanguage;
+    FontVariant fFontVariant;
+};
+
+#endif // #ifdef SK_BUILD_FOR_ANDROID
+#endif // #ifndef SkPaintOptionsAndroid_DEFINED
index e87fa4805a34452f6087ab08b5c627a0e59f6d10..0d89736e7ea9ae03c4615686bf189bfb800aedcd 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef SkTypeface_android_DEFINED
 #define SkTypeface_android_DEFINED
 
+#ifdef SK_BUILD_FOR_ANDROID
+
 #include "SkTypeface.h"
 
 /**
@@ -39,6 +41,8 @@ SK_API void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackco
  *  get the 3rd can still inspect the original, and try to match its
  *  stylistic attributes.
  */
-SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID);
+SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
+                                         const SkPaintOptionsAndroid& options);
 
-#endif
+#endif // #ifdef SK_BUILD_FOR_ANDROID
+#endif // #ifndef SkTypeface_android_DEFINED
index 6c16428d818b5d99220ff1369a81d114ee2b66dc..18cf651616698f276fe14a67ce2a6e17837f84af 100644 (file)
@@ -180,14 +180,19 @@ uint32_t SkPaint::getGenerationID() const {
 void SkPaint::setGenerationID(uint32_t generationID) {
     fGenerationID = generationID;
 }
-#endif
 
-#ifdef SK_BUILD_FOR_ANDROID
 unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
     SkAutoGlyphCache autoCache(*this, NULL, NULL);
     SkGlyphCache* cache = autoCache.getCache();
     return cache->getBaseGlyphCount(text);
 }
+
+void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
+    if(!memcmp(&fPaintOptionsAndroid, &options, sizeof(SkPaintOptionsAndroid))) {
+        fPaintOptionsAndroid = options;
+        GEN_ID_INC;
+    }
+}
 #endif
 
 void SkPaint::setHinting(Hinting hintingLevel) {
@@ -1806,6 +1811,13 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
         rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
     }
 
+#ifdef SK_BUILD_FOR_ANDROID
+    SkOrderedWriteBuffer androidBuffer(128);
+    fPaintOptionsAndroid.flatten(androidBuffer);
+    descSize += androidBuffer.size();
+    entryCount += 1;
+#endif
+
     ///////////////////////////////////////////////////////////////////////////
     // Now that we're done tweaking the rec, call the PostMakeRec cleanup
     SkScalerContext::PostMakeRec(*this, &rec);
@@ -1818,6 +1830,10 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
     desc->init();
     desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
 
+#ifdef SK_BUILD_FOR_ANDROID
+    add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
+#endif
+
     if (pe) {
         add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
     }
diff --git a/src/core/SkPaintOptionsAndroid.cpp b/src/core/SkPaintOptionsAndroid.cpp
new file mode 100644 (file)
index 0000000..ef9375e
--- /dev/null
@@ -0,0 +1,65 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifdef SK_BUILD_FOR_ANDROID
+
+#include "SkPaintOptionsAndroid.h"
+#include "SkFlattenableBuffers.h"
+#include "SkTDict.h"
+#include "SkThread.h"
+#include <cstring>
+
+SkLanguage SkLanguage::getParent() const {
+    SkASSERT(fInfo != NULL);
+    const char* tag = fInfo->fTag.c_str();
+    SkASSERT(tag != NULL);
+
+    // strip off the rightmost "-.*"
+    char* parentTagEnd = strrchr(tag, '-');
+    if (parentTagEnd == NULL) {
+        return SkLanguage("");
+    }
+    size_t parentTagLen = parentTagEnd - tag;
+    char parentTag[parentTagLen + 1];
+    strncpy(parentTag, tag, parentTagLen);
+    parentTag[parentTagLen] = '\0';
+    return SkLanguage(parentTag);
+}
+
+SK_DECLARE_STATIC_MUTEX(gGetInfoMutex);
+const SkLanguageInfo* SkLanguage::getInfo(const char* tag) {
+    SkAutoMutexAcquire lock(gGetInfoMutex);
+
+    static const size_t kDictSize = 128;
+    static SkTDict<SkLanguageInfo*> tagToInfo(kDictSize);
+
+    // try a lookup
+    SkLanguageInfo* info;
+    if (tagToInfo.find(tag, &info)) {
+        return info;
+    }
+
+    // no match - add this language
+    info = new SkLanguageInfo(tag);
+    tagToInfo.set(tag, info);
+    return info;
+}
+
+void SkPaintOptionsAndroid::flatten(SkFlattenableWriteBuffer& buffer) const {
+    buffer.writeUInt(fFontVariant);
+    buffer.writeString(fLanguage.getTag().c_str());
+}
+
+void SkPaintOptionsAndroid::unflatten(SkFlattenableReadBuffer& buffer) {
+    fFontVariant = (FontVariant)buffer.readUInt();
+    char* tag = buffer.readString();
+    fLanguage = SkLanguage(tag);
+    sk_free(tag);
+}
+
+#endif
index ba14908c2e62f008cf4e5fdf2c2c64e03f97a3ff..a7e2432cc1e348e6417460f56a285d67618e611f 100644 (file)
@@ -110,6 +110,14 @@ SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
              desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
         desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
 #endif
+#ifdef SK_BUILD_FOR_ANDROID
+    uint32_t len;
+    const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len);
+    SkASSERT(data);
+    SkOrderedReadBuffer buffer(data, len);
+    fPaintOptionsAndroid.unflatten(buffer);
+    SkASSERT(buffer.offset() == buffer.size());
+#endif
 }
 
 SkScalerContext::~SkScalerContext() {
@@ -125,7 +133,8 @@ SkScalerContext::~SkScalerContext() {
 SkScalerContext* SkScalerContext::allocNextContext() const {
 #ifdef SK_BUILD_FOR_ANDROID
     SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID,
-                                                       fRec.fOrigFontID);
+                                                       fRec.fOrigFontID,
+                                                       fPaintOptionsAndroid);
     if (0 == newFace) {
         return NULL;
     }
index d17b4234963f4b6bb10ebc5c74fa697799267aca..06f5f94e1703af4c20e5f77475f399d09ba6f71c 100644 (file)
 #include "SkPaint.h"
 #include "SkTypeface.h"
 
+#ifdef SK_BUILD_FOR_ANDROID
+    #include "SkPaintOptionsAndroid.h"
+#endif
+
 struct SkGlyph;
 class SkDescriptor;
 class SkMaskFilter;
@@ -217,6 +221,10 @@ private:
     // never null
     SkAutoTUnref<SkTypeface> fTypeface;
 
+#ifdef SK_BUILD_FOR_ANDROID
+    SkPaintOptionsAndroid fPaintOptionsAndroid;
+#endif
+
     // optional object, which may be null
     SkPathEffect*   fPathEffect;
     SkMaskFilter*   fMaskFilter;
@@ -262,6 +270,9 @@ private:
 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
+#ifdef SK_BUILD_FOR_ANDROID
+#define kAndroidOpts_SkDescriptorTag    SkSetFourByteTag('a', 'n', 'd', 'r')
+#endif
 
 ///////////////////////////////////////////////////////////////////////////////
 
index ce478def6bad336527ae30321f8201f59dd428c9..aeeec953d313c3e32ee30ed00776504c5be885fa 100644 (file)
@@ -801,15 +801,15 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
     return tf;
 }
 
-SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID,
-                                         SkFontID origFontID) {
-#if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
+SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
+                                         const SkPaintOptionsAndroid& options) {
+#if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
     // Skia does not support font fallback for ndk applications in order to
     // enable clients such as WebKit to customize their font selection.
     // Clients can use GetFallbackFamilyNameForChar() to get the fallback
     // font for individual characters.
     return NULL;
-#else
+#endif
     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
 
     load_system_fonts();
@@ -845,7 +845,6 @@ SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID,
     // i.e. gFallbackFonts[0] != 0.
     const SkTypeface* firstTypeface = find_from_uniqueID(list[0]);
     return SkRef(find_typeface(firstTypeface, origTypeface->style()));
-#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////