diff options
Diffstat (limited to 'libs/hwui/VectorDrawable.cpp')
-rw-r--r-- | libs/hwui/VectorDrawable.cpp | 281 |
1 files changed, 143 insertions, 138 deletions
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 1cf15ac01154..c72f87d7e481 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -138,18 +138,7 @@ void Path::setPath(const char* pathStr, size_t strLength) { } FullPath::FullPath(const FullPath& path) : Path(path) { - mStrokeWidth = path.mStrokeWidth; - mStrokeColor = path.mStrokeColor; - mStrokeAlpha = path.mStrokeAlpha; - mFillColor = path.mFillColor; - mFillAlpha = path.mFillAlpha; - mTrimPathStart = path.mTrimPathStart; - mTrimPathEnd = path.mTrimPathEnd; - mTrimPathOffset = path.mTrimPathOffset; - mStrokeMiterLimit = path.mStrokeMiterLimit; - mStrokeLineCap = path.mStrokeLineCap; - mStrokeLineJoin = path.mStrokeLineJoin; - + mProperties = path.mProperties; SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient); SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient); } @@ -159,7 +148,7 @@ const SkPath& FullPath::getUpdatedPath() { return mTrimmedSkPath; } Path::getUpdatedPath(); - if (mTrimPathStart != 0.0f || mTrimPathEnd != 1.0f) { + if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) { applyTrim(); return mTrimmedSkPath; } else { @@ -170,14 +159,14 @@ const SkPath& FullPath::getUpdatedPath() { void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) { - mStrokeWidth = strokeWidth; - mStrokeColor = strokeColor; - mStrokeAlpha = strokeAlpha; - mFillColor = fillColor; - mFillAlpha = fillAlpha; - mStrokeMiterLimit = strokeMiterLimit; - mStrokeLineCap = SkPaint::Cap(strokeLineCap); - mStrokeLineJoin = SkPaint::Join(strokeLineJoin); + mProperties.strokeWidth = strokeWidth; + mProperties.strokeColor = strokeColor; + mProperties.strokeAlpha = strokeAlpha; + mProperties.fillColor = fillColor; + mProperties.fillAlpha = fillAlpha; + mProperties.strokeMiterLimit = strokeMiterLimit; + mProperties.strokeLineCap = strokeLineCap; + mProperties.strokeLineJoin = strokeLineJoin; // If any trim property changes, mark trim dirty and update the trim path setTrimPathStart(trimPathStart); @@ -195,12 +184,12 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str // Draw path's fill, if fill color or gradient is valid bool needsFill = false; if (mFillGradient != nullptr) { - mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha)); + mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha)); SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix); mPaint.setShader(newShader); needsFill = true; - } else if (mFillColor != SK_ColorTRANSPARENT) { - mPaint.setColor(applyAlpha(mFillColor, mFillAlpha)); + } else if (mProperties.fillColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha)); needsFill = true; } @@ -213,21 +202,21 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str // Draw path's stroke, if stroke color or gradient is valid bool needsStroke = false; if (mStrokeGradient != nullptr) { - mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha)); + mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha)); SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix); mPaint.setShader(newShader); needsStroke = true; - } else if (mStrokeColor != SK_ColorTRANSPARENT) { - mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha)); + } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha)); needsStroke = true; } if (needsStroke) { mPaint.setStyle(SkPaint::Style::kStroke_Style); mPaint.setAntiAlias(true); - mPaint.setStrokeJoin(mStrokeLineJoin); - mPaint.setStrokeCap(mStrokeLineCap); - mPaint.setStrokeMiter(mStrokeMiterLimit); - mPaint.setStrokeWidth(mStrokeWidth * strokeScale); + mPaint.setStrokeJoin(SkPaint::Join(mProperties.strokeLineJoin)); + mPaint.setStrokeCap(SkPaint::Cap(mProperties.strokeLineCap)); + mPaint.setStrokeMiter(mProperties.strokeMiterLimit); + mPaint.setStrokeWidth(mProperties.strokeWidth * strokeScale); outCanvas->drawPath(renderPath, mPaint); } } @@ -236,14 +225,14 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str * Applies trimming to the specified path. */ void FullPath::applyTrim() { - if (mTrimPathStart == 0.0f && mTrimPathEnd == 1.0f) { + if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) { // No trimming necessary. return; } SkPathMeasure measure(mSkPath, false); float len = SkScalarToFloat(measure.getLength()); - float start = len * fmod((mTrimPathStart + mTrimPathOffset), 1.0f); - float end = len * fmod((mTrimPathEnd + mTrimPathOffset), 1.0f); + float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f); + float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f); mTrimmedSkPath.reset(); if (start > end) { @@ -255,76 +244,69 @@ void FullPath::applyTrim() { mTrimDirty = false; } -inline int putData(int8_t* outBytes, int startIndex, float value) { - int size = sizeof(float); - memcpy(&outBytes[startIndex], &value, size); - return size; -} - -inline int putData(int8_t* outBytes, int startIndex, int value) { - int size = sizeof(int); - memcpy(&outBytes[startIndex], &value, size); - return size; -} - -struct FullPathProperties { - // TODO: Consider storing full path properties in this struct instead of the fields. - float strokeWidth; - SkColor strokeColor; - float strokeAlpha; - SkColor fillColor; - float fillAlpha; - float trimPathStart; - float trimPathEnd; - float trimPathOffset; - int32_t strokeLineCap; - int32_t strokeLineJoin; - float strokeMiterLimit; -}; - -REQUIRE_COMPATIBLE_LAYOUT(FullPathProperties); +REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties); static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t"); static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t"); bool FullPath::getProperties(int8_t* outProperties, int length) { - int propertyDataSize = sizeof(FullPathProperties); + int propertyDataSize = sizeof(Properties); if (length != propertyDataSize) { LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided", propertyDataSize, length); return false; } - // TODO: consider replacing the property fields with a FullPathProperties struct. - FullPathProperties properties; - properties.strokeWidth = mStrokeWidth; - properties.strokeColor = mStrokeColor; - properties.strokeAlpha = mStrokeAlpha; - properties.fillColor = mFillColor; - properties.fillAlpha = mFillAlpha; - properties.trimPathStart = mTrimPathStart; - properties.trimPathEnd = mTrimPathEnd; - properties.trimPathOffset = mTrimPathOffset; - properties.strokeLineCap = mStrokeLineCap; - properties.strokeLineJoin = mStrokeLineJoin; - properties.strokeMiterLimit = mStrokeMiterLimit; - - memcpy(outProperties, &properties, length); + Properties* out = reinterpret_cast<Properties*>(outProperties); + *out = mProperties; return true; } +void FullPath::setColorPropertyValue(int propertyId, int32_t value) { + Property currentProperty = static_cast<Property>(propertyId); + if (currentProperty == Property::StrokeColor) { + mProperties.strokeColor = value; + } else if (currentProperty == Property::FillColor) { + mProperties.fillColor = value; + } else { + LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d", + propertyId); + } +} + +void FullPath::setPropertyValue(int propertyId, float value) { + Property property = static_cast<Property>(propertyId); + switch (property) { + case Property::StrokeWidth: + setStrokeWidth(value); + break; + case Property::StrokeAlpha: + setStrokeAlpha(value); + break; + case Property::FillAlpha: + setFillAlpha(value); + break; + case Property::TrimPathStart: + setTrimPathStart(value); + break; + case Property::TrimPathEnd: + setTrimPathEnd(value); + break; + case Property::TrimPathOffset: + setTrimPathOffset(value); + break; + default: + LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId); + break; + } +} + void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op); } Group::Group(const Group& group) : Node(group) { - mRotate = group.mRotate; - mPivotX = group.mPivotX; - mPivotY = group.mPivotY; - mScaleX = group.mScaleX; - mScaleY = group.mScaleY; - mTranslateX = group.mTranslateX; - mTranslateY = group.mTranslateY; + mProperties = group.mProperties; } void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX, @@ -371,10 +353,11 @@ void Group::getLocalMatrix(SkMatrix* outMatrix) { outMatrix->reset(); // TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of // translating to pivot for rotating and scaling, then translating back. - outMatrix->postTranslate(-mPivotX, -mPivotY); - outMatrix->postScale(mScaleX, mScaleY); - outMatrix->postRotate(mRotate, 0, 0); - outMatrix->postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); + outMatrix->postTranslate(-mProperties.pivotX, -mProperties.pivotY); + outMatrix->postScale(mProperties.scaleX, mProperties.scaleY); + outMatrix->postRotate(mProperties.rotate, 0, 0); + outMatrix->postTranslate(mProperties.translateX + mProperties.pivotX, + mProperties.translateY + mProperties.pivotY); } void Group::addChild(Node* child) { @@ -388,38 +371,68 @@ bool Group::getProperties(float* outProperties, int length) { propertyCount, length); return false; } - for (int i = 0; i < propertyCount; i++) { - Property currentProperty = static_cast<Property>(i); - switch (currentProperty) { - case Property::Rotate_Property: - outProperties[i] = mRotate; - break; - case Property::PivotX_Property: - outProperties[i] = mPivotX; - break; - case Property::PivotY_Property: - outProperties[i] = mPivotY; - break; - case Property::ScaleX_Property: - outProperties[i] = mScaleX; - break; - case Property::ScaleY_Property: - outProperties[i] = mScaleY; - break; - case Property::TranslateX_Property: - outProperties[i] = mTranslateX; - break; - case Property::TranslateY_Property: - outProperties[i] = mTranslateY; - break; - default: - LOG_ALWAYS_FATAL("Invalid input index: %d", i); - return false; - } - } + Properties* out = reinterpret_cast<Properties*>(outProperties); + *out = mProperties; return true; } +// TODO: Consider animating the properties as float pointers +float Group::getPropertyValue(int propertyId) const { + Property currentProperty = static_cast<Property>(propertyId); + switch (currentProperty) { + case Property::Rotate: + return mProperties.rotate; + case Property::PivotX: + return mProperties.pivotX; + case Property::PivotY: + return mProperties.pivotY; + case Property::ScaleX: + return mProperties.scaleX; + case Property::ScaleY: + return mProperties.scaleY; + case Property::TranslateX: + return mProperties.translateX; + case Property::TranslateY: + return mProperties.translateY; + default: + LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId); + return 0; + } +} + +void Group::setPropertyValue(int propertyId, float value) { + Property currentProperty = static_cast<Property>(propertyId); + switch (currentProperty) { + case Property::Rotate: + mProperties.rotate = value; + break; + case Property::PivotX: + mProperties.pivotX = value; + break; + case Property::PivotY: + mProperties.pivotY = value; + break; + case Property::ScaleX: + mProperties.scaleX = value; + break; + case Property::ScaleY: + mProperties.scaleY = value; + break; + case Property::TranslateX: + mProperties.translateX = value; + break; + case Property::TranslateY: + mProperties.translateY = value; + break; + default: + LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId); + } +} + +bool Group::isValidProperty(int propertyId) { + return propertyId >= 0 && propertyId < static_cast<int>(Property::Count); +} + void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds, bool needsMirroring, bool canReuseCache) { // The imageView can scale the canvas in different ways, in order to @@ -445,7 +458,9 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, return; } - int saveCount = outCanvas->save(SaveFlags::MatrixClip); + mPaint.setColorFilter(colorFilter); + + int saveCount = outCanvas->save(SkCanvas::SaveFlags::kMatrixClip_SaveFlag); outCanvas->translate(mBounds.fLeft, mBounds.fTop); // Handle RTL mirroring. @@ -458,43 +473,33 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, // And we use this bound for the destination rect for the drawBitmap, so // we offset to (0, 0); mBounds.offsetTo(0, 0); - createCachedBitmapIfNeeded(scaledWidth, scaledHeight); - if (!mAllowCaching) { - updateCachedBitmap(scaledWidth, scaledHeight); - } else { - if (!canReuseCache || mCacheDirty) { - updateCachedBitmap(scaledWidth, scaledHeight); - } - } - drawCachedBitmapWithRootAlpha(outCanvas, colorFilter, mBounds); + + outCanvas->drawVectorDrawable(this); outCanvas->restoreToCount(saveCount); } -void Tree::drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter, - const SkRect& originalBounds) { +SkPaint* Tree::getPaint() { SkPaint* paint; - if (mRootAlpha == 1.0f && filter == NULL) { + if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) { paint = NULL; } else { mPaint.setFilterQuality(kLow_SkFilterQuality); mPaint.setAlpha(mRootAlpha * 255); - mPaint.setColorFilter(filter); paint = &mPaint; } - outCanvas->drawBitmap(mCachedBitmap, 0, 0, mCachedBitmap.width(), mCachedBitmap.height(), - originalBounds.fLeft, originalBounds.fTop, originalBounds.fRight, - originalBounds.fBottom, paint); + return paint; } -void Tree::updateCachedBitmap(int width, int height) { +const SkBitmap& Tree::getBitmapUpdateIfDirty() { mCachedBitmap.eraseColor(SK_ColorTRANSPARENT); SkCanvas outCanvas(mCachedBitmap); - float scaleX = width / mViewportWidth; - float scaleY = height / mViewportHeight; + float scaleX = (float) mCachedBitmap.width() / mViewportWidth; + float scaleY = (float) mCachedBitmap.height() / mViewportHeight; mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY); mCacheDirty = false; + return mCachedBitmap; } void Tree::createCachedBitmapIfNeeded(int width, int height) { |