blob: 48e7b9b4fc23662d9ccf080973d91e2562e93c6e [file] [log] [blame]
Florin Malitae6345d92018-01-03 23:37:54 -05001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkSGMerge.h"
9
10#include "SkCanvas.h"
11#include "SkPathOps.h"
12
13namespace sksg {
14
Florin Malita418e6582018-07-09 16:20:47 -040015Merge::Merge(std::vector<Rec>&& recs)
16 : fRecs(std::move(recs)) {
17 for (const auto& rec : fRecs) {
18 this->observeInval(rec.fGeo);
Florin Malitae6345d92018-01-03 23:37:54 -050019 }
20}
21
22Merge::~Merge() {
Florin Malita418e6582018-07-09 16:20:47 -040023 for (const auto& rec : fRecs) {
24 this->unobserveInval(rec.fGeo);
Florin Malitae6345d92018-01-03 23:37:54 -050025 }
26}
27
Florin Malita38ea40e2018-01-29 16:31:14 -050028void Merge::onClip(SkCanvas* canvas, bool antiAlias) const {
29 canvas->clipPath(fMerged, SkClipOp::kIntersect, antiAlias);
30}
31
Florin Malitae6345d92018-01-03 23:37:54 -050032void Merge::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
Florin Malitae6345d92018-01-03 23:37:54 -050033 canvas->drawPath(fMerged, paint);
34}
35
36SkPath Merge::onAsPath() const {
37 return fMerged;
38}
39
40static SkPathOp mode_to_op(Merge::Mode mode) {
41 switch (mode) {
42 case Merge::Mode::kUnion:
43 return kUnion_SkPathOp;
44 case Merge::Mode::kIntersect:
45 return kIntersect_SkPathOp;
46 case Merge::Mode::kDifference:
47 return kDifference_SkPathOp;
48 case Merge::Mode::kReverseDifference:
49 return kReverseDifference_SkPathOp;
50 case Merge::Mode::kXOR:
51 return kXOR_SkPathOp;
52 default:
53 break;
54 }
55
56 return kUnion_SkPathOp;
57}
58
Florin Malitac14f1442018-01-05 11:32:31 -050059SkRect Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
Florin Malitae6345d92018-01-03 23:37:54 -050060 SkASSERT(this->hasInval());
61
Florin Malitae6345d92018-01-03 23:37:54 -050062 SkOpBuilder builder;
63
64 fMerged.reset();
Florin Malita418e6582018-07-09 16:20:47 -040065 bool in_builder = false;
Florin Malitae6345d92018-01-03 23:37:54 -050066
Florin Malita418e6582018-07-09 16:20:47 -040067 for (const auto& rec : fRecs) {
68 rec.fGeo->revalidate(ic, ctm);
69
70 // Merge is not currently supported by SkOpBuidler.
71 if (rec.fMode == Mode::kMerge) {
72 if (in_builder) {
73 builder.resolve(&fMerged);
74 in_builder = false;
75 }
76
77 fMerged.addPath(rec.fGeo->asPath());
78 continue;
Florin Malitae6345d92018-01-03 23:37:54 -050079 }
Florin Malita418e6582018-07-09 16:20:47 -040080
81 if (!in_builder) {
82 builder.add(fMerged, kUnion_SkPathOp);
83 in_builder = true;
84 }
85
86 builder.add(rec.fGeo->asPath(), mode_to_op(rec.fMode));
Florin Malitae6345d92018-01-03 23:37:54 -050087 }
88
Florin Malita418e6582018-07-09 16:20:47 -040089 if (in_builder) {
Florin Malitae6345d92018-01-03 23:37:54 -050090 builder.resolve(&fMerged);
91 }
92
Florin Malitaf2ade422018-09-11 16:38:39 -040093 fMerged.shrinkToFit();
94
Florin Malitac14f1442018-01-05 11:32:31 -050095 return fMerged.computeTightBounds();
Florin Malitae6345d92018-01-03 23:37:54 -050096}
97
Florin Malita54f65c42018-01-16 17:04:30 -050098} // namespace sksg