You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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 <tuple>
#include "include/core/SkCanvas.h"
#include "include/core/SkRect.h"
#include "modules/svg/include/SkSVGRect.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGValue.h"
SkSVGRect::SkSVGRect() : INHERITED(SkSVGTag::kRect) {}
bool SkSVGRect::parseAndSetAttribute(const char* n, const char* v) {
return INHERITED::parseAndSetAttribute(n, v) ||
this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", n, v)) ||
this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", n, v)) ||
this->setWidth(SkSVGAttributeParser::parse<SkSVGLength>("width", n, v)) ||
this->setHeight(SkSVGAttributeParser::parse<SkSVGLength>("height", n, v)) ||
this->setRx(SkSVGAttributeParser::parse<SkSVGLength>("rx", n, v)) ||
this->setRy(SkSVGAttributeParser::parse<SkSVGLength>("ry", n, v));
}
SkRRect SkSVGRect::resolve(const SkSVGLengthContext& lctx) const {
const auto rect = lctx.resolveRect(fX, fY, fWidth, fHeight);
// https://www.w3.org/TR/SVG11/shapes.html#RectElementRXAttribute:
//
// - Let rx and ry be length values.
// - If neither rx nor ry are properly specified, then set both rx and ry to 0.
// - Otherwise, if a properly specified value is provided for rx, but not for ry,
// then set both rx and ry to the value of rx.
// - Otherwise, if a properly specified value is provided for ry, but not for rx,
// then set both rx and ry to the value of ry.
// - Otherwise, both rx and ry were specified properly. Set rx to the value of rx
// and ry to the value of ry.
// - If rx is greater than half of width, then set rx to half of width.
// - If ry is greater than half of height, then set ry to half of height.
// - The effective values of rx and ry are rx and ry, respectively.
//
auto radii = [this]() {
return fRx.isValid()
? fRy.isValid()
? std::make_tuple(*fRx, *fRy)
: std::make_tuple(*fRx, *fRx)
: fRy.isValid()
? std::make_tuple(*fRy, *fRy)
: std::make_tuple(SkSVGLength(0), SkSVGLength(0));
};
const auto [ rxlen, rylen ] = radii();
const auto rx = std::min(lctx.resolve(rxlen, SkSVGLengthContext::LengthType::kHorizontal),
rect.width() / 2),
ry = std::min(lctx.resolve(rylen, SkSVGLengthContext::LengthType::kVertical),
rect.height() / 2);
return SkRRect::MakeRectXY(rect, rx, ry);
}
void SkSVGRect::onDraw(SkCanvas* canvas, const SkSVGLengthContext& lctx,
const SkPaint& paint, SkPathFillType) const {
canvas->drawRRect(this->resolve(lctx), paint);
}
SkPath SkSVGRect::onAsPath(const SkSVGRenderContext& ctx) const {
SkPath path = SkPath::RRect(this->resolve(ctx.lengthContext()));
this->mapToParent(&path);
return path;
}
SkRect SkSVGRect::onObjectBoundingBox(const SkSVGRenderContext& ctx) const {
return ctx.lengthContext().resolveRect(fX, fY, fWidth, fHeight);
}