MCPcopy Create free account
hub / github.com/Tencent/tgfx / EmitPath

Method EmitPath

src/pdf/PDFUtils.cpp:277–349  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

275} // namespace
276
277void PDFUtils::EmitPath(const Path& path, bool doConsumeDegerates,
278 const std::shared_ptr<MemoryWriteStream>& content) {
279 if (path.isEmpty()) {
280 PDFUtils::AppendRectangle({0, 0, 0, 0}, content);
281 return;
282 }
283 // Filling a path with no area results in a drawing in PDF renderers but
284 // Chrome expects to be able to draw some such entities with no visible
285 // result, so we detect those cases and discard the drawing for them.
286 // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y).
287
288 auto rect = Rect::MakeEmpty();
289 bool isClosed = true; // Both closure and direction need to be checked.
290 bool isReversed = false;
291 if (path.isRect(&rect, &isClosed, &isReversed) && isClosed &&
292 (!isReversed || PathFillType::EvenOdd == path.getFillType())) {
293 PDFUtils::AppendRectangle(rect, content);
294 return;
295 }
296
297 enum class SkipFillState {
298 Empty,
299 SingleLine,
300 NonSingleLine,
301 };
302
303 auto fillState = SkipFillState::Empty;
304 auto lastMovePt = Point::Make(0, 0);
305 auto currentSegment = MemoryWriteStream::Make();
306
307 auto pathIterator = [&](PathVerb verb, const Point points[4], void* /*info*/) -> void {
308 switch (verb) {
309 case PathVerb::Move:
310 MoveTo(points[0].x, points[0].y, currentSegment);
311 lastMovePt = points[0];
312 fillState = SkipFillState::Empty;
313 break;
314 case PathVerb::Line:
315 if (!doConsumeDegerates || !AllPointsEqual(points, 2)) {
316 AppendLine(points[1].x, points[1].y, currentSegment);
317 if ((fillState == SkipFillState::Empty) && (points[0] != lastMovePt)) {
318 fillState = SkipFillState::SingleLine;
319 break;
320 }
321 fillState = SkipFillState::NonSingleLine;
322 }
323 break;
324 case PathVerb::Quad:
325 if (!doConsumeDegerates || !AllPointsEqual(points, 3)) {
326 AppendQuad(points, currentSegment);
327 fillState = SkipFillState::NonSingleLine;
328 }
329 break;
330 case PathVerb::Cubic:
331 if (!doConsumeDegerates || !AllPointsEqual(points, 4)) {
332 AppendCubic(points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y,
333 currentSegment);
334 fillState = SkipFillState::NonSingleLine;

Callers

nothing calls this directly

Calls 14

MakeFunction · 0.85
MoveToFunction · 0.85
AllPointsEqualFunction · 0.85
AppendLineFunction · 0.85
AppendQuadFunction · 0.85
AppendCubicFunction · 0.85
ClosePathFunction · 0.85
getFillTypeMethod · 0.80
writeToAndResetMethod · 0.80
decomposeMethod · 0.80
writeToStreamMethod · 0.80
isEmptyMethod · 0.45

Tested by

no test coverage detected