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
This commit is contained in:
commit-bot@chromium.org 2013-05-13 14:09:13 +00:00
parent 28ac96e40d
commit c7a20e4093
9 changed files with 230 additions and 10 deletions

View File

@ -79,6 +79,7 @@
[ 'skia_os == "android" and skia_arch_type == "arm" and armv7 == 1', { [ '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. # The code in SkUtilsArm.cpp can be used on an ARM-based Linux system, not only Android.
'sources': [ 'sources': [
'../src/core/SkPaintOptionsAndroid.cpp',
'../src/core/SkUtilsArm.cpp', '../src/core/SkUtilsArm.cpp',
'../src/core/SkUtilsArm.h', '../src/core/SkUtilsArm.h',
], ],

View File

@ -14,6 +14,9 @@
#include "SkColor.h" #include "SkColor.h"
#include "SkDrawLooper.h" #include "SkDrawLooper.h"
#include "SkXfermode.h" #include "SkXfermode.h"
#ifdef SK_BUILD_FOR_ANDROID
#include "SkPaintOptionsAndroid.h"
#endif
class SkAnnotation; class SkAnnotation;
class SkAutoGlyphCache; class SkAutoGlyphCache;
@ -860,6 +863,11 @@ public:
/** Returns the base glyph count for the strike associated with this paint /** Returns the base glyph count for the strike associated with this paint
*/ */
unsigned getBaseGlyphCount(SkUnichar text) const; unsigned getBaseGlyphCount(SkUnichar text) const;
const SkPaintOptionsAndroid& getPaintOptionsAndroid() const {
return fPaintOptionsAndroid;
}
void setPaintOptionsAndroid(const SkPaintOptionsAndroid& options);
#endif #endif
// returns true if the paint's settings (e.g. xfermode + alpha) resolve to // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
@ -990,6 +998,8 @@ private:
friend class SkTextToPathIter; friend class SkTextToPathIter;
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
SkPaintOptionsAndroid fPaintOptionsAndroid;
// In order for the == operator to work properly this must be the last field // 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. // in the struct so that we can do a memcmp to this field's offset.
uint32_t fGenerationID; uint32_t fGenerationID;

View File

@ -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

View File

@ -9,6 +9,8 @@
#ifndef SkTypeface_android_DEFINED #ifndef SkTypeface_android_DEFINED
#define SkTypeface_android_DEFINED #define SkTypeface_android_DEFINED
#ifdef SK_BUILD_FOR_ANDROID
#include "SkTypeface.h" #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 * get the 3rd can still inspect the original, and try to match its
* stylistic attributes. * 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

View File

@ -83,6 +83,7 @@ SkPaint::SkPaint() {
fHinting = SkPaintDefaults_Hinting; fHinting = SkPaintDefaults_Hinting;
fPrivFlags = 0; fPrivFlags = 0;
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
fGenerationID = 0; fGenerationID = 0;
#endif #endif
} }
@ -141,11 +142,15 @@ SkPaint& SkPaint::operator=(const SkPaint& src) {
SkSafeUnref(fAnnotation); SkSafeUnref(fAnnotation);
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
fPaintOptionsAndroid.~SkPaintOptionsAndroid();
uint32_t oldGenerationID = fGenerationID; uint32_t oldGenerationID = fGenerationID;
#endif #endif
memcpy(this, &src, sizeof(src)); memcpy(this, &src, sizeof(src));
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
fGenerationID = oldGenerationID + 1; fGenerationID = oldGenerationID + 1;
new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
#endif #endif
return *this; return *this;
@ -180,14 +185,19 @@ uint32_t SkPaint::getGenerationID() const {
void SkPaint::setGenerationID(uint32_t generationID) { void SkPaint::setGenerationID(uint32_t generationID) {
fGenerationID = generationID; fGenerationID = generationID;
} }
#endif
#ifdef SK_BUILD_FOR_ANDROID
unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const { unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
SkAutoGlyphCache autoCache(*this, NULL, NULL); SkAutoGlyphCache autoCache(*this, NULL, NULL);
SkGlyphCache* cache = autoCache.getCache(); SkGlyphCache* cache = autoCache.getCache();
return cache->getBaseGlyphCount(text); return cache->getBaseGlyphCount(text);
} }
void SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
if (options != fPaintOptionsAndroid) {
fPaintOptionsAndroid = options;
GEN_ID_INC;
}
}
#endif #endif
void SkPaint::setHinting(Hinting hintingLevel) { 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 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 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
SkScalerContext::PostMakeRec(*this, &rec); SkScalerContext::PostMakeRec(*this, &rec);
@ -1818,6 +1835,10 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
desc->init(); desc->init();
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
#ifdef SK_BUILD_FOR_ANDROID
add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
#endif
if (pe) { if (pe) {
add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer); add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
} }
@ -1852,6 +1873,11 @@ void SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
desc2->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) { if (pe) {
add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer); add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer); add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);

View File

@ -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 <cstring>
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

View File

@ -110,6 +110,15 @@ SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc)
desc->findEntry(kPathEffect_SkDescriptorTag, NULL), desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
desc->findEntry(kMaskFilter_SkDescriptorTag, NULL)); desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
#endif #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() { SkScalerContext::~SkScalerContext() {
@ -125,7 +134,8 @@ SkScalerContext::~SkScalerContext() {
SkScalerContext* SkScalerContext::allocNextContext() const { SkScalerContext* SkScalerContext::allocNextContext() const {
#ifdef SK_BUILD_FOR_ANDROID #ifdef SK_BUILD_FOR_ANDROID
SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID, SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID,
fRec.fOrigFontID); fRec.fOrigFontID,
fPaintOptionsAndroid);
if (0 == newFace) { if (0 == newFace) {
return NULL; return NULL;
} }

View File

@ -14,6 +14,10 @@
#include "SkPaint.h" #include "SkPaint.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#ifdef SK_BUILD_FOR_ANDROID
#include "SkPaintOptionsAndroid.h"
#endif
struct SkGlyph; struct SkGlyph;
class SkDescriptor; class SkDescriptor;
class SkMaskFilter; class SkMaskFilter;
@ -217,6 +221,10 @@ private:
// never null // never null
SkAutoTUnref<SkTypeface> fTypeface; SkAutoTUnref<SkTypeface> fTypeface;
#ifdef SK_BUILD_FOR_ANDROID
SkPaintOptionsAndroid fPaintOptionsAndroid;
#endif
// optional object, which may be null // optional object, which may be null
SkPathEffect* fPathEffect; SkPathEffect* fPathEffect;
SkMaskFilter* fMaskFilter; SkMaskFilter* fMaskFilter;
@ -262,6 +270,9 @@ private:
#define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e')
#define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f')
#define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't')
#ifdef SK_BUILD_FOR_ANDROID
#define kAndroidOpts_SkDescriptorTag SkSetFourByteTag('a', 'n', 'd', 'r')
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -801,15 +801,15 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
return tf; return tf;
} }
SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
SkFontID origFontID) { const SkPaintOptionsAndroid& options) {
#if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) #if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
// Skia does not support font fallback for ndk applications in order to // Skia does not support font fallback for ndk applications in order to
// enable clients such as WebKit to customize their font selection. // enable clients such as WebKit to customize their font selection.
// Clients can use GetFallbackFamilyNameForChar() to get the fallback // Clients can use GetFallbackFamilyNameForChar() to get the fallback
// font for individual characters. // font for individual characters.
return NULL; return NULL;
#else #endif
SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
load_system_fonts(); load_system_fonts();
@ -845,7 +845,6 @@ SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID,
// i.e. gFallbackFonts[0] != 0. // i.e. gFallbackFonts[0] != 0.
const SkTypeface* firstTypeface = find_from_uniqueID(list[0]); const SkTypeface* firstTypeface = find_from_uniqueID(list[0]);
return SkRef(find_typeface(firstTypeface, origTypeface->style())); return SkRef(find_typeface(firstTypeface, origTypeface->style()));
#endif
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////