Bug 188060

Summary: SVG text on a path with a gradient fill is very slow to render
Product: WebKit Reporter: Simon Fraser (smfr) <simon.fraser>
Component: SVGAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: dino, sabouhallawa, simon.fraser, webkit-bug-importer, zimmermann
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Testcase (hangs!) none

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