blob: b4cfa277e0eee1931584e6eb775e32b2af4e8511 [file]
/*
* Copyright 2026 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <string>
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "modules/svg/include/SkSVGDOM.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "tests/Test.h"
namespace {
constexpr SkColor kGreen = 0xFF008000;
// Left half is filled with currentColor directly, right half through a gradient
// whose stops are currentColor. Both must resolve to the same color.
constexpr char kInheritedColor[] = R"EOF(
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" color="green">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="currentColor"/>
<stop offset="1" stop-color="currentColor"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="50" height="100" fill="currentColor"/>
<rect x="50" y="0" width="50" height="100" fill="url(#g)"/>
</svg>
)EOF";
constexpr char kSeededColor[] = R"EOF(
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="currentColor"/>
<stop offset="1" stop-color="currentColor"/>
</linearGradient>
</defs>
<g id="glyph1">
<rect x="0" y="0" width="50" height="100" fill="currentColor"/>
<rect x="50" y="0" width="50" height="100" fill="url(#g)"/>
</g>
</svg>
)EOF";
sk_sp<SkSVGDOM> parse(const char* svg) {
auto stream = SkMemoryStream::MakeDirect(svg, strlen(svg));
auto dom = SkSVGDOM::Builder().make(*stream);
if (dom) {
dom->setContainerSize(SkSize::Make(100, 100));
}
return dom;
}
} // namespace
// 'color' inherits through the tree, so currentColor inside a referenced paint
// server must resolve the same as it does on the referencing element.
DEF_TEST(Svg_PaintServer_InheritedCurrentColor, r) {
auto dom = parse(kInheritedColor);
REPORTER_ASSERT(r, dom);
SkBitmap bm;
bm.allocN32Pixels(100, 100);
bm.eraseColor(SK_ColorWHITE);
SkCanvas canvas(bm);
dom->render(&canvas);
REPORTER_ASSERT(r, bm.getColor(25, 50) == kGreen); // fill="currentColor"
REPORTER_ASSERT(r, bm.getColor(75, 50) == kGreen); // fill="url(#g)"
}
// Same requirement when the host seeds the color on the presentation context
// instead of the document supplying it -- the OpenType-SVG path taken by
// SkSVGOpenTypeSVGDecoder::render().
DEF_TEST(Svg_PaintServer_SeededCurrentColor, r) {
auto dom = parse(kSeededColor);
REPORTER_ASSERT(r, dom);
SkBitmap bm;
bm.allocN32Pixels(100, 100);
bm.eraseColor(SK_ColorWHITE);
SkCanvas canvas(bm);
SkSVGPresentationContext pctx;
pctx.fInherited.fColor.set(kGreen);
dom->renderNode(&canvas, pctx, "glyph1");
REPORTER_ASSERT(r, bm.getColor(25, 50) == kGreen); // fill="currentColor"
REPORTER_ASSERT(r, bm.getColor(75, 50) == kGreen); // fill="url(#g)"
}