aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkDevice.cpp')
-rw-r--r--src/core/SkDevice.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index b2ff2423ed..4caa8756cb 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -10,6 +10,7 @@
#include "SkDraw.h"
#include "SkDrawFilter.h"
#include "SkImage_Base.h"
+#include "SkImageCacherator.h"
#include "SkImageFilter.h"
#include "SkImageFilterCache.h"
#include "SkImagePriv.h"
@@ -24,6 +25,7 @@
#include "SkSpecialImage.h"
#include "SkTextBlobRunIterator.h"
#include "SkTextToPathIter.h"
+#include "SkTLazy.h"
SkBaseDevice::SkBaseDevice(const SkImageInfo& info, const SkSurfaceProps& surfaceProps)
: fInfo(info)
@@ -177,9 +179,60 @@ void SkBaseDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSc
}
}
+bool SkBaseDevice::drawExternallyScaledImage(const SkDraw& draw,
+ const SkImage* image,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint& paint,
+ SkCanvas::SrcRectConstraint constraint) {
+ SkImageCacherator* cacherator = as_IB(image)->peekCacherator();
+ if (!cacherator) {
+ return false;
+ }
+
+ SkTLazy<SkRect> tmpSrc(src);
+ if (!tmpSrc.isValid()) {
+ tmpSrc.init(SkRect::Make(image->bounds()));
+ }
+
+ SkMatrix m = *draw.fMatrix;
+ m.preConcat(SkMatrix::MakeRectToRect(*tmpSrc.get(), dst, SkMatrix::kFill_ScaleToFit));
+
+ // constrain src to our bounds
+ if (!image->bounds().contains(*tmpSrc.get()) &&
+ !tmpSrc.get()->intersect(SkRect::Make(image->bounds()))) {
+ return false;
+ }
+
+ SkImageGenerator::ScaledImageRec rec;
+ if (!cacherator->directAccessScaledImage(*tmpSrc.get(), m, paint.getFilterQuality(), &rec)) {
+ return false;
+ }
+
+ SkBitmap bm;
+ if (!as_IB(rec.fImage)->getROPixels(&bm)) {
+ return false;
+ }
+
+ SkTCopyOnFirstWrite<SkPaint> adjustedPaint(paint);
+ if (rec.fQuality != paint.getFilterQuality()) {
+ adjustedPaint.writable()->setFilterQuality(rec.fQuality);
+ }
+
+ this->drawBitmapRect(draw, bm, &rec.fSrcRect, dst, *adjustedPaint, constraint);
+
+ return true;
+}
void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
const SkPaint& paint) {
// Default impl : turns everything into raster bitmap
+
+ if (this->drawExternallyScaledImage(draw, image, nullptr,
+ SkRect::Make(image->bounds()).makeOffset(x, y),
+ paint, SkCanvas::kFast_SrcRectConstraint)) {
+ return;
+ }
+
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm)) {
this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
@@ -190,6 +243,11 @@ void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const
const SkRect& dst, const SkPaint& paint,
SkCanvas::SrcRectConstraint constraint) {
// Default impl : turns everything into raster bitmap
+
+ if (this->drawExternallyScaledImage(draw, image, src, dst, paint, constraint)) {
+ return;
+ }
+
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm)) {
this->drawBitmapRect(draw, bm, src, dst, paint, constraint);