UseSVGImageDecoder/Encoder

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
acreis
Enthusiast
Enthusiast
Posts: 220
Joined: Fri Jun 01, 2012 12:20 am

Re: UseSVGImageDecoder/Encoder

Post by acreis »

Hi Idle,

2.813 kb
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

That's quite large I'm aiming for under 200kb though that won't happen if I need freetype.
edit
I'm trying to fix the SVGmodule. just need to work out how to transform the X and Y
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

I fixed up the SVGmodule
viewtopic.php?p=645872#p645872
acreis
Enthusiast
Enthusiast
Posts: 220
Joined: Fri Jun 01, 2012 12:20 am

Re: UseSVGImageDecoder/Encoder

Post by acreis »

That's great idle, thank you!

But rendering some files results only black shape o inteded drawing.

Same occurs with nanosvg.

I managed to compile a plutosvg.dll, seems more svgs are rendered right.

Old resvg.dll is very good but have some dependency I don't know so I can't use in another machine.

Thanks a lot, I'll stick to pluto.
punak
Enthusiast
Enthusiast
Posts: 106
Joined: Tue Sep 07, 2021 12:08 pm

Re: UseSVGImageDecoder/Encoder

Post by punak »

I spoke with an AI, and it told me that the most complete and flawless library compatible with PureBasic is Skia, which offers full (100%) support for loading and rendering SVG files.

https://github.com/google/skia

Cpp

Code: Select all

#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkData.h"
#include "include/core/SkStream.h"
#include "include/svg/SkSVGDOM.h"

extern "C" __declspec(dllexport) SkSurface* CreateSurface(int width, int height) {
    SkImageInfo info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    return SkSurface::MakeRaster(info).release();
}

extern "C" __declspec(dllexport) SkSVGDOM* LoadSVG(const char* svgPath) {
    std::ifstream file(svgPath, std::ios::binary);
    if (!file) return nullptr;

    std::string svgData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    auto stream = SkMemoryStream::MakeDirect(svgData.data(), svgData.size());
    return SkSVGDOM::MakeFromStream(*stream).release();
}

extern "C" __declspec(dllexport) void RenderSVG(SkSurface* surface, SkSVGDOM* dom) {
    if (!surface || !dom) return;

    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorWHITE);
    dom->render(canvas);
}

extern "C" __declspec(dllexport) const void* GetPixels(SkSurface* surface) {
    if (!surface) return nullptr;

    SkPixmap pixmap;
    if (surface->peekPixels(&pixmap)) {
        return pixmap.addr();
    }
    return nullptr;
}
Pb

Code: Select all

Import "SkiaWrapper.dll"
  CreateSurface(width.l, height.l)
  LoadSVG(path.p-ascii)
  RenderSVG(surface.l, dom.l)
  GetPixels(surface.l)
EndImport

Procedure DrawSVGOnCanvas(canvasID, svgPath$)
  width = 800
  height = 600

  surface = CreateSurface(width, height)
  dom = LoadSVG(svgPath$)
  RenderSVG(surface, dom)

  pixels = GetPixels(surface)
  If pixels
    If CreateImage(0, width, height, 32)
      StartDrawing(ImageOutput(0))
      CopyMemory(pixels, DrawingBuffer(), width * height * 4)
      StopDrawing()
      If OpenWindow(0, 0, 0, width, height, "SVG Viewer", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
        CanvasGadget(0, 0, 0, width, height)
        Repeat
          Event = WaitWindowEvent()
          If Event = #PB_Event_Gadget And EventGadget() = 0
            StartDrawing(CanvasOutput(0))
            DrawImage(ImageID(0), 0, 0)
            StopDrawing()
          EndIf
        Until Event = #PB_Event_CloseWindow
      EndIf
    EndIf
  EndIf
EndProcedure
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

acreis wrote: Mon Sep 29, 2025 12:58 pm That's great idle, thank you!

But rendering some files results only black shape o inteded drawing.

Same occurs with nanosvg.

I managed to compile a plutosvg.dll, seems more svgs are rendered right.

Old resvg.dll is very good but have some dependency I don't know so I can't use in another machine.

Thanks a lot, I'll stick to pluto.
Can you send me a link for a failed render either here or in private.

I've fixed a number of bugs in the pb module and am slowly transforming it with the intent to add more support and also adapt it to use display lists which will vastly improve rendering performance when it comes to redraw, resizing, animation and effects from timer, hover, clicks and callbacks. Rather than parsing the xml file each time it will foreach the display list which call the vector functions with updated parameters.

Ive looked at sika a while ago, might be good 👍
acreis
Enthusiast
Enthusiast
Posts: 220
Joined: Fri Jun 01, 2012 12:20 am

Re: UseSVGImageDecoder/Encoder

Post by acreis »

Seems great................but where can I find the dll?
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

acreis wrote: Mon Sep 29, 2025 9:40 pm Seems great................but where can I find the dll?
it will all be native just using the pb vector lib. I'm still working through it and addressing the issues then I'll look at display lists
and then I can look at adding animations effects and events.

I looked at adding text support to PlutoSVG but it's also got the same problems as Thorsten's module as in to resize an svg it has to reparse the XML which isn't the best option. It literally tears it down and redoes it when it's not necessary but I guess when your source is from js based stuff what do you expect. There are some things I can condone but Shlemiel the painter’s algorithm isn't one of them.
No. This code uses the Shlemiel the painter’s algorithm. Who is Shlemiel? He’s the guy in this joke:

Shlemiel gets a job as a street painter, painting the dotted lines down the middle of the road. On the first day he takes a can of paint out to the road and finishes 300 yards of the road. “That’s pretty good!” says his boss, “you’re a fast worker!” and pays him a kopeck.

The next day Shlemiel only gets 150 yards done. “Well, that’s not nearly as good as yesterday, but you’re still a fast worker. 150 yards is respectable,” and pays him a kopeck.

The next day Shlemiel paints 30 yards of the road. “Only 30!” shouts his boss. “That’s unacceptable! On the first day you did ten times that much work! What’s going on?”

“I can’t help it,” says Shlemiel. “Every day I get farther and farther away from the paint can!”
https://www.joelonsoftware.com/2001/12/ ... to-basics/

So a cached rendering drawn when no change and a display list when there is a change
punak
Enthusiast
Enthusiast
Posts: 106
Joined: Tue Sep 07, 2021 12:08 pm

Re: UseSVGImageDecoder/Encoder

Post by punak »

❌ SVG Features That Are Difficult or Impossible to Implement with pb.

| SVG Feature | Status in VectorDrawing | Notes |
|-------------------------------------|------------------------------------------|-------|
| Filters (blur, drop shadow, feGaussianBlur) | ❌ Not supported | No API for image filters or effects |
| Animations (<animate>, <animateTransform>) | ❌ Impossible | VectorDrawing is designed for static rendering only |
| Custom or bitmap fonts | ❌ Limited | Only vector fonts are allowed; no font registration |
| Complex masks and clip-paths | ⚠️ Limited | ClipPath exists, but lacks full SVG complexity |
| Shape blending and blend modes | ❌ Not supported | No API for blend modes or compositing |
| DOM or interactivity | ❌ Impossible | PureBasic is not designed for interactive SVG |
| CSS styling within SVG | ❌ Impossible | No CSS parser or styling engine |
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

punak wrote: Tue Sep 30, 2025 2:23 am ❌ SVG Features That Are Difficult or Impossible to Implement with pb.

| SVG Feature | Status in VectorDrawing | Notes |
|-------------------------------------|------------------------------------------|-------|
| Filters (blur, drop shadow, feGaussianBlur) | ❌ Not supported | No API for image filters or effects |
| Animations (<animate>, <animateTransform>) | ❌ Impossible | VectorDrawing is designed for static rendering only |
| Custom or bitmap fonts | ❌ Limited | Only vector fonts are allowed; no font registration |
| Complex masks and clip-paths | ⚠️ Limited | ClipPath exists, but lacks full SVG complexity |
| Shape blending and blend modes | ❌ Not supported | No API for blend modes or compositing |
| DOM or interactivity | ❌ Impossible | PureBasic is not designed for interactive SVG |
| CSS styling within SVG | ❌ Impossible | No CSS parser or styling engine |
The font's will be TTF only
Animation will be fine once switched to using display lists
masks and clipping, don't know yet
It will have a form of DOM
CSS yes
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 396
Joined: Thu Jul 09, 2015 9:07 am

Re: UseSVGImageDecoder/Encoder

Post by pf shadoko »

For bitmap fonts, we can handle that.
Take it from my screen library.
viewtopic.php?t=84206&hilit=shader+sprite

Code: Select all

;============================================================================================ fastfont
Procedure SS_InitFont(num,name.s, height.f,style=0,brush=-1,chars.s="")
  Structure ssc
    sx.l
    sl.l
    cl.l
    co.l
  EndStructure
  
  Structure sscfont
    ns.i
    height.f
    Array c.ssc(255)
  EndStructure
  
  Global ScrennFont.sscfont
  
  Protected i,h,l,c.s,ca,im,bx,by,cx,co,cv,cl:Global nf
  If chars="":For i=32 To 128:chars+Chr(i):Next:EndIf
  
  nf=LoadFont(-1,name,height,style)
  If brush>=0:initIF(brush):bx=ImageWidth(brush):by=ImageHeight((brush)):EndIf
  IM=CreateImage(-1,1,1)
  StartDrawing(ImageOutput(im)):DrawingFont(FontID(nf))
  h=TextHeight(" ")+by
  l=TextWidth(chars)*1.3+Len(chars)*bx:cx=0
  StopDrawing()
  FreeImage(im)
  
  IM=CreateImage(-1,l,h,32,#PB_Image_Transparent):StartDrawing(ImageOutput(im)):DrawingMode(#PB_2DDrawing_AllChannels):Box(0,0,l,h,$00ffffff):StopDrawing()
  StartVectorDrawing(ImageVectorOutput(im)):VectorFont(FontID(nf))
  For i=1 To Len(chars)
    c=Mid(chars,i,1):ca=Asc(c)
    With ScrennFont\c(ca)
      co=VectorTextWidth(c,#PB_VectorText_Visible|#PB_VectorText_Offset):If ca=126:co=0:EndIf
      cv=VectorTextWidth(c,#PB_VectorText_Visible)
      cl=VectorTextWidth(c)
      \sx=cx
      \sl=cv+bx+2
      \cl=cl+bx/2
      \co=co
      ;AddPathBox(\sx,0,\sl,h):VectorSourceColor($8800ff00):FillPath()
      MovePathCursor(cx-co+1,0)
      VectorSourceColor($ffffffff):DrawVectorText(c)
      cx+\sl+1
    EndWith
  Next
  StopVectorDrawing()
  
  ScrennFont\ns=SS_CreateSprite(-1,#SHoverlay,im)
  ScrennFont\height=h
EndProcedure

Procedure SS_DrawText(x,y,t.s,size=-1,color=$ffffffff)
  Protected i,ca,cx,c.ssc,zoom.f
  With ScrennFont
    If size=-1:size=\height:EndIf
    zoom=size/\height
    For i=1 To Len(t)
      c=\c(Asc(Mid(t,i,1)))
      SS_ClipSprite(\ns,c\sx,0,c\sl,\height)
      SS_ZoomSprite(\ns,c\sl*zoom,\height*zoom,#SS_unit_Pixel)
      SS_DisplaySprite(\ns,x+c\co*zoom,y,255,color)
      x+c\cl*zoom
    Next
  EndWith
EndProcedure
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

pf shadoko wrote: Tue Sep 30, 2025 6:46 am For bitmap fonts, we can handle that.
Take it from my screen library.
viewtopic.php?t=84206&hilit=shader+sprite

Code: Select all

;============================================================================================ fastfont
Procedure SS_InitFont(num,name.s, height.f,style=0,brush=-1,chars.s="")
  Structure ssc
    sx.l
    sl.l
    cl.l
    co.l
  EndStructure
  
  Structure sscfont
    ns.i
    height.f
    Array c.ssc(255)
  EndStructure
  
  Global ScrennFont.sscfont
  
  Protected i,h,l,c.s,ca,im,bx,by,cx,co,cv,cl:Global nf
  If chars="":For i=32 To 128:chars+Chr(i):Next:EndIf
  
  nf=LoadFont(-1,name,height,style)
  If brush>=0:initIF(brush):bx=ImageWidth(brush):by=ImageHeight((brush)):EndIf
  IM=CreateImage(-1,1,1)
  StartDrawing(ImageOutput(im)):DrawingFont(FontID(nf))
  h=TextHeight(" ")+by
  l=TextWidth(chars)*1.3+Len(chars)*bx:cx=0
  StopDrawing()
  FreeImage(im)
  
  IM=CreateImage(-1,l,h,32,#PB_Image_Transparent):StartDrawing(ImageOutput(im)):DrawingMode(#PB_2DDrawing_AllChannels):Box(0,0,l,h,$00ffffff):StopDrawing()
  StartVectorDrawing(ImageVectorOutput(im)):VectorFont(FontID(nf))
  For i=1 To Len(chars)
    c=Mid(chars,i,1):ca=Asc(c)
    With ScrennFont\c(ca)
      co=VectorTextWidth(c,#PB_VectorText_Visible|#PB_VectorText_Offset):If ca=126:co=0:EndIf
      cv=VectorTextWidth(c,#PB_VectorText_Visible)
      cl=VectorTextWidth(c)
      \sx=cx
      \sl=cv+bx+2
      \cl=cl+bx/2
      \co=co
      ;AddPathBox(\sx,0,\sl,h):VectorSourceColor($8800ff00):FillPath()
      MovePathCursor(cx-co+1,0)
      VectorSourceColor($ffffffff):DrawVectorText(c)
      cx+\sl+1
    EndWith
  Next
  StopVectorDrawing()
  
  ScrennFont\ns=SS_CreateSprite(-1,#SHoverlay,im)
  ScrennFont\height=h
EndProcedure

Procedure SS_DrawText(x,y,t.s,size=-1,color=$ffffffff)
  Protected i,ca,cx,c.ssc,zoom.f
  With ScrennFont
    If size=-1:size=\height:EndIf
    zoom=size/\height
    For i=1 To Len(t)
      c=\c(Asc(Mid(t,i,1)))
      SS_ClipSprite(\ns,c\sx,0,c\sl,\height)
      SS_ZoomSprite(\ns,c\sl*zoom,\height*zoom,#SS_unit_Pixel)
      SS_DisplaySprite(\ns,x+c\co*zoom,y,255,color)
      x+c\cl*zoom
    Next
  EndWith
EndProcedure
Thanks. I will try adding that.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 396
Joined: Thu Jul 09, 2015 9:07 am

Re: UseSVGImageDecoder/Encoder

Post by pf shadoko »

wait a moment, this not work on vectordrawing
i will adapt this
User avatar
idle
Always Here
Always Here
Posts: 5964
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: UseSVGImageDecoder/Encoder

Post by idle »

pf shadoko wrote: Tue Sep 30, 2025 8:53 am wait a moment, this not work on vectordrawing
i will adapt this
no rush there's a lot for me to to do in the mean time but yes please if you can adapt it.
acreis
Enthusiast
Enthusiast
Posts: 220
Joined: Fri Jun 01, 2012 12:20 am

Re: UseSVGImageDecoder/Encoder

Post by acreis »

Hi idle,

I made a mistake, plutosvg and nanosvg was rendering some svg as a black shadow only. UseSvgImage is fine. Great to be true, I'm sticking to it to render toolbar and menu icons.
Post Reply