From c7a20e40938ae031368e3a9e4df33ce90a765aba Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Mon, 13 May 2013 14:09:13 +0000 Subject: [PATCH] API modifications needed to upstream Android font changes. Committed: http://code.google.com/p/skia/source/detail?r=9083 R=reed@google.com Author: djsollen@google.com Review URL: https://chromiumcodereview.appspot.com/14761003 git-svn-id: http://skia.googlecode.com/svn/trunk@9107 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/core.gyp | 1 + include/core/SkPaint.h | 10 +++ include/core/SkPaintOptionsAndroid.h | 117 +++++++++++++++++++++++++++ include/ports/SkTypeface_android.h | 8 +- src/core/SkPaint.cpp | 30 ++++++- src/core/SkPaintOptionsAndroid.cpp | 42 ++++++++++ src/core/SkScalerContext.cpp | 12 ++- src/core/SkScalerContext.h | 11 +++ src/ports/SkFontHost_android.cpp | 9 +-- 9 files changed, 230 insertions(+), 10 deletions(-) create mode 100644 include/core/SkPaintOptionsAndroid.h create mode 100644 src/core/SkPaintOptionsAndroid.cpp diff --git a/gyp/core.gyp b/gyp/core.gyp index 7d9c9d774c..9e0792b773 100644 --- a/gyp/core.gyp +++ b/gyp/core.gyp @@ -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', ], diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index a73a46a2c6..35a502d6b8 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -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 index 0000000000..c38088f730 --- /dev/null +++ b/include/core/SkPaintOptionsAndroid.h @@ -0,0 +1,117 @@ + +/* + * 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; + +/** \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() { } + SkLanguage(const char* tag) : fTag(tag) { } + SkLanguage(const char* tag, size_t len) : fTag(tag, len) { } + SkLanguage(const SkLanguage& b) : fTag(b.fTag) { } + + /** Gets a BCP 47 language identifier for this SkLanguage. + @return a BCP 47 language identifier representing this language + */ + const SkString& getTag() const { return 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 fTag == b.fTag; + } + bool operator!=(const SkLanguage& b) const { + return fTag != b.fTag; + } + SkLanguage& operator=(const SkLanguage& b) { + fTag = b.fTag; + return *this; + } + +private: + //! BCP 47 language identifier + SkString fTag; +}; + +class SkPaintOptionsAndroid { +public: + SkPaintOptionsAndroid() { + fFontVariant = kDefault_Variant; + } + + SkPaintOptionsAndroid& operator=(const SkPaintOptionsAndroid& b) { + fLanguage = b.fLanguage; + fFontVariant = b.fFontVariant; + return *this; + } + + bool operator!=(const SkPaintOptionsAndroid& b) const { + return fLanguage != b.fLanguage || fFontVariant != b.fFontVariant; + } + + void flatten(SkFlattenableWriteBuffer&) const; + void unflatten(SkFlattenableReadBuffer&); + + /** 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; + } + +private: + SkLanguage fLanguage; + FontVariant fFontVariant; +}; + +#endif // #ifdef SK_BUILD_FOR_ANDROID +#endif // #ifndef SkPaintOptionsAndroid_DEFINED diff --git a/include/ports/SkTypeface_android.h b/include/ports/SkTypeface_android.h index e87fa4805a..0d89736e7e 100644 --- a/include/ports/SkTypeface_android.h +++ b/include/ports/SkTypeface_android.h @@ -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 diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 6c16428d81..193568effb 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -83,6 +83,7 @@ SkPaint::SkPaint() { fHinting = SkPaintDefaults_Hinting; fPrivFlags = 0; #ifdef SK_BUILD_FOR_ANDROID + new (&fPaintOptionsAndroid) SkPaintOptionsAndroid; fGenerationID = 0; #endif } @@ -141,11 +142,15 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { SkSafeUnref(fAnnotation); #ifdef SK_BUILD_FOR_ANDROID + fPaintOptionsAndroid.~SkPaintOptionsAndroid(); + uint32_t oldGenerationID = fGenerationID; #endif memcpy(this, &src, sizeof(src)); #ifdef SK_BUILD_FOR_ANDROID fGenerationID = oldGenerationID + 1; + + new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid); #endif return *this; @@ -180,14 +185,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 (options != fPaintOptionsAndroid) { + fPaintOptionsAndroid = options; + GEN_ID_INC; + } +} #endif void SkPaint::setHinting(Hinting hintingLevel) { @@ -1806,6 +1816,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 +1835,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); } @@ -1852,6 +1873,11 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties, desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); +#ifdef SK_BUILD_FOR_ANDROID + add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer); + add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer); +#endif + if (pe) { add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer); add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer); diff --git a/src/core/SkPaintOptionsAndroid.cpp b/src/core/SkPaintOptionsAndroid.cpp new file mode 100644 index 0000000000..7bf6fc44cd --- /dev/null +++ b/src/core/SkPaintOptionsAndroid.cpp @@ -0,0 +1,42 @@ + +/* + * 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 + +SkLanguage SkLanguage::getParent() const { + SkASSERT(!fTag.isEmpty()); + const char* tag = fTag.c_str(); + + // strip off the rightmost "-.*" + char* parentTagEnd = strrchr(tag, '-'); + if (parentTagEnd == NULL) { + return SkLanguage(); + } + size_t parentTagLen = parentTagEnd - tag; + return SkLanguage(tag, parentTagLen); +} + +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 diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index ba14908c2e..1f71bf0885 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -110,6 +110,15 @@ 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); + if (data) { + SkOrderedReadBuffer buffer(data, len); + fPaintOptionsAndroid.unflatten(buffer); + SkASSERT(buffer.offset() == buffer.size()); + } +#endif } SkScalerContext::~SkScalerContext() { @@ -125,7 +134,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; } diff --git a/src/core/SkScalerContext.h b/src/core/SkScalerContext.h index d17b423496..06f5f94e17 100644 --- a/src/core/SkScalerContext.h +++ b/src/core/SkScalerContext.h @@ -14,6 +14,10 @@ #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 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 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp index ce478def6b..aeeec953d3 100644 --- a/src/ports/SkFontHost_android.cpp +++ b/src/ports/SkFontHost_android.cpp @@ -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 } ///////////////////////////////////////////////////////////////////////////////