summaryrefslogtreecommitdiff
path: root/libs/hwui/SkiaCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/SkiaCanvas.cpp')
-rw-r--r--libs/hwui/SkiaCanvas.cpp277
1 files changed, 180 insertions, 97 deletions
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 0a642b60d4c7..2b0b22df7edf 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -23,14 +23,17 @@
#include "hwui/MinikinUtils.h"
#include "pipeline/skia/AnimatedDrawables.h"
+#include <SkAnimatedImage.h>
#include <SkCanvasStateUtils.h>
+#include <SkColorFilter.h>
#include <SkColorSpaceXformCanvas.h>
-#include <SkDrawable.h>
#include <SkDeque.h>
#include <SkDrawFilter.h>
+#include <SkDrawable.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkImagePriv.h>
+#include <SkPicture.h>
#include <SkRSXform.h>
#include <SkShader.h>
#include <SkTemplates.h>
@@ -46,25 +49,34 @@ Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
return new SkiaCanvas(bitmap);
}
-Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB) {
- return new SkiaCanvas(skiaCanvas, xformToSRGB);
+Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
+ return new SkiaCanvas(skiaCanvas);
}
SkiaCanvas::SkiaCanvas() {}
-SkiaCanvas::SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB)
- : mCanvas(canvas)
-{
- LOG_ALWAYS_FATAL_IF(XformToSRGB::kImmediate == xformToSRGB);
-}
+SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
mCanvasOwned =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
- cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
- mCanvas = mCanvasWrapper.get();
+ if (cs.get() == nullptr || cs->isSRGB()) {
+ if (!uirenderer::Properties::isSkiaEnabled()) {
+ mCanvasWrapper =
+ SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), SkColorSpace::MakeSRGB());
+ mCanvas = mCanvasWrapper.get();
+ } else {
+ mCanvas = mCanvasOwned.get();
+ }
+ } else {
+ /** The wrapper is needed if we are drawing into a non-sRGB destination, since
+ * we need to transform all colors (not just bitmaps via filters) into the
+ * destination's colorspace.
+ */
+ mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
+ mCanvas = mCanvasWrapper.get();
+ }
}
SkiaCanvas::~SkiaCanvas() {}
@@ -73,9 +85,9 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) {
if (mCanvas != skiaCanvas) {
mCanvas = skiaCanvas;
mCanvasOwned.reset();
+ mCanvasWrapper.reset();
}
mSaveStack.reset(nullptr);
- mHighContrastText = false;
}
// ----------------------------------------------------------------------------
@@ -86,13 +98,17 @@ void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
std::unique_ptr<SkCanvas> newCanvas =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
- cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
+ std::unique_ptr<SkCanvas> newCanvasWrapper;
+ if (cs.get() != nullptr && !cs->isSRGB()) {
+ newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
+ } else if (!uirenderer::Properties::isSkiaEnabled()) {
+ newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), SkColorSpace::MakeSRGB());
+ }
// deletes the previously owned canvas (if any)
mCanvasOwned = std::move(newCanvas);
mCanvasWrapper = std::move(newCanvasWrapper);
- mCanvas = mCanvasWrapper.get();
+ mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();
// clean up the old save stack
mSaveStack.reset(nullptr);
@@ -141,7 +157,7 @@ void SkiaCanvas::restore() {
}
bool preserveMatrix = !(rec->saveFlags & SaveFlags::Matrix);
- bool preserveClip = !(rec->saveFlags & SaveFlags::Clip);
+ bool preserveClip = !(rec->saveFlags & SaveFlags::Clip);
SkMatrix savedMatrix;
if (preserveMatrix) {
@@ -171,11 +187,6 @@ void SkiaCanvas::restoreToCount(int restoreCount) {
static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
SkCanvas::SaveLayerFlags layerFlags = 0;
- // We intentionally ignore the SaveFlags::HasAlphaLayer and
- // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it
- // and our Android client may use it incorrectly.
- // In Skia, this flag is purely for performance optimization.
-
if (!(flags & SaveFlags::ClipToLayer)) {
layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
}
@@ -183,16 +194,16 @@ static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
return layerFlags;
}
-int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SaveFlags::Flags flags) {
+int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SaveFlags::Flags flags) {
const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags));
return mCanvas->saveLayer(rec);
}
-int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SaveFlags::Flags flags) {
+int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
+ SaveFlags::Flags flags) {
if (static_cast<unsigned>(alpha) < 0xFF) {
SkPaint alphaPaint;
alphaPaint.setAlpha(alpha);
@@ -204,24 +215,24 @@ int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
class SkiaCanvas::Clip {
public:
Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
- : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
+ : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
- : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
+ : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
- : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
+ : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
void apply(SkCanvas* canvas) const {
canvas->setMatrix(mMatrix);
switch (mType) {
- case Type::Rect:
- canvas->clipRect(mRRect.rect(), mOp);
- break;
- case Type::RRect:
- canvas->clipRRect(mRRect, mOp);
- break;
- case Type::Path:
- canvas->clipPath(*mPath.get(), mOp);
- break;
+ case Type::Rect:
+ canvas->clipRect(mRRect.rect(), mOp);
+ break;
+ case Type::RRect:
+ canvas->clipRRect(mRRect, mOp);
+ break;
+ case Type::Path:
+ canvas->clipPath(*mPath.get(), mOp);
+ break;
}
}
@@ -232,19 +243,17 @@ private:
Path,
};
- Type mType;
- SkClipOp mOp;
- SkMatrix mMatrix;
+ Type mType;
+ SkClipOp mOp;
+ SkMatrix mMatrix;
// These are logically a union (tracked separately due to non-POD path).
SkTLazy<SkPath> mPath;
- SkRRect mRRect;
+ SkRRect mRRect;
};
const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
- const SaveRec* rec = mSaveStack
- ? static_cast<const SaveRec*>(mSaveStack->back())
- : nullptr;
+ const SaveRec* rec = mSaveStack ? static_cast<const SaveRec*>(mSaveStack->back()) : nullptr;
int currentSaveCount = mCanvas->getSaveCount();
SkASSERT(!rec || currentSaveCount >= rec->saveCount);
@@ -422,10 +431,9 @@ SkCanvasState* SkiaCanvas::captureCanvasState() const {
// translate & scale transforms, and a simple rectangular clip.
// (This also avoids significant wasted time in calling
// SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
- if (!canvas->isClipRect() ||
- (canvas->getTotalMatrix().getType() &
- ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
- return nullptr;
+ if (!canvas->isClipRect() || (canvas->getTotalMatrix().getType() &
+ ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
+ return nullptr;
}
return SkCanvasStateUtils::CaptureCanvasState(canvas);
@@ -451,7 +459,7 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
SkCanvas::PointMode mode) {
if (CC_UNLIKELY(count < 2 || paint.nothingToDraw())) return;
// convert the floats into SkPoints
- count >>= 1; // now it is the number of points
+ count >>= 1; // now it is the number of points
std::unique_ptr<SkPoint[]> pts(new SkPoint[count]);
for (int i = 0; i < count; i++) {
pts[i].set(points[0], points[1]);
@@ -460,7 +468,6 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
mCanvas->drawPoints(mode, count, pts.get(), paint);
}
-
void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
mCanvas->drawPoint(x, y, paint);
}
@@ -479,11 +486,9 @@ void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint)
this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
}
-void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
+void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
mCanvas->drawRect({left, top, right, bottom}, paint);
-
}
void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
@@ -491,8 +496,8 @@ void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
mCanvas->drawRegion(region, paint);
}
-void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) {
+void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
mCanvas->drawRoundRect(rect, rx, ry, paint);
@@ -509,15 +514,22 @@ void SkiaCanvas::drawOval(float left, float top, float right, float bottom, cons
mCanvas->drawOval(oval, paint);
}
-void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, bool useCenter, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+ if (fabs(sweepAngle) >= 360.0f) {
+ mCanvas->drawOval(arc, paint);
+ } else {
+ mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+ }
}
void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
if (CC_UNLIKELY(paint.nothingToDraw())) return;
+ if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
+ return;
+ }
mCanvas->drawPath(path, paint);
}
@@ -529,26 +541,65 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
+const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
+ sk_sp<SkColorFilter> colorSpaceFilter) {
+ /* We don't apply the colorSpace filter if this canvas is already wrapped with
+ * a SkColorSpaceXformCanvas since it already takes care of converting the
+ * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
+ * should only be used if this canvas is backed by a surface/bitmap that is known
+ * to have a non-sRGB colorspace.
+ */
+ if (!mCanvasWrapper && colorSpaceFilter) {
+ if (origPaint) {
+ *tmpPaint = *origPaint;
+ }
+
+ if (tmpPaint->getColorFilter()) {
+ tmpPaint->setColorFilter(
+ SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
+ LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
+ } else {
+ tmpPaint->setColorFilter(colorSpaceFilter);
+ }
+
+ return tmpPaint;
+ } else {
+ return origPaint;
+ }
+}
+
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- mCanvas->drawImage(bitmap.makeImage(), left, top, paint);
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter));
}
-void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
SkAutoCanvasRestore acr(mCanvas, true);
mCanvas->concat(matrix);
- mCanvas->drawImage(hwuiBitmap.makeImage(), 0, 0, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter));
}
-void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
+void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
+ float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, const SkPaint* paint) {
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- mCanvas->drawImageRect(hwuiBitmap.makeImage(), srcRect, dstRect, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter),
+ SkCanvas::kFast_SrcRectConstraint);
}
-void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
+void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) {
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
const int indexCount = meshWidth * meshHeight * 6;
uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
@@ -565,8 +616,8 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
// cons up texture coordinates and indices
{
- const SkScalar w = SkIntToScalar(hwuiBitmap.width());
- const SkScalar h = SkIntToScalar(hwuiBitmap.height());
+ const SkScalar w = SkIntToScalar(bitmap.width());
+ const SkScalar h = SkIntToScalar(bitmap.height());
const SkScalar dx = w / meshWidth;
const SkScalar dy = h / meshHeight;
@@ -612,7 +663,7 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
SkASSERT(indexPtr - indices == indexCount);
}
- // double-check that we have legal indices
+// double-check that we have legal indices
#ifdef SK_DEBUG
{
for (int i = 0; i < indexCount; i++) {
@@ -627,19 +678,26 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& hwuiBitmap, int meshWidth, int meshHeigh
tmpPaint = *paint;
}
- sk_sp<SkImage> image = hwuiBitmap.makeImage();
- tmpPaint.setShader(image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode));
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ sk_sp<SkShader> shader =
+ image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ if (colorFilter) {
+ shader = shader->makeWithColorFilter(colorFilter);
+ }
+ tmpPaint.setShader(shader);
mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint);
}
-void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
- float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
-
+void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
+ float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) {
SkCanvas::Lattice lattice;
- NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+ NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
- lattice.fFlags = nullptr;
+ lattice.fRectTypes = nullptr;
+ lattice.fColors = nullptr;
int numFlags = 0;
if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
// We can expect the framework to give us a color for every distinct rect.
@@ -647,14 +705,23 @@ void SkiaCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
}
- SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
+ SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
+ SkAutoSTMalloc<25, SkColor> colors(numFlags);
if (numFlags > 0) {
- NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
+ NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
}
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- mCanvas->drawImageLattice(hwuiBitmap.makeImage().get(), lattice, dst, paint);
+
+ SkPaint tmpPaint;
+ sk_sp<SkColorFilter> colorFilter;
+ sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter));
+}
+
+double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
+ return imgDrawable->drawStaging(mCanvas);
}
void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
@@ -666,17 +733,24 @@ void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
// ----------------------------------------------------------------------------
void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& paint, float x,
- float y, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
- float totalAdvance) {
+ float y, float boundsLeft, float boundsTop, float boundsRight,
+ float boundsBottom, float totalAdvance) {
if (count <= 0 || paint.nothingToDraw()) return;
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
// care of all alignment.
SkPaint paintCopy(paint);
paintCopy.setTextAlign(SkPaint::kLeft_Align);
+ SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+ // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
+ // older.
+ if (!mCanvasOwned && sApiLevel <= 27 && paintCopy.getStrokeWidth() <= 0
+ && paintCopy.getStyle() == SkPaint::kStroke_Style) {
+ paintCopy.setStyle(SkPaint::kFill_Style);
+ }
- SkRect bounds = SkRect::MakeLTRB(boundsLeft + x, boundsTop + y,
- boundsRight + x, boundsBottom + y);
+ SkRect bounds =
+ SkRect::MakeLTRB(boundsLeft + x, boundsTop + y, boundsRight + x, boundsBottom + y);
SkTextBlobBuilder builder;
const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(paintCopy, count, &bounds);
@@ -688,7 +762,8 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p
}
void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
- const SkPaint& paint, const SkPath& path, size_t start, size_t end) {
+ const SkPaint& paint, const SkPath& path, size_t start,
+ size_t end) {
const int N = end - start;
SkAutoSTMalloc<1024, uint8_t> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform)));
SkRSXform* xform = (SkRSXform*)storage.get();
@@ -697,7 +772,8 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
for (size_t i = start; i < end; i++) {
glyphs[i - start] = layout.getGlyphId(i);
- float x = hOffset + layout.getX(i);
+ float halfWidth = layout.getCharAdvance(i) * 0.5f;
+ float x = hOffset + layout.getX(i) + halfWidth;
float y = vOffset + layout.getY(i);
SkPoint pos;
@@ -708,8 +784,8 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
}
xform[i - start].fSCos = tan.x();
xform[i - start].fSSin = tan.y();
- xform[i - start].fTx = pos.x() - tan.y() * y;
- xform[i - start].fTy = pos.y() + tan.x() * y;
+ xform[i - start].fTx = pos.x() - tan.y() * y - halfWidth * tan.x();
+ xform[i - start].fTy = pos.y() + tan.x() * y - halfWidth * tan.y();
}
this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paint);
@@ -720,17 +796,24 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
// ----------------------------------------------------------------------------
void SkiaCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
- uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
- uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
- uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
+ uirenderer::CanvasPropertyPrimitive* top,
+ uirenderer::CanvasPropertyPrimitive* right,
+ uirenderer::CanvasPropertyPrimitive* bottom,
+ uirenderer::CanvasPropertyPrimitive* rx,
+ uirenderer::CanvasPropertyPrimitive* ry,
+ uirenderer::CanvasPropertyPaint* paint) {
sk_sp<uirenderer::skiapipeline::AnimatedRoundRect> drawable(
- new uirenderer::skiapipeline::AnimatedRoundRect(left, top, right, bottom, rx, ry, paint));
+ new uirenderer::skiapipeline::AnimatedRoundRect(left, top, right, bottom, rx, ry,
+ paint));
mCanvas->drawDrawable(drawable.get());
}
-void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y,
- uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) {
- sk_sp<uirenderer::skiapipeline::AnimatedCircle> drawable(new uirenderer::skiapipeline::AnimatedCircle(x, y, radius, paint));
+void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x,
+ uirenderer::CanvasPropertyPrimitive* y,
+ uirenderer::CanvasPropertyPrimitive* radius,
+ uirenderer::CanvasPropertyPaint* paint) {
+ sk_sp<uirenderer::skiapipeline::AnimatedCircle> drawable(
+ new uirenderer::skiapipeline::AnimatedCircle(x, y, radius, paint));
mCanvas->drawDrawable(drawable.get());
}
@@ -747,8 +830,8 @@ void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
}
void SkiaCanvas::callDrawGLFunction(Functor* functor,
- uirenderer::GlFunctorLifecycleListener* listener) {
+ uirenderer::GlFunctorLifecycleListener* listener) {
LOG_ALWAYS_FATAL("SkiaCanvas can't directly draw GL Content");
}
-} // namespace android
+} // namespace android