| @@ -9,6 +9,7 @@ | |||||
| .kdev_include_paths | .kdev_include_paths | ||||
| examples/app | examples/app | ||||
| examples/cairo | |||||
| examples/color | examples/color | ||||
| examples/images | examples/images | ||||
| examples/nekobi-ui | examples/nekobi-ui | ||||
| @@ -21,6 +21,8 @@ | |||||
| #include <cairo.h> | #include <cairo.h> | ||||
| #include <cstdio> | |||||
| START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -36,56 +38,63 @@ public: | |||||
| { | { | ||||
| } | } | ||||
| protected: | |||||
| virtual void cairoDisplay(cairo_t* const context) = 0; | |||||
| private: | |||||
| void onReshape(int width, int height) override | |||||
| virtual void setWidth(int width) override | |||||
| { | { | ||||
| // handle resize | |||||
| setSize(width, height); | |||||
| Widget::onReshape(width, height); | |||||
| if (fArea.getWidth() == width) | |||||
| return; | |||||
| // free previous if needed | |||||
| onClose(); | |||||
| Widget::setWidth(width); | |||||
| _recreateSurface(); | |||||
| } | |||||
| // create new | |||||
| fSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); | |||||
| fContext = cairo_create(fSurface); | |||||
| virtual void setHeight(int height) override | |||||
| { | |||||
| if (fArea.getHeight() == height) | |||||
| return; | |||||
| glGenTextures(1, &fTextureId); | |||||
| Widget::setHeight(height); | |||||
| _recreateSurface(); | |||||
| } | } | ||||
| void onClose() override | |||||
| virtual void setSize(const Size<int>& size) override | |||||
| { | { | ||||
| if (fContext != nullptr) | |||||
| { | |||||
| cairo_destroy(fContext); | |||||
| fContext = nullptr; | |||||
| } | |||||
| if (fArea.getSize() == size) | |||||
| return; | |||||
| if (fSurface != nullptr) | |||||
| { | |||||
| cairo_surface_destroy(fSurface); | |||||
| fSurface = nullptr; | |||||
| } | |||||
| Widget::setSize(size); | |||||
| _recreateSurface(); | |||||
| } | |||||
| if (fTextureId != 0) | |||||
| { | |||||
| glDeleteTextures(1, &fTextureId); | |||||
| fTextureId = 0; | |||||
| } | |||||
| void setSize(int width, int height) | |||||
| { | |||||
| setSize(Size<int>(width, height)); | |||||
| } | } | ||||
| protected: | |||||
| virtual void cairoDisplay(cairo_t* const context) = 0; | |||||
| private: | |||||
| void onDisplay() override | void onDisplay() override | ||||
| { | { | ||||
| // wait for first resize | |||||
| // wait for sizing | |||||
| if (fSurface == nullptr || fContext == nullptr) | if (fSurface == nullptr || fContext == nullptr) | ||||
| { | { | ||||
| glClear(GL_COLOR_BUFFER_BIT); | |||||
| printf("invalid surface\n"); | |||||
| return; | return; | ||||
| } | } | ||||
| if (fTextureId == 0) | |||||
| glGenTextures(1, &fTextureId); | |||||
| if (fTextureId == 0) | |||||
| { | |||||
| // TODO: invalidate widget | |||||
| printf("invalid texture\n"); | |||||
| return; | |||||
| } | |||||
| #if 1 | |||||
| const int x = getX(); | |||||
| const int y = getY(); | |||||
| const int width = getWidth(); | const int width = getWidth(); | ||||
| const int height = getHeight(); | const int height = getHeight(); | ||||
| @@ -108,25 +117,80 @@ private: | |||||
| glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData); | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData); | ||||
| // draw the texture | // draw the texture | ||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |||||
| glBegin(GL_QUADS); | |||||
| glTexCoord2i(0, height); | |||||
| glVertex2i(0, height); | |||||
| // glBegin(GL_QUADS); | |||||
| // glTexCoord2f(0.0f, 0.0f); | |||||
| // glVertex2i(x, y); | |||||
| // | |||||
| // glTexCoord2f(1.0f, 0.0f); | |||||
| // glVertex2i(x+width, y); | |||||
| // | |||||
| // glTexCoord2f(1.0f, 1.0f); | |||||
| // glVertex2i(x+width, y+height); | |||||
| // | |||||
| // glTexCoord2f(0.0f, 1.0f); | |||||
| // glVertex2i(x, y+height); | |||||
| // glEnd(); | |||||
| glTexCoord2i(width, height); | |||||
| glVertex2i(width, height); | |||||
| glBegin(GL_QUADS); | |||||
| //glTexCoord2i(x, y); | |||||
| glTexCoord2i(0, 0); | |||||
| glVertex2i(x, y); | |||||
| //glTexCoord2i(x+width, y); | |||||
| glTexCoord2i(width, 0); | glTexCoord2i(width, 0); | ||||
| glVertex2i(width, 0); | |||||
| glVertex2i(x+width, y); | |||||
| glTexCoord2i(0, 0); | |||||
| glVertex2i(0, 0); | |||||
| //glTexCoord2i(x+width, y+height); | |||||
| glTexCoord2i(width, height); | |||||
| glVertex2i(x+width, y+height); | |||||
| //glTexCoord2i(x, y+height); | |||||
| glTexCoord2i(0, height); | |||||
| glVertex2i(x, y+height); | |||||
| glEnd(); | glEnd(); | ||||
| // cleanup | // cleanup | ||||
| glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); | ||||
| glDisable(GL_TEXTURE_RECTANGLE_ARB); | glDisable(GL_TEXTURE_RECTANGLE_ARB); | ||||
| #endif | |||||
| } | |||||
| void onClose() override | |||||
| { | |||||
| if (fContext != nullptr) | |||||
| { | |||||
| cairo_destroy(fContext); | |||||
| fContext = nullptr; | |||||
| } | |||||
| if (fSurface != nullptr) | |||||
| { | |||||
| cairo_surface_destroy(fSurface); | |||||
| fSurface = nullptr; | |||||
| } | |||||
| if (fTextureId != 0) | |||||
| { | |||||
| glDeleteTextures(1, &fTextureId); | |||||
| fTextureId = 0; | |||||
| } | |||||
| } | |||||
| void _recreateSurface() | |||||
| { | |||||
| if (fContext != nullptr) | |||||
| cairo_destroy(fContext); | |||||
| if (fSurface != nullptr) | |||||
| cairo_surface_destroy(fSurface); | |||||
| fSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, fArea.getWidth(), fArea.getHeight()); | |||||
| if (fSurface != nullptr) | |||||
| fContext = cairo_create(fSurface); | |||||
| else | |||||
| fContext = nullptr; | |||||
| } | } | ||||
| private: | private: | ||||
| @@ -60,10 +60,15 @@ public: | |||||
| int getHeight() const noexcept; | int getHeight() const noexcept; | ||||
| const Size<int>& getSize() const noexcept; | const Size<int>& getSize() const noexcept; | ||||
| void setWidth(int width); | |||||
| void setHeight(int height); | |||||
| void setSize(int width, int height); | |||||
| void setSize(const Size<int>& size); | |||||
| // virtual needed by cairo | |||||
| virtual void setWidth(int width); | |||||
| virtual void setHeight(int height); | |||||
| virtual void setSize(const Size<int>& size); | |||||
| void setSize(int width, int height) | |||||
| { | |||||
| setSize(Size<int>(width, height)); | |||||
| } | |||||
| const Rectangle<int>& getArea() const noexcept; | const Rectangle<int>& getArea() const noexcept; | ||||
| @@ -90,6 +95,7 @@ private: | |||||
| bool fVisible; | bool fVisible; | ||||
| Rectangle<int> fArea; | Rectangle<int> fArea; | ||||
| friend class CairoWidget; | |||||
| friend class Window; | friend class Window; | ||||
| }; | }; | ||||
| @@ -153,11 +153,6 @@ void Widget::setHeight(int height) | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| } | } | ||||
| void Widget::setSize(int width, int height) | |||||
| { | |||||
| setSize(Size<int>(width, height)); | |||||
| } | |||||
| void Widget::setSize(const Size<int>& size) | void Widget::setSize(const Size<int>& size) | ||||
| { | { | ||||
| if (fArea.getSize() == size) | if (fArea.getSize() == size) | ||||
| @@ -14,9 +14,9 @@ LINK_FLAGS += -L.. -ldgl $(DGL_LIBS) | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| ifeq ($(WIN32),true) | ifeq ($(WIN32),true) | ||||
| TARGETS = app.exe color images.exe nekobi-ui.exe | |||||
| TARGETS = app.exe cairo.exe color images.exe nekobi-ui.exe | |||||
| else | else | ||||
| TARGETS = app color images nekobi-ui | |||||
| TARGETS = app cairo color images nekobi-ui | |||||
| endif | endif | ||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| @@ -35,6 +35,9 @@ all: ../libdgl.a $(TARGETS) | |||||
| app: app.cpp ../dgl/* | app: app.cpp ../dgl/* | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | ||||
| cairo: cairo.cpp ../dgl/* | |||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags --libs cairo) $(LINK_FLAGS) -o $@ | |||||
| color: color.cpp ../dgl/* | color: color.cpp ../dgl/* | ||||
| $(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | $(CXX) $< $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ | ||||
| @@ -0,0 +1,213 @@ | |||||
| /* | |||||
| * DISTRHO Plugin Toolkit (DPT) | |||||
| * Copyright (C) 2012-2013 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. | |||||
| */ | |||||
| // ------------------------------------------------------ | |||||
| // DGL Stuff | |||||
| #include "App.hpp" | |||||
| #include "CairoWidget.hpp" | |||||
| #include "Window.hpp" | |||||
| #include <cstdio> | |||||
| // ------------------------------------------------------ | |||||
| // use namespace | |||||
| using namespace DGL; | |||||
| // ------------------------------------------------------ | |||||
| // Background widget (cairo will be painted on top) | |||||
| class BackgroundWidget : public Widget | |||||
| { | |||||
| public: | |||||
| BackgroundWidget(Window& parent) | |||||
| : Widget(parent) | |||||
| { | |||||
| } | |||||
| private: | |||||
| void onDisplay() override | |||||
| { | |||||
| int x = 0; | |||||
| int y = 0; | |||||
| int width = getWidth(); | |||||
| int height = getHeight(); | |||||
| // paint bg color (in full size) | |||||
| glColor3b(20, 80, 20); | |||||
| glBegin(GL_QUADS); | |||||
| glTexCoord2f(0.0f, 0.0f); | |||||
| glVertex2i(x, y); | |||||
| glTexCoord2f(1.0f, 0.0f); | |||||
| glVertex2i(x+width, y); | |||||
| glTexCoord2f(1.0f, 1.0f); | |||||
| glVertex2i(x+width, y+height); | |||||
| glTexCoord2f(0.0f, 1.0f); | |||||
| glVertex2i(x, y+height); | |||||
| glEnd(); | |||||
| } | |||||
| void onReshape(int width, int height) override | |||||
| { | |||||
| // make this widget same size as window | |||||
| setSize(width, height); | |||||
| Widget::onReshape(width, height); | |||||
| } | |||||
| }; | |||||
| // ------------------------------------------------------ | |||||
| // Custom Cairo Widget | |||||
| class CustomCairoWidget : public App::IdleCallback, | |||||
| CairoWidget | |||||
| { | |||||
| public: | |||||
| CustomCairoWidget(Window& parent) | |||||
| : CairoWidget(parent), | |||||
| value(0.0f), | |||||
| pressed(false) | |||||
| { | |||||
| setSize(100, 100); | |||||
| } | |||||
| private: | |||||
| void idleCallback() override | |||||
| { | |||||
| value += 0.001f; | |||||
| if (value > 1.0f) | |||||
| value = 0; | |||||
| repaint(); | |||||
| } | |||||
| void cairoDisplay(cairo_t* const context) override | |||||
| { | |||||
| const int w = getWidth(); | |||||
| const int h = getHeight(); | |||||
| float radius = 40.0f; | |||||
| // * 0.9 for line width to remain inside redraw area | |||||
| if (w > h) | |||||
| radius = (h / 2.0f)*0.9f; | |||||
| else | |||||
| radius = (w / 2.0f)*0.9f; | |||||
| cairo_save(context); | |||||
| cairo_rectangle(context, 0, 0, w, h ); | |||||
| cairo_set_source_rgba(context, 1.1, 0.1, 0.1, 0 ); | |||||
| cairo_fill(context); | |||||
| cairo_set_line_join(context, CAIRO_LINE_JOIN_ROUND); | |||||
| cairo_set_line_cap(context, CAIRO_LINE_CAP_ROUND); | |||||
| cairo_set_line_width(context, 5-0.2); | |||||
| cairo_move_to(context, w/2, h/2); | |||||
| cairo_line_to(context, w/2, h/2); | |||||
| cairo_set_source_rgba(context, 0.1, 0.1, 0.1, 0 ); | |||||
| cairo_stroke(context); | |||||
| cairo_arc(context, w/2, h/2, radius, 2.46, 0.75 ); | |||||
| cairo_set_source_rgb(context, 0.1, 0.1, 0.1 ); | |||||
| cairo_stroke(context); | |||||
| float angle = 2.46 + ( 4.54 * value ); | |||||
| cairo_set_line_width(context, 5); | |||||
| cairo_arc(context, w/2, h/2, radius, 2.46, angle ); | |||||
| cairo_line_to(context, w/2, h/2); | |||||
| cairo_set_source_rgba(context, 1.0, 0.48, 0, 0.8); | |||||
| cairo_stroke(context); | |||||
| cairo_restore(context); | |||||
| } | |||||
| bool onMouse(int button, bool press, int x, int y) | |||||
| { | |||||
| if (button == 1) | |||||
| { | |||||
| pressed = press; | |||||
| if (press) | |||||
| { | |||||
| setX(x-100/2); | |||||
| setY(y-100/2); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool onMotion(int x, int y) | |||||
| { | |||||
| if (pressed) | |||||
| { | |||||
| setX(x-100/2); | |||||
| setY(y-100/2); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| float value; | |||||
| bool pressed; | |||||
| }; | |||||
| // ------------------------------------------------------ | |||||
| // Custom window, with bg + cairo + image | |||||
| class CustomWindow : public Window | |||||
| { | |||||
| public: | |||||
| CustomWindow(App& app) | |||||
| : Window(app), | |||||
| bg(*this), | |||||
| cairo(*this) | |||||
| { | |||||
| app.addIdleCallback(&cairo); | |||||
| } | |||||
| private: | |||||
| BackgroundWidget bg; | |||||
| CustomCairoWidget cairo; | |||||
| }; | |||||
| // ------------------------------------------------------ | |||||
| // main entry point | |||||
| int main() | |||||
| { | |||||
| App app; | |||||
| CustomWindow win(app); | |||||
| win.setSize(300, 300); | |||||
| win.setTitle("Cairo"); | |||||
| win.show(); | |||||
| app.exec(); | |||||
| return 0; | |||||
| } | |||||
| // ------------------------------------------------------ | |||||
| @@ -35,7 +35,7 @@ using namespace DGL; | |||||
| // our widget | // our widget | ||||
| class ExampleImagesWidget : public App::IdleCallback, | class ExampleImagesWidget : public App::IdleCallback, | ||||
| Widget | |||||
| Widget | |||||
| { | { | ||||
| public: | public: | ||||
| static const int kImg1y = 0; | static const int kImg1y = 0; | ||||