/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkSGMerge.h" #include "SkCanvas.h" #include "SkPathOps.h" namespace sksg { Merge::Merge(std::vector>&& geos, Mode mode) : fGeos(std::move(geos)) , fMode(mode) { for (const auto& geo : fGeos) { this->observeInval(geo); } } Merge::~Merge() { for (const auto& geo : fGeos) { this->unobserveInval(geo); } } void Merge::onDraw(SkCanvas* canvas, const SkPaint& paint) const { canvas->drawPath(fMerged, paint); } SkPath Merge::onAsPath() const { return fMerged; } static SkPathOp mode_to_op(Merge::Mode mode) { switch (mode) { case Merge::Mode::kUnion: return kUnion_SkPathOp; case Merge::Mode::kIntersect: return kIntersect_SkPathOp; case Merge::Mode::kDifference: return kDifference_SkPathOp; case Merge::Mode::kReverseDifference: return kReverseDifference_SkPathOp; case Merge::Mode::kXOR: return kXOR_SkPathOp; default: break; } return kUnion_SkPathOp; } SkRect Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); const auto op = mode_to_op(fMode); SkOpBuilder builder; fMerged.reset(); for (const auto& geo : fGeos) { geo->revalidate(ic, ctm); if (fMode == Mode::kMerge) { fMerged.addPath(geo->asPath()); } else { builder.add(geo->asPath(), geo == fGeos.front() ? kUnion_SkPathOp : op); } } if (fMode != Mode::kMerge) { builder.resolve(&fMerged); } return fMerged.computeTightBounds(); } } // namespace sksg