2019-09-04 21:39:42 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2019 Google LLC
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "samplecode/Sample.h"
|
|
|
|
|
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkColor.h"
|
|
|
|
#include "include/core/SkFont.h"
|
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/core/SkPath.h"
|
|
|
|
#include "include/core/SkPoint.h"
|
|
|
|
#include "include/core/SkRect.h"
|
|
|
|
|
|
|
|
#include "tools/ToolUtils.h"
|
|
|
|
|
|
|
|
static constexpr float kLineHeight = 16.f;
|
|
|
|
static constexpr float kLineInset = 8.f;
|
|
|
|
|
|
|
|
static float print_size(SkCanvas* canvas, const char* prefix, const SkIRect& rect,
|
2019-09-05 17:10:21 +00:00
|
|
|
float x, float y, const SkFont& font, const SkPaint& paint) {
|
2019-09-04 21:39:42 +00:00
|
|
|
canvas->drawString(prefix, x, y, font, paint);
|
|
|
|
y += kLineHeight;
|
|
|
|
SkString sz;
|
|
|
|
sz.appendf("%d x %d", rect.width(), rect.height());
|
|
|
|
canvas->drawString(sz, x, y, font, paint);
|
|
|
|
return y + kLineHeight;
|
|
|
|
}
|
|
|
|
|
2019-09-05 17:10:21 +00:00
|
|
|
static float print_info(SkCanvas* canvas, const SkIRect& origLayerBounds,
|
|
|
|
const SkIRect& localLayerBounds, const SkIRect& filterInputBounds,
|
|
|
|
const SkIRect& devLayerBounds) {
|
2019-09-04 21:39:42 +00:00
|
|
|
SkFont font(nullptr, 12);
|
|
|
|
SkPaint text;
|
|
|
|
text.setAntiAlias(true);
|
|
|
|
|
|
|
|
float y = kLineHeight;
|
|
|
|
|
|
|
|
text.setColor(SK_ColorBLACK);
|
|
|
|
y = print_size(canvas, "Orig layer", origLayerBounds, kLineInset, y, font, text);
|
|
|
|
text.setColor(SK_ColorRED);
|
|
|
|
y = print_size(canvas, "Filter layer", localLayerBounds, kLineInset, y, font, text);
|
|
|
|
text.setColor(SK_ColorBLUE);
|
|
|
|
y = print_size(canvas, "Filter input", filterInputBounds, kLineInset, y, font, text);
|
|
|
|
text.setColor(SK_ColorMAGENTA);
|
|
|
|
y = print_size(canvas, "Backdrop size", devLayerBounds, kLineInset, y, font, text);
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SkPaint line_paint(SkScalar width, SkColor color) {
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor(color);
|
|
|
|
paint.setStrokeWidth(width);
|
|
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
return paint;
|
|
|
|
}
|
|
|
|
|
|
|
|
class BackdropBoundsSample : public Sample {
|
|
|
|
public:
|
|
|
|
BackdropBoundsSample() {}
|
|
|
|
|
|
|
|
void onDrawContent(SkCanvas* canvas) override {
|
|
|
|
SkMatrix ctm = canvas->getTotalMatrix();
|
|
|
|
|
|
|
|
// This decomposition is for the backdrop filtering, and does not represent the CTM that
|
|
|
|
// the layer actually uses (unless it also has a filter during restore).
|
|
|
|
SkMatrix toGlobal, layerMatrix;
|
|
|
|
SkSize scale;
|
|
|
|
if (ctm.isScaleTranslate()) {
|
|
|
|
// No decomposition needed
|
|
|
|
toGlobal = SkMatrix::I();
|
|
|
|
layerMatrix = ctm;
|
|
|
|
} else if (ctm.decomposeScale(&scale, &toGlobal)) {
|
2020-05-21 16:05:02 +00:00
|
|
|
layerMatrix = SkMatrix::MakeScale(scale.fWidth, scale.fHeight);
|
2019-09-04 21:39:42 +00:00
|
|
|
} else {
|
|
|
|
toGlobal = ctm;
|
|
|
|
layerMatrix = SkMatrix::I();
|
|
|
|
}
|
|
|
|
|
|
|
|
SkMatrix fromGlobal;
|
|
|
|
if (!toGlobal.invert(&fromGlobal)) {
|
|
|
|
SkDebugf("Unable to invert CTM\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The local content, e.g. what would be submitted to drawRect
|
|
|
|
const SkRect localContentRect = SkRect::MakeLTRB(45.5f, 23.123f, 150.f, 140.45f);
|
|
|
|
canvas->drawRect(localContentRect, line_paint(0.f, SK_ColorBLACK));
|
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
// The layer bounds of the content, this is the size of the actual layer and does not
|
|
|
|
// reflect the backdrop specific decomposition.
|
|
|
|
canvas->setMatrix(SkMatrix::I());
|
|
|
|
SkIRect origLayerBounds = ctm.mapRect(localContentRect).roundOut();
|
|
|
|
canvas->drawRect(SkRect::Make(origLayerBounds), line_paint(1.f, SK_ColorBLACK));
|
|
|
|
|
|
|
|
// Have to undo the full CTM transform on the layer bounds to get the layer bounds
|
|
|
|
// for the specific backdrop filter decomposition
|
|
|
|
canvas->setMatrix(toGlobal);
|
|
|
|
SkIRect layerBounds = fromGlobal.mapRect(SkRect::Make(origLayerBounds)).roundOut();
|
|
|
|
canvas->drawRect(SkRect::Make(layerBounds), line_paint(0.5f, SK_ColorRED));
|
|
|
|
|
|
|
|
// Input bounds for the backdrop filter to cover the actual layer bounds (emulate some
|
|
|
|
// blur that must outset by 5px for reading on the edge).
|
|
|
|
SkIRect filterInputBounds = layerBounds;
|
|
|
|
filterInputBounds.outset(5, 5);
|
|
|
|
canvas->drawRect(SkRect::Make(filterInputBounds), line_paint(1.f, SK_ColorBLUE));
|
|
|
|
|
|
|
|
// The destination bounds that must be snapped in order to transform and fill the
|
|
|
|
// filterInputBounds
|
|
|
|
canvas->setMatrix(SkMatrix::I());
|
|
|
|
SkIRect devLayerBounds = toGlobal.mapRect(SkRect::Make(filterInputBounds)).roundOut();
|
|
|
|
canvas->drawRect(SkRect::Make(devLayerBounds), line_paint(2.f, SK_ColorMAGENTA));
|
|
|
|
|
|
|
|
// The destination bounds mapped back into the layer space, which should cover 'layerBounds'
|
|
|
|
SkPath backdropCoveringBounds;
|
|
|
|
|
|
|
|
// Add axis lines, to show perspective distortion
|
|
|
|
SkIRect local = fromGlobal.mapRect(SkRect::Make(devLayerBounds)).roundOut();
|
|
|
|
static int kAxisSpace = 10;
|
|
|
|
for (int y = local.fTop + kAxisSpace; y <= local.fBottom - kAxisSpace; y += kAxisSpace) {
|
|
|
|
backdropCoveringBounds.moveTo(local.fLeft, y);
|
|
|
|
backdropCoveringBounds.lineTo(local.fRight, y);
|
|
|
|
}
|
|
|
|
for (int x = local.fLeft + kAxisSpace; x <= local.fRight - kAxisSpace; x += kAxisSpace) {
|
|
|
|
backdropCoveringBounds.moveTo(x, local.fTop);
|
|
|
|
backdropCoveringBounds.lineTo(x, local.fBottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
canvas->setMatrix(toGlobal);
|
|
|
|
canvas->drawPath(backdropCoveringBounds, line_paint(0.f, SK_ColorGREEN));
|
|
|
|
|
|
|
|
canvas->resetMatrix();
|
|
|
|
print_info(canvas, origLayerBounds, layerBounds, filterInputBounds, devLayerBounds);
|
|
|
|
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
SkString name() override { return SkString("BackdropBounds"); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
typedef Sample INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
DEF_SAMPLE(return new BackdropBoundsSample();)
|