| /* | |
| * Copyright 2006 The Android Open Source Project | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/core/SkPath.h" | |
| #include "include/core/SkPathBuilder.h" | |
| #include "include/core/SkSpan.h" | |
| #include "include/core/SkStream.h" | |
| #include "src/base/SkFloatBits.h" | |
| #include "src/core/SkStringUtils.h" | |
| #include <functional> | |
| char const * const gFillTypeStrs[] = { | |
| "Winding", | |
| "EvenOdd", | |
| "InverseWinding", | |
| "InverseEvenOdd", | |
| }; | |
| constexpr float kSentinelConicWeight = -12345; // not a valid weight | |
| static void append_params(SkString* str, const char label[], SkSpan<const SkPoint> pts, | |
| SkScalarAsStringType strType, bool useSemicolon, | |
| SkScalar conicWeight = kSentinelConicWeight) { | |
| str->append(label); | |
| str->append("("); | |
| const SkScalar* values = &pts[0].fX; | |
| size_t count = pts.size() * 2; | |
| for (size_t i = 0; i < count; ++i) { | |
| SkAppendScalar(str, values[i], strType); | |
| if (i < count - 1) { | |
| str->append(", "); | |
| } | |
| } | |
| if (conicWeight != kSentinelConicWeight) { | |
| str->append(", "); | |
| SkAppendScalar(str, conicWeight, strType); | |
| } | |
| str->append(useSemicolon ? ");" : ")"); | |
| if (kHex_SkScalarAsStringType == strType) { | |
| str->append(" // "); | |
| for (size_t i = 0; i < count; ++i) { | |
| SkAppendScalarDec(str, values[i]); | |
| if (i < count - 1) { | |
| str->append(", "); | |
| } | |
| } | |
| if (conicWeight >= 0) { | |
| str->append(", "); | |
| SkAppendScalarDec(str, conicWeight); | |
| } | |
| } | |
| str->append("\n"); | |
| } | |
| static void dump_iter(SkPathIter iter, SkString* builder, const char cmdPrefix[], | |
| SkScalarAsStringType strType, bool useSemicolon, | |
| std::function<void()> postVerbProc) { | |
| while (auto rec = iter.next()) { | |
| SkString cmd(cmdPrefix); | |
| SkSpan<const SkPoint> pts; | |
| float cw = kSentinelConicWeight; | |
| switch (rec->fVerb) { | |
| case SkPathVerb::kMove: | |
| cmd.append(".moveTo"); | |
| pts = {&rec->fPoints[0], 1}; | |
| break; | |
| case SkPathVerb::kLine: | |
| cmd.append(".lineTo"); | |
| pts = {&rec->fPoints[1], 1}; | |
| break; | |
| case SkPathVerb::kQuad: | |
| cmd.append(".quadTo"); | |
| pts = {&rec->fPoints[1], 2}; | |
| break; | |
| case SkPathVerb::kConic: | |
| cmd.append(".conicTo"); | |
| pts = {&rec->fPoints[1], 2}; | |
| cw = rec->conicWeight(); | |
| break; | |
| case SkPathVerb::kCubic: | |
| cmd.append(".cubicTo"); | |
| pts = {&rec->fPoints[1], 3}; | |
| break; | |
| case SkPathVerb::kClose: | |
| cmd.append(".close()"); | |
| if (useSemicolon) { | |
| cmd.append(";"); | |
| } | |
| cmd.append("\n"); | |
| builder->append(cmd.c_str()); | |
| break; | |
| } | |
| // we don't do this for kClose | |
| if (pts.size()) { | |
| append_params(builder, cmd.c_str(), pts, strType, useSemicolon, cw); | |
| } | |
| postVerbProc(); | |
| } | |
| } | |
| void SkPath::dump(SkWStream* wStream, bool dumpAsHex) const { | |
| SkScalarAsStringType asType = dumpAsHex ? kHex_SkScalarAsStringType : kDec_SkScalarAsStringType; | |
| SkString builder; | |
| builder.printf("path.setFillType(SkPathFillType::k%s);\n", | |
| gFillTypeStrs[(int) this->getFillType()]); | |
| dump_iter(this->iter(), &builder, "path", asType, true, [&]() { | |
| if (!wStream && builder.size()) { | |
| SkDebugf("%s", builder.c_str()); | |
| builder.reset(); | |
| } | |
| }); | |
| if (wStream) { | |
| wStream->writeText(builder.c_str()); | |
| } | |
| } | |
| SkString SkPathBuilder::dumpToString(DumpFormat format) const { | |
| SkScalarAsStringType asType = format == DumpFormat::kHex ? kHex_SkScalarAsStringType | |
| : kDec_SkScalarAsStringType; | |
| SkString builder; | |
| builder.printf("SkPathBuilder(SkPathFillType::k%s)\n", | |
| gFillTypeStrs[(int) this->fillType()]); | |
| dump_iter(this->iter(), &builder, "", asType, false, [](){}); | |
| return builder; | |
| } | |
| void SkPathBuilder::dump(DumpFormat format) const { | |
| SkDebugf("%s", dumpToString().c_str()); | |
| } |