diff --git a/libs/flake/svg/SvgMeshArray.cpp b/libs/flake/svg/SvgMeshArray.cpp index a4260a96a5..527513ead1 100644 --- a/libs/flake/svg/SvgMeshArray.cpp +++ b/libs/flake/svg/SvgMeshArray.cpp @@ -1,144 +1,163 @@ /* * Copyright (c) 2020 Sharaf Zaman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SvgMeshArray.h" #include #include SvgMeshArray::SvgMeshArray() { } +SvgMeshArray::SvgMeshArray(SvgMeshArray& other) +{ + // FIXME The way SvgParser works with gradients is, it frequently destroys the objects holding reference to + // SvgMeshGradients, so rather than copying we move it. This certainly needs a design refactor. + m_array = std::move(other.m_array); + +} + SvgMeshArray::~SvgMeshArray() { for (auto& row: m_array) { for (auto& patch: row) { delete patch; } } } void SvgMeshArray::newRow() { m_array << QVector(); } bool SvgMeshArray::addPatch(QList> stops, const QPointF initialPoint) { // This is function is full of edge-case landmines, please run TestMeshArray after any changes if (stops.size() > 4 || stops.size() < 2) return false; SvgMeshPatch *patch = new SvgMeshPatch(initialPoint); if (m_array.empty()) { patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Top); stops.removeFirst(); m_array.append(QVector() << patch); } else { m_array.last().append(patch); } int irow = m_array.size() - 1; int icol = m_array.last().size() - 1; // first stop, except for the very first in the array if (irow != 0 || icol != 0) { // For first row, parse patches if (irow == 0) { patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Top); stops.removeFirst(); } else { // path is already defined for rows >= 1 QColor color = getStop(SvgMeshPatch::Left, irow - 1, icol).color; QList points = getPath(SvgMeshPatch::Bottom, irow - 1, icol); std::reverse(points.begin(), points.end()); patch->addStop(points, color, SvgMeshPatch::Top); } } // Right will always be independent patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Right); stops.removeFirst(); if (icol > 0) { patch->addStop( stops[0].first, stops[0].second, SvgMeshPatch::Bottom, true, getStop(SvgMeshPatch::Bottom, irow, icol - 1).point); stops.removeFirst(); } else { patch->addStop(stops[0].first, stops[0].second, SvgMeshPatch::Bottom); stops.removeFirst(); } // last stop if (icol == 0) { // if stop is in the 0th column, parse path patch->addStop( stops[0].first, stops[0].second, SvgMeshPatch::Left, true, getStop(SvgMeshPatch::Top, irow, icol).point); stops.removeFirst(); } else { QColor color = getStop(SvgMeshPatch::Bottom, irow, icol - 1).color; // reuse Right side of the previous patch QList points = getPath(SvgMeshPatch::Right, irow, icol - 1); std::reverse(points.begin(), points.end()); patch->addStop(points, color, SvgMeshPatch::Left); } return true; } SvgMeshStop SvgMeshArray::getStop(const SvgMeshPatch::Type edge, const int row, const int col) const { assert(row < m_array.size() && col < m_array[row].size() && row >= 0 && col >= 0); SvgMeshPatch *patch = m_array[row][col]; SvgMeshStop *node = patch->getStop(edge); if (node != nullptr) { return *node; } switch (patch->countPoints()) { case 3: case 2: if (edge == SvgMeshPatch::Top) return getStop(SvgMeshPatch::Left, row - 1, col); else if (edge == SvgMeshPatch::Left) return getStop(SvgMeshPatch::Bottom, row, col - 1); } assert(false); } QList SvgMeshArray::getPath(const SvgMeshPatch::Type edge, const int row, const int col) const { assert(row < m_array.size() && col < m_array[row].size() && row >= 0 && col >= 0); return m_array[row][col]->getPath(edge).controlPoints(); } +int SvgMeshArray::numRows() const +{ + return m_array.size(); +} + +int SvgMeshArray::numColumns() const +{ + if (m_array.isEmpty()) + return 0; + return m_array.first().size(); +} diff --git a/libs/flake/svg/SvgMeshArray.h b/libs/flake/svg/SvgMeshArray.h index df86170dca..8e495bb956 100644 --- a/libs/flake/svg/SvgMeshArray.h +++ b/libs/flake/svg/SvgMeshArray.h @@ -1,47 +1,55 @@ /* * Copyright (c) 2020 Sharaf Zaman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef SVGMESHARRAY_H #define SVGMESHARRAY_H #include #include "SvgMeshPatch.h" class KRITAFLAKE_EXPORT SvgMeshArray { public: SvgMeshArray(); + + // MOVES the elements of m_array from other to this + SvgMeshArray(SvgMeshArray& other); + ~SvgMeshArray(); void newRow(); bool addPatch(QList> stops, const QPointF initialPoint); /// Get the point of a node in mesharray SvgMeshStop getStop(const SvgMeshPatch::Type edge, const int row, const int col) const; - + /// Get the Path Points for a segment of the meshpatch QList getPath(const SvgMeshPatch::Type edge, const int row, const int col) const; + int numRows() const; + int numColumns() const; + + private: /// where each vector is a meshrow QVector> m_array; }; #endif // SVGMESHARRAY_H diff --git a/libs/flake/svg/SvgMeshGradient.cpp b/libs/flake/svg/SvgMeshGradient.cpp index 24af524d48..6337785ce3 100644 --- a/libs/flake/svg/SvgMeshGradient.cpp +++ b/libs/flake/svg/SvgMeshGradient.cpp @@ -1,38 +1,54 @@ /* * Copyright (c) 2020 Sharaf Zaman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "SvgMeshGradient.h" SvgMeshGradient::SvgMeshGradient() : m_mesharray(new SvgMeshArray()) { } +SvgMeshGradient::SvgMeshGradient(const SvgMeshGradient& other) + : m_type(other.m_type) + , m_mesharray(new SvgMeshArray(*other.m_mesharray)) +{ +} + SvgMeshGradient::~SvgMeshGradient() { delete m_mesharray; } void SvgMeshGradient::setType(SvgMeshGradient::Type type) { m_type = type; } +SvgMeshGradient::Type SvgMeshGradient::type() const +{ + return m_type; +} + +bool SvgMeshGradient::isValid() const +{ + return m_mesharray->numRows() != 0; +} + SvgMeshArray* SvgMeshGradient::getMeshArray() const { return m_mesharray; } diff --git a/libs/flake/svg/SvgMeshGradient.h b/libs/flake/svg/SvgMeshGradient.h index a140f36540..1b362ea53d 100644 --- a/libs/flake/svg/SvgMeshGradient.h +++ b/libs/flake/svg/SvgMeshGradient.h @@ -1,47 +1,50 @@ /* * Copyright (c) 2020 Sharaf Zaman * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISMESHGRADIENT_H #define KISMESHGRADIENT_H #include #include "SvgMeshPatch.h" #include "SvgMeshArray.h" class SvgMeshGradient { public: enum Type { BILINEAR, BICUBIC, }; SvgMeshGradient(); - + SvgMeshGradient(const SvgMeshGradient& other); ~SvgMeshGradient(); void setType(Type type); + SvgMeshGradient::Type type() const; + + bool isValid() const; SvgMeshArray* getMeshArray() const; private: Type m_type; SvgMeshArray* m_mesharray; }; #endif // KISMESHGRADIENT_H