Browse Source

Initial work on SVG support

pull/141/head
Patrick Desaulniers 6 years ago
parent
commit
fa450e2696
22 changed files with 26469 additions and 3 deletions
  1. +5
    -3
      Makefile
  2. +6
    -0
      dgl/Image.hpp
  3. +1
    -0
      dgl/ImageBase.hpp
  4. +1
    -0
      dgl/Makefile
  5. +73
    -0
      dgl/SVG.hpp
  6. +5
    -0
      dgl/src/Image.cpp
  7. +88
    -0
      dgl/src/SVG.cpp
  8. +18
    -0
      dgl/src/nanosvg/LICENSE.txt
  9. +2975
    -0
      dgl/src/nanosvg/nanosvg.h
  10. +1452
    -0
      dgl/src/nanosvg/nanosvgrast.h
  11. +36
    -0
      examples/MidiKeyboard/DistrhoPluginInfo.h
  12. +28
    -0
      examples/MidiKeyboard/KeyboardWidget.hpp
  13. +45
    -0
      examples/MidiKeyboard/Makefile
  14. +132
    -0
      examples/MidiKeyboard/MidiKeyboardExamplePlugin.cpp
  15. +102
    -0
      examples/MidiKeyboard/MidiKeyboardExampleUI.cpp
  16. +8
    -0
      examples/MidiKeyboard/README.md
  17. +13796
    -0
      examples/MidiKeyboard/resources/MidiKeyboardResources.cpp
  18. +30
    -0
      examples/MidiKeyboard/resources/MidiKeyboardResources.hpp
  19. +1917
    -0
      examples/MidiKeyboard/resources/black_key.svg
  20. +1917
    -0
      examples/MidiKeyboard/resources/black_key_pressed.svg
  21. +1917
    -0
      examples/MidiKeyboard/resources/white_key.svg
  22. +1917
    -0
      examples/MidiKeyboard/resources/white_key_pressed.svg

+ 5
- 3
Makefile View File

@@ -20,10 +20,11 @@ examples: dgl
$(MAKE) all -C examples/MidiThrough
$(MAKE) all -C examples/Parameters
$(MAKE) all -C examples/States
$(MAKE) all -C examples/MidiKeyboard

ifeq ($(HAVE_CAIRO),true)
$(MAKE) all -C examples/CairoUI
endif
#ifeq ($(HAVE_CAIRO),true)
# $(MAKE) all -C examples/CairoUI
#endif

ifneq ($(MACOS_OR_WINDOWS),true)
# ExternalUI is WIP
@@ -60,6 +61,7 @@ clean:
$(MAKE) clean -C examples/MidiThrough
$(MAKE) clean -C examples/Parameters
$(MAKE) clean -C examples/States
$(MAKE) clean -C examples/MidiKeyboard
$(MAKE) clean -C utils/lv2-ttl-generator
rm -rf bin build



+ 6
- 0
dgl/Image.hpp View File

@@ -92,6 +92,12 @@ public:
const GLenum format = GL_BGRA,
const GLenum type = GL_UNSIGNED_BYTE) noexcept;

/**
* Load image data from an SVG.
* @note The SVG instance must remain valid during the lifetime of this image.
*/
void loadFromSVG(const SVG& svg) noexcept;

/**
Get the image format.
*/


+ 1
- 0
dgl/ImageBase.hpp View File

@@ -18,6 +18,7 @@
#define DGL_IMAGE_BASE_HPP_INCLUDED

#include "Geometry.hpp"
#include "SVG.hpp"

START_NAMESPACE_DGL



+ 1
- 0
dgl/Makefile View File

@@ -25,6 +25,7 @@ OBJS_common = \
../build/dgl/Geometry.cpp.o \
../build/dgl/ImageBase.cpp.o \
../build/dgl/Resources.cpp.o \
../build/dgl/SVG.cpp.o \
../build/dgl/Widget.cpp.o

# TODO: ImageWidgets.cpp


+ 73
- 0
dgl/SVG.hpp View File

@@ -0,0 +1,73 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DGL_SVG_HPP_INCLUDED
#define DGL_SVG_HPP_INCLUDED

#include "src/nanosvg/nanosvg.h"
#include "Geometry.hpp"

struct NSVGrasterizer;

START_NAMESPACE_DGL

/**
* Utility class for loading SVGs.
*/
class SVG
{
public:

/**
Constructor for a null SVG.
*/
SVG();

/**
Constructor using raw SVG data.
*/
SVG(const char* const data, const uint width, const uint height, const float scaling = 1.0f);

/**
Destructor.
*/
~SVG();
/**
Check if this SVG is valid.
*/
const Size<uint>& getSize() const noexcept;

/**
Get the RGBA data of the rasterized SVG.
*/
const unsigned char* getRGBAData() const noexcept;

/**
Check if this SVG is valid.
*/
bool isValid() const noexcept;

private:
Size<uint> fSize;
NSVGrasterizer* fRasterizer;
NSVGimage* fImage;
unsigned char* fRGBAData;
};

END_NAMESPACE_DGL

#endif

+ 5
- 0
dgl/src/Image.cpp View File

@@ -92,6 +92,11 @@ void Image::loadFromMemory(const char* const rawData,
fIsReady = false;
}

void Image::loadFromSVG(const SVG& svg) noexcept
{
loadFromMemory((const char*)svg.getRGBAData(), svg.getSize(), GL_RGBA);
}

GLenum Image::getFormat() const noexcept
{
return fFormat;


+ 88
- 0
dgl/src/SVG.cpp View File

@@ -0,0 +1,88 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "SVG.hpp"

#define NANOSVG_IMPLEMENTATION
#include "nanosvg/nanosvg.h"

#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvg/nanosvgrast.h"


START_NAMESPACE_DGL

SVG::SVG()
: fSize(),
fRasterizer(nullptr),
fImage(nullptr),
fRGBAData(nullptr)
{

}

SVG::SVG(const char* const data, const uint width, const uint height, const float scaling)
: fSize(width * scaling, height * scaling)
{
DISTRHO_SAFE_ASSERT_RETURN(data != nullptr,)
DISTRHO_SAFE_ASSERT_RETURN(fSize.isValid(),)

fRasterizer = nsvgCreateRasterizer();

const size_t bufferSize = width * height * 4;

// nsvgParse modifies the input data, so we must use a temporary buffer
char tmpBuffer[bufferSize];
strncpy(tmpBuffer, data, bufferSize);
const float dpi = 96 * scaling;
fImage = nsvgParse(tmpBuffer, "px", dpi);

DISTRHO_SAFE_ASSERT_RETURN(fImage != nullptr,)

const uint scaledWidth = width * scaling;
const uint scaledHeight = height * scaling;

fRGBAData = (unsigned char *)malloc(scaledWidth * scaledHeight * 4);

nsvgRasterize(fRasterizer, fImage, 0, 0, 1, fRGBAData, scaledWidth, scaledHeight, scaledWidth * 4);
}

SVG::~SVG()
{
nsvgDelete(fImage);
nsvgDeleteRasterizer(fRasterizer);

free(fRGBAData);
}
const Size<uint>& SVG::getSize() const noexcept
{
return fSize;
}

const unsigned char* SVG::getRGBAData() const noexcept
{
return fRGBAData;
}

bool SVG::isValid() const noexcept
{
return (fRGBAData != nullptr && fSize.isValid());
}

END_NAMESPACE_DGL


+ 18
- 0
dgl/src/nanosvg/LICENSE.txt View File

@@ -0,0 +1,18 @@
Copyright (c) 2013-14 Mikko Mononen memon@inside.org

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.


+ 2975
- 0
dgl/src/nanosvg/nanosvg.h
File diff suppressed because it is too large
View File


+ 1452
- 0
dgl/src/nanosvg/nanosvgrast.h
File diff suppressed because it is too large
View File


+ 36
- 0
examples/MidiKeyboard/DistrhoPluginInfo.h View File

@@ -0,0 +1,36 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
#define DISTRHO_PLUGIN_INFO_H_INCLUDED

#define DISTRHO_PLUGIN_BRAND "DISTRHO"
#define DISTRHO_PLUGIN_NAME "MidiKeyboard"
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/MidiKeyboard"

#define DISTRHO_PLUGIN_HAS_UI 1
#define DISTRHO_PLUGIN_IS_RT_SAFE 1
#define DISTRHO_PLUGIN_NUM_INPUTS 0
#define DISTRHO_PLUGIN_NUM_OUTPUTS 0
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 1
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 1

#define DISTRHO_UI_USE_NANOVG 1
#define DISTRHO_UI_USER_RESIZABLE 1

#define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:MIDIPlugin"

#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED

+ 28
- 0
examples/MidiKeyboard/KeyboardWidget.hpp View File

@@ -0,0 +1,28 @@
#include "Widget.hpp"


START_NAMESPACE_DISTRHO

class KeyboardWidget : public Widget
{
public:
KeyboardWidget(Window& parent) : Widget(parent)
{

}

void onDisplay() override
{
const SVG &svg = SVG(MidiKeyboardResources::black_keyData,
MidiKeyboardResources::black_keyWidth,
MidiKeyboardResources::black_keyHeight,
1.0f);
Image img = Image();
img.loadFromSVG(svg);

img.drawAt(0,0);
}
};

END_NAMESPACE_DISTRHO

+ 45
- 0
examples/MidiKeyboard/Makefile View File

@@ -0,0 +1,45 @@
#!/usr/bin/make -f
# Makefile for DISTRHO Plugins #
# ---------------------------- #
# Created by falkTX
#

# --------------------------------------------------------------
# Project name, used for binaries

NAME = d_midiKeyboard

# --------------------------------------------------------------
# Files to build

FILES_DSP = \
MidiKeyboardExamplePlugin.cpp

FILES_UI = \
resources/MidiKeyboardResources.cpp \
MidiKeyboardExampleUI.cpp


# --------------------------------------------------------------
# Do some magic

include ../../Makefile.plugins.mk

# --------------------------------------------------------------
# Additional flags

BASE_FLAGS += -I../../dgl/src/nanovg

# --------------------------------------------------------------
# Enable all possible plugin types

ifeq ($(LINUX),true)
TARGETS += jack
endif

TARGETS += lv2_dsp
TARGETS += vst

all: $(TARGETS)

# --------------------------------------------------------------

+ 132
- 0
examples/MidiKeyboard/MidiKeyboardExamplePlugin.cpp View File

@@ -0,0 +1,132 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "DistrhoPlugin.hpp"
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------------------------------------------
class MidiKeyboardExamplePlugin : public Plugin
{
public:
MidiKeyboardExamplePlugin()
: Plugin(0, 0, 0) {}
protected:
/* --------------------------------------------------------------------------------------------------------
* Information */
/**
Get the plugin label.
This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
*/
const char* getLabel() const override
{
return "MidiKeyboard";
}
/**
Get an extensive comment/description about the plugin.
*/
const char* getDescription() const override
{
return "Plugin that demonstrates how to make a MIDI keyboard widget using DPF.";
}
/**
Get the plugin author/maker.
*/
const char* getMaker() const override
{
return "DISTRHO";
}
/**
Get the plugin homepage.
*/
const char* getHomePage() const override
{
return "https://github.com/DISTRHO/DPF";
}
/**
Get the plugin license name (a single line of text).
For commercial plugins this should return some short copyright information.
*/
const char* getLicense() const override
{
return "ISC";
}
/**
Get the plugin version, in hexadecimal.
*/
uint32_t getVersion() const override
{
return d_version(1, 0, 0);
}
/**
Get the plugin unique Id.
This value is used by LADSPA, DSSI and VST plugin formats.
*/
int64_t getUniqueId() const override
{
return d_cconst('d', 'M', 'k', 'e');
}
/* --------------------------------------------------------------------------------------------------------
* Init and Internal data, unused in this plugin */
void initParameter(uint32_t, Parameter&) override {}
float getParameterValue(uint32_t) const override { return 0.0f;}
void setParameterValue(uint32_t, float) override {}
/* --------------------------------------------------------------------------------------------------------
* Audio/MIDI Processing */
/**
Run/process function for plugins with MIDI input.
In this case we just pass-through all MIDI events.
*/
void run(const float**, float**, uint32_t,
const MidiEvent* midiEvents, uint32_t midiEventCount) override
{
for (uint32_t i=0; i<midiEventCount; ++i)
writeMidiEvent(midiEvents[i]);
}
// -------------------------------------------------------------------------------------------------------
private:
/**
Set our plugin class as non-copyable and add a leak detector just in case.
*/
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiKeyboardExamplePlugin)
};
/* ------------------------------------------------------------------------------------------------------------
* Plugin entry point, called by DPF to create a new plugin instance. */
Plugin* createPlugin()
{
return new MidiKeyboardExamplePlugin();
}
// -----------------------------------------------------------------------------------------------------------
END_NAMESPACE_DISTRHO

+ 102
- 0
examples/MidiKeyboard/MidiKeyboardExampleUI.cpp View File

@@ -0,0 +1,102 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoUI.hpp"
#include "Window.hpp"
#include "KeyboardWidget.hpp"

START_NAMESPACE_DISTRHO

/**
We need the rectangle class from DGL.
*/
using DGL::Rectangle;

// -----------------------------------------------------------------------------------------------------------

class MidiKeyboardExampleUI : public UI
{
public:
/* constructor */
MidiKeyboardExampleUI()
: UI(512, 512)
{
//getParentWindow().focus();
// Add a min-size constraint to the window, to make sure that it can't become too small
setGeometryConstraints(getWidth(), getHeight(), true, true);
}

protected:
/* --------------------------------------------------------------------------------------------------------
* DSP/Plugin Callbacks */

/**
A parameter has changed on the plugin side.
This is called by the host to inform the UI about parameter changes.
*/
void parameterChanged(uint32_t index, float value) override
{
}

/* --------------------------------------------------------------------------------------------------------
* Widget Callbacks */

/**
The OpenGL drawing function.
*/
void onNanoDisplay() override
{
const uint width = getWidth();
const uint height = getHeight();

//KeyboardRenderer().draw(getContext());
}

/**
Mouse press event.
*/
bool onMouse(const MouseEvent &ev) override
{
return false;
}

bool onKeyboard(const KeyboardEvent &ev) override
{
fprintf(stderr, "%u\n", ev.key);
repaint();
return false;
}

// -------------------------------------------------------------------------------------------------------

private:
/**
Set our UI class as non-copyable and add a leak detector just in case.
*/
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiKeyboardExampleUI)
};

/* ------------------------------------------------------------------------------------------------------------
* UI entry point, called by DPF to create a new UI instance. */

UI *createUI()
{
return new MidiKeyboardExampleUI();
}

// -----------------------------------------------------------------------------------------------------------

END_NAMESPACE_DISTRHO

+ 8
- 0
examples/MidiKeyboard/README.md View File

@@ -0,0 +1,8 @@
# MidiKeyboard example

This example will show how to use the following features of DPF:<br/>

- `sendNote`
- `getState`
- Layout-independent keyboard handling using keycodes


+ 13796
- 0
examples/MidiKeyboard/resources/MidiKeyboardResources.cpp
File diff suppressed because it is too large
View File


+ 30
- 0
examples/MidiKeyboard/resources/MidiKeyboardResources.hpp View File

@@ -0,0 +1,30 @@
/* (Auto-generated binary data file). */

#ifndef BINARY_MIDIKEYBOARDRESOURCES_HPP
#define BINARY_MIDIKEYBOARDRESOURCES_HPP

namespace MidiKeyboardResources
{
extern const char* black_keyData;
const unsigned int black_keyDataSize = 72329;
const unsigned int black_keyWidth = 32;
const unsigned int black_keyHeight = 72;

extern const char* black_key_pressedData;
const unsigned int black_key_pressedDataSize = 72336;
const unsigned int black_key_pressedWidth = 32;
const unsigned int black_key_pressedHeight = 72;

extern const char* white_keyData;
const unsigned int white_keyDataSize = 72329;
const unsigned int white_keyWidth = 46;
const unsigned int white_keyHeight = 112;

extern const char* white_key_pressedData;
const unsigned int white_key_pressedDataSize = 72338;
const unsigned int white_key_pressedWidth = 46;
const unsigned int white_key_pressedHeight = 112;
}

#endif // BINARY_MIDIKEYBOARDRESOURCES_HPP


+ 1917
- 0
examples/MidiKeyboard/resources/black_key.svg
File diff suppressed because it is too large
View File


+ 1917
- 0
examples/MidiKeyboard/resources/black_key_pressed.svg
File diff suppressed because it is too large
View File


+ 1917
- 0
examples/MidiKeyboard/resources/white_key.svg
File diff suppressed because it is too large
View File


+ 1917
- 0
examples/MidiKeyboard/resources/white_key_pressed.svg
File diff suppressed because it is too large
View File


Loading…
Cancel
Save