2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 VDasher::VDasher(const float *dashArray, int size)
27 mDashArray = reinterpret_cast<const VDasher::Dash *>(dashArray);
28 mArraySize = size / 2;
30 mDashOffset = dashArray[size - 1];
36 void VDasher::moveTo(const VPointF &p)
39 mStartNewSegment = true;
43 if (!vCompare(mDashOffset, 0.0f)) {
44 float totalLength = 0.0;
45 for (int i = 0; i < mArraySize; i++) {
46 totalLength = mDashArray[i].length + mDashArray[i].gap;
48 float normalizeLen = fmod(mDashOffset, totalLength);
49 if (normalizeLen < 0.0) {
50 normalizeLen = totalLength + normalizeLen;
52 // now the length is less than total length and +ve
53 // findout the current dash index , dashlength and gap.
54 for (int i = 0; i < mArraySize; i++) {
55 if (normalizeLen < mDashArray[i].length) {
57 mCurrentLength = mDashArray[i].length - normalizeLen;
61 normalizeLen -= mDashArray[i].length;
62 if (normalizeLen < mDashArray[i].gap) {
64 mCurrentLength = mDashArray[i].gap - normalizeLen;
68 normalizeLen -= mDashArray[i].gap;
71 mCurrentLength = mDashArray[mIndex].length;
73 if (vIsZero(mCurrentLength)) updateActiveSegment();
76 void VDasher::addLine(const VPointF &p)
80 if (mStartNewSegment) {
81 mResult.moveTo(mCurPt);
82 mStartNewSegment = false;
87 void VDasher::updateActiveSegment()
89 mStartNewSegment = true;
93 mIndex = (mIndex + 1) % mArraySize;
94 mCurrentLength = mDashArray[mIndex].length;
97 mCurrentLength = mDashArray[mIndex].gap;
99 if (vIsZero(mCurrentLength)) updateActiveSegment();
102 void VDasher::lineTo(const VPointF &p)
105 VLine line(mCurPt, p);
106 float length = line.length();
108 if (length <= mCurrentLength) {
109 mCurrentLength -= length;
112 while (length > mCurrentLength) {
113 length -= mCurrentLength;
114 line.splitAtLength(mCurrentLength, left, right);
117 updateActiveSegment();
124 mCurrentLength -= length;
129 if (mCurrentLength < 1.0) updateActiveSegment();
134 void VDasher::addCubic(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
136 if (mDiscard) return;
138 if (mStartNewSegment) {
139 mResult.moveTo(mCurPt);
140 mStartNewSegment = false;
142 mResult.cubicTo(cp1, cp2, e);
145 void VDasher::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
149 VBezier b = VBezier::fromPoints(mCurPt, cp1, cp2, e);
152 if (bezLen <= mCurrentLength) {
153 mCurrentLength -= bezLen;
154 addCubic(cp1, cp2, e);
156 while (bezLen > mCurrentLength) {
157 bezLen -= mCurrentLength;
158 b.splitAtLength(mCurrentLength, &left, &right);
160 addCubic(left.pt2(), left.pt3(), left.pt4());
161 updateActiveSegment();
168 mCurrentLength -= bezLen;
169 addCubic(b.pt2(), b.pt3(), b.pt4());
173 if (mCurrentLength < 1.0) updateActiveSegment();
178 VPath VDasher::dashed(const VPath &path)
180 if (path.empty()) return VPath();
184 const std::vector<VPath::Element> &elms = path.elements();
185 const std::vector<VPointF> & pts = path.points();
186 const VPointF * ptPtr = pts.data();
188 for (auto &i : elms) {
190 case VPath::Element::MoveTo: {
194 case VPath::Element::LineTo: {
198 case VPath::Element::CubicTo: {
199 cubicTo(*ptPtr, *(ptPtr + 1), *(ptPtr + 2));
203 case VPath::Element::Close: {
204 // The point is already joined to start point in VPath
205 // no need to do anything here.
212 return std::move(mResult);