blob: b68c2ba47d5bbba14d35e1f044df4cd44f909109 [file] [log] [blame]
package parse
import (
"testing"
"github.com/stretchr/testify/assert"
"go.skia.org/infra/go/testutils/unittest"
)
const goodSample = `// 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 "fiddle/examples.h"
// HASH=bc9c7ea424d10bbcd1e5a88770d4794e
REG_FIDDLE(Alpha_Constants_a, 400, 600, true, 2) {
void draw(SkCanvas* canvas) {
std::vector<int32_t> srcPixels;
srcPixels.resize(source.height() * source.rowBytes());
SkPixmap pixmap(SkImageInfo::MakeN32Premul(source.width(), source.height()),
&srcPixels.front(), source.rowBytes());
source.readPixels(pixmap, 0, 0);
for (int y = 0; y < 16; ++y) {
for (int x = 0; x < 16; ++x) {
int32_t* blockStart = &srcPixels.front() + y * source.width() * 16 + x * 16;
size_t transparentCount = 0;
for (int fillY = 0; fillY < source.height() / 16; ++fillY) {
for (int fillX = 0; fillX < source.width() / 16; ++fillX) {
const SkColor color = SkUnPreMultiply::PMColorToColor(blockStart[fillX]);
transparentCount += SkColorGetA(color) == SK_AlphaTRANSPARENT;
}
blockStart += source.width();
}
if (transparentCount > 200) {
blockStart = &srcPixels.front() + y * source.width() * 16 + x * 16;
for (int fillY = 0; fillY < source.height() / 16; ++fillY) {
for (int fillX = 0; fillX < source.width() / 16; ++fillX) {
blockStart[fillX] = SK_ColorRED;
}
blockStart += source.width();
}
}
}
}
SkBitmap bitmap;
bitmap.installPixels(pixmap);
canvas->drawBitmap(bitmap, 0, 0);
}
} // END FIDDLE`
const shortSample = `// Copyright 2019 Google LLC.
REG_FIDDLE(EmptyFiddle, 256, 128, false, 1) {
void draw(SkCanvas* canvas) {
}
} // END FIDDLE`
const missingEndSample = `// Copyright 2019 Google LLC.
REG_FIDDLE(Alpha_Constants_a, 256, 128, false, 1) {
void draw(SkCanvas* canvas) {
}
}`
const inactiveSample = `#if 0 // Disabled until updated to use current API.
// 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 "fiddle/examples.h"
// HASH=f0e584aec20eaee7a5bfed62aa885eee
REG_FIDDLE(TextBlobBuilder_allocRun, 256, 60, false, 0) {
void draw(SkCanvas* canvas) {
SkTextBlobBuilder builder;
SkFont font;
SkPaint paint;
const SkTextBlobBuilder::RunBuffer& run = builder.allocRun(font, 5, 20, 20);
paint.textToGlyphs("hello", 5, run.glyphs);
canvas->drawRect({20, 20, 30, 30}, paint);
canvas->drawTextBlob(builder.make(), 20, 20, paint);
}
} // END FIDDLE
#endif // Disabled until updated to use current API.`
const missingRegSample = `
// Copyright 2019 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
void draw(SkCanvas* canvas) {
SkTextBlobBuilder builder;
SkFont font;
SkPaint paint;
const SkTextBlobBuilder::RunBuffer& run = builder.allocRun(font, 5, 20, 20);
paint.textToGlyphs("hello", 5, run.glyphs);
canvas->drawRect({20, 20, 30, 30}, paint);
canvas->drawTextBlob(builder.make(), 20, 20, paint);
}
} // END FIDDLE`
const badMacro = `REG_FIDDLE(TextBlobBuilder_allocRun, foo, 60, false, 0) {`
const textonlySample = `// Copyright 2019 Google LLC.
REG_FIDDLE(50_percent_gray, 256, 128, true, 0) {
void draw(SkCanvas* canvas) {
}
} // END FIDDLE`
const animatedSample = `// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "tools/fiddle/examples.h"
REG_FIDDLE_ANIMATED(pong, 256, 300, false, 0, 10.5) {
static SkScalar PingPong(double t, SkScalar period, SkScalar phase,
SkScalar ends, SkScalar mid) {
double value = ::fmod(t + phase, period);
double half = period / 2.0;
double diff = ::fabs(value - half);
return SkDoubleToScalar(ends + (1.0 - diff / half) * (mid - ends));
}
void draw(SkCanvas* canvas) {
canvas->clear(SK_ColorBLACK);
float ballX = PingPong(frame * duration, 2.5f, 0.0f, 0.0f, 1.0f);
float ballY = PingPong(frame * duration, 2.0f, 0.4f, 0.0f, 1.0f);
SkPaint p;
p.setColor(SK_ColorWHITE);
p.setAntiAlias(true);
float bX = ballX * 472 + 20;
float bY = ballY * 200 + 28;
if (canvas->recordingContext()) {
canvas->drawRect(SkRect::MakeXYWH(236, bY - 15, 10, 30), p);
bX -= 256;
} else {
canvas->drawRect(SkRect::MakeXYWH(10, bY - 15, 10, 30), p);
}
canvas->drawCircle(bX, bY, 5, p);
}
} // END FIDDLE`
const srgbSample = `// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "tools/fiddle/examples.h"
REG_FIDDLE_SRGB(50_percent_gray, 530, 150, true, 0, 18.5, true) {
static sk_sp<SkShader> make_bw_dither() {
auto surf = SkSurface::MakeRasterN32Premul(2, 2);
surf->getCanvas()->drawColor(SK_ColorWHITE);
surf->getCanvas()->drawRect({0, 0, 1, 1}, SkPaint());
surf->getCanvas()->drawRect({1, 1, 2, 2}, SkPaint());
return surf->makeImageSnapshot()->makeShader(SkTileMode::kRepeat,
SkTileMode::kRepeat,
SkSamplingOptions(SkFilterMode::kLinear));
}
void draw(SkCanvas* canvas) {
canvas->drawColor(SK_ColorWHITE);
SkFont font(nullptr, 12);
// BW Dither
canvas->translate(5, 5);
SkPaint p;
p.setShader(make_bw_dither());
canvas->drawRect({0, 0, 100, 100}, p);
SkPaint black;
canvas->drawString("BW Dither", 0, 125, font, black);
}
} // END FIDDLE`
func TestParse_ValidSamples_InformationExtracted(t *testing.T) {
unittest.SmallTest(t)
fc, err := ParseCpp(goodSample)
assert.NoError(t, err)
assert.Equal(t, "Alpha_Constants_a", fc.Name)
assert.Equal(t, 400, fc.Options.Width)
assert.Equal(t, 600, fc.Options.Height)
assert.Equal(t, 2, fc.Options.Source)
assert.True(t, fc.Options.TextOnly)
fc, err = ParseCpp(shortSample)
assert.NoError(t, err)
assert.Equal(t, "EmptyFiddle", fc.Name)
assert.Equal(t, "void draw(SkCanvas* canvas) {\n}", fc.Code)
assert.Equal(t, 256, fc.Options.Width)
assert.Equal(t, 128, fc.Options.Height)
assert.Equal(t, 1, fc.Options.Source)
assert.False(t, fc.Options.TextOnly)
fc, err = ParseCpp(textonlySample)
assert.NoError(t, err)
assert.Equal(t, "50_percent_gray", fc.Name)
assert.Equal(t, "void draw(SkCanvas* canvas) {\n}", fc.Code)
assert.Equal(t, 256, fc.Options.Width)
assert.Equal(t, 128, fc.Options.Height)
assert.Equal(t, 0, fc.Options.Source)
assert.True(t, fc.Options.TextOnly)
}
func TestParse_AnimatedSample_InformationExtracted(t *testing.T) {
unittest.SmallTest(t)
fc, err := ParseCpp(animatedSample)
assert.NoError(t, err)
assert.Equal(t, "pong", fc.Name)
assert.Equal(t, 256, fc.Options.Width)
assert.Equal(t, 300, fc.Options.Height)
assert.Equal(t, 0, fc.Options.Source)
assert.False(t, fc.Options.TextOnly)
assert.True(t, fc.Options.Animated)
assert.Equal(t, 10.5, fc.Options.Duration)
}
func TestParse_SRGBSample_InformationExtracted(t *testing.T) {
unittest.SmallTest(t)
fc, err := ParseCpp(srgbSample)
assert.NoError(t, err)
assert.Equal(t, "50_percent_gray", fc.Name)
assert.Equal(t, 530, fc.Options.Width)
assert.Equal(t, 150, fc.Options.Height)
assert.Equal(t, 0, fc.Options.Source)
assert.True(t, fc.Options.TextOnly)
assert.True(t, fc.Options.Animated)
assert.Equal(t, 18.5, fc.Options.Duration)
assert.True(t, fc.Options.F16)
assert.True(t, fc.Options.SRGB)
}
func TestParse_MissingEndFiddle_ReturnsError(t *testing.T) {
unittest.SmallTest(t)
_, err := ParseCpp(missingEndSample)
assert.Error(t, err)
assert.Contains(t, err.Error(), "END FIDDLE")
}
func TestParse_FiddleIfDeffedOut_ReturnsError(t *testing.T) {
unittest.SmallTest(t)
_, err := ParseCpp(inactiveSample)
assert.Equal(t, err, ErrorInactiveExample)
}
func TestParse_MissingRegFiddle_ReturnsError(t *testing.T) {
unittest.SmallTest(t)
_, err := ParseCpp(missingRegSample)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to find any REG_FIDDLE*")
}
func TestParse_MacroBadWidthParam_ReturnsError(t *testing.T) {
unittest.SmallTest(t)
_, err := ParseCpp(badMacro)
assert.Error(t, err)
assert.Contains(t, err.Error(), "parsing width")
}