Changeset 258492 in webkit


Ignore:
Timestamp:
Mar 16, 2020 5:41:52 AM (4 years ago)
Author:
Carlos Garcia Campos
Message:

[Cairo][SVG] marker-mid isn't shown on a joint of rectilinearly connected line-to path segments
https://bugs.webkit.org/show_bug.cgi?id=113849

Reviewed by Adrian Perez de Castro.

Source/WebCore:

Marker-mid of svg is not displayed because path elements that added to
cairo backend are optimized. If the new line_to has same slope with
the previous path element, then the path element is joined to previous
path element.

Example:

added path elements : moveto(-5,-2), lineto(0,-2), lineto(5,-2)
cairo_path_data : moveto(-5,-2), lineto(5, -2)

This patch stores all of path informations separately in order to avoid
this problem. When generating positions of markers, we use stored path
informations instead of cairo_path_data.

When a new operation can't be directly stored in an ElementPath, we fallback to use cairo_path_data() in
Path::apply().

  • platform/graphics/Path.h: Add new constructor that receives a cairo context, make ensureCairoPath() private

and add m_elements member.

  • platform/graphics/cairo/FontCairo.cpp:

(WebCore::Font::platformPathForGlyph const): Create a cairo context for the path and use the new constructor
that receives a RefPtr<cairo_t>&&.

  • platform/graphics/cairo/PathCairo.cpp:

(WebCore::Path::Path): Initialize m_elements to an empty vector when created without a cairo context.
(WebCore::Path::operator=): Also copy m_elements.
(WebCore::Path::clear): Initialize m_elements to an empty vector.
(WebCore::Path::translate): Apply the translate to elements in m_elements.
(WebCore::Path::appendElement): Helper to add an operation to m_elements.
(WebCore::Path::moveToSlowCase): Call appendElement() if m_elements is not nullopt.
(WebCore::Path::addLineToSlowCase): Ditto.
(WebCore::Path::addRect): Ditto.
(WebCore::Path::addQuadCurveToSlowCase): Ditto.
(WebCore::Path::addBezierCurveToSlowCase): Ditto.
(WebCore::Path::addArcSlowCase): Set m_elements to nullopt.
(WebCore::Path::addArcTo): Ditto.
(WebCore::Path::addEllipse): Ditto.
(WebCore::Path::addPath): Ditto.
(WebCore::Path::closeSubpath): Call appendElement() if m_elements is not nullopt.
(WebCore::Path::applySlowCase const): Use elements from m_elements if it's not nullopt, otherwise fallback to
use cairo_path_data.
(WebCore::Path::transform): Apply the transform to elements in m_elements.

LayoutTests:

Remove svg/custom/local-url-reference-marker.html from expectations and rebaseline other tests.

  • platform/gtk/TestExpectations:
  • platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-01-b-manual-expected.txt:
  • platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-02-b-manual-expected.txt:
  • platform/gtk/imported/w3c/web-platform-tests/svg/painting/marker-008-expected.txt:
  • platform/gtk/imported/w3c/web-platform-tests/svg/text/reftests/textpath-shape-001-expected.txt:
  • platform/gtk/svg/text/text-path-01-b-expected.png:
  • platform/gtk/svg/text/text-path-01-b-expected.txt:
  • platform/wpe/TestExpectations:
Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r258491 r258492  
     12020-03-16  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [Cairo][SVG] marker-mid isn't shown on a joint of rectilinearly connected line-to path segments
     4        https://bugs.webkit.org/show_bug.cgi?id=113849
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        Remove svg/custom/local-url-reference-marker.html from expectations and rebaseline other tests.
     9
     10        * platform/gtk/TestExpectations:
     11        * platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-01-b-manual-expected.txt:
     12        * platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-02-b-manual-expected.txt:
     13        * platform/gtk/imported/w3c/web-platform-tests/svg/painting/marker-008-expected.txt:
     14        * platform/gtk/imported/w3c/web-platform-tests/svg/text/reftests/textpath-shape-001-expected.txt:
     15        * platform/gtk/svg/text/text-path-01-b-expected.png:
     16        * platform/gtk/svg/text/text-path-01-b-expected.txt:
     17        * platform/wpe/TestExpectations:
     18
    1192020-03-16  Nikolas Zimmermann  <nzimmermann@igalia.com>
    220
  • trunk/LayoutTests/platform/gtk/TestExpectations

    r258489 r258492  
    36053605webkit.org/b/107825 media/video-controls-fullscreen-volume.html [ Failure Crash ]
    36063606
    3607 webkit.org/b/113849 svg/custom/local-url-reference-marker.html [ ImageOnlyFailure ]
    3608 
    36093607# Test marked in TestExpectations as failing on non-retina displays, passing on GTK port
    36103608webkit.org/b/129113 fast/multicol/newmulticol/clipping.html [ Pass ]
  • trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-01-b-manual-expected.txt

    r250598 r258492  
    1919              chunk 1 text run 3 at (220.27,49.99) startOffset 2 endOffset 3 width 18.00: "x"
    2020              chunk 1 text run 4 at (229.72,39.54) startOffset 3 endOffset 4 width 10.20: "t"
    21               chunk 1 text run 5 at (237.20,33.54) startOffset 4 endOffset 5 width 9.00: " "
     21              chunk 1 text run 5 at (237.20,33.53) startOffset 4 endOffset 5 width 9.00: " "
    2222              chunk 1 text run 6 at (249.38,27.89) startOffset 5 endOffset 6 width 18.00: "o"
    2323              chunk 1 text run 7 at (267.06,29.00) startOffset 6 endOffset 7 width 18.00: "n"
     
    4646              chunk 1 text run 1 at (64.17,96.02) startOffset 0 endOffset 1 width 10.20: "t"
    4747              chunk 1 text run 2 at (71.65,90.02) startOffset 1 endOffset 2 width 9.00: " "
    48               chunk 1 text run 3 at (83.84,84.39) startOffset 2 endOffset 3 width 18.00: "o"
     48              chunk 1 text run 3 at (83.85,84.39) startOffset 2 endOffset 3 width 18.00: "o"
    4949              chunk 1 text run 4 at (101.52,85.48) startOffset 3 endOffset 4 width 18.00: "n"
    5050              chunk 1 text run 5 at (113.05,92.40) startOffset 4 endOffset 5 width 9.00: " "
  • trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/svg/import/text-path-02-b-manual-expected.txt

    r250598 r258492  
    1616              RenderSVGInlineText {#text} at (0,0) size 208x124
    1717                chunk 1 text run 1 at (199.12,88.96) startOffset 16 endOffset 17 width 25.80: "N"
    18                 chunk 1 text run 2 at (208.45,68.19) startOffset 17 endOffset 18 width 19.80: "e"
     18                chunk 1 text run 2 at (208.44,68.18) startOffset 17 endOffset 18 width 19.80: "e"
    1919                chunk 1 text run 3 at (218.99,51.66) startOffset 18 endOffset 19 width 19.44: "g"
    2020                chunk 1 text run 4 at (232.27,37.27) startOffset 19 endOffset 20 width 19.80: "a"
     
    6767                  chunk 1 text run 5 at (291.95,49.56) startOffset 4 endOffset 5 width 10.20: "t"
    6868                  chunk 1 text run 6 at (297.50,56.64) startOffset 5 endOffset 6 width 7.80: "i"
    69                   chunk 1 text run 7 at (305.18,67.01) startOffset 6 endOffset 7 width 18.00: "v"
     69                  chunk 1 text run 7 at (305.18,67.00) startOffset 6 endOffset 7 width 18.00: "v"
    7070                  chunk 1 text run 8 at (317.13,81.15) startOffset 7 endOffset 8 width 19.08: "e"
    7171                  chunk 1 text run 9 at (328.39,90.49) startOffset 8 endOffset 9 width 10.20: " "
     
    7373                  chunk 1 text run 11 at (355.23,103.11) startOffset 10 endOffset 11 width 9.84: "f"
    7474                  chunk 1 text run 12 at (363.89,104.73) startOffset 11 endOffset 12 width 7.80: "f"
    75                   chunk 1 text run 13 at (376.37,104.23) startOffset 12 endOffset 13 width 17.28: "s"
     75                  chunk 1 text run 13 at (376.37,104.22) startOffset 12 endOffset 13 width 17.28: "s"
    7676                  chunk 1 text run 14 at (392.89,96.17) startOffset 13 endOffset 14 width 19.80: "e"
    7777                  chunk 1 text run 15 at (404.03,86.40) startOffset 14 endOffset 15 width 9.84: "t"
     
    9898                chunk 1 text run 13 at (210.84,160.73) startOffset 12 endOffset 13 width 17.28: "s"
    9999                chunk 1 text run 14 at (227.36,152.66) startOffset 13 endOffset 14 width 19.80: "e"
    100                 chunk 1 text run 15 at (238.49,142.90) startOffset 14 endOffset 15 width 9.84: "t"
     100                chunk 1 text run 15 at (238.49,142.89) startOffset 14 endOffset 15 width 9.84: "t"
    101101                chunk 1 text run 16 at (245.90,136.15) startOffset 15 endOffset 16 width 10.20: " "
    102102            RenderSVGInlineText {#text} at (0,0) size 0x0
  • trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/svg/painting/marker-008-expected.txt

    r250598 r258492  
    1515    RenderSVGPath {polyline} at (150,199) size 150x56 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [end marker=markerTest] [points="150 200 200 200 250 200"]
    1616    RenderSVGPath {line} at (300,49) size 100x2 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [x1=300.00] [y1=50.00] [x2=400.00] [y2=50.00]
    17     RenderSVGPath {path} at (300,99) size 100x2 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [data="M 300 100 L 350 100 L 400 100"]
     17    RenderSVGPath {path} at (300,99) size 100x56 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [data="M 300 100 L 350 100 L 400 100"]
    1818    RenderSVGPath {polygon} at (300,149) size 100x56 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [points="300 150 350 150"]
    19     RenderSVGPath {polyline} at (300,199) size 100x2 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [points="300 200 350 200 400 200"]
     19    RenderSVGPath {polyline} at (300,199) size 100x56 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#000000]}] [middle marker=markerTest] [points="300 200 350 200 400 200"]
  • trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/svg/text/reftests/textpath-shape-001-expected.txt

    r254744 r258492  
    3333            chunk 1 text run 19 at (189.67,233.66) startOffset 18 endOffset 19 width 9.00: "s"
    3434            chunk 1 text run 20 at (187.42,239.83) startOffset 19 endOffset 20 width 4.20: "i"
    35             chunk 1 text run 21 at (184.79,243.47) startOffset 20 endOffset 21 width 4.80: "t"
     35            chunk 1 text run 21 at (184.78,243.47) startOffset 20 endOffset 21 width 4.80: "t"
    3636            chunk 1 text run 22 at (181.16,246.60) startOffset 21 endOffset 22 width 4.80: " "
    3737            chunk 1 text run 23 at (174.60,249.47) startOffset 22 endOffset 23 width 9.60: "a"
     
    4343            chunk 1 text run 29 at (126.94,250.00) startOffset 28 endOffset 29 width 9.00: "c"
    4444            chunk 1 text run 30 at (117.64,250.00) startOffset 29 endOffset 30 width 9.60: "o"
    45             chunk 1 text run 31 at (108.05,249.91) startOffset 30 endOffset 31 width 9.60: "n"
     45            chunk 1 text run 31 at (108.04,249.91) startOffset 30 endOffset 31 width 9.60: "n"
    4646            chunk 1 text run 32 at (99.33,246.92) startOffset 31 endOffset 32 width 9.00: "s"
    4747            chunk 1 text run 33 at (92.87,240.34) startOffset 32 endOffset 33 width 9.60: "e"
     
    5858            chunk 1 text run 44 at (93.29,159.01) startOffset 43 endOffset 44 width 10.20: "p"
    5959            chunk 1 text run 45 at (98.23,153.83) startOffset 44 endOffset 45 width 4.20: "i"
    60             chunk 1 text run 46 at (104.10,150.88) startOffset 45 endOffset 46 width 9.00: "s"
     60            chunk 1 text run 46 at (104.11,150.88) startOffset 45 endOffset 46 width 9.00: "s"
    6161        RenderSVGInlineText {#text} at (0,0) size 0x0
    6262      RenderSVGContainer {use} at (482,249) size 169x169
  • trunk/LayoutTests/platform/gtk/svg/text/text-path-01-b-expected.txt

    r238733 r258492  
    1818              chunk 1 text run 3 at (220.27,49.99) startOffset 2 endOffset 3 width 18.00: "x"
    1919              chunk 1 text run 4 at (229.72,39.54) startOffset 3 endOffset 4 width 10.20: "t"
    20               chunk 1 text run 5 at (237.20,33.54) startOffset 4 endOffset 5 width 9.00: " "
     20              chunk 1 text run 5 at (237.20,33.53) startOffset 4 endOffset 5 width 9.00: " "
    2121              chunk 1 text run 6 at (249.38,27.89) startOffset 5 endOffset 6 width 18.00: "o"
    2222              chunk 1 text run 7 at (267.06,29.00) startOffset 6 endOffset 7 width 18.00: "n"
     
    4444              chunk 1 text run 1 at (64.17,96.02) startOffset 0 endOffset 1 width 10.20: "t"
    4545              chunk 1 text run 2 at (71.65,90.02) startOffset 1 endOffset 2 width 9.00: " "
    46               chunk 1 text run 3 at (83.84,84.39) startOffset 2 endOffset 3 width 18.00: "o"
     46              chunk 1 text run 3 at (83.85,84.39) startOffset 2 endOffset 3 width 18.00: "o"
    4747              chunk 1 text run 4 at (101.52,85.48) startOffset 3 endOffset 4 width 18.00: "n"
    4848              chunk 1 text run 5 at (113.05,92.40) startOffset 4 endOffset 5 width 9.00: " "
  • trunk/LayoutTests/platform/wpe/TestExpectations

    r258485 r258492  
    19491949webkit.org/b/134758 svg/custom/composited-svg-with-opacity.html [ ImageOnlyFailure Pass ]
    19501950webkit.org/b/131347 svg/custom/hidpi-masking-clipping.svg [ Failure ImageOnlyFailure Timeout ]
    1951 webkit.org/b/113849 svg/custom/local-url-reference-marker.html [ ImageOnlyFailure ]
    19521951webkit.org/b/160137 svg/custom/non-scaling-stroke.svg [ Failure Pass ]
    19531952webkit.org/b/160137 svg/custom/non-scaling-stroke-update.svg [ ImageOnlyFailure Pass ]
  • trunk/Source/WebCore/ChangeLog

    r258488 r258492  
     12020-03-16  Hurnjoo Lee  <hurnjoo.lee@samsung.com>, Fujii Hironori  <Hironori.Fujii@sony.com>, Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [Cairo][SVG] marker-mid isn't shown on a joint of rectilinearly connected line-to path segments
     4        https://bugs.webkit.org/show_bug.cgi?id=113849
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        Marker-mid of svg is not displayed because path elements that added to
     9        cairo backend are optimized. If the new line_to has same slope with
     10        the previous path element, then the path element is joined to previous
     11        path element.
     12
     13        Example:
     14
     15        added path elements : moveto(-5,-2), lineto(0,-2), lineto(5,-2)
     16        cairo_path_data : moveto(-5,-2), lineto(5, -2)
     17
     18        This patch stores all of path informations separately in order to avoid
     19        this problem. When generating positions of markers, we use stored path
     20        informations instead of cairo_path_data.
     21
     22        When a new operation can't be directly stored in an ElementPath, we fallback to use cairo_path_data() in
     23        Path::apply().
     24
     25        * platform/graphics/Path.h: Add new constructor that receives a cairo context, make ensureCairoPath() private
     26        and add m_elements member.
     27        * platform/graphics/cairo/FontCairo.cpp:
     28        (WebCore::Font::platformPathForGlyph const): Create a cairo context for the path and use the new constructor
     29        that receives a RefPtr<cairo_t>&&.
     30        * platform/graphics/cairo/PathCairo.cpp:
     31        (WebCore::Path::Path): Initialize m_elements to an empty vector when created without a cairo context.
     32        (WebCore::Path::operator=): Also copy m_elements.
     33        (WebCore::Path::clear): Initialize m_elements to an empty vector.
     34        (WebCore::Path::translate): Apply the translate to elements in m_elements.
     35        (WebCore::Path::appendElement): Helper to add an operation to m_elements.
     36        (WebCore::Path::moveToSlowCase): Call appendElement() if m_elements is not nullopt.
     37        (WebCore::Path::addLineToSlowCase): Ditto.
     38        (WebCore::Path::addRect): Ditto.
     39        (WebCore::Path::addQuadCurveToSlowCase): Ditto.
     40        (WebCore::Path::addBezierCurveToSlowCase): Ditto.
     41        (WebCore::Path::addArcSlowCase): Set m_elements to nullopt.
     42        (WebCore::Path::addArcTo): Ditto.
     43        (WebCore::Path::addEllipse): Ditto.
     44        (WebCore::Path::addPath): Ditto.
     45        (WebCore::Path::closeSubpath): Call appendElement() if m_elements is not nullopt.
     46        (WebCore::Path::applySlowCase const): Use elements from m_elements if it's not nullopt, otherwise fallback to
     47        use cairo_path_data.
     48        (WebCore::Path::transform): Apply the transform to elements in m_elements.
     49
    1502020-03-16  Rob Buis  <rbuis@igalia.com>
    251
  • trunk/Source/WebCore/platform/graphics/Path.h

    r258204 r258492  
    123123    Path(RetainPtr<CGMutablePathRef>&&);
    124124#endif
     125#if USE(CAIRO)
     126    explicit Path(RefPtr<cairo_t>&&);
     127#endif
    125128    WEBCORE_EXPORT ~Path();
    126129
     
    193196#endif
    194197
     198#if !USE(CAIRO)
    195199    // ensurePlatformPath() will allocate a PlatformPath if it has not yet been and will never return null.
    196 #if USE(CAIRO)
    197     cairo_t* ensureCairoPath();
    198 #else
    199200    WEBCORE_EXPORT PlatformPathPtr ensurePlatformPath();
    200201#endif
     
    258259
    259260#if USE(CAIRO)
     261    cairo_t* ensureCairoPath();
     262    void appendElement(PathElement::Type, Vector<FloatPoint, 3>&&);
     263#endif
     264
     265#if USE(CAIRO)
    260266    RefPtr<cairo_t> m_path;
    261267#else
     
    274280#if USE(CG)
    275281    mutable bool m_copyPathBeforeMutation { false };
     282#endif
     283#if USE(CAIRO)
     284    Optional<Vector<PathElement>> m_elements;
    276285#endif
    277286};
  • trunk/Source/WebCore/platform/graphics/cairo/FontCairo.cpp

    r258204 r258492  
    4444#include "Pattern.h"
    4545#include "PlatformContextCairo.h"
     46#include "RefPtrCairo.h"
    4647#include "ShadowBlur.h"
    4748
     
    8283Path Font::platformPathForGlyph(Glyph glyph) const
    8384{
    84     Path path;
    85     cairo_t* cr = path.ensureCairoPath();
     85    RefPtr<cairo_t> cr = adoptRef(cairo_create(adoptRef(cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1)).get()));
    8686
    8787    cairo_glyph_t cairoGlyph = { glyph, 0, 0 };
    88     cairo_set_scaled_font(cr, platformData().scaledFont());
    89     cairo_glyph_path(cr, &cairoGlyph, 1);
     88    cairo_set_scaled_font(cr.get(), platformData().scaledFont());
     89    cairo_glyph_path(cr.get(), &cairoGlyph, 1);
    9090
    9191    float syntheticBoldOffset = this->syntheticBoldOffset();
    9292    if (syntheticBoldOffset) {
    93         cairo_translate(cr, syntheticBoldOffset, 0);
    94         cairo_glyph_path(cr, &cairoGlyph, 1);
     93        cairo_translate(cr.get(), syntheticBoldOffset, 0);
     94        cairo_glyph_path(cr.get(), &cairoGlyph, 1);
    9595    }
    96     return path;
     96    return Path(WTFMove(cr));
    9797}
    9898
  • trunk/Source/WebCore/platform/graphics/cairo/PathCairo.cpp

    r258206 r258492  
    4040namespace WebCore {
    4141
    42 Path::Path() = default;
     42Path::Path()
     43    : m_elements(Vector<PathElement>())
     44{
     45}
     46
     47Path::Path(RefPtr<cairo_t>&& path)
     48    : m_path(WTFMove(path))
     49{
     50}
    4351
    4452Path::~Path() = default;
     
    5563    CairoUniquePtr<cairo_path_t> pathCopy(cairo_copy_path(other.m_path.get()));
    5664    cairo_append_path(ensureCairoPath(), pathCopy.get());
     65    m_elements = other.m_elements;
    5766}
    5867
     
    7180    if (other.isNull()) {
    7281        m_path = nullptr;
     82        m_elements = Vector<PathElement>();
    7383        return *this;
    7484    }
     
    7787    CairoUniquePtr<cairo_path_t> pathCopy(cairo_copy_path(other.m_path.get()));
    7888    cairo_append_path(ensureCairoPath(), pathCopy.get());
     89    m_elements = other.m_elements;
    7990
    8091    return *this;
     
    8899    cairo_identity_matrix(m_path.get());
    89100    cairo_new_path(m_path.get());
     101    m_elements = Vector<PathElement>();
    90102}
    91103
     
    107119{
    108120    cairo_translate(ensureCairoPath(), -p.width(), -p.height());
     121
     122    if (!m_elements)
     123        return;
     124
     125    for (auto& element : m_elements.value()) {
     126        switch (element.type) {
     127        case PathElement::Type::MoveToPoint:
     128        case PathElement::Type::AddLineToPoint:
     129            element.points[0].move(p);
     130            break;
     131        case PathElement::Type::AddQuadCurveToPoint:
     132            element.points[0].move(p);
     133            element.points[1].move(p);
     134            break;
     135        case PathElement::Type::AddCurveToPoint:
     136            element.points[0].move(p);
     137            element.points[1].move(p);
     138            element.points[2].move(p);
     139            break;
     140        case PathElement::Type::CloseSubpath:
     141            break;
     142        }
     143    }
     144}
     145
     146void Path::appendElement(PathElement::Type type, Vector<FloatPoint, 3>&& points)
     147{
     148    PathElement element;
     149    element.type = type;
     150    switch (type) {
     151    case PathElement::Type::MoveToPoint:
     152    case PathElement::Type::AddLineToPoint:
     153        element.points[0] = points[0];
     154        break;
     155    case PathElement::Type::AddQuadCurveToPoint:
     156        element.points[0] = points[0];
     157        element.points[1] = points[1];
     158        break;
     159    case PathElement::Type::AddCurveToPoint:
     160        element.points[0] = points[0];
     161        element.points[1] = points[1];
     162        element.points[2] = points[2];
     163        break;
     164    case PathElement::Type::CloseSubpath:
     165        break;
     166    }
     167    m_elements->append(WTFMove(element));
    109168}
    110169
     
    112171{
    113172    cairo_move_to(ensureCairoPath(), p.x(), p.y());
     173    if (m_elements)
     174        appendElement(PathElement::Type::MoveToPoint, { p });
    114175}
    115176
     
    117178{
    118179    cairo_line_to(ensureCairoPath(), p.x(), p.y());
     180    if (m_elements)
     181        appendElement(PathElement::Type::AddLineToPoint, { p });
    119182}
    120183
     
    122185{
    123186    cairo_rectangle(ensureCairoPath(), rect.x(), rect.y(), rect.width(), rect.height());
     187
     188    if (!m_elements)
     189        return;
     190
     191    FloatPoint point(rect.location());
     192    appendElement(PathElement::Type::MoveToPoint, { point });
     193    point.move(rect.width(), 0);
     194    appendElement(PathElement::Type::AddLineToPoint, { point });
     195    point.move(0, rect.height());
     196    appendElement(PathElement::Type::AddLineToPoint, { point });
     197    point.move(-rect.width(), 0);
     198    appendElement(PathElement::Type::AddLineToPoint, { point });
     199    appendElement(PathElement::Type::CloseSubpath, { });
     200    if (cairo_has_current_point(m_path.get()))
     201        appendElement(PathElement::Type::MoveToPoint, { currentPointSlowCase() });
    124202}
    125203
     
    137215        x2 + 2.0 / 3.0 * (x1 - x2), y2 + 2.0 / 3.0 * (y1 - y2),
    138216        x2, y2);
     217    if (m_elements)
     218        appendElement(PathElement::Type::AddQuadCurveToPoint, { controlPoint, point  });
    139219}
    140220
     
    143223    cairo_curve_to(ensureCairoPath(), controlPoint1.x(), controlPoint1.y(),
    144224        controlPoint2.x(), controlPoint2.y(), controlPoint3.x(), controlPoint3.y());
     225    if (m_elements)
     226        appendElement(PathElement::Type::AddCurveToPoint, { controlPoint1, controlPoint2, controlPoint3 });
    145227}
    146228
    147229void Path::addArcSlowCase(const FloatPoint& p, float r, float startAngle, float endAngle, bool anticlockwise)
    148230{
     231    m_elements = WTF::nullopt;
    149232    cairo_t* cr = ensureCairoPath();
    150233    float sweep = endAngle - startAngle;
     
    186269        || !areaOfTriangleFormedByPoints(p0, p1, p2)) {
    187270        cairo_line_to(m_path.get(), p1.x(), p1.y());
     271        if (m_elements)
     272            appendElement(PathElement::Type::AddLineToPoint, { p1 });
    188273        return;
    189274    }
     
    197282    if (cos_phi == -1) {
    198283        cairo_line_to(m_path.get(), p1.x(), p1.y());
     284        if (m_elements)
     285            appendElement(PathElement::Type::AddLineToPoint, { p1 });
    199286        return;
    200287    }
     
    205292        FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y()));
    206293        cairo_line_to(m_path.get(), ep.x(), ep.y());
    207         return;
    208     }
    209 
     294        if (m_elements)
     295            appendElement(PathElement::Type::AddLineToPoint, { ep });
     296        return;
     297    }
     298
     299    m_elements = WTF::nullopt;
    210300    float tangent = radius / tan(acos(cos_phi) / 2);
    211301    float factor_p1p0 = tangent / p1p0_length;
     
    251341void Path::addEllipse(FloatPoint point, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
    252342{
     343    m_elements = WTF::nullopt;
    253344    cairo_t* cr = ensureCairoPath();
    254345    cairo_save(cr);
     
    267358void Path::addEllipse(const FloatRect& rect)
    268359{
     360    m_elements = WTF::nullopt;
    269361    cairo_t* cr = ensureCairoPath();
    270362    cairo_save(cr);
     
    286378        return;
    287379
     380    m_elements = WTF::nullopt;
     381
    288382    cairo_t* cr = path.cairoPath();
    289383    cairo_save(cr);
     
    297391{
    298392    cairo_close_path(ensureCairoPath());
     393    if (m_elements) {
     394        appendElement(PathElement::Type::CloseSubpath, { });
     395        if (cairo_has_current_point(m_path.get()))
     396            appendElement(PathElement::Type::MoveToPoint, { currentPointSlowCase() });
     397    }
    299398}
    300399
     
    349448void Path::applySlowCase(const PathApplierFunction& function) const
    350449{
     450    if (m_elements) {
     451        for (const auto& element : m_elements.value())
     452            function(element);
     453        return;
     454    }
     455
    351456    CairoUniquePtr<cairo_path_t> pathCopy(cairo_copy_path(m_path.get()));
    352457    cairo_path_data_t* data;
     
    391496    cairo_matrix_invert(&matrix);
    392497    cairo_transform(ensureCairoPath(), &matrix);
     498
     499    if (!m_elements)
     500        return;
     501
     502    for (auto& element : m_elements.value()) {
     503        switch (element.type) {
     504        case PathElement::Type::MoveToPoint:
     505        case PathElement::Type::AddLineToPoint:
     506            element.points[0] = transform.mapPoint(element.points[0]);
     507            break;
     508        case PathElement::Type::AddQuadCurveToPoint:
     509            element.points[0] = transform.mapPoint(element.points[0]);
     510            element.points[1] = transform.mapPoint(element.points[1]);
     511            break;
     512        case PathElement::Type::AddCurveToPoint:
     513            element.points[0] = transform.mapPoint(element.points[0]);
     514            element.points[1] = transform.mapPoint(element.points[1]);
     515            element.points[2] = transform.mapPoint(element.points[2]);
     516            break;
     517        case PathElement::Type::CloseSubpath:
     518            break;
     519        }
     520    }
    393521}
    394522
Note: See TracChangeset for help on using the changeset viewer.