2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 VDasher::VDasher(const float *dashArray, int size)
25 mDashArray = reinterpret_cast<const VDasher::Dash *>(dashArray);
26 mArraySize = size / 2;
28 mDashOffset = dashArray[size - 1];
34 void VDasher::moveTo(const VPointF &p)
37 mStartNewSegment = true;
41 if (!vCompare(mDashOffset, 0.0f)) {
42 float totalLength = 0.0;
43 for (int i = 0; i < mArraySize; i++) {
44 totalLength = mDashArray[i].length + mDashArray[i].gap;
46 float normalizeLen = fmod(mDashOffset, totalLength);
47 if (normalizeLen < 0.0) {
48 normalizeLen = totalLength + normalizeLen;
50 // now the length is less than total length and +ve
51 // findout the current dash index , dashlength and gap.
52 for (int i = 0; i < mArraySize; i++) {
53 if (normalizeLen < mDashArray[i].length) {
55 mCurrentLength = mDashArray[i].length - normalizeLen;
59 normalizeLen -= mDashArray[i].length;
60 if (normalizeLen < mDashArray[i].gap) {
62 mCurrentLength = mDashArray[i].gap - normalizeLen;
66 normalizeLen -= mDashArray[i].gap;
69 mCurrentLength = mDashArray[mIndex].length;
71 if (vIsZero(mCurrentLength)) updateActiveSegment();
74 void VDasher::addLine(const VPointF &p)
78 if (mStartNewSegment) {
79 mResult.moveTo(mCurPt);
80 mStartNewSegment = false;
85 void VDasher::updateActiveSegment()
87 mStartNewSegment = true;
91 mIndex = (mIndex + 1) % mArraySize;
92 mCurrentLength = mDashArray[mIndex].length;
95 mCurrentLength = mDashArray[mIndex].gap;
97 if (vIsZero(mCurrentLength)) updateActiveSegment();
100 void VDasher::lineTo(const VPointF &p)
103 VLine line(mCurPt, p);
104 float length = line.length();
106 if (length <= mCurrentLength) {
107 mCurrentLength -= length;
110 while (length > mCurrentLength) {
111 length -= mCurrentLength;
112 line.splitAtLength(mCurrentLength, left, right);
115 updateActiveSegment();
122 mCurrentLength -= length;
127 if (mCurrentLength < 1.0) updateActiveSegment();
132 void VDasher::addCubic(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
134 if (mDiscard) return;
136 if (mStartNewSegment) {
137 mResult.moveTo(mCurPt);
138 mStartNewSegment = false;
140 mResult.cubicTo(cp1, cp2, e);
143 void VDasher::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
147 VBezier b = VBezier::fromPoints(mCurPt, cp1, cp2, e);
150 if (bezLen <= mCurrentLength) {
151 mCurrentLength -= bezLen;
152 addCubic(cp1, cp2, e);
154 while (bezLen > mCurrentLength) {
155 bezLen -= mCurrentLength;
156 b.splitAtLength(mCurrentLength, &left, &right);
158 addCubic(left.pt2(), left.pt3(), left.pt4());
159 updateActiveSegment();
166 mCurrentLength -= bezLen;
167 addCubic(b.pt2(), b.pt3(), b.pt4());
171 if (mCurrentLength < 1.0) updateActiveSegment();
176 VPath VDasher::dashed(const VPath &path)
178 if (path.empty()) return VPath();
182 const std::vector<VPath::Element> &elms = path.elements();
183 const std::vector<VPointF> & pts = path.points();
184 const VPointF * ptPtr = pts.data();
186 for (auto &i : elms) {
188 case VPath::Element::MoveTo: {
192 case VPath::Element::LineTo: {
196 case VPath::Element::CubicTo: {
197 cubicTo(*ptPtr, *(ptPtr + 1), *(ptPtr + 2));
201 case VPath::Element::Close: {
202 // The point is already joined to start point in VPath
203 // no need to do anything here.
210 return std::move(mResult);