/* * Copyright 2022 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gm/gm.h" #include "include/core/SkCanvas.h" #include "include/core/SkPath.h" static SkPath get_path() { SkPath path; path.setFillType(SkPathFillType::kWinding); path.moveTo(SkBits2Float(0x45034ec4), SkBits2Float(0x42e7fb80)); // 2100.92f, 115.991f path.quadTo(SkBits2Float(0x4500f46c), SkBits2Float(0x43333300), SkBits2Float(0x4500f46c), SkBits2Float(0x431f0ec0)); // 2063.28f, 179.199f, 2063.28f, 159.058f path.quadTo(SkBits2Float(0x4500f46c), SkBits2Float(0x430ad7c0), SkBits2Float(0x45019462), SkBits2Float(0x42fed580)); // 2063.28f, 138.843f, 2073.27f, 127.417f path.quadTo(SkBits2Float(0x45023458), SkBits2Float(0x42e7fb80), SkBits2Float(0x45034ec4), SkBits2Float(0x42e7fb80)); // 2083.27f, 115.991f, 2100.92f, 115.991f path.close(); return path; } // Reproduces the underlying problem from skbug.com/12866. // The path (part of a glyph) was being drawn stroked, and with a perspective matrix. // The perspective matrix forces a very large resScale when stroking the path. // The resulting filled path is incorrect. Note that stroking with a smaller resScale works fine. DEF_SIMPLE_GM(bug12866, canvas, 128, 64) { SkPaint strokePaint; strokePaint.setAntiAlias(true); strokePaint.setStyle(SkPaint::kStroke_Style); strokePaint.setStrokeWidth(3); SkPaint fillPaint; fillPaint.setAntiAlias(true); SkPath strokePath = get_path(); SkPath fillPath; strokePaint.getFillPath(strokePath, &fillPath, nullptr, 1200.0f); SkRect strokeBounds = strokePath.getBounds(); SkRect fillBounds = fillPath.getBounds(); // Draw the stroked path. This (internally) uses a resScale of 1.0, and looks good. canvas->save(); canvas->translate(10 - strokeBounds.fLeft, 10 - strokeBounds.fTop); canvas->drawPath(strokePath, strokePaint); canvas->restore(); // With a perspective CTM, it's possible for resScale to become large. Draw the filled // path produced by the stroker in that situation, which ends up being incorrect. canvas->save(); canvas->translate(74 - fillBounds.fLeft, 10 - fillBounds.fTop); canvas->drawPath(fillPath, fillPaint); canvas->restore(); }