dumping SkSVGCanvas to PNG and XML-string

284 views
Skip to first unread message

kat...@gmail.com

unread,
May 3, 2019, 11:05:12 AM5/3/19
to skia-discuss
Hi,

I have the following piece of code and want to do two things:

1- how can I get the relative xml string from SkSVGCanvas ?

2- how can I dump SkSVGCanvas to a PNG buffer? 

Thanks
Hoss
            
 SkDynamicMemoryWStream svgStream;

 std
::unique_ptr<SkXMLWriter> xmlWriter(
 
new SkXMLStreamWriter(&svgStream));
 
SkRect bounds = SkRect::MakeIWH(2000, 2000);
 std
::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(bounds, &svgStream);
 

 
SkPaint strokePaint;
 strokePaint
.setStyle(SkPaint::kStroke_Style);
 strokePaint
.setColor(SK_ColorBLACK);
 strokePaint
.setAntiAlias(true);
 strokePaint
.setStrokeWidth(5);
 
static SkScalar x,y, x2,y2;
 
static double angle = M_PI/6;
 

 
for (int i = 0; i < 10000; i++)
 
{
 x2
+=5;
 y
= 400+sin(angle/2)*300;
 angle
+= M_PI/6;
 y2
= 400+sin(angle/2)*300;
 svgCanvas
->drawLine(x,y,x2,y2,strokePaint);
 x
= x2;
 
}

 svgCanvas->save();






Yesenia Jenkins

unread,
May 4, 2019, 3:14:38 AM5/4/19
to skia-discuss

Florin Malita

unread,
May 5, 2019, 2:10:33 PM5/5/19
to skia-d...@googlegroups.com
On Fri, May 3, 2019 at 11:05 AM <kat...@gmail.com> wrote:
Hi,

I have the following piece of code and want to do two things:

1- how can I get the relative xml string from SkSVGCanvas ?

The XML output is directed to the backing stream - svgStream.  You can grab it as an SkData using svgStream.detachAsData() and go from there.

(IIRC you need to destroy svgCanvas first, to force it to flush)

 
2- how can I dump SkSVGCanvas to a PNG buffer? 

Do you want the result of rasterizing SVG (Skia -> SVG -> raster), or the result of rasterizing Skia draw commands (Skia -> raster)?

Neither is directly available from SkSVGCanvas, but there are ways to generate - depending on which one you need.

 

Thanks
Hoss
            
 SkDynamicMemoryWStream svgStream;

 std
::unique_ptr<SkXMLWriter> xmlWriter(
 
new SkXMLStreamWriter(&svgStream));
 
SkRect bounds = SkRect::MakeIWH(2000, 2000);
 std
::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(bounds, &svgStream);
 

 
SkPaint strokePaint;
 strokePaint
.setStyle(SkPaint::kStroke_Style);
 strokePaint
.setColor(SK_ColorBLACK);
 strokePaint
.setAntiAlias(true);
 strokePaint
.setStrokeWidth(5);
 
static SkScalar x,y, x2,y2;
 
static double angle = M_PI/6;
 

 
for (int i = 0; i < 10000; i++)
 
{
 x2
+=5;
 y
= 400+sin(angle/2)*300;
 angle
+= M_PI/6;
 y2
= 400+sin(angle/2)*300;
 svgCanvas
->drawLine(x,y,x2,y2,strokePaint);
 x
= x2;
 
}

 svgCanvas->save();






--
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...@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.

kat...@gmail.com

unread,
May 6, 2019, 5:52:57 AM5/6/19
to skia-discuss
Thanks for the reply.

- XML output:
I tried the below code but still cant see a thing...
sk_sp<SkData> data = svgStream.detachAsData();
fwrite
(data->data(), data->size(), 1, stdout);


- PNG output:
Do you want the result of rasterizing SVG (Skia -> SVG -> raster), or the result of rasterizing Skia draw commands (Skia -> raster)?

ideally, the latter one. but it'd be great if i can see both.

there is also a function in skiaserve called Request::writeCanvasToPng but when i pass my canvas to it, i am hitting the assert within it.. 
SkAssertResult(canvas->readPixels(bmp, 0, 0)); 

but let me not confuse you, i still want the PNG in a buffer as I would to embed it in my application which then in turn sends it to a browser. 

To unsubscribe from this group and stop receiving emails from it, send an email to skia-d...@googlegroups.com.

Florin Malita

unread,
May 6, 2019, 10:01:54 AM5/6/19
to skia-d...@googlegroups.com
From: <kat...@gmail.com>
Date: Mon, May 6, 2019 at 5:53 AM
To: skia-discuss

Thanks for the reply.

- XML output:
I tried the below code but still cant see a thing...
sk_sp<SkData> data = svgStream.detachAsData();
fwrite
(data->data(), data->size(), 1, stdout);


Not sure why.  This works as expected for me at HEAD:

    SkDynamicMemoryWStream svgStream;

    SkRect bounds = SkRect::MakeIWH(2000, 2000);
    auto svgCanvas = SkSVGCanvas::Make(bounds, &svgStream);

    SkPaint strokePaint;
    strokePaint.setStyle(SkPaint::kStroke_Style);
    strokePaint.setColor(SK_ColorBLACK);
    strokePaint.setAntiAlias(true);
    strokePaint.setStrokeWidth(5);
    static SkScalar x,y, x2,y2;
    static double angle = M_PI/6;


    for (int i = 0; i < 10000; i++)
    {
     x2+=5;
     y = 400+sin(angle/2)*300;
     angle += M_PI/6;
     y2 = 400+sin(angle/2)*300;
     svgCanvas->drawLine(x,y,x2,y2,strokePaint);
     x = x2;
    }

    svgCanvas = nullptr; // force-flush to stream

    auto data = svgStream.detachAsData();
    fwrite(data->data(), data->size(), 1, stdout);

Output:

<?xml version="1.0" encoding="utf-8" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2000" height="2000">
<path fill="none" stroke="rgb(0,0,0)" stroke-width="5" stroke-miterlimit="4" d="M0 477.646L5 550"/>
<path fill="none" stroke="rgb(0,0,0)" stroke-width="5" stroke-miterlimit="4" d="M5 550L10 612.132"/>
        ...

 
- PNG output:
Do you want the result of rasterizing SVG (Skia -> SVG -> raster), or the result of rasterizing Skia draw commands (Skia -> raster)?

ideally, the latter one. but it'd be great if i can see both.

there is also a function in skiaserve called Request::writeCanvasToPng but when i pass my canvas to it, i am hitting the assert within it.. 
SkAssertResult(canvas->readPixels(bmp, 0, 0));
Right, SkSVGCanvas is not backed by pixels.

You have to explicitly draw the same content to a rasterizing canvas, then grab the result from there.  You can use an SkNWayCanvas to draw to both targets at the same time (untested):

...
auto rasterSurface = SkSurface::MakeRasterN32Premul(bounds.width(), bounds.height());

auto dispatchCanvas = sk_make_sp<SkNWayCanvas>();
dispatchCanvas->addCanvas(rasterSurface->getCanvas());
dispatchCanvas->addCanvas(svgCanvas.get());

// now draw to dispatchCanvas instead of svgCanvas
dispatchCanvas->lineTo(...);
...

// grab the XML output as before
...

// grab the raster result
auto rasterImage = rasterSurface->makeImageSnapshot();
auto pngData = rasterImage->encodeToData();

 
If you want to rasterize the SVG output, you can use SkSVGDOM (under experimental/svg) and render to a raster surface same as above, or an external SVG renderer (since SkSVGDOM only supports a limited set of SVG features).


To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.

Hoss Ajallooiean

unread,
May 8, 2019, 3:56:44 AM5/8/19
to skia-discuss
Many thanks.

I have updated my HEAD and now its working. 
Reply all
Reply to author
Forward
0 new messages