1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "Sk2DPathEffect.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h"
146db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com#include "SkRegion.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1616edff2b1cbd80e36456138f8631711a585205bareed@google.comSk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) {
1790bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    fMatrixIsInvertible = mat.invert(&fInverse);
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20548a1f321011292359ef163f78c8a1d4871b3b7freed@google.combool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src,
214bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com                                SkStrokeRec*, const SkRect*) const {
2290bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    if (!fMatrixIsInvertible) {
2390bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org        return false;
2490bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    }
2590bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org
266db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com    SkPath  tmp;
276db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com    SkIRect ir;
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    src.transform(fInverse, &tmp);
30d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    tmp.getBounds().round(&ir);
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!ir.isEmpty()) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->begin(ir, dst);
336db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com
346db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com        SkRegion rgn;
356db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com        rgn.setPath(tmp, SkRegion(ir));
366db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com        SkRegion::Iterator iter(rgn);
376db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com        for (; !iter.done(); iter.next()) {
386db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com            const SkIRect& rect = iter.rect();
396db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com            for (int y = rect.fTop; y < rect.fBottom; ++y) {
406db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com                this->nextSpan(rect.fLeft, y, rect.width(), dst);
416db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com            }
426db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com        }
436db9375b4f695c68a4e56e38bcd70f983440c2d5reed@google.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->end(dst);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid Sk2DPathEffect::nextSpan(int x, int y, int count, SkPath* path) const {
5090bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    if (!fMatrixIsInvertible) {
5190bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org        return;
5290bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    }
5390bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMatrix& mat = this->getMatrix();
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint src, dst;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf);
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        mat.mapPoints(&dst, &src, 1);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->next(dst, x++, y, path);
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src.fX += SK_Scalar1;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count > 0);
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid Sk2DPathEffect::begin(const SkIRect& uvBounds, SkPath* dst) const {}
66548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid Sk2DPathEffect::next(const SkPoint& loc, int u, int v, SkPath* dst) const {}
67548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid Sk2DPathEffect::end(SkPath* dst) const {}
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6916edff2b1cbd80e36456138f8631711a585205bareed@google.com///////////////////////////////////////////////////////////////////////////////
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid Sk2DPathEffect::flatten(SkWriteBuffer& buffer) const {
7254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com    this->INHERITED::flatten(buffer);
73d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com    buffer.writeMatrix(fMatrix);
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSk2DPathEffect::Sk2DPathEffect(SkReadBuffer& buffer) {
78d2700eec7eb2e26beb206b88a0f0b6f3c5f49118djsollen@google.com    buffer.readMatrix(&fMatrix);
7990bf427001fd4f6d9fcee88911deb015aeb4ab7cmike@reedtribe.org    fMatrixIsInvertible = fMatrix.invert(&fInverse);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
83e28b917669fc4677b2f1c0a08c4711b651cbf1a1reed@google.com///////////////////////////////////////////////////////////////////////////////
84d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
85548a1f321011292359ef163f78c8a1d4871b3b7freed@google.combool SkLine2DPathEffect::filterPath(SkPath* dst, const SkPath& src,
864bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com                            SkStrokeRec* rec, const SkRect* cullRect) const {
874bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com    if (this->INHERITED::filterPath(dst, src, rec, cullRect)) {
88d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        rec->setStrokeStyle(fWidth);
89d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        return true;
90d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    }
91d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    return false;
92d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com}
93d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
94548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid SkLine2DPathEffect::nextSpan(int u, int v, int ucount, SkPath* dst) const {
95d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    if (ucount > 1) {
96d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        SkPoint    src[2], dstP[2];
97d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
98d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
99d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
100d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        this->getMatrix().mapPoints(dstP, src, 2);
101d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
102d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        dst->moveTo(dstP[0]);
103d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com        dst->lineTo(dstP[1]);
104d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    }
105d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com}
106d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
1079fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1088b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLine2DPathEffect::SkLine2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
109d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    fWidth = buffer.readScalar();
110d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com}
1119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkLine2DPathEffect::CreateProc(SkReadBuffer& buffer) {
1149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkMatrix matrix;
1159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readMatrix(&matrix);
1169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar width = buffer.readScalar();
1179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkLine2DPathEffect::Create(width, matrix);
1189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
119d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
1208b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLine2DPathEffect::flatten(SkWriteBuffer &buffer) const {
1219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeMatrix(this->getMatrix());
122d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com    buffer.writeScalar(fWidth);
123d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com}
124d8a6cc814f1a0a8faaddad05ae765ad2f6b11aacscroggo@google.com
12518dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com///////////////////////////////////////////////////////////////////////////////
12618dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com
12718dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.comSkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p)
12818dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com    : INHERITED(m), fPath(p) {
12918dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com}
13018dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com
1319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkPath2DPathEffect::SkPath2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {
1332b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    buffer.readPath(&fPath);
13418dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com}
1359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPath2DPathEffect::CreateProc(SkReadBuffer& buffer) {
1389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkMatrix matrix;
1399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readMatrix(&matrix);
1409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkPath path;
1419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readPath(&path);
1429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkPath2DPathEffect::Create(matrix, path);
1439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
14418dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com
1458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPath2DPathEffect::flatten(SkWriteBuffer& buffer) const {
1469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeMatrix(this->getMatrix());
1472b2ede3e713065e1bac461787b0aafb03eaf871fdjsollen@google.com    buffer.writePath(fPath);
14818dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com}
14918dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com
150548a1f321011292359ef163f78c8a1d4871b3b7freed@google.comvoid SkPath2DPathEffect::next(const SkPoint& loc, int u, int v,
151548a1f321011292359ef163f78c8a1d4871b3b7freed@google.com                              SkPath* dst) const {
15218dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com    dst->addPath(fPath, loc.fX, loc.fY);
15318dc47731f4b37d8896b51f1b92ab31abd78b5a0reed@google.com}
154