Skia and dashed lines

1,659 views
Skip to first unread message

Dirk Weltz

unread,
Apr 3, 2018, 10:18:38 AM4/3/18
to skia-discuss
Hello,

I'm quite new to Skia and work with SkiaSharp. I work under Win 10 with Wpf SkiaSharp implementation, but don't assume, that this is the problem.

If I create a path (polygon with hole) with very long lines (around 10000000 pixels width and height) and draw this path, than dashed lines are drawn solid. If I shorten them to max 2^32 pixels per line, they are drawn dashed, but horrible slow. They aren't clipped. If I clip them by hand, it works all ok.

I created a fiddl to show this, but don't know, how to save this. So I put the code here:

void draw(SkCanvas* canvas) {
    canvas->drawColor(SK_ColorBLACK);
    canvas->scale(1.0f, 1.0f);

    SkPaint paint1;
    paint1.setStyle(SkPaint::kFill_Style);
    paint1.setStrokeWidth(1);
    paint1.setColor(0xff808080);
    paint1.setAntiAlias(true);
    paint1.setStrokeCap(SkPaint::kRound_Cap);

    SkPath path0;
    path0.moveTo(-2000000, -2000000);
    path0.lineTo(100, -2000000);
    path0.lineTo(100, 100);
    path0.lineTo(-2000000, 100);
    path0.moveTo(-1999900, -1999900);
    path0.lineTo(-1999900, 90);
    path0.lineTo(90, 90);
    path0.lineTo(90, -1999900);
    path0.lineTo(-1999900, -1999900);

    canvas->drawPath(path0, paint1);

    SkPaint paint2;
    SkScalar intervals[] = {10, 10};
    paint2.setStyle(SkPaint::kStroke_Style);
    paint2.setStrokeWidth(2);
    paint2.setColor(0xffffffff);
    paint2.setAntiAlias(true);
    paint2.setStrokeCap(SkPaint::kRound_Cap);
    paint2.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 1));   
    canvas->drawPath(path0, paint2);
}

Here DrawPath needs around 400 ms to draw the screen. Same without path effect: under 1 ms.

And another funny thing: if I use "SkScalar intervals[] = {30, 10};" as dash array, it is rendered twice as fast as " {10, 10}" :)

Is there a reason, why Skia doesn't clip such polygons? And why is the length of dashed lines limited?

Shawn Riordan

unread,
Apr 3, 2018, 8:01:45 PM4/3/18
to skia-discuss
I don't know if it is related to your problem, but be aware that Skia surfaces are limited to dimensions of 32k x 32k

Cary Clark

unread,
Apr 4, 2018, 7:43:16 AM4/4/18
to skia-d...@googlegroups.com
If you dash a path with very long lines, Skia creates all of the dashes, then draws the visible ones. This is the core of the performance problem you observe.
We've added two optimizations to work around this; dashing very long lines, and very long rectangles. These geometries skip the dash elements
fall outside the visible area. We don't have a generalized optimization.

You can clip the polygon to the visible area with Op(), but we don't have a utility to return the length of the parts; to keep the dash phase correct, you'll need to measure each part of the polygon that's clipped out.

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss+unsubscribe@googlegroups.com.
To post to this group, send email to skia-d...@googlegroups.com.
Visit this group at https://groups.google.com/group/skia-discuss.
For more options, visit https://groups.google.com/d/optout.

Dirk Weltz

unread,
Apr 4, 2018, 7:50:04 AM4/4/18
to skia-discuss
So you say, that, if I'm use DrawLine() or DrawRect() instead of DrawPath(), this optimizations take place. And if I want to use DrawPath(), I should calc the length of part from start outside of the clip rect to the end and to modulo this with the dash length, so that I get a correct phase for starting the dash. Correct?

Cary Clark

unread,
Apr 4, 2018, 9:24:18 AM4/4/18
to skia-d...@googlegroups.com
There are a number of conditions that must be met to trigger the special case. The lines must be horizontal or vertical. The dash count must be 2. The dash intervals must be equal and integral. The SkPaint cap must be kButt_Cap.
There are other restrictions: see SkDashImpl::asPoints().

It doesn't matter what call you use; if the SkPath contains a line, that will work. 

Your approach to using DrawPath() sounds right.

Cary


On Wed, Apr 4, 2018 at 7:50 AM, Dirk Weltz <w...@weltz-online.de> wrote:
So you say, that, if I'm use DrawLine() or DrawRect() instead of DrawPath(), this optimizations take place. And if I want to use DrawPath(), I should calc the length of part from start outside of the clip rect to the end and to modulo this with the dash length, so that I get a correct phase for starting the dash. Correct?

Reply all
Reply to author
Forward
0 new messages