Skip to content

Releases: sammycage/lunasvg

v3.4.0

27 Jul 01:44
Compare
Choose a tag to compare

Generic Fonts, System Fonts, and DOM Hit Testing

This release introduces significant improvements to text rendering and interactivity in LunaSVG. It adds support for CSS generic font families (such as serif, sans-serif, and monospace) and automatic resolution of system-installed fonts, enabling more consistent and portable typography.

Additionally, LunaSVG now includes pointer event hit testing via the new Document::elementFromPoint() API, allowing developers to query which SVG element is located at a specific screen coordinate. These features lay the foundation for building interactive SVG applications with clickable regions, tooltips, and more.

Generic Fonts

LunaSVG now supports CSS generic font families, allowing SVG authors to specify widely recognized font categories such as serif, sans-serif, monospace, cursive, and fantasy. These generic families are automatically resolved to appropriate system-installed fonts at runtime, enabling more portable and visually consistent text rendering across different platforms.

The example below demonstrates how to apply generic fonts using inline styles:

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">
  <style>
    .label {
      font-size: 40px;
      fill: black;
    }
    .serif { font-family: serif; }
    .sans { font-family: sans-serif; }
    .mono { font-family: monospace; }
    .cursive { font-family: cursive; }
    .fantasy { font-family: fantasy; }
  </style>

  <text x="20" y="50" class="label serif">Serif</text>
  <text x="20" y="100" class="label sans">Sans-serif</text>
  <text x="20" y="150" class="label mono">Monospace</text>
  <text x="20" y="200" class="label cursive">Cursive</text>
  <text x="20" y="250" class="label fantasy">Fantasy</text>
</svg>
Browser Rendering LunaSVG Rendering
generic-fonts.svg generic-fonts.svg.png

System Fonts

LunaSVG now supports automatic resolution of system-installed fonts using font family names. This allows SVG content to reference fonts that are already available on the user's system without requiring manual font registration. When multiple font names are provided in the font-family list, LunaSVG will try each in order until a matching font is found, following the standard CSS fallback behavior.

This feature is enabled by default, but it can be turned off at build time if needed. To disable system font loading, define the LUNASVG_DISABLE_LOAD_SYSTEM_FONTS macro when building the library. In CMake-based builds, this can be done by passing -DLUNASVG_DISABLE_LOAD_SYSTEM_FONTS=ON on the command line. In Meson builds, use -Dload-system-fonts=disabled.

The example below demonstrates how to use a prioritized list of common CJK system fonts:

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="150">
  <style>
    text {
      font-family: "Noto Sans CJK SC", "PingFang SC", "SimHei", sans-serif;
      font-size: 24px;
      fill: black;
    }
  </style>

  <!-- Chinese (Simplified) -->
  <text x="20" y="40">你好,世界</text>

  <!-- Japanese -->
  <text x="20" y="80">こんにちは世界</text>

  <!-- Korean -->
  <text x="20" y="120">안녕하세요 세계</text>
</svg>
Browser Rendering LunaSVG Rendering
cjk-fonts.svg cjk-fonts.svg.png

DOM Hit Testing

LunaSVG now supports DOM hit testing through the new Document::elementFromPoint(x, y) API. This function allows applications to determine which SVG element is located at a specific coordinate within the document's viewport.

Hit testing respects the current visual layout of the SVG content, including geometry, transforms, visibility, and the newly supported pointer-events property. The pointer-events attribute controls whether an element can receive pointer input; for example, setting pointer-events="none" excludes an element from hit testing, making it transparent to interaction.

The following example demonstrates how Document::elementFromPoint(x, y) can be used to perform DOM hit testing in LunaSVG. It renders two circles: one with pointer-events="auto" and another with pointer-events="none". Although both are visible, only the green circle is considered interactive. When queried with specific coordinates, the API identifies the green circle as the target element, while the red circle is ignored due to its pointer-events setting. This highlights how LunaSVG integrates pointer event semantics into its hit testing logic.

#include <lunasvg.h>

#include <iostream>
#include <utility>

using namespace lunasvg;

static const char kSVGContent[] = R"SVG(
<svg width="300" height="100" xmlns="http://www.w3.org/2000/svg">
  <!-- This circle will be ignored by hit testing -->
  <circle id="circle-none" cx="75" cy="50" r="40" fill="red" pointer-events="none"/>
  
  <!-- This circle will be detected -->
  <circle id="circle-auto" cx="225" cy="50" r="40" fill="green" pointer-events="auto"/>
</svg>
)SVG";

int main()
{
    auto document = Document::loadFromData(kSVGContent);

    const std::pair<float, float> points[] = {
        {225, 50},  // center of green circle (pointer-events: auto)
        {75, 50},   // center of red circle (pointer-events: none)
    };

    for(const auto& [x, y] : points) {
        if(auto element = document->elementFromPoint(x, y)) {
            std::cout << "Hit element: " << element.getAttribute("id") << "\n";
        } else {
            std::cout << "No element found at (" << x << ", " << y << ")\n";
        }
    }

    return 0;
}

Expected Output:

Hit element: circle-auto
No element found at (75, 50)

v3.3.0

15 May 16:23
Compare
Choose a tag to compare
  • Remove plutovg submodule and embed its source directly into lunasvg (#216)
  • Add CMake option to use system-installed plutovg instead of embedded source @hatch01
  • Clip plutovg rasterizer lines to clip_box using Cyrus-Beck to prevent infinite loops in gray_render_line (#217)
  • Enforce valid (0 < size < 32K) constraint on plutovg surface dimensions (#143, #221, #222)
  • Generate lunasvg.pc from CMake for pkg-config support

v3.2.1

08 Mar 03:59
Compare
Choose a tag to compare

Support for textLength and lengthAdjust Attributes (#215)

This update now lets you control SVG text rendering with the textLength and lengthAdjust attributes. You can set a fixed width for your text and decide whether to tweak only the spacing between characters or to also stretch the glyphs.

https://www.w3.org/Graphics/SVG/Test/20061213/svggen/text-text-01-b.svg

We sincerely thank @terjehelgesen from Software Companions for their generous financial contribution, which helped make this feature possible!

v3.2.0

16 Feb 12:25
Compare
Choose a tag to compare

🚀 New Feature: Document::querySelectorAll()

querySelectorAll() is a powerful way to select multiple elements from a Document using CSS selectors. Unlike getElementById(), which only fetches a single element by its ID, querySelectorAll() allows you to retrieve multiple elements that match the given selector(s).

It works exactly like the JavaScript querySelectorAll() method in the DOM:
👉 MDN Reference

📌 Example Usage

Consider an SVG with multiple <circle> elements:

<svg width="200" height="200">
  <circle cx="50" cy="50" r="40" fill="red" />
  <circle cx="150" cy="50" r="40" fill="blue" />
</svg>

✔️ This selects all <circle> elements and stores them in an ElementList.

ElementList circles = document->querySelectorAll("circle");

Now, let's update all circles to green:

for (Element& circle : circles) {
  circle.setAttribute("fill", "green");
}

All circles turn green! 🎨

v3.1.1

31 Jan 17:04
Compare
Choose a tag to compare
  • Set needsLayout when TextNode is modified
  • Reload image exclusively when href is modified
  • Added back plutovg as a submodule #207
  • Fix undefined behavior caused by a null clip path #209
  • Fix undefined behavior caused by invalid geometry elements with markers
  • Fix viewBox clipping

🎄 LunaSVG v3.1.0

23 Dec 17:03
Compare
Choose a tag to compare

What's New

  • Dynamic Styling with CSS:
    Introduced a new applyStyleSheet method for dynamic styling, making it easier to apply CSS styles to SVG content. See an example here.

  • Automatic Layout Updates:
    The library now detects document modifications and updates the layout automatically when necessary, eliminating the need for manual updateLayout calls.

  • Enhanced Layout Control:
    Added the forceLayout method to trigger immediate layout updates when needed.

  • Improved Text Rendering:
    Support for CSS properties like baseline-shift, alignment-baseline, and dominant-baseline has been added, significantly enhancing text rendering capabilities.

Cheers to creating awesome things with these new features! Happy holidays and happy coding! 🎉

v3.0.1

03 Nov 22:26
Compare
Choose a tag to compare
  • Fix stroke-miterlimit parsing
  • Fix Bitmap::valid checks #190
  • Support font-family names with quotes #186

Happy coding! 🎉

LunaSVG v3.0

12 Oct 09:54
Compare
Choose a tag to compare

It has been over five months since I first announced the development of LunaSVG version 3.0, and today, I am beyond excited to finally share it with you! This journey has been filled with countless learning experiences, and while there’s still more work to be done, the library is now ready for use.

I want to express my deepest gratitude to all the LunaSVG users who took the time to test version 3.0 during its development. Your feedback, suggestions, and bug reports have been invaluable in shaping the final product, and I truly appreciate your efforts.

API Changes

The API for rendering and rasterization—the core of what LunaSVG is most often used for—remains mostly unchanged. However, there have been significant updates to the API for document manipulation. You can find the full API reference in the lunasvg.h header file. I am also planning to release demos and examples soon, so stay tuned for that!

What’s New

A lot of work has gone into improving the core of LunaSVG. Much of the code has been rewritten to enhance quality and introduce exciting new features. I’ve also made it easier for LunaSVG to be integrated into other projects using CMake or Meson. Here’s a summary of what’s new:

  • Support for text and image tags
  • Meson build system support
  • Modernized CMake
  • Transition to C++17
  • Introduction of plutovg as a dependency
  • Improved document manipulation capabilities

Acknowledgments

None of this would have been possible without the incredible support of my donors. Your generosity allows me to dedicate more time to maintaining and improving my open-source projects, and I’m deeply thankful for your trust. I also want to extend a heartfelt thank you to everyone who contributed by submitting pull requests or detailed bug reports. Your help in reproducing and fixing issues made this process much smoother.

Thank you all for being part of this journey. I hope LunaSVG v3.0 serves you well!

v2.4.1

22 Aug 18:01
Compare
Choose a tag to compare

What's Changed

  • Add DomElement::render
  • Update minimum cmake version to 3.5 by @WerWolv in #174

New Contributors

Full Changelog: v2.4.0...v2.4.1

v2.4.0

04 Jul 07:54
Compare
Choose a tag to compare

What's Changed

  • rename inner selector in seletor to subselector by @toge in #147
  • Add SvgBooga to list of projects using LunaSVG by @etodanik in #148
  • Add render child element by @lolpie244 in #162

New Contributors

Full Changelog: v2.3.9...v2.4.0