소스 검색

Added support for scaling images into a pixmap of a specified size.

Brucey 11 달 전
부모
커밋
c0dee32279
5개의 변경된 파일153개의 추가작업 그리고 12개의 파일을 삭제
  1. 1 1
      svg.mod/common.bmx
  2. 45 0
      svg.mod/examples/example_02.bmx
  3. 17 0
      svg.mod/examples/planet.svg
  4. 1 1
      svg.mod/glue.c
  5. 89 10
      svg.mod/svg.bmx

+ 1 - 1
svg.mod/common.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2022-2023 Bruce A Henderson
+' Copyright (c) 2022-2024 Bruce A Henderson
 ' 
 ' This software is provided 'as-is', without any express or implied
 ' warranty. In no event will the authors be held liable for any damages

+ 45 - 0
svg.mod/examples/example_02.bmx

@@ -0,0 +1,45 @@
+SuperStrict
+
+Framework SDL.SDLRenderMax2D
+Import Image.SVG
+
+Local w:Int = DesktopWidth() * .75
+Local h:Int = DeskTopHeight() * .75
+
+Graphics w, h, 0
+
+AutoMidHandle(True)
+
+Local svg:TSvgImage = TSvgImage.LoadImage("planet.svg")
+
+Local pix:TPixmap = svg.FitPixmap(DesktopWidth(), DesktopHeight())
+
+Local img:TImage = LoadImage(pix)
+
+
+If Not img Then
+	Throw "Failed to load image"
+End If
+
+Local image:Int
+
+Local scale:Float = 0.5
+
+While Not KeyDown(Key_ESCAPE)
+
+	Cls
+
+	If KeyDown(Key_UP) Then
+		scale = Min(1, scale + 0.01)
+	End If
+
+	If KeyDown(Key_DOWN) Then
+		scale = Max(0.1, scale - 0.01)
+	End If
+
+	SetScale scale, scale
+	DrawImage img, w / 2, h / 2
+
+	Flip
+
+Wend

+ 17 - 0
svg.mod/examples/planet.svg

@@ -0,0 +1,17 @@
+<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
+  <!-- Background -->
+  <rect width="100%" height="100%" fill="black"/>
+  
+  <!-- Saturn's Rings -->
+  <ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="lightgrey" stroke-width="15"/>
+  <ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="darkgrey" stroke-width="5"/>
+  
+  <!-- Saturn's Body -->
+  <circle cx="100" cy="100" r="50" fill="gold" />
+
+  <!-- Ring Highlight (to give depth) -->
+  <ellipse cx="100" cy="100" rx="80" ry="30" fill="none" stroke="white" stroke-width="2" opacity="0.5"/>
+
+  <!-- Saturn's Shadow on Rings -->
+  <ellipse cx="100" cy="120" rx="60" ry="20" fill="black" opacity="0.2"/>
+</svg>

+ 1 - 1
svg.mod/glue.c

@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2022-2023 Bruce A Henderson
+  Copyright (c) 2022-2024 Bruce A Henderson
   
   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any damages

+ 89 - 10
svg.mod/svg.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2022-2023 Bruce A Henderson
+' Copyright (c) 2022-2024 Bruce A Henderson
 ' 
 ' This software is provided 'as-is', without any express or implied
 ' warranty. In no event will the authors be held liable for any damages
@@ -25,11 +25,13 @@ The SVG loader module provides the ability to load SVG format #pixmaps.
 End Rem
 Module Image.SVG
 
-ModuleInfo "Version: 1.01"
+ModuleInfo "Version: 1.02"
 ModuleInfo "Author: 2013-14 Mikko Mononen"
 ModuleInfo "License: ZLib/PNG License"
 ModuleInfo "Credit: Adapted for BlitzMax by Bruce A Henderson"
 
+ModuleInfo "History: 1.02"
+ModuleInfo "History: Added support for scaling images into a pixmap of a specified size."
 ModuleInfo "History: 1.01"
 ModuleInfo "History: Update to nanosvg 706eb06"
 ModuleInfo "History: 1.00"
@@ -39,6 +41,9 @@ Import BRL.Pixmap
 
 Import "common.bmx"
 
+Rem
+bbdoc: An SVG image.
+End Rem
 Type TSvgImage
 
 	Field svgImage:SNSVGimage Ptr
@@ -54,9 +59,6 @@ Type TSvgImage
 		Free()
 	End Method
 
-	Rem
-	bbdoc: 
-	End Rem
 	Method Load:TPixmap(stream:TStream, units:String, dpi:Float)
 		Local data:Byte[] = LoadByteArray( stream )
 		Local u:Byte Ptr = units.ToCString()
@@ -67,15 +69,92 @@ Type TSvgImage
 			Return Null
 		End If
 
-		Local pix:TPixmap = CreatePixmap( Int(svgImage.width), Int(svgImage.height), PF_RGBA8888, 4 )
+		Return GetPixmap(Int(svgImage.width), Int(svgImage.height))
+	End Method
 
-		Local raster:Byte Ptr = nsvgCreateRasterizer()
+	Rem
+	bbdoc: Loads the SVG image from the specified object.
+	about: The units and DPI are used to determine the size of the image.
+	End Rem
+	Function LoadImage:TSvgImage(obj:Object, units:String = "px", dpi:Float = 96)
+		Local image:TSvgImage = New TSvgImage()
 
-		nsvgRasterize(raster, svgImage, 0, 0, 1, pix.pixels, pix.width, pix.height, pix.pitch);
+		Local data:Byte[] = LoadByteArray( obj )
+		Local u:Byte Ptr = units.ToCString()
+		image.svgImage = nsvgParse(data, u, dpi)
+		MemFree(u)
 
-		nsvgDeleteRasterizer(raster)
+		Return image
+	End Function
 
-		Return pix
+	Rem
+	bbdoc: Returns the dimensions of the SVG image.
+	about: The width and height are in the units specified when the SVG image was loaded.
+	End Rem
+	Method Dimensions(width:Float Var, height:Float Var)
+		If svgImage Then
+			width = svgImage.width
+			height = svgImage.height
+		End If
+	End Method
+
+	Rem
+	bbdoc: Returns the width of the SVG image.
+	about: The width is in the units specified when the SVG image was loaded.
+	End Rem
+	Method Width:Float()
+		If svgImage Then
+			Return svgImage.width
+		End If
+		Return 0
+	End Method
+
+	Rem
+	bbdoc: Returns the height of the SVG image.
+	about: The height is in the units specified when the SVG image was loaded.
+	End Rem
+	Method Height:Float()
+		If svgImage Then
+			Return svgImage.height
+		End If
+		Return 0
+	End Method
+
+	Rem
+	bbdoc: Gets a rasterized representation of the SVG image of the specified size and scale.
+	about: A scale of 1 will render the image at the original size - which can be determined by calling the #Width, #Height or #Dimensions methods.
+	End Rem
+	Method GetPixmap:TPixmap(width:Int, height:Int, scale:Float = 1.0)
+		If svgImage Then
+			Local pix:TPixmap = CreatePixmap( width, height, PF_RGBA8888, 4 )
+
+			Local raster:Byte Ptr = nsvgCreateRasterizer()
+
+			nsvgRasterize(raster, svgImage, 0, 0, scale, pix.pixels, pix.width, pix.height, pix.pitch);
+
+			nsvgDeleteRasterizer(raster)
+
+			Return pix
+		End If
+	End Method
+
+	Rem
+	bbdoc: Gets a rasterized representation of the SVG image that fits within the specified maximum width and height.
+	about: The aspect ratio of the image is maintained.
+	If the height is not specified, it will be the same as the width.
+	End Rem
+	Method FitPixmap:TPixmap(maxWidth:Int, maxHeight:Int = 0)
+		Local width:Float
+		Local height:Float
+		Dimensions(width, height)
+
+		If maxHeight = 0 Then
+			maxHeight = maxWidth
+		End If
+
+		Local ratio:Float = Min(maxWidth / width, maxHeight / height)
+
+		Return GetPixmap(Int(width * ratio), Int(height * ratio), ratio)
 	End Method
 
 End Type