Bug 188060 - SVG text on a path with a gradient fill is very slow to render
Summary: SVG text on a path with a gradient fill is very slow to render
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-07-26 08:59 PDT by Simon Fraser (smfr)
Modified: 2018-07-28 15:15 PDT (History)
5 users (show)

See Also:


Attachments
Testcase (hangs!) (2.52 KB, image/svg+xml)
2018-07-26 08:59 PDT, Simon Fraser (smfr)
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Fraser (smfr) 2018-07-26 08:59:52 PDT
Created attachment 345849 [details]
Testcase (hangs!)

The attached file causes a webcontent hang.

Lots of CPU time under:

       2035 WebCore::RenderLineBoxList::paint(WebCore::RenderBoxModelObject*, WebCore::PaintInfo&, WebCore::LayoutPoint const&) const  (in WebCore) + 870  [0x108234cf6]
         2035 WebCore::SVGRootInlineBox::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&, WebCore::LayoutUnit, WebCore::LayoutUnit)  (in WebCore) + 276  [0x1083a8bf4]
           1990 WebCore::SVGInlineFlowBox::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&, WebCore::LayoutUnit, WebCore::LayoutUnit)  (in WebCore) + 100  [0x1095f29a4]
           ! 1989 WebCore::SVGInlineTextBox::paint(WebCore::PaintInfo&, WebCore::LayoutPoint const&, WebCore::LayoutUnit, WebCore::LayoutUnit)  (in WebCore) + 865  [0x1083a9021]
           ! : 1989 WebCore::SVGInlineTextBox::paintText(WebCore::GraphicsContext&, WebCore::RenderStyle const&, WebCore::RenderStyle const&, WebCore::SVGTextFragment const&, bool, bool)  (in WebCore) + 469  [0x1095f7295]
           ! :   1947 WebCore::SVGInlineTextBox::paintTextWithShadows(WebCore::GraphicsContext&, WebCore::RenderStyle const&, WebCore::TextRun&, WebCore::SVGTextFragment const&, unsigned int, unsigned int)  (in WebCore) + 481  [0x1095f78b1]
           ! :   | 1931 WebCore::RenderSVGResourceGradient::postApplyResource(WebCore::RenderElement&, WebCore::GraphicsContext*&, WTF::OptionSet<WebCore::RenderSVGResourceMode>, WebCore::Path const*, WebCore::RenderSVGShape const*)  (in WebCore) + 685  [0x1095e451d]
           ! :   | + 1931 WebCore::ImageBufferData::~ImageBufferData()  (in WebCore) + 99  [0x1093b06e3]
           ! :   | +   1931 WebCore::GraphicsContext::~GraphicsContext()  (in WebCore) + 18  [0x109367042]
           ! :   | +     1931 WebCore::GraphicsContext::platformDestroy()  (in WebCore) + 34  [0x1081dbee2]


and huge memory use (> 1GB).
Comment 1 Radar WebKit Bug Importer 2018-07-26 09:05:14 PDT
<rdar://problem/42625890>
Comment 2 Said Abou-Hallawa 2018-07-26 10:31:59 PDT
I did not see a hang when I opened the attached test case in either WK1 or WK2,

WebKit is just extremely slow. After few seconds, I could see the path text filed with gradient as expected and I could even select the text and interact with the Mini-Browser UI but with a large delay.

I did not see a huge memory allocation when opening this file. All I saw was allocation of 35MB.

When opening the attached test case in Chrome, the text shows a lot faster and the selection is drawn instantaneously.
Comment 3 Simon Fraser (smfr) 2018-07-28 15:13:04 PDT
For text on a path, we split the text into text fragments, each of which is one glyph. For each fragment (including whitespace?) we run through RenderStyle::paintTypesForPaintOrder(), each of which hits RenderSVGResourceGradient::postApplyResource() which does the gradient fill, and each gradient fill involves rendering to an image buffer and clipping. That's a lot of work!
Comment 4 Simon Fraser (smfr) 2018-07-28 15:14:52 PDT
Optimization thoughts:
* paint all the text for one path in one go, doing the gradient fill and clip once.
* avoid doing work for whitespace-only text fragments
* cache the gradient rendering
* optimize away 'paintOrder' paths that will paint nothing