Skip to content

Commit 36aa245

Browse files
committed
Update to latest resvg (0.34.1)
PhotoDemon uses the resvg library for SVG import. This update brings many compatibility, memory usage, and performance improvements over the previously supported version (0.28). Note that this update includes major API changes, including a switch from doubles to floats for internal geometry (and wrapping APIs).
1 parent c5056c8 commit 36aa245

File tree

4 files changed

+75
-77
lines changed

4 files changed

+75
-77
lines changed

App/PhotoDemon/Plugins/resvg.dll

88.5 KB
Binary file not shown.

Modules/Plugin_Management.bas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Private Const EXPECTED_LIBJXL_VERSION As String = "0.7.0"
6969
Private Const EXPECTED_LITTLECMS_VERSION As String = "2.13.1"
7070
Private Const EXPECTED_LZ4_VERSION As String = "10904"
7171
Private Const EXPECTED_PSPI_VERSION As String = "0.9"
72-
Private Const EXPECTED_RESVG_VERSION As String = "0.28"
72+
Private Const EXPECTED_RESVG_VERSION As String = "0.34"
7373
Private Const EXPECTED_WEBP_VERSION As String = "1.2.4"
7474
Private Const EXPECTED_ZSTD_VERSION As String = "10502"
7575

Modules/Plugin_resvg.bas

Lines changed: 73 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ Attribute VB_Name = "Plugin_resvg"
33
'resvg Library Interface (SVG import)
44
'Copyright 2022-2023 by Tanner Helland
55
'Created: 28/February/22
6-
'Last updated: 15/October/22
7-
'Last update: fix load behavior during batch processing
6+
'Last updated: 16/June/23
7+
'Last update: rewrite against latest resvg (0.34.1)
88
'
99
'Per its documentation (available at https://github.com/RazrFalcon/resvg), resvg is...
1010
'
@@ -30,7 +30,7 @@ Attribute VB_Name = "Plugin_resvg"
3030
Option Explicit
3131

3232
'Information on individual resvg calls can be saved to the debug log via this constant;
33-
' please DISABLE in production builds
33+
' please DISABLE in production builds (as reporting is quite noisy!)
3434
Private Const SVG_DEBUG_VERBOSE As Boolean = False
3535

3636
Private Enum resvg_result
@@ -56,23 +56,6 @@ End Enum
5656
Private Const RESVG_OK = 0, RESVG_ERROR_NOT_AN_UTF8_STR = 1, RESVG_ERROR_FILE_OPEN_FAILED = 2, RESVG_ERROR_MALFORMED_GZIP = 3, RESVG_ERROR_ELEMENTS_LIMIT_REACHED = 4, RESVG_ERROR_INVALID_SIZE = 5, RESVG_ERROR_PARSING_FAILED = 6
5757
#End If
5858

59-
'A "fit to" type.
60-
' (All types produce proportional scaling.)
61-
Private Enum resvg_fit_to_type
62-
'Use an original image size.
63-
RESVG_FIT_TO_TYPE_ORIGINAL
64-
'Fit an image to a specified width.
65-
RESVG_FIT_TO_TYPE_WIDTH
66-
'Fit an image to a specified height.
67-
RESVG_FIT_TO_TYPE_HEIGHT
68-
'Zoom an image using scaling factor.
69-
RESVG_FIT_TO_TYPE_ZOOM
70-
End Enum
71-
72-
#If False Then
73-
Private Const RESVG_FIT_TO_TYPE_ORIGINAL = 0, RESVG_FIT_TO_TYPE_WIDTH = 0, RESVG_FIT_TO_TYPE_HEIGHT = 0, RESVG_FIT_TO_TYPE_ZOOM = 0
74-
#End If
75-
7659
'An image rendering method.
7760
Private Enum resvg_image_rendering
7861
RESVG_IMAGE_RENDERING_OPTIMIZE_QUALITY
@@ -107,48 +90,28 @@ End Enum
10790

10891
'A 2D transform representation.
10992
Private Type resvg_transform
110-
a As Double
111-
b As Double
112-
c As Double
113-
d As Double
114-
e As Double
115-
f As Double
93+
a As Single
94+
b As Single
95+
c As Single
96+
d As Single
97+
e As Single
98+
f As Single
11699
End Type
117100

118101
'A size representation.
119102
' (Width and height are guaranteed to be > 0.)
120103
Private Type resvg_size
121-
svg_width As Double
122-
svg_height As Double
104+
svg_width As Single
105+
svg_height As Single
123106
End Type
124107

125108
'A rectangle representation.
126109
' (Width *and* height are guarantee to be > 0.)
127110
Private Type resvg_rect
128-
x As Double
129-
y As Double
130-
Width As Double
131-
Height As Double
132-
End Type
133-
134-
'A path bbox representation.
135-
' (Width *or* height are guarantee to be > 0.)
136-
Private Type resvg_path_bbox
137-
x As Double
138-
y As Double
139-
Width As Double
140-
Height As Double
141-
End Type
142-
143-
'A "fit to" property.
144-
Private Type resvg_fit_to
145-
'A fit type.
146-
fit_type As resvg_fit_to_type
147-
'Fit to value
148-
'* Not used by RESVG_FIT_TO_ORIGINAL.
149-
'* Must be >= 1 for RESVG_FIT_TO_WIDTH and RESVG_FIT_TO_HEIGHT.
150-
'* Must be > 0 for RESVG_FIT_TO_ZOOM.
151-
fit_value As Single
111+
x As Single
112+
y As Single
113+
Width As Single
114+
Height As Single
152115
End Type
153116

154117
Private Declare Function resvg_transform_identity Lib "resvg" () As resvg_transform
@@ -177,15 +140,15 @@ Private Declare Function resvg_parse_tree_from_data Lib "resvg" (ByVal ptrToData
177140
Private Declare Function resvg_is_image_empty Lib "resvg" (ByVal resvg_render_tree As Long) As Long
178141
Private Declare Function resvg_get_image_size Lib "resvg" (ByVal resvg_render_tree As Long) As resvg_size
179142
Private Declare Function resvg_get_image_viewbox Lib "resvg" (ByVal resvg_render_tree As Long) As resvg_rect
180-
Private Declare Function resvg_get_imgae_bbox Lib "resvg" (ByVal resvg_render_tree As Long, ByRef dst_resvg_rect As resvg_rect) As Long
143+
Private Declare Function resvg_get_image_bbox Lib "resvg" (ByVal resvg_render_tree As Long, ByRef dst_resvg_rect As resvg_rect) As Long
181144
Private Declare Function resvg_node_exists Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long) As Long
182145
Private Declare Function resvg_get_node_transform Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long, ByRef dst_resvg_transform As resvg_transform) As Long
183-
Private Declare Function resvg_get_node_bbox Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long, ByRef dst_resvg_path_bbox As resvg_path_bbox) As Long
146+
Private Declare Function resvg_get_node_bbox Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long, ByRef dst_resvg_path_bbox As resvg_rect) As Long
184147
Private Declare Sub resvg_tree_destroy Lib "resvg" (ByVal resvg_render_tree As Long)
185-
Private Declare Sub resvg_render Lib "resvg" (ByVal resvg_render_tree As Long, ByRef fit_to As resvg_fit_to, ByRef srcTransform As resvg_transform, ByVal surfaceWidth As Long, ByVal surfaceHeight As Long, ByVal ptrToSurface As Long)
148+
Private Declare Sub resvg_render Lib "resvg" (ByVal resvg_render_tree As Long, ByRef srcTransform As resvg_transform, ByVal surfaceWidth As Long, ByVal surfaceHeight As Long, ByVal ptrToSurface As Long)
186149

187150
'Note: node rendering needs custom resvg modifications to change the way fit_to is passed
188-
'Private Declare Sub resvg_render_node Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long, ByVal fit_to As resvg_fit_to, ByVal srcTransform As resvg_transform, ByVal surfaceWidth As Long, ByVal surfaceHeight As Long, ByVal ptrToSurface As Long)
151+
'Private Declare Sub resvg_render_node Lib "resvg" (ByVal resvg_render_tree As Long, ByVal ptrToConstUtf8ID As Long, ByVal srcTransform As resvg_transform, ByVal surfaceWidth As Long, ByVal surfaceHeight As Long, ByVal ptrToSurface As Long)
189152

190153
'A single persistent SVG options handle is maintained for the life of a session.
191154
' (Initializing this object is expensive because it needs to scan system fonts.)
@@ -208,7 +171,7 @@ Public Function GetVersion() As String
208171
'resvg does not provide an externally accessible version string by default.
209172
' I do not expect users to custom-build it, so we return a hard-coded version
210173
' against the copy supplied with a default PD install.
211-
GetVersion = "0.28.0"
174+
GetVersion = "0.34.1"
212175

213176
End Function
214177

@@ -420,11 +383,6 @@ Public Function LoadSVG_FromFile(ByRef srcFile As String, ByRef dstImage As pdIm
420383
'SVG renders will always be premultiplied
421384
dstDIB.SetInitialAlphaPremultiplicationState True
422385

423-
'Specify fitting behavior (we always use original fit - you'll see why in a moment)
424-
Dim fitBehavior As resvg_fit_to
425-
fitBehavior.fit_type = RESVG_FIT_TO_TYPE_ORIGINAL
426-
fitBehavior.fit_value = 1!
427-
428386
'If custom destination width/height is specified, we want to use the final transform matrix
429387
' to apply the resize.
430388
Dim idMatrix As resvg_transform
@@ -439,10 +397,10 @@ Public Function LoadSVG_FromFile(ByRef srcFile As String, ByRef dstImage As pdIm
439397
Set cMatrix = New pd2DTransform
440398
cMatrix.ApplyScaling userWidth / intWidth, userHeight / intHeight
441399

400+
'Pull the class into a bare list of floats, then relay those floats to a resvg matrix struct
442401
Dim tmpFloats() As Single
443402
If cMatrix.GetMatrixPoints(tmpFloats) Then
444403

445-
'resvg uses doubles, not floats
446404
With idMatrix
447405
.a = tmpFloats(0)
448406
.b = tmpFloats(1)
@@ -451,14 +409,15 @@ Public Function LoadSVG_FromFile(ByRef srcFile As String, ByRef dstImage As pdIm
451409
.e = tmpFloats(4)
452410
.f = tmpFloats(5)
453411
End With
454-
455-
'no Else required, since we've already initialized the matrix to its identity form
412+
413+
Else
414+
InternalError "Bad matrix retrieval in LoadSVG_FromFile"
456415
End If
457416

458417
End If
459418

460419
'Render!
461-
resvg_render svgTree, fitBehavior, idMatrix, userWidth, userHeight, dstDIB.GetDIBPointer()
420+
resvg_render svgTree, idMatrix, userWidth, userHeight, dstDIB.GetDIBPointer()
462421
PDDebug.LogAction "Finished render"
463422

464423
'Finally, we need to swizzle RGBA order to BGRA order
@@ -498,21 +457,29 @@ End Sub
498457

499458
'Do not call this function. It is only designed to be used for previews on the SVG import screen.
500459
Public Function RenderToArbitraryDIB(ByVal hResvgTree As Long, ByRef dstDIB As pdDIB) As Boolean
501-
502-
'Specify fitting behavior
503-
Dim fitBehavior As resvg_fit_to
504-
fitBehavior.fit_type = RESVG_FIT_TO_TYPE_ORIGINAL
505-
fitBehavior.fit_value = 1!
506-
460+
461+
If SVG_DEBUG_VERBOSE Then PDDebug.LogAction "Preparing to render tree #" & CStr(hResvgTree) & " to DIB..."
462+
507463
'If custom destination width/height is specified, we want to use the final transform matrix
508464
' to apply the resize.
509465
Dim idMatrix As resvg_transform
510466
idMatrix = resvg_transform_identity()
511467

468+
If SVG_DEBUG_VERBOSE Then
469+
PDDebug.LogAction "Retrieved identity matrix OK"
470+
With idMatrix
471+
PDDebug.LogAction .a & ", " & .b & ", " & .c
472+
PDDebug.LogAction .d & ", " & .e & ", " & .f
473+
End With
474+
End If
475+
512476
'Scale to fit the destination DIB (if its size doesn't match the original width/height)
513477
Dim imgSize As resvg_size
514478
imgSize = resvg_get_image_size(hResvgTree)
515479

480+
If SVG_DEBUG_VERBOSE Then PDDebug.LogAction "Retrieved size is " & CStr(imgSize.svg_width) & " x " & CStr(imgSize.svg_height)
481+
482+
'Calculate integer dimensions prior to positioning
516483
Dim intWidth As Long, intHeight As Long
517484
intWidth = Int(imgSize.svg_width)
518485
intHeight = Int(imgSize.svg_height)
@@ -523,12 +490,43 @@ Public Function RenderToArbitraryDIB(ByVal hResvgTree As Long, ByRef dstDIB As p
523490
' for previews on the import screen - so its guaranteed that the passed DIB will always
524491
' be the same aspect ratio as the source SVG.
525492
If (dstDIB.GetDIBWidth <> intWidth) Or (dstDIB.GetDIBHeight <> intHeight) Then
526-
fitBehavior.fit_type = RESVG_FIT_TO_TYPE_ZOOM
527-
fitBehavior.fit_value = dstDIB.GetDIBWidth / intWidth
493+
494+
'Here's a nice twist - let's make our code more readable by using a pd2D class to
495+
' produce the scale transform for us! (Ideally, we could also use this to apply
496+
' skew and rotate in the future.)
497+
Dim cMatrix As pd2DTransform
498+
Set cMatrix = New pd2DTransform
499+
cMatrix.ApplyScaling dstDIB.GetDIBWidth / intWidth, dstDIB.GetDIBHeight / intHeight
500+
501+
Dim tmpFloats() As Single
502+
If cMatrix.GetMatrixPoints(tmpFloats) Then
503+
With idMatrix
504+
.a = tmpFloats(0)
505+
.b = tmpFloats(1)
506+
.c = tmpFloats(2)
507+
.d = tmpFloats(3)
508+
.e = tmpFloats(4)
509+
.f = tmpFloats(5)
510+
End With
511+
Else
512+
InternalError "Bad matrix retrieval in RenderToArbitraryDIB"
513+
End If
514+
515+
If SVG_DEBUG_VERBOSE Then
516+
PDDebug.LogAction "Scaling matrix will be applied: "
517+
With idMatrix
518+
PDDebug.LogAction .a & ", " & .b & ", " & .c
519+
PDDebug.LogAction .d & ", " & .e & ", " & .f
520+
End With
521+
End If
522+
528523
End If
529524

530525
'Render and swizzle
531-
resvg_render hResvgTree, fitBehavior, idMatrix, dstDIB.GetDIBWidth, dstDIB.GetDIBHeight, dstDIB.GetDIBPointer()
526+
If SVG_DEBUG_VERBOSE Then PDDebug.LogAction "Attempting render to DIB with size " & dstDIB.GetDIBWidth & " x " & dstDIB.GetDIBHeight
527+
resvg_render hResvgTree, idMatrix, dstDIB.GetDIBWidth, dstDIB.GetDIBHeight, dstDIB.GetDIBPointer()
528+
529+
If SVG_DEBUG_VERBOSE Then PDDebug.LogAction "Render successful. Swizzling channels before exiting..."
532530
DIBs.SwizzleBR dstDIB
533531

534532
End Function

PhotoDemon.vbp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ Description="PhotoDemon Photo Editor"
518518
CompatibleMode="0"
519519
MajorVer=9
520520
MinorVer=1
521-
RevisionVer=147
521+
RevisionVer=152
522522
AutoIncrementVer=1
523523
ServerSupportFiles=0
524524
VersionComments="Copyright 2000-2023 Tanner Helland - photodemon.org"

0 commit comments

Comments
 (0)