[Webkit-unassigned] [Bug 53512] [CG] getBBox() on a SVGPathElement with curves incorrectly includes control points

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Jul 28 17:53:21 PDT 2011


https://bugs.webkit.org/show_bug.cgi?id=53512





--- Comment #4 from Nikolas Zimmermann <zimmermann at kde.org>  2011-07-28 17:53:21 PST ---
(In reply to comment #2)
> Created an attachment (id=102313)
 --> (https://bugs.webkit.org/attachment.cgi?id=102313&action=review) [details]
> pure-CG non-reproducing case
> 
> I haven't taken enough of a look yet, but attached is a pure-CG example that gets the bounding box for exactly the same shape perfectly correct.
> 
> So, it could still be CG, if we're getting it in some weird state, but someone will have to dig deeper.

Great catch! I traced down what we're passing to CG, by breaking on SVGPathBuilder::moveTo/lineTo/curveToCubic.

Let's compare your testcase and what we feed to CG:

1.
<code>
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 131, 210);
</code>

WebCore::Path::moveTo (this=0x21bd315c, point=@0x21b5bbe8) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/platform/graphics/cg/PathCG.cpp:191
191        CGPathMoveToPoint(m_path, 0, point.x(), point.y());
(gdb) p point
$9 = (const 'WebCore::FloatPoint' &) @0x21b5bbe8: {
  m_x = 131, 
  m_y = 210
}

That's the same.

2.
<code>
    CGPathAddCurveToPoint(path, NULL, 152, 173, 207, 125, 240, 177);
</code>

WebCore::Path::addBezierCurveTo (this=0x21bd315c, cp1=@0xbfffbd08, cp2=@0xbfffbd00, p=@0x21b5bbe8) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/platform/graphics/cg/PathCG.cpp:206
206        CGPathAddCurveToPoint(m_path, 0, cp1.x(), cp1.y(), cp2.x(), cp2.y(), p.x(), p.y());
(gdb) p cp1
$10 = (const 'WebCore::FloatPoint' &) @0xbfffbd08: {
  m_x = 152, 
  m_y = 173
}
(gdb) p cp2
$11 = (const 'WebCore::FloatPoint' &) @0xbfffbd00: {
  m_x = 207, 
  m_y = 125
}
(gdb) p p
$12 = (const 'WebCore::FloatPoint' &) @0x21b5bbe8: {
  m_x = 240, 
  m_y = 177
}

That's the same.

3.
<code>
    CGPathAddCurveToPoint(path, NULL, 273, 229, 211, 293, 193, 257);
</code>

WebCore::Path::addBezierCurveTo (this=0x21bd315c, cp1=@0xbfffbd08, cp2=@0xbfffbd00, p=@0x21b5bbe8) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/platform/graphics/cg/PathCG.cpp:206
206        CGPathAddCurveToPoint(m_path, 0, cp1.x(), cp1.y(), cp2.x(), cp2.y(), p.x(), p.y());
(gdb) p cp1
$13 = (const 'WebCore::FloatPoint' &) @0xbfffbd08: {
  m_x = 273, 
  m_y = 229
}
(gdb) p cp2
$14 = (const 'WebCore::FloatPoint' &) @0xbfffbd00: {
  m_x = 211, 
  m_y = 293
}
(gdb) p p
$15 = (const 'WebCore::FloatPoint' &) @0x21b5bbe8: {
  m_x = 193, 
  m_y = 257
}

That's the same.

4.
<code>
    CGPathAddCurveToPoint(path, NULL, 175, 221, 110, 247, 131, 210);
</code>

WebCore::Path::addBezierCurveTo (this=0x21bd315c, cp1=@0xbfffbd08, cp2=@0xbfffbd00, p=@0x21b5bbe8) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/platform/graphics/cg/PathCG.cpp:206
206        CGPathAddCurveToPoint(m_path, 0, cp1.x(), cp1.y(), cp2.x(), cp2.y(), p.x(), p.y());
(gdb) p cp1
$16 = (const 'WebCore::FloatPoint' &) @0xbfffbd08: {
  m_x = 175, 
  m_y = 221
}
(gdb) p cp2
$17 = (const 'WebCore::FloatPoint' &) @0xbfffbd00: {
  m_x = 110, 
  m_y = 247
}
(gdb) p p
$18 = (const 'WebCore::FloatPoint' &) @0x21b5bbe8: {
  m_x = 131, 
  m_y = 210
}

That's the same.

5.
<code>
    CGPathCloseSubpath(path);
</code>

WebCore::Path::closeSubpath (this=0x21bd315c) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/platform/graphics/cg/PathCG.cpp:216
216        CGPathCloseSubpath(m_path);

Also the same!
So we're constructing the path in an identical way.

Okay, where's the problem?
Stepping down from my last breakpoint SVGPathBuilder::closePath shows the answer:

Breakpoint 4, WebCore::SVGPathBuilder::closePath (this=0x108ca590) at SVGPathBuilder.cpp:66
66        ASSERT(m_path);
(gdb) s
67        m_path->closeSubpath();
(gdb) fin
Run till exit from #0  WebCore::SVGPathBuilder::closePath (this=0x108ca590) at SVGPathBuilder.cpp:67
WebCore::SVGPathParser::parseClosePathSegment (this=0x108c49c0) at SVGPathParser.cpp:48
48    }
(gdb) fin
Run till exit from #0  WebCore::SVGPathParser::parseClosePathSegment (this=0x108c49c0) at SVGPathParser.cpp:48
WebCore::SVGPathParser::parsePathDataFromSource (this=0x108c49c0, pathParsingMode=WebCore::NormalizedParsing) at SVGPathParser.cpp:331
331                break;
(gdb) fin
Run till exit from #0  WebCore::SVGPathParser::parsePathDataFromSource (this=0x108c49c0, pathParsingMode=WebCore::NormalizedParsing) at SVGPathParser.cpp:331
0x09b421ca in WebCore::SVGPathParserFactory::buildPathFromByteStream (this=0x108c4990, stream=0x108c4050, result=@0x108c4d9c) at SVGPathParserFactory.cpp:172
172        bool ok = parser->parsePathDataFromSource(NormalizedParsing);
Value returned is $59 = true
(gdb) p (CGRect)CGPathGetPathBoundingBox(result.m_path)
$60 = {
  origin = {
    x = 126.869362, 
    y = 154.158096
  }, 
  size = {
    width = 122.646141, 
    height = 113.340134
  }
}
(gdb) 

All fine here at this point!

(gdb) fin
Run till exit from #0  0x09b421ca in WebCore::SVGPathParserFactory::buildPathFromByteStream (this=0x11a2f140, stream=0x11a361a0, result=@0x11a3fc6c) at SVGPathParserFactory.cpp:172
WebCore::SVGPathElement::toPathData (this=0x11a54f10, path=@0x11a3fc6c) at SVGPathElement.cpp:334
334    }
Value returned is $70 = true
(gdb) fin
Run till exit from #0  WebCore::SVGPathElement::toPathData (this=0x11a54f10, path=@0x11a3fc6c) at SVGPathElement.cpp:334
WebCore::RenderSVGPath::layout (this=0x11a3fc4c) at RenderSVGPath.cpp:120
120            m_needsPathUpdate = false;
(gdb) pQuit
(gdb) p (CGRect)CGPathGetPathBoundingBox(m_path.m_path)
$71 = {
  origin = {
    x = 126.869362, 
    y = 154.158096
  }, 
  size = {
    width = 122.646141, 
    height = 113.340134
  }
}
(gdb) 

Still fine.

Stepping on...

359        m_fillBoundingBox = m_path.boundingRect();
Value returned is $74 = {m_location = {m_x = 110, m_y = 125}, m_size = {m_width = 163, m_height = 168}}


FloatRect Path::boundingRect() const
{
    return CGPathGetBoundingBox(m_path);
}

Funny bug, eh? :-) The value magically is truncated.


I've stepped through WebCore::SVGPathParserFactory::buildPathFromByteStream (this=0x209b8200, stream=0x209b7440, result=@0x21bd315c) at SVGPathParserFactory.cpp:174
and it turns out that
(gdb) p (CGRect)CGPathGetPathBoundingBox(result.m_path)
$23 = {
  origin = {
    x = 126.869362, 
    y = 154.158096
  }, 
  size = {
    width = 122.646141, 
    height = 113.340134
  }


Your program gives:
x=126.869362, y=154.158096, w=122.646141, h=113.340134

At this point your CG demo program and WebCore still agree!

Breaking on the next call of Path::boundingRect(), gives:
0x09a2a92d in WebCore::RenderSVGPath::updateCachedBoundaries (this=0x21bd313c) at RenderSVGPath.cpp:359
359        m_fillBoundingBox = m_path.boundingRect();
Value returned is $25 = {m_location = {m_x = 110, m_y = 125}, m_size = {m_width = 163, m_height = 168}}

-- 
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.



More information about the webkit-unassigned mailing list