7 VDasher::VDasher(const float *dashArray, int size)
9 mDashArray = reinterpret_cast<const VDasher::Dash *>(dashArray);
10 mArraySize = size / 2;
12 mDashOffset = dashArray[size - 1];
18 void VDasher::moveTo(const VPointF &p)
21 mStartNewSegment = true;
25 if (!vCompare(mDashOffset, 0.0f)) {
26 float totalLength = 0.0;
27 for (int i = 0; i < mArraySize; i++) {
28 totalLength = mDashArray[i].length + mDashArray[i].gap;
30 float normalizeLen = fmod(mDashOffset, totalLength);
31 if (normalizeLen < 0.0) {
32 normalizeLen = totalLength + normalizeLen;
34 // now the length is less than total length and +ve
35 // findout the current dash index , dashlength and gap.
36 for (int i = 0; i < mArraySize; i++) {
37 if (normalizeLen < mDashArray[i].length) {
39 mCurrentLength = mDashArray[i].length - normalizeLen;
43 normalizeLen -= mDashArray[i].length;
44 if (normalizeLen < mDashArray[i].gap) {
46 mCurrentLength = mDashArray[i].gap - normalizeLen;
50 normalizeLen -= mDashArray[i].gap;
53 mCurrentLength = mDashArray[mIndex].length;
55 if (vIsZero(mCurrentLength)) updateActiveSegment();
58 void VDasher::addLine(const VPointF &p)
62 if (mStartNewSegment) {
63 mResult.moveTo(mCurPt);
64 mStartNewSegment = false;
69 void VDasher::updateActiveSegment()
71 mStartNewSegment = true;
75 mIndex = (mIndex + 1) % mArraySize;
76 mCurrentLength = mDashArray[mIndex].length;
79 mCurrentLength = mDashArray[mIndex].gap;
81 if (vIsZero(mCurrentLength)) updateActiveSegment();
84 void VDasher::lineTo(const VPointF &p)
87 VLine line(mCurPt, p);
88 float length = line.length();
90 if (length <= mCurrentLength) {
91 mCurrentLength -= length;
94 while (length > mCurrentLength) {
95 length -= mCurrentLength;
96 line.splitAtLength(mCurrentLength, left, right);
99 updateActiveSegment();
106 mCurrentLength -= length;
111 if (mCurrentLength < 1.0) updateActiveSegment();
116 void VDasher::addCubic(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
118 if (mDiscard) return;
120 if (mStartNewSegment) {
121 mResult.moveTo(mCurPt);
122 mStartNewSegment = false;
124 mResult.cubicTo(cp1, cp2, e);
127 void VDasher::cubicTo(const VPointF &cp1, const VPointF &cp2, const VPointF &e)
131 VBezier b = VBezier::fromPoints(mCurPt, cp1, cp2, e);
134 if (bezLen <= mCurrentLength) {
135 mCurrentLength -= bezLen;
136 addCubic(cp1, cp2, e);
138 while (bezLen > mCurrentLength) {
139 bezLen -= mCurrentLength;
140 b.splitAtLength(mCurrentLength, &left, &right);
142 addCubic(left.pt2(), left.pt3(), left.pt4());
143 updateActiveSegment();
150 mCurrentLength -= bezLen;
151 addCubic(b.pt2(), b.pt3(), b.pt4());
155 if (mCurrentLength < 1.0) updateActiveSegment();
160 VPath VDasher::dashed(const VPath &path)
162 if (path.empty()) return VPath();
166 const std::vector<VPath::Element> &elms = path.elements();
167 const std::vector<VPointF> & pts = path.points();
168 const VPointF * ptPtr = pts.data();
170 for (auto &i : elms) {
172 case VPath::Element::MoveTo: {
176 case VPath::Element::LineTo: {
180 case VPath::Element::CubicTo: {
181 cubicTo(*ptPtr, *(ptPtr + 1), *(ptPtr + 2));
185 case VPath::Element::Close: {
186 // The point is already joined to start point in VPath
187 // no need to do anything here.
194 return std::move(mResult);