/*
* 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());
}
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland