Implementing SVG attribute "stroke-miterlimit" ( tdf#48066)

Armin Le Grand armin_le_grand at
Mon Apr 11 10:46:00 UTC 2016

Hi Regina,

comments inline :-)

Am 08.04.2016 um 18:27 schrieb Regina Henschel:
> Hi Armin,
> since yesterday I have thought about it. I now think, that I will use 
> the GDI+ type 'LineJoinMiterClipped'. That makes rendering inside LO 
> consistent and that is more important as interoperability with foreign 
> applications. It is then still possible to implement the use of the 
> GDI+ type 'LineJoinMiter' in addition later on, and use it for pptx.

I checked and agree - when the limit is exceeded, fallback to bevel 
should happen. This is exactly what we do and what others do, e.g. cairo:

"If the current line join style is set to |CAIRO_LINE_JOIN_MITER| 
(see |cairo_set_line_join()| 
the miter limit is used to determine whether the lines should be joined 
with a bevel instead of a miter. Cairo divides the length of the miter 
by the line width. If the result is greater than the miter limit, the 
style is converted to a bevel."

> It is not a problem of scaling, but the kind how the sharp corner is 
> clipped is fundamental different.

Yes, extending it somehow - instead of just doing a bevel it 'keeps' 
some lengths - stragne ;.)

> If you think I should do it different, please tell me.
> Next problem: When testing a curve I got bug
> Rendering of 
> mitered curve changes with zoom level
> That is independent of SVG, but effects the rendering of SVG too. Do 
> you have a code pointer, where I should look for the reason?

I am surprised - and indeed, it is already in aoo. Sigh.
Entry is in VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect, 
two hits, 1st is the fat line, 2nd the hairline. This goes down to the 
Gdiplus renderer WinSalGraphicsImpl::drawPolyLine which does

                 const Gdiplus::REAL aMiterLimit(15.0);

If this does not work (hopefully better with LineJoinMiterClipped) we 
have a problem with WIndows.
BTW: jumping in the debugger over tryDrawPolygonStrokePrimitive2DDirect 
in VclPixelProcessor2D::processBasePrimitive2D and using the 
decomposition works...


> The state is now, that I have finished the transport of 
> fMiterMinimumAngle for Windows. The rendering is already good with 
> decomposition and with anti-aliasing on as well, here on Windows. I 
> have started to adapt the headers for the other OS. A MetaXYAction is 
> still missing.
> Kind regards
> Regina
> Armin Le Grand schrieb:
>> Hi Regina,
>> yes, the MiterLimits are different in different systems, but all are
>> somehow specified using the angle between the two vectors involved. I
>> remember to have seen some definitions, most using the same and 15 as
>> default value. The ways to be compatible with MS are:
>> - find a definition somewhere, mqaybe in forums or newsgroups (I have
>> none, sorry)
>> - reverse engineer by trying out. Probability is high that there is a
>> (linear?) relationship between the values, so it might be a simple 
>> scaling
>> HTH!
>> Regards,
>> Armin
>> Am 07.04.2016 um 14:35 schrieb Regina Henschel:
>>> Hi all,
>>> I have made some progress. But a new problem comes up.
>>> I have changed WinSalGraphicsImpl::drawPolyLine [3] so that it gets an
>>> additional parameter fMiterMinimumAngle (same meaning as in
>>> createAreaGeometryForJoin) and uses it for gdi+. The rendering in
>>> edit-mode in Draw and Impress is correct then with gdi+ on Windows.
>>> Even Text in SVG works out of the box. [BTW: The current rendering
>>> using gdi+ is wrong, see my report bug#99102.]
>>> The behavior of gdi+ is described in [1]. To get the same kind of
>>> behavior as in LO, when the miter limit is exceeded, the LineJoin type
>>> 'LineJoinMiterClipped' has to be used.
>>> Being only in LibreOffice and SVG, that would be no problem. But MS
>>> seems to use different defaults. The rendering in PowerPoint looks
>>> like gdi+ type 'LineJoinMiter'. The specification for 'lim' in
>>> ECMA-376, Part 1, chapter, has no details, and I have not
>>> found details otherwhere.
>>> This gdi+ type 'LineJoinMiter' kind of clipping (see the image in the
>>> article [1]) will be used in SVG 2 [2] too under the identifier
>>> 'miter-clip'.
>>> So my question: Ignore interoperability with MS? If not, how to 
>>> solve it?
>>> Kind regards
>>> Regina
>>> [1]
>>> [2]
>>> [3]
>>> diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
>>> index 7febbe8..36ecb31 100644
>>> --- a/vcl/win/gdi/gdiimpl.cxx
>>> +++ b/vcl/win/gdi/gdiimpl.cxx
>>> @@ -2031,7 +2031,8 @@ bool WinSalGraphicsImpl::drawPolyLine(
>>>      double fTransparency,
>>>      const basegfx::B2DVector& rLineWidths,
>>>      basegfx::B2DLineJoin eLineJoin,
>>> -    css::drawing::LineCap eLineCap)
>>> +    css::drawing::LineCap eLineCap,
>>> +    double fMiterMinimumAngle)
>>>  {
>>>      const sal_uInt32 nCount(rPolygon.count());
>>> @@ -2064,9 +2065,9 @@ bool WinSalGraphicsImpl::drawPolyLine(
>>>              }
>>>              case basegfx::B2DLineJoin::Miter :
>>>              {
>>> -                const Gdiplus::REAL aMiterLimit(15.0);
>>> +                const Gdiplus::REAL
>>> aMiterLimit(1/sin(fMiterMinimumAngle/2.0));
>>> Gdiplus::DllExports::GdipSetPenMiterLimit(pTestPen, aMiterLimit);
>>> - Gdiplus::DllExports::GdipSetPenLineJoin(pTestPen,
>>> Gdiplus::LineJoinMiter);
>>> + Gdiplus::DllExports::GdipSetPenLineJoin(pTestPen,
>>> Gdiplus::LineJoinMiterClipped);
>>>                  break;
>>>              }
>>>              case basegfx::B2DLineJoin::Round :
>>> _______________________________________________
>>> LibreOffice mailing list
>>> LibreOffice at

ALG (PGP Key: EE1C 4B3F E751 D8BC C485 DEC1 3C59 F953 D81C F4A2)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the LibreOffice mailing list