| @@ -9,6 +9,7 @@ | |||
| .kdev_include_paths | |||
| examples/app | |||
| examples/cairo | |||
| examples/color | |||
| examples/images | |||
| examples/nekobi-ui | |||
| @@ -21,6 +21,8 @@ | |||
| #include <cairo.h> | |||
| #include <cstdio> | |||
| 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 | |||
| { | |||
| // wait for first resize | |||
| // wait for sizing | |||
| if (fSurface == nullptr || fContext == nullptr) | |||
| { | |||
| glClear(GL_COLOR_BUFFER_BIT); | |||
| printf("invalid surface\n"); | |||
| 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 height = getHeight(); | |||
| @@ -108,25 +117,80 @@ private: | |||
| glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData); | |||
| // 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); | |||
| 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(); | |||
| // cleanup | |||
| glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); | |||
| 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: | |||
| @@ -60,10 +60,15 @@ public: | |||
| int getHeight() 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; | |||
| @@ -90,6 +95,7 @@ private: | |||
| bool fVisible; | |||
| Rectangle<int> fArea; | |||
| friend class CairoWidget; | |||
| friend class Window; | |||
| }; | |||
| @@ -153,11 +153,6 @@ void Widget::setHeight(int height) | |||
| fParent.repaint(); | |||
| } | |||
| void Widget::setSize(int width, int height) | |||
| { | |||
| setSize(Size<int>(width, height)); | |||
| } | |||
| void Widget::setSize(const Size<int>& size) | |||
| { | |||
| if (fArea.getSize() == size) | |||
| @@ -14,9 +14,9 @@ LINK_FLAGS += -L.. -ldgl $(DGL_LIBS) | |||
| # -------------------------------------------------------------- | |||
| ifeq ($(WIN32),true) | |||
| TARGETS = app.exe color images.exe nekobi-ui.exe | |||
| TARGETS = app.exe cairo.exe color images.exe nekobi-ui.exe | |||
| else | |||
| TARGETS = app color images nekobi-ui | |||
| TARGETS = app cairo color images nekobi-ui | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| @@ -35,6 +35,9 @@ all: ../libdgl.a $(TARGETS) | |||
| app: app.cpp ../dgl/* | |||
| $(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/* | |||
| $(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 | |||
| class ExampleImagesWidget : public App::IdleCallback, | |||
| Widget | |||
| Widget | |||
| { | |||
| public: | |||
| static const int kImg1y = 0; | |||