2016-10-11 14:18:18 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gm.h"
|
|
|
|
#include "SkRRect.h"
|
|
|
|
#include "SkGaussianEdgeShader.h"
|
|
|
|
|
|
|
|
//#define VIZ 1
|
|
|
|
|
|
|
|
#ifdef VIZ
|
|
|
|
#include "SkStroke.h"
|
|
|
|
|
|
|
|
static void draw_stroke(SkCanvas* canvas, const SkRRect& rr, const SkPaint& p, SkColor color) {
|
|
|
|
SkPath output;
|
|
|
|
|
|
|
|
if (SkPaint::kFill_Style == p.getStyle()) {
|
|
|
|
output.addRRect(rr);
|
|
|
|
} else {
|
|
|
|
SkPath input;
|
|
|
|
input.addRRect(rr);
|
|
|
|
|
|
|
|
SkStroke stroke(p);
|
|
|
|
stroke.strokePath(input, &output);
|
|
|
|
}
|
|
|
|
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
paint.setColor(color);
|
|
|
|
|
|
|
|
canvas->drawPath(output, paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extract_pts(const SkBitmap& bm, SkTDArray<SkPoint>* pts,
|
|
|
|
int xOff, int width) {
|
|
|
|
pts->rewind();
|
|
|
|
|
|
|
|
for (int x = 0; x < width; ++x) {
|
|
|
|
SkColor color = bm.getColor(xOff+x, 0);
|
|
|
|
|
|
|
|
pts->append()->set(SkIntToScalar(x), 255.0f-SkColorGetB(color));
|
|
|
|
if (x > 0 && x < width-1) {
|
|
|
|
pts->append()->set(SkIntToScalar(x), 255.0f-SkColorGetB(color));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_row(SkCanvas* canvas, int row, int width) {
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
|
|
|
|
SkBitmap readback;
|
|
|
|
|
|
|
|
if (!canvas->readPixels(SkIRect::MakeXYWH(0, row, width, 1), &readback)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkTDArray<SkPoint> pts;
|
|
|
|
pts.setReserve(width/3);
|
|
|
|
|
|
|
|
extract_pts(readback, &pts, 0, width/3);
|
|
|
|
paint.setColor(SK_ColorRED);
|
|
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
|
|
|
|
|
|
|
|
extract_pts(readback, &pts, width/3, width/3);
|
|
|
|
paint.setColor(SK_ColorGREEN);
|
|
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
|
|
|
|
|
|
|
|
extract_pts(readback, &pts, 2*width/3, width/3);
|
|
|
|
paint.setColor(SK_ColorBLUE);
|
|
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace skiagm {
|
|
|
|
|
|
|
|
// This GM exercises the SkGaussianEdgeShader.
|
|
|
|
// It draws three columns showing filled, stroked, and stroke and filled rendering.
|
|
|
|
// It draws three rows showing a blur radius smaller than, equal to
|
|
|
|
// and, finally, double the RRect's corner radius
|
|
|
|
// In VIZ mode an extra column is drawn showing the blur ramps (they should all line up).
|
|
|
|
class GaussianEdgeGM : public GM {
|
|
|
|
public:
|
|
|
|
GaussianEdgeGM() {
|
|
|
|
this->setBGColor(SK_ColorWHITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
SkString onShortName() override {
|
|
|
|
return SkString("gaussianedge");
|
|
|
|
}
|
|
|
|
|
|
|
|
SkISize onISize() override {
|
|
|
|
int numCols = kNumBaseCols;
|
|
|
|
#ifdef VIZ
|
|
|
|
numCols++;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return SkISize::Make(kPad + numCols*(kCellWidth+kPad),
|
|
|
|
kPad + kNumRows*(kCellWidth+kPad));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DrawRow(SkCanvas* canvas, int blurRad, int midLine) {
|
|
|
|
SkAutoCanvasRestore acr(canvas, true);
|
|
|
|
|
|
|
|
SkRRect rrects[kNumBaseCols];
|
|
|
|
SkPaint paints[kNumBaseCols];
|
|
|
|
|
|
|
|
{
|
|
|
|
const SkRect r = SkRect::MakeIWH(kRRSize, kRRSize);
|
|
|
|
const SkRRect baseRR = SkRRect::MakeRectXY(r,
|
|
|
|
SkIntToScalar(kRRRad),
|
|
|
|
SkIntToScalar(kRRRad));
|
|
|
|
|
|
|
|
SkPaint basePaint;
|
|
|
|
basePaint.setAntiAlias(true);
|
|
|
|
basePaint.setShader(SkGaussianEdgeShader::Make());
|
|
|
|
basePaint.setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff, 0));
|
|
|
|
|
|
|
|
//----
|
|
|
|
paints[0] = basePaint;
|
|
|
|
rrects[0] = baseRR;
|
|
|
|
|
|
|
|
//----
|
|
|
|
paints[1] = basePaint;
|
|
|
|
paints[1].setStyle(SkPaint::kStroke_Style);
|
|
|
|
|
|
|
|
rrects[1] = baseRR;
|
|
|
|
if (blurRad/2.0f < kRRRad) {
|
|
|
|
rrects[1].inset(blurRad/2.0f, blurRad/2.0f);
|
|
|
|
paints[1].setStrokeWidth(SkIntToScalar(blurRad));
|
|
|
|
} else {
|
|
|
|
SkScalar inset = kRRRad - 0.5f;
|
|
|
|
rrects[1].inset(inset, inset);
|
|
|
|
SkScalar pad = blurRad/2.0f - inset;
|
|
|
|
paints[1].setStrokeWidth(blurRad + 2.0f * pad);
|
|
|
|
paints[1].setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff,
|
|
|
|
(int)(4.0f*pad)));
|
|
|
|
}
|
|
|
|
|
|
|
|
//----
|
|
|
|
paints[2] = basePaint;
|
|
|
|
paints[2].setStyle(SkPaint::kStrokeAndFill_Style);
|
|
|
|
|
|
|
|
rrects[2] = baseRR;
|
|
|
|
if (blurRad/2.0f < kRRRad) {
|
|
|
|
rrects[2].inset(blurRad/2.0f, blurRad/2.0f);
|
|
|
|
paints[2].setStrokeWidth(SkIntToScalar(blurRad));
|
|
|
|
} else {
|
|
|
|
SkScalar inset = kRRRad - 0.5f;
|
|
|
|
rrects[2].inset(inset, inset);
|
|
|
|
SkScalar pad = blurRad/2.0f - inset;
|
|
|
|
paints[2].setStrokeWidth(blurRad + 2.0f * pad);
|
|
|
|
paints[2].setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff,
|
|
|
|
(int)(4.0f*pad)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----
|
|
|
|
canvas->save();
|
|
|
|
// draw the shadows
|
|
|
|
for (int i = 0; i < kNumBaseCols; ++i) {
|
|
|
|
canvas->drawRRect(rrects[i], paints[i]);
|
|
|
|
canvas->translate(SkIntToScalar(kCellWidth+kPad), 0.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef VIZ
|
|
|
|
// draw the visualization of the shadow ramps
|
|
|
|
draw_row(canvas, midLine, 3*(kRRSize+kPad));
|
|
|
|
#endif
|
|
|
|
canvas->restore();
|
|
|
|
|
|
|
|
#ifdef VIZ
|
|
|
|
const SkColor colors[kNumBaseCols] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
|
|
|
|
|
|
|
|
// circle back and draw the stroked geometry (they would mess up the viz otherwise)
|
|
|
|
for (int i = 0; i < kNumBaseCols; ++i) {
|
|
|
|
draw_stroke(canvas, rrects[i], paints[i], colors[i]);
|
|
|
|
canvas->translate(SkIntToScalar(kCellWidth+kPad), 0.0f);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
2016-10-27 18:47:55 +00:00
|
|
|
GrRenderTargetContext* renderTargetContext =
|
|
|
|
canvas->internal_private_accessTopLayerRenderTargetContext();
|
|
|
|
if (!renderTargetContext) {
|
2016-10-11 14:18:18 +00:00
|
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int blurRadii[kNumRows] = { kRRRad/2, kRRRad, 2*kRRRad };
|
|
|
|
|
|
|
|
canvas->translate(SkIntToScalar(kPad), SkIntToScalar(kPad));
|
|
|
|
for (int i = 0; i < kNumRows; ++i) {
|
|
|
|
DrawRow(canvas, blurRadii[i], kPad+(i*kRRSize)+kRRSize/2);
|
|
|
|
canvas->translate(0.0f, SkIntToScalar(kCellWidth+kPad));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static const int kNumRows = 3;
|
|
|
|
static const int kNumBaseCols = 3;
|
|
|
|
static const int kPad = 5;
|
|
|
|
static const int kRRSize = 256;
|
|
|
|
static const int kRRRad = 64;
|
|
|
|
static const int kCellWidth = kRRSize;
|
|
|
|
|
|
|
|
typedef GM INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
DEF_GM(return new GaussianEdgeGM;)
|
|
|
|
}
|