blob: fc80857586d85d3efe108b07de8d706c8841e0e3 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_TEST_PAINT_OP_HELPER_H_
#define CC_TEST_PAINT_OP_HELPER_H_
#include <sstream>
#include <string>
#include <vector>
#include "base/strings/stringprintf.h"
#include "cc/paint/draw_looper.h"
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_op.h"
#include "cc/paint/paint_op_buffer_iterator.h"
#include "cc/paint/skottie_wrapper.h"
namespace cc {
// A helper class to help with debugging PaintOp/PaintOpBuffer.
// Note that this file is primarily used for debugging. As such, it isn't
// typically a part of BUILD.gn (except for self-testing), so all of the
// implementation should be limited ot the header.
class PaintOpHelper {
public:
// Print optional/nullable wrapper types are using underlying types.
template <typename T>
static std::string ToString(const T* ptr) {
return ptr ? ToString(*ptr) : "(nil)";
}
template <typename T>
static std::string ToString(const sk_sp<T>& ptr) {
return ptr ? ToString(*ptr) : "(nil)";
}
template <typename T>
static std::string ToString(scoped_refptr<T> ptr) {
return ptr ? ToString(*ptr) : "(nil)";
}
template <typename T>
static std::string ToString(const std::optional<T>& opt) {
return opt.has_value() ? ToString(*opt) : "(nil)";
}
template <typename T>
static std::string ToString(const std::vector<T>& vec) {
std::ostringstream str;
str << "{";
bool is_first = true;
for (const T& element : vec) {
if (!is_first) {
str << ", ";
}
str << ToString(element);
is_first = false;
}
str << "}";
return str.str();
}
static std::string ToString(const PaintOp& base_op) {
std::ostringstream str;
str << std::boolalpha << base_op.GetType() << "(";
switch (base_op.GetType()) {
case PaintOpType::kAnnotate: {
const auto& op = static_cast<const AnnotateOp&>(base_op);
str << "type=" << ToString(op.annotation_type)
<< ", rect=" << ToString(op.rect) << ", data=" << ToString(op.data);
break;
}
case PaintOpType::kClipPath: {
const auto& op = static_cast<const ClipPathOp&>(base_op);
str << "path=" << ToString(op.path) << ", op=" << ToString(op.op)
<< ", antialias=" << op.antialias
<< ", use_cache=" << (op.use_cache == UsePaintCache::kEnabled);
break;
}
case PaintOpType::kClipRect: {
const auto& op = static_cast<const ClipRectOp&>(base_op);
str << "rect=" << ToString(op.rect) << ", op=" << ToString(op.op)
<< ", antialias=" << op.antialias;
break;
}
case PaintOpType::kClipRRect: {
const auto& op = static_cast<const ClipRRectOp&>(base_op);
str << "rrect=" << ToString(op.rrect) << ", op=" << ToString(op.op)
<< ", antialias=" << op.antialias;
break;
}
case PaintOpType::kConcat: {
const auto& op = static_cast<const ConcatOp&>(base_op);
str << "matrix=" << ToString(op.matrix);
break;
}
case PaintOpType::kCustomData: {
const auto& op = static_cast<const CustomDataOp&>(base_op);
str << "id=" << ToString(op.id);
break;
}
case PaintOpType::kDrawColor: {
const auto& op = static_cast<const DrawColorOp&>(base_op);
str << "color=" << ToString(op.color) << ", mode=" << ToString(op.mode);
break;
}
case PaintOpType::kDrawDRRect: {
const auto& op = static_cast<const DrawDRRectOp&>(base_op);
str << "outer=" << ToString(op.outer)
<< ", inner=" << ToString(op.inner)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawImage: {
const auto& op = static_cast<const DrawImageOp&>(base_op);
str << "image=" << ToString(op.image) << ", left=" << ToString(op.left)
<< ", top=" << ToString(op.top) << ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawImageRect: {
const auto& op = static_cast<const DrawImageRectOp&>(base_op);
str << "image=" << ToString(op.image) << ", src=" << ToString(op.src)
<< ", dst=" << ToString(op.dst)
<< ", constraint=" << ToString(op.constraint)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawIRect: {
const auto& op = static_cast<const DrawIRectOp&>(base_op);
str << "rect=" << ToString(op.rect) << ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawLine: {
const auto& op = static_cast<const DrawLineOp&>(base_op);
str << "x0=" << ToString(op.x0) << ", y0=" << ToString(op.y0)
<< ", x1=" << ToString(op.x1) << ", y1=" << ToString(op.y1)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawLineLite: {
const auto& op = static_cast<const DrawLineLiteOp&>(base_op);
str << "x0=" << ToString(op.x0) << ", y0=" << ToString(op.y0)
<< ", x1=" << ToString(op.x1) << ", y1=" << ToString(op.y1)
<< ", flags=" << ToString(op.core_paint_flags);
break;
}
case PaintOpType::kDrawArc: {
const auto& op = static_cast<const DrawArcOp&>(base_op);
str << "oval=" << ToString(op.oval)
<< ", start_angle=" << ToString(op.start_angle_degrees)
<< ", sweep_angle=" << ToString(op.sweep_angle_degrees)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawArcLite: {
const auto& op = static_cast<const DrawArcLiteOp&>(base_op);
str << "oval=" << ToString(op.oval)
<< ", start_angle=" << ToString(op.start_angle_degrees)
<< ", sweep_angle=" << ToString(op.sweep_angle_degrees)
<< ", flags=" << ToString(op.core_paint_flags);
break;
}
case PaintOpType::kDrawOval: {
const auto& op = static_cast<const DrawOvalOp&>(base_op);
str << "oval=" << ToString(op.oval) << ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawPath: {
const auto& op = static_cast<const DrawPathOp&>(base_op);
str << "path=" << ToString(op.path) << ", flags=" << ToString(op.flags)
<< ", use_cache=" << (op.use_cache == UsePaintCache::kEnabled);
break;
}
case PaintOpType::kDrawRecord: {
const auto& op = static_cast<const DrawRecordOp&>(base_op);
str << "record=" << ToString(op.record);
break;
}
case PaintOpType::kDrawRect: {
const auto& op = static_cast<const DrawRectOp&>(base_op);
str << "rect=" << ToString(op.rect) << ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawRRect: {
const auto& op = static_cast<const DrawRRectOp&>(base_op);
str << "rrect=" << ToString(op.rrect)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawScrollingContents: {
str << "scroll_element_id="
<< static_cast<const DrawScrollingContentsOp&>(base_op)
.scroll_element_id;
break;
}
case PaintOpType::kDrawSkottie: {
const auto& op = static_cast<const DrawSkottieOp&>(base_op);
str << "skottie=" << ToString(op.skottie)
<< ", dst=" << ToString(op.dst) << ", t=" << op.t;
break;
}
case PaintOpType::kDrawTextBlob: {
const auto& op = static_cast<const DrawTextBlobOp&>(base_op);
str << "blob=" << ToString(op.blob) << ", x=" << ToString(op.x)
<< ", y=" << ToString(op.y) << ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawSlug: {
const auto& op = static_cast<const DrawSlugOp&>(base_op);
str << "flags=" << ToString(op.flags);
break;
}
case PaintOpType::kDrawVertices: {
const auto& op = static_cast<const DrawVerticesOp&>(base_op);
str << "flags=" << ToString(op.flags);
break;
}
case PaintOpType::kNoop:
break;
case PaintOpType::kRestore:
break;
case PaintOpType::kRotate: {
const auto& op = static_cast<const RotateOp&>(base_op);
str << "degrees=" << ToString(op.degrees);
break;
}
case PaintOpType::kSave:
break;
case PaintOpType::kSaveLayer: {
const auto& op = static_cast<const SaveLayerOp&>(base_op);
str << "bounds=" << ToString(op.bounds)
<< ", flags=" << ToString(op.flags);
break;
}
case PaintOpType::kSaveLayerAlpha: {
const auto& op = static_cast<const SaveLayerAlphaOp&>(base_op);
str << "bounds=" << ToString(op.bounds)
<< ", alpha=" << ToString(op.alpha);
break;
}
case PaintOpType::kSaveLayerFilters: {
const auto& op = static_cast<const SaveLayerFiltersOp&>(base_op);
str << "flags=" << ToString(op.flags)
<< ", filters=" << ToString(op.filters);
break;
}
case PaintOpType::kScale: {
const auto& op = static_cast<const ScaleOp&>(base_op);
str << "sx=" << ToString(op.sx) << ", sy=" << ToString(op.sy);
break;
}
case PaintOpType::kSetMatrix: {
const auto& op = static_cast<const SetMatrixOp&>(base_op);
str << "matrix=" << ToString(op.matrix);
break;
}
case PaintOpType::kTranslate: {
const auto& op = static_cast<const TranslateOp&>(base_op);
str << "dx=" << ToString(op.dx) << ", dy=" << ToString(op.dy);
break;
}
case PaintOpType::kSetNodeId: {
const auto& op = static_cast<const SetNodeIdOp&>(base_op);
str << "id=" << op.node_id;
break;
}
}
str << ")";
return str.str();
}
static std::string ToString(uint8_t value) {
return base::StringPrintf("%d", value);
}
static std::string ToString(const SkScalar& scalar) {
return base::StringPrintf("%.3f", scalar);
}
static std::string ToString(const SkPoint& point) {
return base::StringPrintf("[%.3f,%.3f]", point.fX, point.fY);
}
static std::string ToString(const SkRect& rect) {
return base::StringPrintf("[%.3f,%.3f %.3fx%.3f]", rect.x(), rect.y(),
rect.width(), rect.height());
}
static std::string ToString(const SkIRect& rect) {
return base::StringPrintf("[%d,%d %dx%d]", rect.x(), rect.y(), rect.width(),
rect.height());
}
static std::string ToString(const SkRRect& rect) {
return base::StringPrintf("[bounded by %.3f,%.3f %.3fx%.3f]",
rect.rect().x(), rect.rect().y(),
rect.rect().width(), rect.rect().height());
}
static std::string ToString(const SkRegion& rect) {
return ToString(rect.getBounds());
}
static std::string ToString(const SkM44& matrix) {
return base::StringPrintf(
"[%8.4f %8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f "
"%8.4f][%8.4f %8.4f %8.4f %8.4f]]",
matrix.rc(0, 0), matrix.rc(0, 1), matrix.rc(0, 2), matrix.rc(0, 3),
matrix.rc(1, 0), matrix.rc(1, 1), matrix.rc(1, 2), matrix.rc(1, 3),
matrix.rc(2, 0), matrix.rc(2, 1), matrix.rc(2, 2), matrix.rc(2, 3),
matrix.rc(3, 0), matrix.rc(3, 1), matrix.rc(3, 2), matrix.rc(3, 3));
}
static std::string ToString(const SkMatrix& matrix) {
return base::StringPrintf(
"[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]]",
matrix.rc(0, 0), matrix.rc(0, 1), matrix.rc(0, 2), matrix.rc(1, 0),
matrix.rc(1, 1), matrix.rc(1, 2), matrix.rc(2, 0), matrix.rc(2, 1),
matrix.rc(2, 2));
}
static std::string ToString(const SkColor& color) {
return base::StringPrintf("rgba(%d, %d, %d, %d)", SkColorGetR(color),
SkColorGetG(color), SkColorGetB(color),
SkColorGetA(color));
}
static std::string ToString(const SkColor4f& color) {
return base::StringPrintf("rgba(%f, %f, %f, %f)", color.fR, color.fG,
color.fB, color.fA);
}
static std::string ToString(const SkISize& size) {
return base::StringPrintf("SkISize(%d, %d)", size.width(), size.height());
}
static std::string ToString(const SkIPoint& point) {
return base::StringPrintf("SkIPoint(%d, %d)", point.x(), point.y());
}
static std::string ToString(const SkPoint3& point) {
return base::StringPrintf(
"SkPoint3(%s, %s, %s)", ToString(point.x()).c_str(),
ToString(point.y()).c_str(), ToString(point.z()).c_str());
}
static std::string ToString(SkColorChannel channel) {
switch (channel) {
case SkColorChannel::kR:
return "kR";
case SkColorChannel::kG:
return "kG";
case SkColorChannel::kB:
return "kB";
case SkColorChannel::kA:
return "kA";
}
NOTREACHED();
}
static std::string ToString(const SkBlendMode& mode) {
switch (mode) {
default:
break;
case SkBlendMode::kClear:
return "kClear";
case SkBlendMode::kSrc:
return "kSrc";
case SkBlendMode::kDst:
return "kDst";
case SkBlendMode::kSrcOver:
return "kSrcOver";
case SkBlendMode::kDstOver:
return "kDstOver";
case SkBlendMode::kSrcIn:
return "kSrcIn";
case SkBlendMode::kDstIn:
return "kDstIn";
case SkBlendMode::kSrcOut:
return "kSrcOut";
case SkBlendMode::kDstOut:
return "kDstOut";
case SkBlendMode::kSrcATop:
return "kSrcATop";
case SkBlendMode::kDstATop:
return "kDstATop";
case SkBlendMode::kXor:
return "kXor";
case SkBlendMode::kPlus:
return "kPlus";
case SkBlendMode::kModulate:
return "kModulate";
case SkBlendMode::kScreen:
return "kScreen";
case SkBlendMode::kOverlay:
return "kOverlay";
case SkBlendMode::kDarken:
return "kDarken";
case SkBlendMode::kLighten:
return "kLighten";
case SkBlendMode::kColorDodge:
return "kColorDodge";
case SkBlendMode::kColorBurn:
return "kColorBurn";
case SkBlendMode::kHardLight:
return "kHardLight";
case SkBlendMode::kSoftLight:
return "kSoftLight";
case SkBlendMode::kDifference:
return "kDifference";
case SkBlendMode::kExclusion:
return "kExclusion";
case SkBlendMode::kMultiply:
return "kMultiply";
case SkBlendMode::kHue:
return "kHue";
case SkBlendMode::kSaturation:
return "kSaturation";
case SkBlendMode::kColor:
return "kColor";
case SkBlendMode::kLuminosity:
return "kLuminosity";
}
return "<unknown SkBlendMode>";
}
static std::string ToString(const SkClipOp& op) {
switch (op) {
default:
break;
case SkClipOp::kDifference:
return "kDifference";
case SkClipOp::kIntersect:
return "kIntersect";
}
return "<unknown SkClipOp>";
}
static std::string ToString(const SkData& data) { return "<SkData>"; }
static std::string ToString(const ThreadsafePath& path) {
return ToString(static_cast<const SkPath&>(path));
}
static std::string ToString(const SkPath& path) {
// TODO(vmpstr): SkPath has a dump function which we can use here?
return "<SkPath>";
}
static std::string ToString(PaintFlags::FilterQuality quality) {
switch (quality) {
case PaintFlags::FilterQuality::kNone:
return "kNone_SkFilterQuality";
case PaintFlags::FilterQuality::kLow:
return "kLow_SkFilterQuality";
case PaintFlags::FilterQuality::kMedium:
return "kMedium_SkFilterQuality";
case PaintFlags::FilterQuality::kHigh:
return "kHigh_SkFilterQuality";
}
return "<unknown FilterQuality>";
}
static std::string ToString(PaintFlags::Cap cap) {
switch (cap) {
case PaintFlags::kButt_Cap:
return "kButt_Cap";
case PaintFlags::kRound_Cap:
return "kRound_Cap";
case PaintFlags::kSquare_Cap:
return "kSquare_Cap";
}
return "<unknown PaintFlags::Cap>";
}
static std::string ToString(PaintFlags::Join join) {
switch (join) {
case PaintFlags::kMiter_Join:
return "kMiter_Join";
case PaintFlags::kRound_Join:
return "kRound_Join";
case PaintFlags::kBevel_Join:
return "kBevel_Join";
}
return "<unknown PaintFlags::Join>";
}
static std::string ToString(TurbulencePaintFilter::TurbulenceType type) {
switch (type) {
case TurbulencePaintFilter::TurbulenceType::kTurbulence:
return "kTurbulence";
case TurbulencePaintFilter::TurbulenceType::kFractalNoise:
return "kFractalNoise";
}
return "<unknown TurbulencePaintFilter::TurbulenceType>";
}
static std::string ToString(MorphologyPaintFilter::MorphType type) {
switch (type) {
case MorphologyPaintFilter::MorphType::kDilate:
return "kDilate";
case MorphologyPaintFilter::MorphType::kErode:
return "kErode";
}
return "<unknown MorphologyPaintFilter::MorphType>";
}
static std::string ToString(PaintFilter::LightingType type) {
switch (type) {
case PaintFilter::LightingType::kDiffuse:
return "kDiffuse";
case PaintFilter::LightingType::kSpecular:
return "kSpecular";
}
return "<unknown PaintFilter::LightingType>";
}
static std::string ToString(DropShadowPaintFilter::ShadowMode shadow_mode) {
switch (shadow_mode) {
case DropShadowPaintFilter::ShadowMode::kDrawShadowAndForeground:
return "kDrawShadowAndForeground";
case DropShadowPaintFilter::ShadowMode::kDrawShadowOnly:
return "kDrawShadowOnly";
}
return "<unknown DropShadowPaintFilter::ShadowMode>";
}
static std::string ToString(const SkImageFilters::Dither dither) {
switch (dither) {
case SkImageFilters::Dither::kNo:
return "kNo";
case SkImageFilters::Dither::kYes:
return "kYes";
}
return "<unknown SkImageFilters::Dither>";
}
static std::string ToString(const ColorFilter& filter) {
return "ColorFilter";
}
static std::string ToString(const PathEffect& effect) { return "PathEffect"; }
static std::string ToString(const DrawLooper& looper) { return "DrawLooper"; }
static std::string ToString(PaintCanvas::AnnotationType type) {
switch (type) {
default:
break;
case PaintCanvas::AnnotationType::kUrl:
return "URL";
case PaintCanvas::AnnotationType::kNameDestination:
return "NAMED_DESTINATION";
case PaintCanvas::AnnotationType::kLinkToDestination:
return "LINK_TO_DESTINATION";
}
return "<unknown AnnotationType>";
}
static std::string ToString(const SkCanvas::SrcRectConstraint& constraint) {
switch (constraint) {
default:
break;
case SkCanvas::kStrict_SrcRectConstraint:
return "kStrict_SrcRectConstraint";
case SkCanvas::kFast_SrcRectConstraint:
return "kFast_SrcRectConstraint";
}
return "<unknown SrcRectConstraint>";
}
static std::string ToString(PaintShader::ScalingBehavior behavior) {
switch (behavior) {
case PaintShader::ScalingBehavior::kRasterAtScale:
return "kRasterAtScale";
case PaintShader::ScalingBehavior::kFixedScale:
return "kFixedScale";
}
return "<unknown ScalingBehavior>";
}
static std::string ToString(PaintShader::Type type) {
switch (type) {
case PaintShader::Type::kEmpty:
return "kEmpty";
case PaintShader::Type::kColor:
return "kColor";
case PaintShader::Type::kLinearGradient:
return "kLinearGradient";
case PaintShader::Type::kRadialGradient:
return "kRadialGradient";
case PaintShader::Type::kTwoPointConicalGradient:
return "kTwoPointConicalGradient";
case PaintShader::Type::kSweepGradient:
return "kSweepGradient";
case PaintShader::Type::kImage:
return "kImage";
case PaintShader::Type::kPaintRecord:
return "kPaintRecord";
case PaintShader::Type::kSkSLCommand:
return "kSkSLCommand";
case PaintShader::Type::kShaderCount:
return "kShaderCount";
}
return "<unknown PaintShader::Type>";
}
static std::string ToString(const PaintImage& image) {
return "<paint image>";
}
static std::string ToString(const SkottieWrapper& skottie) {
std::ostringstream str;
str << "<skottie [";
str << "duration=" << skottie.duration() << " seconds";
str << ", width=" << ToString(skottie.size().width());
str << ", height=" << ToString(skottie.size().height());
str << "]";
return str.str();
}
static std::string ToString(const PaintRecord& record) {
std::ostringstream str;
str << "<PaintRecord>[";
bool is_first = true;
for (const PaintOp& op : record) {
if (!is_first) {
str << ", ";
}
str << ToString(op);
is_first = false;
}
str << "]";
return str.str();
}
static std::string ToString(const SkTextBlob& blob) {
return "<sk text blob>";
}
static std::string ToString(SkTileMode tile_mode) {
switch (tile_mode) {
case SkTileMode::kClamp:
return "kClamp";
case SkTileMode::kRepeat:
return "kRepeat";
case SkTileMode::kMirror:
return "kMirror";
case SkTileMode::kDecal:
return "kDecal";
}
return "<unknown SkTileMode>";
}
static std::string ToString(const gfx::SizeF& size) {
return base::StringPrintf("[%s]", size.ToString().c_str());
}
static std::string ToString(const PaintShader& shader) {
std::ostringstream str;
str << "[type=" << ToString(shader.shader_type());
str << ", flags=" << shader.flags_;
str << ", end_radius=" << shader.end_radius_;
str << ", start_radius=" << shader.start_radius_;
str << ", tx=" << static_cast<unsigned>(shader.tx_);
str << ", ty=" << static_cast<unsigned>(shader.ty_);
str << ", fallback_color=" << ToString(shader.fallback_color_);
str << ", scaling_behavior=" << ToString(shader.scaling_behavior_);
str << ", local_matrix=" << ToString(shader.local_matrix_);
str << ", center=" << ToString(shader.center_);
str << ", tile=" << ToString(shader.tile_);
str << ", start_point=" << ToString(shader.start_point_);
str << ", end_point=" << ToString(shader.end_point_);
str << ", start_degrees=" << shader.start_degrees_;
str << ", end_degrees=" << shader.end_degrees_;
if (shader.shader_type() == PaintShader::Type::kImage) {
str << ", image=" << ToString(shader.image_);
} else {
str << ", image=(nil)";
}
str << ", record=" << ToString(shader.record_);
str << ", id=" << shader.id_;
str << ", tile_scale=" << ToString(shader.tile_scale_);
if (shader.colors_.size() > 0) {
str << ", colors=[" << ToString(shader.colors_[0]);
for (size_t i = 1; i < shader.colors_.size(); ++i) {
str << ", " << ToString(shader.colors_[i]);
}
str << "]";
} else {
str << ", colors=(nil)";
}
if (shader.positions_.size() > 0) {
str << ", positions=[" << shader.positions_[0];
for (size_t i = 1; i < shader.positions_.size(); ++i) {
str << ", " << shader.positions_[i];
}
str << "]";
} else {
str << ", positions=(nil)";
}
str << "]";
return str.str();
}
static std::string ToString(const PaintFilter& base_filter) {
std::ostringstream str;
str << std::boolalpha;
switch (base_filter.type()) {
case PaintFilter::Type::kNullFilter:
str << "NullFilter()";
break;
case PaintFilter::Type::kColorFilter: {
const auto& filter =
static_cast<const ColorFilterPaintFilter&>(base_filter);
str << "ColorFilterPaintFilter("
<< "color_filter=" << ToString(filter.color_filter())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kBlur: {
const auto& filter = static_cast<const BlurPaintFilter&>(base_filter);
str << "BlurPaintFilter("
<< "sigma_x=" << ToString(filter.sigma_x())
<< ", sigma_y=" << ToString(filter.sigma_y())
<< ", tile_mode=" << ToString(filter.tile_mode())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kDropShadow: {
const auto& filter =
static_cast<const DropShadowPaintFilter&>(base_filter);
str << "DropShadowPaintFilter("
<< "dx=" << ToString(filter.dx())
<< ", dy=" << ToString(filter.dy())
<< ", sigma_x=" << ToString(filter.sigma_x())
<< ", sigma_y=" << ToString(filter.sigma_y())
<< ", color=" << ToString(filter.color())
<< ", shadow_mode=" << ToString(filter.shadow_mode())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kMagnifier: {
const auto& filter =
static_cast<const MagnifierPaintFilter&>(base_filter);
str << "MagnifierPaintFilter("
<< "lens_bounds=" << ToString(filter.lens_bounds())
<< ", zoom_amount=" << ToString(filter.zoom_amount())
<< ", inset=" << ToString(filter.inset())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kCompose: {
const auto& filter =
static_cast<const ComposePaintFilter&>(base_filter);
str << "ComposePaintFilter("
<< "outer=" << ToString(filter.outer())
<< ", inner=" << ToString(filter.inner())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kAlphaThreshold: {
const auto& filter =
static_cast<const AlphaThresholdPaintFilter&>(base_filter);
str << "AlphaThresholdPaintFilter("
<< "region=" << ToString(filter.region())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kXfermode: {
const auto& filter =
static_cast<const XfermodePaintFilter&>(base_filter);
str << "XfermodePaintFilter("
<< "blend_mode=" << ToString(filter.blend_mode())
<< ", background=" << ToString(filter.background())
<< ", foreground=" << ToString(filter.foreground())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kArithmetic: {
const auto& filter =
static_cast<const ArithmeticPaintFilter&>(base_filter);
str << "ArithmeticPaintFilter("
<< "k1=" << filter.k1() << ", k2=" << filter.k2()
<< ", k3=" << filter.k3() << ", k4=" << filter.k4()
<< ", enfore_pm_color=" << filter.enforce_pm_color()
<< ", background=" << ToString(filter.background())
<< ", foreground=" << ToString(filter.foreground())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kMatrixConvolution: {
const auto& filter =
static_cast<const MatrixConvolutionPaintFilter&>(base_filter);
const SkISize& kernel_size = filter.kernel_size();
str << "MatrixConvolutionPaintFilter("
<< "kernel_size=" << ToString(kernel_size) << ", kernel=[";
for (int32_t i = 0; i < kernel_size.width() * kernel_size.height();
++i) {
str << (i != 0 ? ", " : "") << ToString(filter.kernel_at(i));
}
str << "], gain=" << ToString(filter.gain())
<< ", bias=" << ToString(filter.bias())
<< ", kernel_offset=" << ToString(filter.kernel_offset())
<< ", tile_mode=" << ToString(filter.tile_mode())
<< ", convolve_alpha=" << filter.convolve_alpha()
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kDisplacementMapEffect: {
const auto& filter =
static_cast<const DisplacementMapEffectPaintFilter&>(base_filter);
str << "DisplacementMapEffectPaintFilter("
<< "channel_x=" << ToString(filter.channel_x())
<< ", channel_y=" << ToString(filter.channel_y())
<< ", scale=" << ToString(filter.scale())
<< ", displacement=" << ToString(filter.displacement())
<< ", color=" << ToString(filter.color())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kImage: {
const auto& filter = static_cast<const ImagePaintFilter&>(base_filter);
str << "ImagePaintFilter("
<< "image=" << ToString(filter.image())
<< ", src_rect=" << ToString(filter.src_rect())
<< ", dst_rect=" << ToString(filter.dst_rect())
<< ", filter_quality=" << ToString(filter.filter_quality())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kPaintRecord: {
const auto& filter = static_cast<const RecordPaintFilter&>(base_filter);
str << "RecordPaintFilter("
<< "record=" << ToString(filter.record())
<< ", record_bounds=" << ToString(filter.record_bounds())
<< ", raster_scale=" << ToString(filter.raster_scale())
<< ", scaling_behavior=" << ToString(filter.scaling_behavior())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kMerge: {
const auto& filter = static_cast<const MergePaintFilter&>(base_filter);
str << "MergePaintFilter("
<< "input_count=" << filter.input_count() << ", input=[";
for (size_t i = 0; i < filter.input_count(); ++i) {
str << (i != 0 ? ", " : "") << ToString(filter.input_at(i));
}
str << "], crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kMorphology: {
const auto& filter =
static_cast<const MorphologyPaintFilter&>(base_filter);
str << "MorphologyPaintFilter("
<< "morph_type=" << ToString(filter.morph_type())
<< ", radius_x=" << filter.radius_x()
<< ", radius_y=" << filter.radius_y()
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kOffset: {
const auto& filter = static_cast<const OffsetPaintFilter&>(base_filter);
str << "OffsetPaintFilter("
<< "dx=" << filter.dx() << ", dy=" << filter.dy()
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kTile: {
const auto& filter = static_cast<const TilePaintFilter&>(base_filter);
str << "TilePaintFilter("
<< "src=" << ToString(filter.src())
<< ", dst=" << ToString(filter.dst())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kTurbulence: {
const auto& filter =
static_cast<const TurbulencePaintFilter&>(base_filter);
str << "TurbulencePaintFilter("
<< "turbulence_type=" << ToString(filter.turbulence_type())
<< ", base_frequency_x=" << ToString(filter.base_frequency_x())
<< ", base_frequency_y=" << ToString(filter.base_frequency_y())
<< ", num_octaves=" << filter.num_octaves()
<< ", seed=" << ToString(filter.seed())
<< ", tile_size=" << ToString(filter.tile_size())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kShader: {
const auto& filter = static_cast<const ShaderPaintFilter&>(base_filter);
str << "ShaderPaintFilter("
<< "shader=" << ToString(filter.shader())
<< ", alpha=" << ToString(filter.alpha())
<< ", filter_quality=" << ToString(filter.filter_quality())
<< ", dither=" << ToString(filter.dither())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kMatrix: {
const auto& filter = static_cast<const MatrixPaintFilter&>(base_filter);
str << "MatrixPaintFilter("
<< "matrix=" << ToString(filter.matrix())
<< ", filter_quality=" << ToString(filter.filter_quality())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kLightingDistant: {
const auto& filter =
static_cast<const LightingDistantPaintFilter&>(base_filter);
str << "LightingDistantPaintFilter("
<< "lighting_type=" << ToString(filter.lighting_type())
<< ", direction=" << ToString(filter.direction())
<< ", light_color=" << ToString(filter.light_color())
<< ", surface_scale=" << ToString(filter.surface_scale())
<< ", kconstant=" << ToString(filter.kconstant())
<< ", shininess=" << ToString(filter.shininess())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kLightingPoint: {
const auto& filter =
static_cast<const LightingPointPaintFilter&>(base_filter);
str << "LightingPointPaintFilter("
<< "lighting_type=" << ToString(filter.lighting_type())
<< ", location=" << ToString(filter.location())
<< ", light_color=" << ToString(filter.light_color())
<< ", surface_scale=" << ToString(filter.surface_scale())
<< ", kconstant=" << ToString(filter.kconstant())
<< ", shininess=" << ToString(filter.shininess())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
break;
}
case PaintFilter::Type::kLightingSpot: {
const auto& filter =
static_cast<const LightingSpotPaintFilter&>(base_filter);
str << "LightingSpotPaintFilter("
<< "lighting_type=" << ToString(filter.lighting_type())
<< ", location=" << ToString(filter.location())
<< ", target=" << ToString(filter.target())
<< ", specular_exponent=" << ToString(filter.specular_exponent())
<< ", cutoff_angle=" << ToString(filter.cutoff_angle())
<< ", light_color=" << ToString(filter.light_color())
<< ", surface_scale=" << ToString(filter.surface_scale())
<< ", kconstant=" << ToString(filter.kconstant())
<< ", shininess=" << ToString(filter.shininess())
<< ", input=" << ToString(filter.input())
<< ", crop_rect=" << ToString(filter.GetCropRect()) << ")";
}
}
return str.str();
}
static std::string ToString(const PaintFlags& flags) {
std::ostringstream str;
str << std::boolalpha;
str << "[color=" << ToString(flags.getColor());
str << ", blendMode=" << ToString(flags.getBlendMode());
str << ", isAntiAlias=" << flags.isAntiAlias();
str << ", isDither=" << flags.isDither();
str << ", filterQuality=" << ToString(flags.getFilterQuality());
str << ", strokeWidth=" << ToString(flags.getStrokeWidth());
str << ", strokeMiter=" << ToString(flags.getStrokeMiter());
str << ", strokeCap=" << ToString(flags.getStrokeCap());
str << ", strokeJoin=" << ToString(flags.getStrokeJoin());
str << ", colorFilter=" << ToString(flags.getColorFilter());
str << ", shader=" << ToString(flags.getShader());
str << ", hasShader=" << flags.HasShader();
str << ", shaderIsOpaque=" << (flags.HasShader() && flags.ShaderIsOpaque());
str << ", pathEffect=" << ToString(flags.getPathEffect());
str << ", imageFilter=" << ToString(flags.getImageFilter());
str << ", drawLooper=" << ToString(flags.getLooper());
str << ", supportsFoldingAlpha=" << flags.SupportsFoldingAlpha();
str << ", isValid=" << flags.IsValid();
str << ", hasDiscardableImages=" << flags.HasDiscardableImages();
str << "]";
return str.str();
}
static std::string ToString(const CorePaintFlags& flags) {
PaintFlags paint_flags(flags);
return ToString(paint_flags);
}
};
} // namespace cc
#endif // CC_TEST_PAINT_OP_HELPER_H_