Browse Source

CairoWidget fixes; add cairo example (needs a little more work)

gh-pages
falkTX 7 years ago
parent
commit
8aad566744
7 changed files with 335 additions and 53 deletions
  1. +1
    -0
      .gitignore
  2. +105
    -41
      dgl/CairoWidget.hpp
  3. +10
    -4
      dgl/Widget.hpp
  4. +0
    -5
      dgl/src/Widget.cpp
  5. +5
    -2
      examples/Makefile
  6. +213
    -0
      examples/cairo.cpp
  7. +1
    -1
      examples/images.cpp

+ 1
- 0
.gitignore View File

@@ -9,6 +9,7 @@
.kdev_include_paths

examples/app
examples/cairo
examples/color
examples/images
examples/nekobi-ui

+ 105
- 41
dgl/CairoWidget.hpp View File

@@ -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:


+ 10
- 4
dgl/Widget.hpp View File

@@ -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;
};



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

@@ -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)


+ 5
- 2
examples/Makefile View File

@@ -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 $@



+ 213
- 0
examples/cairo.cpp View File

@@ -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;
}

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

+ 1
- 1
examples/images.cpp View File

@@ -35,7 +35,7 @@ using namespace DGL;
// our widget

class ExampleImagesWidget : public App::IdleCallback,
Widget
Widget
{
public:
static const int kImg1y = 0;


Loading…
Cancel
Save