diff options
Diffstat (limited to 'libs/hwui/VectorDrawable.h')
-rw-r--r-- | libs/hwui/VectorDrawable.h | 308 |
1 files changed, 129 insertions, 179 deletions
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index efbb695a14dd..d9cf8ab7eedf 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -17,15 +17,15 @@ #ifndef ANDROID_HWUI_VPATH_H #define ANDROID_HWUI_VPATH_H -#include "hwui/Canvas.h" +#include "DisplayList.h" #include "hwui/Bitmap.h" +#include "hwui/Canvas.h" #include "renderthread/CacheManager.h" -#include "DisplayList.h" #include <SkBitmap.h> +#include <SkCanvas.h> #include <SkColor.h> #include <SkColorFilter.h> -#include <SkCanvas.h> #include <SkMatrix.h> #include <SkPaint.h> #include <SkPath.h> @@ -36,25 +36,35 @@ #include <cutils/compiler.h> #include <stddef.h> -#include <vector> #include <string> +#include <vector> namespace android { namespace uirenderer { // Debug #if DEBUG_VECTOR_DRAWABLE - #define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__) +#define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__) #else - #define VECTOR_DRAWABLE_LOGD(...) +#define VECTOR_DRAWABLE_LOGD(...) #endif namespace VectorDrawable { -#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false) +#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) \ + (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false) #define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false) -#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value));\ - onPropertyChanged(); retVal;}) -#define UPDATE_SKPROP(field, value) ({bool retVal = ((field) != (value)); if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); retVal;}) +#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) \ + ({ \ + bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value)); \ + onPropertyChanged(); \ + retVal; \ + }) +#define UPDATE_SKPROP(field, value) \ + ({ \ + bool retVal = ((field) != (value)); \ + if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); \ + retVal; \ + }) /* A VectorDrawable is composed of a tree of nodes. * Each node can be a group node, or a path. @@ -85,12 +95,9 @@ class PropertyChangedListener { public: PropertyChangedListener(bool* dirty, bool* stagingDirty) : mDirty(dirty), mStagingDirty(stagingDirty) {} - void onPropertyChanged() { - *mDirty = true; - } - void onStagingPropertyChanged() { - *mStagingDirty = true; - } + void onPropertyChanged() { *mDirty = true; } + void onStagingPropertyChanged() { *mStagingDirty = true; } + private: bool* mDirty; bool* mStagingDirty; @@ -101,27 +108,24 @@ public: class Properties { public: explicit Properties(Node* node) : mNode(node) {} - inline void onPropertyChanged() { - mNode->onPropertyChanged(this); - } + inline void onPropertyChanged() { mNode->onPropertyChanged(this); } + private: Node* mNode; }; - Node(const Node& node) { - mName = node.mName; - } + Node(const Node& node) { mName = node.mName; } Node() {} virtual void draw(SkCanvas* outCanvas, bool useStagingData) = 0; virtual void dump() = 0; - void setName(const char* name) { - mName = name; - } + void setName(const char* name) { mName = name; } virtual void setPropertyChangedListener(PropertyChangedListener* listener) { mPropertyChangedListener = listener; } virtual void onPropertyChanged(Properties* properties) = 0; - virtual ~Node(){} + virtual ~Node() {} virtual void syncProperties() = 0; + virtual void setAntiAlias(bool aa) = 0; + protected: std::string mName; PropertyChangedListener* mPropertyChangedListener = nullptr; @@ -134,8 +138,7 @@ public: std::vector<size_t> verbSizes; std::vector<float> points; bool operator==(const Data& data) const { - return verbs == data.verbs && verbSizes == data.verbSizes - && points == data.points; + return verbs == data.verbs && verbSizes == data.verbSizes && points == data.points; } }; @@ -156,11 +159,9 @@ public: } mData = data; onPropertyChanged(); - - } - const Data& getData() const { - return mData; } + const Data& getData() const { return mData; } + private: Data mData; }; @@ -177,7 +178,7 @@ public: if (mPropertyChangedListener) { mPropertyChangedListener->onStagingPropertyChanged(); } - } else if (prop == &mProperties){ + } else if (prop == &mProperties) { mSkPathDirty = true; if (mPropertyChangedListener) { mPropertyChangedListener->onPropertyChanged(); @@ -203,7 +204,7 @@ private: bool mStagingPropertiesDirty = true; }; -class ANDROID_API FullPath: public Path { +class ANDROID_API FullPath : public Path { public: class FullPathProperties : public Properties { public: @@ -234,87 +235,59 @@ public: onPropertyChanged(); } void setFillGradient(SkShader* gradient) { - if(UPDATE_SKPROP(fillGradient, gradient)) { + if (UPDATE_SKPROP(fillGradient, gradient)) { onPropertyChanged(); } } void setStrokeGradient(SkShader* gradient) { - if(UPDATE_SKPROP(strokeGradient, gradient)) { + if (UPDATE_SKPROP(strokeGradient, gradient)) { onPropertyChanged(); } } - SkShader* getFillGradient() const { - return fillGradient; - } - SkShader* getStrokeGradient() const { - return strokeGradient; - } - float getStrokeWidth() const{ - return mPrimitiveFields.strokeWidth; - } + SkShader* getFillGradient() const { return fillGradient; } + SkShader* getStrokeGradient() const { return strokeGradient; } + float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; } void setStrokeWidth(float strokeWidth) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth); } - SkColor getStrokeColor() const{ - return mPrimitiveFields.strokeColor; - } + SkColor getStrokeColor() const { return mPrimitiveFields.strokeColor; } void setStrokeColor(SkColor strokeColor) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeColor, strokeColor); } - float getStrokeAlpha() const{ - return mPrimitiveFields.strokeAlpha; - } + float getStrokeAlpha() const { return mPrimitiveFields.strokeAlpha; } void setStrokeAlpha(float strokeAlpha) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeAlpha, strokeAlpha); } - SkColor getFillColor() const { - return mPrimitiveFields.fillColor; - } + SkColor getFillColor() const { return mPrimitiveFields.fillColor; } void setFillColor(SkColor fillColor) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillColor, fillColor); } - float getFillAlpha() const{ - return mPrimitiveFields.fillAlpha; - } + float getFillAlpha() const { return mPrimitiveFields.fillAlpha; } void setFillAlpha(float fillAlpha) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillAlpha, fillAlpha); } - float getTrimPathStart() const{ - return mPrimitiveFields.trimPathStart; - } + float getTrimPathStart() const { return mPrimitiveFields.trimPathStart; } void setTrimPathStart(float trimPathStart) { VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathStart, trimPathStart, mTrimDirty); } - float getTrimPathEnd() const{ - return mPrimitiveFields.trimPathEnd; - } + float getTrimPathEnd() const { return mPrimitiveFields.trimPathEnd; } void setTrimPathEnd(float trimPathEnd) { VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathEnd, trimPathEnd, mTrimDirty); } - float getTrimPathOffset() const{ - return mPrimitiveFields.trimPathOffset; - } + float getTrimPathOffset() const { return mPrimitiveFields.trimPathOffset; } void setTrimPathOffset(float trimPathOffset) { VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathOffset, trimPathOffset, mTrimDirty); } - float getStrokeMiterLimit() const { - return mPrimitiveFields.strokeMiterLimit; - } - float getStrokeLineCap() const { - return mPrimitiveFields.strokeLineCap; - } - float getStrokeLineJoin() const { - return mPrimitiveFields.strokeLineJoin; - } - float getFillType() const { - return mPrimitiveFields.fillType; - } + float getStrokeMiterLimit() const { return mPrimitiveFields.strokeMiterLimit; } + float getStrokeLineCap() const { return mPrimitiveFields.strokeLineCap; } + float getStrokeLineJoin() const { return mPrimitiveFields.strokeLineJoin; } + float getFillType() const { return mPrimitiveFields.fillType; } bool copyProperties(int8_t* outProperties, int length) const; void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, - SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, - float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, - int fillType) { + SkColor fillColor, float fillAlpha, float trimPathStart, + float trimPathEnd, float trimPathOffset, float strokeMiterLimit, + int strokeLineCap, int strokeLineJoin, int fillType) { mPrimitiveFields.strokeWidth = strokeWidth; mPrimitiveFields.strokeColor = strokeColor; mPrimitiveFields.strokeAlpha = strokeAlpha; @@ -334,6 +307,7 @@ public: void setColorPropertyValue(int propertyId, int32_t value); void setPropertyValue(int propertyId, float value); bool mTrimDirty; + private: enum class Property { strokeWidth = 0, @@ -356,7 +330,7 @@ public: }; // Called from UI thread - FullPath(const FullPath& path); // for cloning + FullPath(const FullPath& path); // for cloning FullPath(const char* path, size_t strLength) : Path(path, strLength) {} FullPath() : Path() {} void draw(SkCanvas* outCanvas, bool useStagingData) override; @@ -381,29 +355,32 @@ public: } } } + virtual void setAntiAlias(bool aa) { mAntiAlias = aa; } protected: const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) override; -private: +private: FullPathProperties mProperties = FullPathProperties(this); FullPathProperties mStagingProperties = FullPathProperties(this); bool mStagingPropertiesDirty = true; // Intermediate data for drawing, render thread only SkPath mTrimmedSkPath; - + // Default to use AntiAlias + bool mAntiAlias = true; }; -class ANDROID_API ClipPath: public Path { +class ANDROID_API ClipPath : public Path { public: ClipPath(const ClipPath& path) : Path(path) {} ClipPath(const char* path, size_t strLength) : Path(path, strLength) {} ClipPath() : Path() {} void draw(SkCanvas* outCanvas, bool useStagingData) override; + virtual void setAntiAlias(bool aa) {} }; -class ANDROID_API Group: public Node { +class ANDROID_API Group : public Node { public: class GroupProperties : public Properties { public: @@ -421,50 +398,26 @@ public: mPrimitiveFields = prop.mPrimitiveFields; onPropertyChanged(); } - float getRotation() const { - return mPrimitiveFields.rotate; - } - void setRotation(float rotation) { - VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation); - } - float getPivotX() const { - return mPrimitiveFields.pivotX; - } - void setPivotX(float pivotX) { - VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX); - } - float getPivotY() const { - return mPrimitiveFields.pivotY; - } - void setPivotY(float pivotY) { - VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY); - } - float getScaleX() const { - return mPrimitiveFields.scaleX; - } - void setScaleX(float scaleX) { - VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX); - } - float getScaleY() const { - return mPrimitiveFields.scaleY; - } - void setScaleY(float scaleY) { - VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY); - } - float getTranslateX() const { - return mPrimitiveFields.translateX; - } + float getRotation() const { return mPrimitiveFields.rotate; } + void setRotation(float rotation) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation); } + float getPivotX() const { return mPrimitiveFields.pivotX; } + void setPivotX(float pivotX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX); } + float getPivotY() const { return mPrimitiveFields.pivotY; } + void setPivotY(float pivotY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY); } + float getScaleX() const { return mPrimitiveFields.scaleX; } + void setScaleX(float scaleX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX); } + float getScaleY() const { return mPrimitiveFields.scaleY; } + void setScaleY(float scaleY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY); } + float getTranslateX() const { return mPrimitiveFields.translateX; } void setTranslateX(float translateX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateX, translateX); } - float getTranslateY() const { - return mPrimitiveFields.translateY; - } + float getTranslateY() const { return mPrimitiveFields.translateY; } void setTranslateY(float translateY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateY, translateY); } - void updateProperties(float rotate, float pivotX, float pivotY, - float scaleX, float scaleY, float translateX, float translateY) { + void updateProperties(float rotate, float pivotX, float pivotY, float scaleX, float scaleY, + float translateX, float translateY) { mPrimitiveFields.rotate = rotate; mPrimitiveFields.pivotX = pivotX; mPrimitiveFields.pivotY = pivotY; @@ -478,6 +431,7 @@ public: float getPropertyValue(int propertyId) const; bool copyProperties(float* outProperties, int length) const; static bool isValidProperty(int propertyId); + private: enum class Property { rotate = 0, @@ -498,7 +452,7 @@ public: virtual void setPropertyChangedListener(PropertyChangedListener* listener) override { Node::setPropertyChangedListener(listener); for (auto& child : mChildren) { - child->setPropertyChangedListener(listener); + child->setPropertyChangedListener(listener); } } virtual void syncProperties() override; @@ -527,11 +481,17 @@ public: } } + virtual void setAntiAlias(bool aa) { + for (auto& child : mChildren) { + child->setAntiAlias(aa); + } + } + private: GroupProperties mProperties = GroupProperties(this); GroupProperties mStagingProperties = GroupProperties(this); bool mStagingPropertiesDirty = true; - std::vector< std::unique_ptr<Node> > mChildren; + std::vector<std::unique_ptr<Node> > mChildren; }; class ANDROID_API Tree : public VirtualLightRefBase { @@ -547,17 +507,25 @@ public: } // Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input // canvas. Returns the number of pixels needed for the bitmap cache. - int draw(Canvas* outCanvas, SkColorFilter* colorFilter, - const SkRect& bounds, bool needsMirroring, bool canReuseCache); + int draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds, + bool needsMirroring, bool canReuseCache); void drawStaging(Canvas* canvas); Bitmap& getBitmapUpdateIfDirty(); - void setAllowCaching(bool allowCaching) { - mAllowCaching = allowCaching; - } + void setAllowCaching(bool allowCaching) { mAllowCaching = allowCaching; } SkPaint* getPaint(); void syncProperties() { if (mStagingProperties.mNonAnimatablePropertiesDirty) { + mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth != + mStagingProperties.mNonAnimatableProperties.viewportWidth) || + (mProperties.mNonAnimatableProperties.viewportHeight != + mStagingProperties.mNonAnimatableProperties.viewportHeight) || + (mProperties.mNonAnimatableProperties.scaledWidth != + mStagingProperties.mNonAnimatableProperties.scaledWidth) || + (mProperties.mNonAnimatableProperties.scaledHeight != + mStagingProperties.mNonAnimatableProperties.scaledHeight) || + (mProperties.mNonAnimatableProperties.bounds != + mStagingProperties.mNonAnimatableProperties.bounds); mProperties.syncNonAnimatableProperties(mStagingProperties); mStagingProperties.mNonAnimatablePropertiesDirty = false; } @@ -583,9 +551,7 @@ public: int scaledWidth = 0; int scaledHeight = 0; SkColorFilter* colorFilter = nullptr; - ~NonAnimatableProperties() { - SkSafeUnref(colorFilter); - } + ~NonAnimatableProperties() { SkSafeUnref(colorFilter); } } mNonAnimatableProperties; bool mNonAnimatablePropertiesDirty = true; @@ -596,14 +562,14 @@ public: // Copy over the data that can only be changed in UI thread if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) { SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter, - prop.mNonAnimatableProperties.colorFilter); + prop.mNonAnimatableProperties.colorFilter); } mNonAnimatableProperties = prop.mNonAnimatableProperties; } void setViewportSize(float width, float height) { - if (mNonAnimatableProperties.viewportWidth != width - || mNonAnimatableProperties.viewportHeight != height) { + if (mNonAnimatableProperties.viewportWidth != width || + mNonAnimatableProperties.viewportHeight != height) { mNonAnimatablePropertiesDirty = true; mNonAnimatableProperties.viewportWidth = width; mNonAnimatableProperties.viewportHeight = height; @@ -622,12 +588,12 @@ public: // If the requested size is bigger than what the bitmap was, then // we increase the bitmap size to match. The width and height // are bound by MAX_CACHED_BITMAP_SIZE. - if (mNonAnimatableProperties.scaledWidth < width - || mNonAnimatableProperties.scaledHeight < height) { - mNonAnimatableProperties.scaledWidth = std::max(width, - mNonAnimatableProperties.scaledWidth); - mNonAnimatableProperties.scaledHeight = std::max(height, - mNonAnimatableProperties.scaledHeight); + if (mNonAnimatableProperties.scaledWidth < width || + mNonAnimatableProperties.scaledHeight < height) { + mNonAnimatableProperties.scaledWidth = + std::max(width, mNonAnimatableProperties.scaledWidth); + mNonAnimatableProperties.scaledHeight = + std::max(height, mNonAnimatableProperties.scaledHeight); mNonAnimatablePropertiesDirty = true; mTree->onPropertyChanged(this); } @@ -638,25 +604,13 @@ public: mTree->onPropertyChanged(this); } } - SkColorFilter* getColorFilter() const{ - return mNonAnimatableProperties.colorFilter; - } + SkColorFilter* getColorFilter() const { return mNonAnimatableProperties.colorFilter; } - float getViewportWidth() const { - return mNonAnimatableProperties.viewportWidth; - } - float getViewportHeight() const { - return mNonAnimatableProperties.viewportHeight; - } - float getScaledWidth() const { - return mNonAnimatableProperties.scaledWidth; - } - float getScaledHeight() const { - return mNonAnimatableProperties.scaledHeight; - } - void syncAnimatableProperties(const TreeProperties& prop) { - mRootAlpha = prop.mRootAlpha; - } + float getViewportWidth() const { return mNonAnimatableProperties.viewportWidth; } + float getViewportHeight() const { return mNonAnimatableProperties.viewportHeight; } + float getScaledWidth() const { return mNonAnimatableProperties.scaledWidth; } + float getScaledHeight() const { return mNonAnimatableProperties.scaledHeight; } + void syncAnimatableProperties(const TreeProperties& prop) { mRootAlpha = prop.mRootAlpha; } bool setRootAlpha(float rootAlpha) { if (rootAlpha != mRootAlpha) { mAnimatablePropertiesDirty = true; @@ -666,10 +620,8 @@ public: } return false; } - float getRootAlpha() const { return mRootAlpha;} - const SkRect& getBounds() const { - return mNonAnimatableProperties.bounds; - } + float getRootAlpha() const { return mRootAlpha; } + const SkRect& getBounds() const { return mNonAnimatableProperties.bounds; } Tree* mTree; }; void onPropertyChanged(TreeProperties* prop); @@ -700,11 +652,13 @@ public: */ void updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context); + void setAntiAlias(bool aa) { mRootNode->setAntiAlias(aa); } + private: class Cache { public: - sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software - //TODO: use surface instead of bitmap when drawing in software canvas + sk_sp<Bitmap> bitmap; // used by HWUI pipeline and software + // TODO: use surface instead of bitmap when drawing in software canvas bool dirty = true; // the rest of the code in Cache is used by Skia pipelines only @@ -715,7 +669,7 @@ private: * Stores a weak pointer to the atlas and a key. */ void setAtlas(sp<skiapipeline::VectorDrawableAtlas> atlas, - skiapipeline::AtlasKey newAtlasKey); + skiapipeline::AtlasKey newAtlasKey); /** * Gets a surface and bounds from the atlas. @@ -728,6 +682,7 @@ private: * Releases atlas key from the atlas, which makes it available for reuse. */ void clear(); + private: wp<skiapipeline::VectorDrawableAtlas> mAtlas; skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY; @@ -738,11 +693,6 @@ private: bool canReuseBitmap(Bitmap*, int width, int height); void updateBitmapCache(Bitmap& outCache, bool useStagingData); - /** - * Draws the root node into "surface" at a given "dst" position. - */ - void draw(SkSurface* surface, const SkRect& dst); - // Cap the bitmap size, such that it won't hurt the performance too much // and it won't crash due to a very large scale. // The drawable will look blurry above this size. @@ -759,16 +709,16 @@ private: Cache mStagingCache; Cache mCache; - PropertyChangedListener mPropertyChangedListener - = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty); + PropertyChangedListener mPropertyChangedListener = + PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty); mutable bool mWillBeConsumed = false; }; -} // namespace VectorDrawable +} // namespace VectorDrawable typedef VectorDrawable::Path::Data PathData; -} // namespace uirenderer -} // namespace android +} // namespace uirenderer +} // namespace android -#endif // ANDROID_HWUI_VPATH_H +#endif // ANDROID_HWUI_VPATH_H |