├── .gitignore ├── .gitmodules ├── Modules └── Resvg4JUCE │ ├── Resvg4JUCE.cpp │ ├── Resvg4JUCE.h │ ├── Components │ ├── jb_SVGButton.h │ └── jb_SVGComponent.h │ └── RenderTree │ ├── jb_ResvgRenderTree.h │ └── jb_ResvgRenderTree.cpp ├── Examples └── ViewSVG │ ├── Source │ ├── MainComponent.h │ ├── MainComponent.cpp │ └── Main.cpp │ └── CMakeLists.txt ├── README.md ├── CMakeLists.txt └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | Examples/ViewSVG/Builds/ 3 | 4 | Examples/ViewSVG/JuceLibraryCode/ 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Ext/resvg"] 2 | path = Ext/resvg 3 | url = https://github.com/linebender/resvg.git 4 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/Resvg4JUCE.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | #include "RenderTree/jb_ResvgRenderTree.cpp" 11 | -------------------------------------------------------------------------------- /Examples/ViewSVG/Source/MainComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | //============================================================================== 6 | /* 7 | This component lives inside our window, and this is where you should put all 8 | your controls and content. 9 | */ 10 | class MainComponent : public juce::Component, public juce::FileDragAndDropTarget 11 | { 12 | public: 13 | //============================================================================== 14 | MainComponent(); 15 | ~MainComponent() override; 16 | 17 | //============================================================================== 18 | void paint (juce::Graphics&) override; 19 | void resized() override; 20 | 21 | //============================================================================== 22 | bool isInterestedInFileDrag (const juce::StringArray& files) override; 23 | void filesDropped (const juce::StringArray& files, int, int) override; 24 | 25 | 26 | private: 27 | //============================================================================== 28 | // Your private member variables go here... 29 | 30 | std::unique_ptr svg; 31 | 32 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent) 33 | }; 34 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/Resvg4JUCE.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | /******************************************************************************* 11 | The block below describes the properties of this module, and is read by 12 | the Projucer to automatically generate project code that uses it. 13 | For details about the syntax and how to create or use a module, see the 14 | JUCE Module Format.txt file. 15 | 16 | 17 | BEGIN_JUCE_MODULE_DECLARATION 18 | 19 | ID: Resvg4JUCE 20 | vendor: Janos Buttgereit 21 | version: 1.0.0 22 | name: Resvg4JUCE 23 | description: JUCE wrapper for the resvg SVG rendering library 24 | website: www.github.com/janosgit 25 | license: MPL v2 26 | 27 | dependencies: juce_gui_basics 28 | 29 | windowsLibs: userenv 30 | 31 | END_JUCE_MODULE_DECLARATION 32 | 33 | *******************************************************************************/ 34 | 35 | #pragma once 36 | 37 | #include "RenderTree/jb_ResvgRenderTree.h" 38 | #include "Components/jb_SVGComponent.h" 39 | #include "Components/jb_SVGButton.h" 40 | -------------------------------------------------------------------------------- /Examples/ViewSVG/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ==================================================================== 2 | # 3 | # This file is part of Resvg4JUCE. 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | # 9 | # ==================================================================== 10 | 11 | cmake_minimum_required (VERSION 3.16) 12 | 13 | project (ViewSVG VERSION 0.2.0) 14 | 15 | find_package (JUCE CONFIG REQUIRED) 16 | 17 | juce_add_gui_app (ViewSVG PRODUCT_NAME "View SVG") 18 | 19 | target_sources (ViewSVG PRIVATE 20 | Source/Main.cpp 21 | Source/MainComponent.cpp) 22 | 23 | target_compile_definitions(ViewSVG PRIVATE 24 | JUCE_WEB_BROWSER=0 25 | JUCE_USE_CURL=0 26 | JUCE_APPLICATION_NAME_STRING="$" 27 | JUCE_APPLICATION_VERSION_STRING="$") 28 | 29 | # Simply add Resvg4JUCE as subdirectory and link your target to it 30 | add_subdirectory (../../Modules/Resvg4JUCE) 31 | target_link_libraries (ViewSVG 32 | PRIVATE 33 | juce::juce_gui_extra 34 | jb::Resvg4JUCE 35 | 36 | PUBLIC 37 | juce::juce_recommended_config_flags 38 | juce::juce_recommended_lto_flags 39 | juce::juce_recommended_warning_flags) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Resvg4JUCE 2 | A JUCE module that wraps the resvg SVG rendering library in a JUCE compatible interface. The project is currently based on resvg 0.19.0. 3 | 4 | This is an attempt to use resvg to overcome problems with the JUCE integrated SVG rendering facility. It comes with two important classes: 5 | `jb::Resvg::RenderTree`, which encapsulates a subset of the original resvg interface in a convenient C++ class. It allows rendering SVG files to a `juce::Image`. `jb::SVGComponent` is a `juce::Component` that owns a render tree and automatically displays the rendered image on the components surface. 6 | 7 | While being built for JUCE, this module is not desgined to work with the Projucer but only with the newer CMake based build of JUCE. Usage is pretty simple: 8 | 9 | ``` 10 | # Add JUCE in one of the recomended ways before this line 11 | 12 | # Make your projects CMakeList.txt find Resvg4JUCE 13 | add_subdirectory (Path/To/Resvg4JUCE) 14 | 15 | # Create a plugin or standalone juce target 16 | juce_add_xy (Foo ...) 17 | 18 | # Link Resvg4JUCE to that target 19 | target_link_libraries (Foo jb::Resvg4JUCE) 20 | ``` 21 | 22 | As resvg is a rust library, your build machine needs all the rust build tools. The rust sources of the library will be compiled into a static library that will be linked to your target. 23 | 24 | Note for Windows: Rust libraries are always compiled against the dynamic linked Visual C++ runtime. Please make sure that you'll link your whole project against the dynamic runtime and not the static one, other combinations are likely to fail with compiling at all. 25 | 26 | Note for macOS: The library is built as universal binary for x86_64 and arm64. To compile for arm64 Xcode 12.2 or later is required. The mininum deployment target is set to macOS 10.7 27 | -------------------------------------------------------------------------------- /Examples/ViewSVG/Source/MainComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "MainComponent.h" 2 | 3 | //============================================================================== 4 | MainComponent::MainComponent() 5 | { 6 | setSize (600, 800); 7 | } 8 | 9 | MainComponent::~MainComponent() 10 | { 11 | } 12 | 13 | //============================================================================== 14 | void MainComponent::paint (juce::Graphics& g) 15 | { 16 | g.fillCheckerBoard (getLocalBounds().toFloat(), 20, 20, juce::Colours::white, juce::Colours::lightgrey); 17 | 18 | if (svg == nullptr) 19 | { 20 | g.setFont (juce::Font (20.0f)); 21 | g.setColour (juce::Colours::black); 22 | g.drawText ("Drag & Drop your SVG file into this window", getLocalBounds(), juce::Justification::centred, true); 23 | } 24 | } 25 | 26 | void MainComponent::resized() 27 | { 28 | if (svg != nullptr) 29 | svg->setBounds (getLocalBounds()); 30 | } 31 | 32 | bool MainComponent::isInterestedInFileDrag (const juce::StringArray& files) 33 | { 34 | if (files.size() != 1) 35 | return false; 36 | 37 | juce::File possibleSVG (files[0]); 38 | 39 | if (possibleSVG.hasFileExtension ("svg") || possibleSVG.hasFileExtension ("svgz")) 40 | return true; 41 | 42 | return false; 43 | } 44 | 45 | void MainComponent::filesDropped (const juce::StringArray& files, int, int) 46 | { 47 | juce::File newSVGFile (files[0]); 48 | 49 | jb::Resvg::RenderTree tree; 50 | 51 | if (tree.loadFromFile (newSVGFile)) 52 | { 53 | if (svg != nullptr) 54 | removeChildComponent (svg.get()); 55 | 56 | svg = std::make_unique (std::move (tree)); 57 | 58 | addAndMakeVisible (*svg); 59 | 60 | resized(); 61 | repaint(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/Components/jb_SVGButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | namespace jb 11 | { 12 | 13 | /** A simple two state button using two SVGs for on and off state */ 14 | class SVGButton : public juce::Button 15 | { 16 | public: 17 | 18 | SVGButton (const char* offData, int offSize, const char* onData, int onSize, const juce::String& buttonName = "") 19 | : juce::Button (buttonName) 20 | { 21 | auto successLoadingOff = offSVG.loadFromBinaryData (offData, offSize); 22 | auto successLoadingOn = onSVG.loadFromBinaryData (onData, onSize); 23 | 24 | jassert (successLoadingOff); 25 | jassert (successLoadingOn); 26 | 27 | juce::ignoreUnused (successLoadingOff, successLoadingOn); 28 | } 29 | 30 | void resized() override 31 | { 32 | auto displayScale = juce::Desktop::getInstance().getDisplays().getDisplayForPoint (getBounds().getCentre())->scale; 33 | auto componentScale = getApproximateScaleFactorForComponent (this); 34 | 35 | auto newImageBounds = getLocalBounds().toFloat() * displayScale * componentScale; 36 | 37 | if (newImageBounds == cachedImageBounds) 38 | return; 39 | 40 | offImage = offSVG.render (newImageBounds, backgroundColour); 41 | onImage = onSVG.render (newImageBounds, backgroundColour); 42 | 43 | cachedImageBounds = newImageBounds; 44 | } 45 | 46 | private: 47 | Resvg::RenderTree offSVG; 48 | Resvg::RenderTree onSVG; 49 | 50 | juce::Image offImage; 51 | juce::Image onImage; 52 | 53 | juce::Colour backgroundColour = juce::Colours::transparentBlack; 54 | 55 | juce::Rectangle cachedImageBounds; 56 | 57 | void paintButton (juce::Graphics& g, bool, bool) override 58 | { 59 | auto& imageToDraw = getToggleState() ? onImage : offImage; 60 | 61 | g.drawImage (imageToDraw, getLocalBounds().toFloat(), juce::RectanglePlacement::centred); 62 | } 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/Components/jb_SVGComponent.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | namespace jb 11 | { 12 | 13 | /** 14 | * A component that owns an Resvg::RenderTree. On each resize, it renders an Image according to the Components size 15 | * and displays it according to the placement set through setImagePlacement (default is centred) 16 | */ 17 | class SVGComponent : public juce::Component 18 | { 19 | public: 20 | 21 | /** 22 | * Creates an SVGComponent from an svg file. You have to make sure that this is a valid svg, otherwise 23 | * behaviour is undefined 24 | */ 25 | SVGComponent (const juce::File& svgFile) 26 | { 27 | auto successLoading = svg.loadFromFile (svgFile); 28 | 29 | jassert (successLoading); 30 | juce::ignoreUnused (successLoading); 31 | } 32 | 33 | /** 34 | * Creates an SVGComponent from an binary data. You have to make sure that this is a valid svg, otherwise 35 | * behaviour is undefined 36 | */ 37 | SVGComponent (const char* svgData, int svgSize) 38 | { 39 | auto successLoading = svg.loadFromBinaryData (svgData, svgSize); 40 | 41 | jassert (successLoading); 42 | juce::ignoreUnused (successLoading); 43 | } 44 | 45 | /** Creates an SVGComponent from a pre-generated svgRenderTree */ 46 | SVGComponent (Resvg::RenderTree&& svgRenderTree) : svg (std::move (svgRenderTree)) 47 | { 48 | jassert (svg.isValid()); 49 | } 50 | 51 | /** Sets how the image generated from the SVG is placed on the components surface */ 52 | void setImagePlacement (juce::RectanglePlacement placement) 53 | { 54 | imagePlacement = placement; 55 | } 56 | 57 | /** Returns how the image generated from the SVG is placed on the components surface */ 58 | juce::RectanglePlacement getImagePlacement() 59 | { 60 | return imagePlacement; 61 | } 62 | 63 | void resized() override 64 | { 65 | auto displayScale = juce::Desktop::getInstance().getDisplays().getDisplayForPoint (getBounds().getCentre())->scale; 66 | auto componentScale = getApproximateScaleFactorForComponent (this); 67 | 68 | auto newImageBounds = getLocalBounds().toFloat() * displayScale * componentScale; 69 | 70 | if (newImageBounds == cachedImageBounds) 71 | return; 72 | 73 | cachedImage = svg.render (newImageBounds); 74 | cachedImageBounds = newImageBounds; 75 | } 76 | 77 | void paint (juce::Graphics& g) override 78 | { 79 | g.drawImage (cachedImage, getLocalBounds().toFloat(), imagePlacement); 80 | } 81 | 82 | private: 83 | SVGComponent() {} 84 | 85 | Resvg::RenderTree svg; 86 | 87 | juce::Image cachedImage; 88 | juce::Rectangle cachedImageBounds; 89 | 90 | juce::RectanglePlacement imagePlacement = juce::RectanglePlacement::centred; 91 | }; 92 | 93 | } 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ==================================================================== 2 | # 3 | # This file is part of Resvg4JUCE. 4 | # 5 | # This Source Code Form is subject to the terms of the Mozilla Public 6 | # License, v. 2.0. If a copy of the MPL was not distributed with this 7 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | # 9 | # ==================================================================== 10 | 11 | cmake_minimum_required (VERSION 3.16) 12 | 13 | project (RESVG4JUCE VERSION 0.2.0) 14 | 15 | # Some CMake exporters (e.g. ninja) need a dummy library file to be present before the 16 | # build target referencing this file and triggering the prior build has been executed. 17 | # Therefore we create a dummy library output file here first 18 | set (RESVG_LIB_OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/Ext/resvg/target/release) 19 | 20 | if (WIN32) 21 | set (RESVG_LIB_OUTPUT ${RESVG_LIB_OUTPUT_DIR}/resvg.lib) 22 | else() 23 | set (RESVG_LIB_OUTPUT ${RESVG_LIB_OUTPUT_DIR}/libresvg.a) 24 | endif() 25 | 26 | file (MAKE_DIRECTORY ${RESVG_LIB_OUTPUT_DIR}) 27 | file (TOUCH ${RESVG_LIB_OUTPUT}) 28 | 29 | # The target to trigger the rust cargo based compilation of the resvg library used. 30 | # For macOS we need to ensure the C-Parts of it being built for the right deployment 31 | # target by setting an environment variable first 32 | if (APPLE) 33 | add_custom_target (resvg_cargo_build_arm64 34 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/resvg/c-api 35 | COMMAND ${CMAKE_COMMAND} -E env MACOSX_DEPLOYMENT_TARGET=10.7 cargo build --release --target aarch64-apple-darwin) 36 | 37 | add_custom_target (resvg_cargo_build_x86_64 38 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/resvg/c-api 39 | COMMAND ${CMAKE_COMMAND} -E env MACOSX_DEPLOYMENT_TARGET=10.7 cargo build --release --target x86_64-apple-darwin) 40 | 41 | add_custom_target (resvg_cargo_build 42 | WORKING_DIRECTORY ${RESVG_LIB_OUTPUT_DIR} 43 | COMMAND lipo -create -output libresvg.a ../aarch64-apple-darwin/release/libresvg.a ../x86_64-apple-darwin/release/libresvg.a) 44 | 45 | add_dependencies (resvg_cargo_build resvg_cargo_build_arm64 resvg_cargo_build_x86_64) 46 | else() 47 | add_custom_target (resvg_cargo_build 48 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/Ext/resvg/c-api 49 | COMMAND cargo build --release) 50 | endif() 51 | 52 | # Make an imported targe that references the library just built 53 | add_library (resvg STATIC IMPORTED) 54 | add_dependencies (resvg resvg_cargo_build) 55 | set_target_properties (resvg PROPERTIES IMPORTED_LOCATION ${RESVG_LIB_OUTPUT}) 56 | target_include_directories (resvg INTERFACE ${CMAKE_CURRENT_LIST_DIR}/Ext/resvg/c-api) 57 | 58 | # Seems like bcrypt is a dependency on Windows 59 | if (WIN32) 60 | target_link_libraries (resvg INTERFACE bcrypt) 61 | endif() 62 | 63 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 64 | # Only apply SSE3 optimization to x86 architectures 65 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64|i686)") 66 | target_compile_options (resvg INTERFACE -mssse3) 67 | endif() 68 | endif() 69 | 70 | # Create the Resvg4JUCE juce module target. This depends on the resvg library created above and on the juce_gui_basics module 71 | juce_add_module (Modules/Resvg4JUCE) 72 | target_link_libraries (Resvg4JUCE INTERFACE resvg) 73 | 74 | # Export an alias target 75 | add_library (jb::Resvg4JUCE ALIAS Resvg4JUCE) 76 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/RenderTree/jb_ResvgRenderTree.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | #include 11 | 12 | namespace jb 13 | { 14 | 15 | namespace Resvg 16 | { 17 | 18 | enum class ShapeRenderingMode 19 | { 20 | optimizeSpeed, 21 | crispEdges, 22 | geometricPrecision, 23 | }; 24 | 25 | enum class TextRenderingMode 26 | { 27 | optimizeSpeed, 28 | optimizeLegibility, 29 | geometricPrecision, 30 | }; 31 | 32 | enum class ImageRenderingMode 33 | { 34 | optimizeQuality, 35 | optimizeSpeed, 36 | }; 37 | 38 | struct Options 39 | { 40 | double dpi = 96; 41 | 42 | ShapeRenderingMode shapeRendering = ShapeRenderingMode::geometricPrecision; 43 | 44 | TextRenderingMode textRendering = TextRenderingMode::optimizeLegibility; 45 | 46 | ImageRenderingMode imageRendering = ImageRenderingMode::optimizeQuality; 47 | }; 48 | 49 | /* 50 | * Initializes the resvg library log. 51 | * 52 | * Use it if you want to see any internal resvg warnings, they will be printed to stderr 53 | * Must be called only once. 54 | */ 55 | void initLog(); 56 | 57 | /** 58 | * This class encapsulates an resvg_render_tree and gives you functions to load svg files into it and render them 59 | * to a juce::Image. Once you have loaded an svg into the tree, you can call render multiple times without re-loading 60 | * the svg. 61 | */ 62 | class RenderTree 63 | { 64 | public: 65 | 66 | /** Creates a render tree with default options */ 67 | RenderTree(); 68 | 69 | /** Creates a render tree with a custom DPI preference */ 70 | RenderTree (double dpi); 71 | 72 | /** Creates a render tree with custom options */ 73 | RenderTree (const Options& renderingOptions); 74 | 75 | /** Moves constructor */ 76 | RenderTree (RenderTree&& other); 77 | 78 | ~RenderTree(); 79 | 80 | /** Parses an SVG file into this tree. Returns true on success, false otherwise */ 81 | bool loadFromFile (const juce::File& svgFile); 82 | 83 | /** Parses an SVG file from binary data into this tree. Returns true on success, false otherwise */ 84 | bool loadFromBinaryData (const char* data, int size); 85 | 86 | /** Returns true if a file has been successfully loaded into this tree */ 87 | bool isValid(); 88 | 89 | /** Returns the size that is stored in the SVG. Returns an empty rectangle if no SVG has been loaded yet */ 90 | juce::Rectangle getSize(); 91 | 92 | /** Returns the aspect ratio (width over height) of the SVG. Returns -1.0 if no SVG has been loaded yet*/ 93 | float getAspectRatio(); 94 | 95 | /** 96 | * Renders the SVG to an image of the size matching the size stored in the SVG. The background can be either fully 97 | * transparent or a fully solid colour. 98 | */ 99 | juce::Image render (juce::Colour backgroundColour = juce::Colours::transparentBlack); 100 | 101 | /** 102 | * Renders the SVG to an image of the size matching the size stored in the SVG adusted by the zoom factor passed in. 103 | * The background can be either fully transparent or a fully solid colour. 104 | */ 105 | juce::Image render (float zoomFactor, juce::Colour backgroundColour = juce::Colours::transparentBlack); 106 | 107 | /** 108 | * Renders the SVG to an image that fits the given destination rectangle. The image returned might be smaller than 109 | * the destination rectangle passed, as this call always preserves the apsect ratio of the original SVG. 110 | * The background can be either fully transparent or a fully solid colour. 111 | */ 112 | juce::Image render (juce::Rectangle dstSize, juce::Colour backgroundColour = juce::Colours::transparentBlack); 113 | 114 | 115 | private: 116 | 117 | // Using void pointers to not expose resvg types to the public interface 118 | void* options = nullptr; 119 | void *tree = nullptr; 120 | 121 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RenderTree) 122 | }; 123 | 124 | } 125 | 126 | } 127 | 128 | -------------------------------------------------------------------------------- /Examples/ViewSVG/Source/Main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | This file contains the basic startup code for a JUCE application. 5 | 6 | ============================================================================== 7 | */ 8 | 9 | #include 10 | #include "MainComponent.h" 11 | 12 | //============================================================================== 13 | class ViewSVGApplication : public juce::JUCEApplication 14 | { 15 | public: 16 | //============================================================================== 17 | ViewSVGApplication() {} 18 | 19 | const juce::String getApplicationName() override { return ProjectInfo::projectName; } 20 | const juce::String getApplicationVersion() override { return ProjectInfo::versionString; } 21 | bool moreThanOneInstanceAllowed() override { return true; } 22 | 23 | //============================================================================== 24 | void initialise (const juce::String& /* commandLine */) override 25 | { 26 | // This method is where you should put your application's initialisation code.. 27 | 28 | mainWindow.reset (new MainWindow (getApplicationName())); 29 | 30 | jb::Resvg::initLog(); 31 | } 32 | 33 | void shutdown() override 34 | { 35 | // Add your application's shutdown code here.. 36 | 37 | mainWindow = nullptr; // (deletes our window) 38 | } 39 | 40 | //============================================================================== 41 | void systemRequestedQuit() override 42 | { 43 | // This is called when the app is being asked to quit: you can ignore this 44 | // request and let the app carry on running, or call quit() to allow the app to close. 45 | quit(); 46 | } 47 | 48 | void anotherInstanceStarted (const juce::String& commandLine) override 49 | { 50 | // When another instance of the app is launched while this one is running, 51 | // this method is invoked, and the commandLine parameter tells you what 52 | // the other instance's command-line arguments were. 53 | } 54 | 55 | //============================================================================== 56 | /* 57 | This class implements the desktop window that contains an instance of 58 | our MainComponent class. 59 | */ 60 | class MainWindow : public juce::DocumentWindow 61 | { 62 | public: 63 | MainWindow (juce::String name) 64 | : DocumentWindow (name, 65 | juce::Desktop::getInstance().getDefaultLookAndFeel() 66 | .findColour (juce::ResizableWindow::backgroundColourId), 67 | DocumentWindow::allButtons) 68 | { 69 | setUsingNativeTitleBar (true); 70 | setContentOwned (new MainComponent(), true); 71 | 72 | #if JUCE_IOS || JUCE_ANDROID 73 | setFullScreen (true); 74 | #else 75 | setResizable (true, true); 76 | centreWithSize (getWidth(), getHeight()); 77 | #endif 78 | 79 | setVisible (true); 80 | } 81 | 82 | void closeButtonPressed() override 83 | { 84 | // This is called when the user tries to close this window. Here, we'll just 85 | // ask the app to quit when this happens, but you can change this to do 86 | // whatever you need. 87 | JUCEApplication::getInstance()->systemRequestedQuit(); 88 | } 89 | 90 | /* Note: Be careful if you override any DocumentWindow methods - the base 91 | class uses a lot of them, so by overriding you might break its functionality. 92 | It's best to do all your work in your content component instead, but if 93 | you really have to override any DocumentWindow methods, make sure your 94 | subclass also calls the superclass's method. 95 | */ 96 | 97 | private: 98 | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow) 99 | }; 100 | 101 | private: 102 | std::unique_ptr mainWindow; 103 | }; 104 | 105 | //============================================================================== 106 | // This macro generates the main() routine that launches the app. 107 | START_JUCE_APPLICATION (ViewSVGApplication) 108 | -------------------------------------------------------------------------------- /Modules/Resvg4JUCE/RenderTree/jb_ResvgRenderTree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of Resvg4JUCE. 3 | 4 | This Source Code Form is subject to the terms of the Mozilla Public 5 | License, v. 2.0. If a copy of the MPL was not distributed with this 6 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | 8 | */ 9 | 10 | #include "jb_ResvgRenderTree.h" 11 | 12 | #if JUCE_INTEL 13 | #include "immintrin.h" 14 | #endif 15 | 16 | #include 17 | 18 | namespace jb 19 | { 20 | 21 | namespace Resvg 22 | { 23 | 24 | // Helper function to cast our public enum classes into the resvg enum types 25 | template 26 | constexpr DstEnumType to (SrcEnumClassType src) 27 | { 28 | using UT = typename std::underlying_type::type; 29 | return static_cast (static_cast (src)); 30 | } 31 | 32 | // Make sure that our public enum class constants match the resv constants 33 | static_assert (RESVG_SHAPE_RENDERING_OPTIMIZE_SPEED == to (ShapeRenderingMode::optimizeSpeed), ""); 34 | static_assert (RESVG_SHAPE_RENDERING_CRISP_EDGES == to (ShapeRenderingMode::crispEdges), ""); 35 | static_assert (RESVG_SHAPE_RENDERING_GEOMETRIC_PRECISION == to (ShapeRenderingMode::geometricPrecision), ""); 36 | 37 | static_assert (RESVG_TEXT_RENDERING_OPTIMIZE_SPEED == to (TextRenderingMode::optimizeSpeed), ""); 38 | static_assert (RESVG_TEXT_RENDERING_GEOMETRIC_PRECISION == to (TextRenderingMode::geometricPrecision), ""); 39 | static_assert (RESVG_TEXT_RENDERING_OPTIMIZE_LEGIBILITY == to (TextRenderingMode::optimizeLegibility), ""); 40 | 41 | static_assert (RESVG_IMAGE_RENDERING_OPTIMIZE_SPEED == to (ImageRenderingMode::optimizeSpeed), ""); 42 | static_assert (RESVG_IMAGE_RENDERING_OPTIMIZE_QUALITY == to (ImageRenderingMode::optimizeQuality), ""); 43 | 44 | // Internal function to swap the red and blue component of a colour since resvg expects them swapped in comparison to juce 45 | juce::Colour swapRB (juce::Colour c) 46 | { 47 | auto* asUint8 = reinterpret_cast (&c); 48 | 49 | std::swap (asUint8[0], asUint8[2]); 50 | 51 | return c; 52 | } 53 | 54 | constexpr int64_t bytesPerPixel = 4; 55 | 56 | // Swaps the red and blue compoment of an rgba image with a certain number of pixels via a for loop over all pixels 57 | void swapRBnonSIMD (uint8_t* data, int64_t numPixel) 58 | { 59 | const auto* end = data + (bytesPerPixel * numPixel); 60 | 61 | for (; data != end; data += bytesPerPixel) 62 | std::swap (data[0], data[2]); 63 | } 64 | 65 | #if JUCE_INTEL && defined (__SSSE3__) 66 | // SSE optimized implementation of swapRB 67 | void swapRBSSE (uint8_t* data, int64_t numPixel) 68 | { 69 | const auto* end = data + (bytesPerPixel * numPixel); 70 | int64_t numBytes = end - data; 71 | 72 | auto* simdAlignedData = juce::snapPointerToAlignment (data, sizeof (__m128i)); 73 | 74 | const int64_t numBytesPreSIMD = simdAlignedData - data; 75 | 76 | if (numBytesPreSIMD % bytesPerPixel != 0) 77 | { 78 | swapRBnonSIMD (data, numPixel); 79 | return; 80 | } 81 | 82 | swapRBnonSIMD (data, numBytesPreSIMD / bytesPerPixel); 83 | numBytes -= numBytesPreSIMD; 84 | 85 | const int64_t numBytesPostSIMD= numBytes % int (sizeof (__m128i)); 86 | const auto* endSIMD = simdAlignedData + (numBytes - numBytesPostSIMD); 87 | 88 | __m128i shuffleMask = _mm_set_epi8 (15, 12, 13, 14, 89 | 11, 8, 9, 10, 90 | 7, 4, 5, 6, 91 | 3, 0, 1, 2); 92 | 93 | for (; simdAlignedData != endSIMD; simdAlignedData += sizeof (__m128i)) 94 | { 95 | auto in = _mm_load_si128 (reinterpret_cast<__m128i*> (simdAlignedData)); 96 | auto out = _mm_shuffle_epi8 (in, shuffleMask); 97 | _mm_store_si128 (reinterpret_cast<__m128i*> (simdAlignedData), out); 98 | } 99 | 100 | swapRBnonSIMD (simdAlignedData, numBytesPostSIMD / bytesPerPixel); 101 | } 102 | 103 | void swapRB (uint8_t* data, int64_t numBytes) 104 | { 105 | swapRBSSE (data, numBytes); 106 | } 107 | 108 | #else 109 | void swapRB (uint8_t* data, int64_t numBytes) 110 | { 111 | swapRBnonSIMD (data, numBytes); 112 | } 113 | #endif 114 | 115 | // Internal function to perform the actual rendering behind the various RenderTree::render functions 116 | juce::Image renderTree (resvg_render_tree* tree, resvg_fit_to fit, juce::Colour backgroundColour, juce::Rectangle&& imageBounds) 117 | { 118 | // Before rendering an SVG you need to have successfully loaded one into the tree 119 | jassert (tree != nullptr); 120 | 121 | const auto h = imageBounds.getHeight(); 122 | const auto w = imageBounds.getWidth(); 123 | 124 | juce::Image image (juce::Image::PixelFormat::ARGB, w, h, backgroundColour.isTransparent()); 125 | 126 | image.clear (imageBounds, swapRB (backgroundColour)); 127 | 128 | juce::Image::BitmapData dstData (image, 0, 0, w, h, juce::Image::BitmapData::ReadWriteMode::writeOnly); 129 | 130 | resvg_render (tree, fit, 131 | static_cast (w), 132 | static_cast (h), 133 | reinterpret_cast (dstData.data)); 134 | 135 | // Red and blue components have to be swapped since resvg orders them differently compared to juce 136 | swapRB (dstData.data, static_cast (w) * static_cast (h)); 137 | 138 | return image; 139 | } 140 | 141 | juce::Image renderTree (resvg_render_tree* tree, resvg_fit_to fit, juce::Colour backgroundColour) 142 | { 143 | // Before rendering an SVG you need to have successfully loaded one into the tree 144 | jassert (tree != nullptr); 145 | 146 | auto imageSize = resvg_get_image_size (tree); 147 | 148 | if (fit.type == RESVG_FIT_TO_ZOOM) 149 | { 150 | imageSize.width *= fit.value; 151 | imageSize.height *= fit.value; 152 | } 153 | 154 | return renderTree (tree, fit, backgroundColour, juce::Rectangle (imageSize.width, imageSize.height).toNearestIntEdges()); 155 | } 156 | 157 | void initLog() 158 | { 159 | resvg_init_log(); 160 | } 161 | 162 | RenderTree::RenderTree () 163 | { 164 | options = resvg_options_create(); 165 | jassert (options != nullptr); 166 | } 167 | 168 | RenderTree::RenderTree (double dpi) : RenderTree() 169 | { 170 | resvg_options_set_dpi ((resvg_options*) options, dpi); 171 | } 172 | 173 | RenderTree::RenderTree (const Options& renderingOptions) : RenderTree() 174 | { 175 | resvg_options_set_dpi ((resvg_options*) options, renderingOptions.dpi); 176 | resvg_options_set_shape_rendering_mode ((resvg_options*) options, to (renderingOptions.shapeRendering)); 177 | resvg_options_set_text_rendering_mode ((resvg_options*) options, to (renderingOptions.textRendering)); 178 | resvg_options_set_image_rendering_mode ((resvg_options*) options, to (renderingOptions.imageRendering)); 179 | } 180 | 181 | RenderTree::RenderTree (RenderTree&& other) 182 | : options (other.options), 183 | tree (other.tree) 184 | { 185 | other.options = nullptr; 186 | other.tree = nullptr; 187 | } 188 | 189 | RenderTree::~RenderTree () 190 | { 191 | if (options != nullptr) 192 | resvg_options_destroy ((resvg_options*) options); 193 | 194 | if (tree != nullptr) 195 | resvg_tree_destroy ((resvg_render_tree*) tree); 196 | } 197 | 198 | bool RenderTree::loadFromFile (const juce::File& svgFile) 199 | { 200 | jassert (svgFile.existsAsFile()); 201 | auto fullPath = svgFile.getFullPathName(); 202 | 203 | if (tree != nullptr) 204 | resvg_tree_destroy ((resvg_render_tree*) tree); 205 | 206 | auto result = resvg_parse_tree_from_file (fullPath.toRawUTF8(), (resvg_options*) options, (resvg_render_tree**) &tree); 207 | 208 | if (result != RESVG_OK || tree == nullptr) 209 | { 210 | tree = nullptr; 211 | return false; 212 | } 213 | 214 | return true; 215 | } 216 | 217 | bool RenderTree::loadFromBinaryData (const char* data, int size) 218 | { 219 | if (tree != nullptr) 220 | resvg_tree_destroy ((resvg_render_tree*) tree); 221 | 222 | auto result = resvg_parse_tree_from_data (data, static_cast(size), (resvg_options*) options, (resvg_render_tree**) &tree); 223 | 224 | if (result != RESVG_OK || tree == nullptr) 225 | { 226 | tree = nullptr; 227 | return false; 228 | } 229 | 230 | return true; 231 | } 232 | 233 | bool RenderTree::isValid() 234 | { 235 | return tree != nullptr; 236 | } 237 | 238 | juce::Rectangle RenderTree::getSize() 239 | { 240 | if (tree == nullptr) 241 | return {}; 242 | 243 | auto size = resvg_get_image_size ((resvg_render_tree*) tree); 244 | 245 | return { static_cast (size.width), static_cast (size.height) }; 246 | } 247 | 248 | float RenderTree::getAspectRatio() 249 | { 250 | if (tree == nullptr) 251 | return -1.0f; 252 | 253 | auto size = resvg_get_image_size ((resvg_render_tree*) tree); 254 | 255 | return static_cast (size.width / size.height); 256 | } 257 | 258 | juce::Image RenderTree::render (juce::Colour backgroundColour) 259 | { 260 | resvg_fit_to fit { resvg_fit_to_type::RESVG_FIT_TO_ORIGINAL, 1.0f }; 261 | return renderTree ((resvg_render_tree*) tree, fit, backgroundColour); 262 | } 263 | 264 | juce::Image RenderTree::render (float zoomFactor, juce::Colour backgroundColour) 265 | { 266 | resvg_fit_to fit { resvg_fit_to_type::RESVG_FIT_TO_ZOOM, zoomFactor }; 267 | return renderTree ((resvg_render_tree*) tree, fit, backgroundColour); 268 | } 269 | 270 | juce::Image RenderTree::render (juce::Rectangle dstSize, juce::Colour backgroundColour) 271 | { 272 | auto dstAspectRatio = dstSize.getAspectRatio(); 273 | auto srcAspectRatio = getAspectRatio(); 274 | 275 | resvg_fit_to fit; 276 | if (srcAspectRatio < dstAspectRatio) 277 | { 278 | // The source image is wider than the destination image --> fit to height 279 | fit.type = RESVG_FIT_TO_HEIGHT; 280 | fit.value = dstSize.getHeight(); 281 | 282 | dstSize.setWidth (fit.value * srcAspectRatio); 283 | } 284 | else 285 | { 286 | fit.type = RESVG_FIT_TO_WIDTH; 287 | fit.value = dstSize.getWidth(); 288 | 289 | dstSize.setHeight (fit.value / srcAspectRatio); 290 | } 291 | 292 | jassert (fit.value >= 1.0f); 293 | 294 | return renderTree ((resvg_render_tree*) tree, fit, backgroundColour, dstSize.toNearestIntEdges()); 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | --------------------------------------------------------------------------------