c84ccb0702
This change updates feSpotLight to match the spec via two changes: 1) specularExponent is ignored if the spotlight has no coneAngle (GPU bug only). This change updates the GPU path so that it matches the CPU path and the spec in this regard. 2) specularExponent is clamped to the 1-128 range. The spec does not specify a clamp for the specularExponent attribute of feSpotLight. Note that the spec *does* specify this clamp for the specularExponent attribute of feSpecularLighting. It looks like we incorrectly applied this to both specularExponent attributes. This change (along with a parallel change in Blink) allows us to pass the SVG filter effects conformance test here: http://www.w3.org/Graphics/SVG/Test/20110816/harness/htmlObject/filters-light-01-f.html Additionally, this brings our behavior in line with Safari and Edge’s behavior on this filter. Two new cases were added to gm/lighting.cpp to catch these issues: - The existing spotlight case exercised the path where our specular exponent was between 1-128 and had a limiting cone angle. - The first new spotlight case exercises the path where our specular exponent is between 1-128 and we do not have a limiting cone angle. - The second new spotlight case exercises the path where the specular exponent is not within the 1-128 range, to ensure that we don’t incorrectly clip to this range. BUG=472849 Review URL: https://codereview.chromium.org/1403403003
210 lines
12 KiB
C++
210 lines
12 KiB
C++
/*
|
|
* Copyright 2012 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 "SkLightingImageFilter.h"
|
|
#include "SkOffsetImageFilter.h"
|
|
#include "SkPoint3.h"
|
|
|
|
#define WIDTH 550
|
|
#define HEIGHT 660
|
|
|
|
namespace skiagm {
|
|
|
|
class ImageLightingGM : public GM {
|
|
public:
|
|
ImageLightingGM() {
|
|
this->setBGColor(0xFF000000);
|
|
}
|
|
|
|
protected:
|
|
|
|
SkString onShortName() override {
|
|
return SkString("lighting");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(WIDTH, HEIGHT);
|
|
}
|
|
|
|
void drawClippedBitmap(SkCanvas* canvas, const SkPaint& paint, int x, int y) {
|
|
canvas->save();
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
canvas->clipRect(SkRect::MakeWH(
|
|
SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height())));
|
|
canvas->drawBitmap(fBitmap, 0, 0, &paint);
|
|
canvas->restore();
|
|
}
|
|
|
|
void onOnceBeforeDraw() override {
|
|
fBitmap = sk_tool_utils::create_string_bitmap(100, 100, 0xFFFFFFFF, 20, 70, 96, "e");
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
canvas->clear(sk_tool_utils::color_to_565(0xFF101010));
|
|
SkPaint checkPaint;
|
|
checkPaint.setColor(sk_tool_utils::color_to_565(0xFF202020));
|
|
for (int y = 0; y < HEIGHT; y += 16) {
|
|
for (int x = 0; x < WIDTH; x += 16) {
|
|
canvas->save();
|
|
canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint);
|
|
canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint);
|
|
canvas->restore();
|
|
}
|
|
}
|
|
SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10));
|
|
SkScalar azimuthRad = SkDegreesToRadians(SkIntToScalar(225));
|
|
SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5));
|
|
SkPoint3 distantDirection = SkPoint3::Make(SkScalarMul(SkScalarCos(azimuthRad),
|
|
SkScalarCos(elevationRad)),
|
|
SkScalarMul(SkScalarSin(azimuthRad),
|
|
SkScalarCos(elevationRad)),
|
|
SkScalarSin(elevationRad));
|
|
SkPoint3 spotLocation = SkPoint3::Make(SkIntToScalar(-10),
|
|
SkIntToScalar(-10),
|
|
SkIntToScalar(20));
|
|
SkPoint3 spotTarget = SkPoint3::Make(SkIntToScalar(40), SkIntToScalar(40), 0);
|
|
SkScalar spotExponent1 = SK_Scalar1;
|
|
SkScalar spotExponent0 = SkIntToScalar(0);
|
|
SkScalar cutoffAngleSmall = SkIntToScalar(15);
|
|
SkScalar cutoffAngleNone = SkIntToScalar(180);
|
|
SkScalar kd = SkIntToScalar(2);
|
|
SkScalar ks = SkIntToScalar(1);
|
|
SkScalar shininess = SkIntToScalar(8);
|
|
SkScalar surfaceScale = SkIntToScalar(1);
|
|
SkColor white(0xFFFFFFFF);
|
|
SkPaint paint;
|
|
|
|
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65));
|
|
SkImageFilter::CropRect fullSizeCropRect(SkRect::MakeXYWH(0, 0, 100, 100));
|
|
SkAutoTUnref<SkImageFilter> noopCropped(SkOffsetImageFilter::Create(0, 0, nullptr, &cropRect));
|
|
|
|
int y = 0;
|
|
for (int i = 0; i < 3; i++) {
|
|
const SkImageFilter::CropRect* cr = (i == 1) ? &cropRect : (i == 2) ? &fullSizeCropRect : nullptr;
|
|
SkImageFilter* input = (i == 2) ? noopCropped.get() : nullptr;
|
|
paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation,
|
|
white,
|
|
surfaceScale,
|
|
kd,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 0, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection,
|
|
white,
|
|
surfaceScale,
|
|
kd,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 110, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation,
|
|
spotTarget,
|
|
spotExponent1,
|
|
cutoffAngleSmall,
|
|
white,
|
|
surfaceScale,
|
|
kd,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 220, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation,
|
|
spotTarget,
|
|
spotExponent1,
|
|
cutoffAngleNone,
|
|
white,
|
|
surfaceScale,
|
|
kd,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 330, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation,
|
|
spotTarget,
|
|
spotExponent0,
|
|
cutoffAngleNone,
|
|
white,
|
|
surfaceScale,
|
|
kd,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 440, y);
|
|
|
|
y += 110;
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation,
|
|
white,
|
|
surfaceScale,
|
|
ks,
|
|
shininess,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 0, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection,
|
|
white,
|
|
surfaceScale,
|
|
ks,
|
|
shininess,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 110, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation,
|
|
spotTarget,
|
|
spotExponent1,
|
|
cutoffAngleSmall,
|
|
white,
|
|
surfaceScale,
|
|
ks,
|
|
shininess,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 220, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation,
|
|
spotTarget,
|
|
spotExponent1,
|
|
cutoffAngleNone,
|
|
white,
|
|
surfaceScale,
|
|
ks,
|
|
shininess,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 330, y);
|
|
|
|
paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation,
|
|
spotTarget,
|
|
spotExponent0,
|
|
cutoffAngleNone,
|
|
white,
|
|
surfaceScale,
|
|
ks,
|
|
shininess,
|
|
input,
|
|
cr))->unref();
|
|
drawClippedBitmap(canvas, paint, 440, y);
|
|
|
|
y += 110;
|
|
}
|
|
}
|
|
|
|
private:
|
|
SkBitmap fBitmap;
|
|
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DEF_GM(return new ImageLightingGM;)
|
|
}
|