aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dw/Makefile.am1
-rw-r--r--dw/imgrenderer.cc29
-rw-r--r--dw/imgrenderer.hh30
-rw-r--r--dw/style.cc71
-rw-r--r--dw/style.hh44
-rw-r--r--test/Makefile.am9
-rw-r--r--test/dw_image_background.cc143
7 files changed, 318 insertions, 9 deletions
diff --git a/dw/Makefile.am b/dw/Makefile.am
index 06a7af51..d0d56d2a 100644
--- a/dw/Makefile.am
+++ b/dw/Makefile.am
@@ -15,6 +15,7 @@ libDw_core_a_SOURCES = \
findtext.hh \
imgbuf.hh \
imgrenderer.hh \
+ imgrenderer.cc \
iterator.cc \
iterator.hh \
layout.cc \
diff --git a/dw/imgrenderer.cc b/dw/imgrenderer.cc
new file mode 100644
index 00000000..c5e6ea07
--- /dev/null
+++ b/dw/imgrenderer.cc
@@ -0,0 +1,29 @@
+#include "core.hh"
+
+namespace dw {
+namespace core {
+
+using namespace lout::container;
+using namespace lout::object;
+
+void ImgRendererDist::setBuffer (core::Imgbuf *buffer, bool resize)
+{
+ for (typed::Iterator <TypedPointer <ImgRenderer> > it =
+ children->iterator (); it.hasNext (); ) {
+ TypedPointer <ImgRenderer> *tp = it.getNext ();
+ tp->getTypedValue()->setBuffer (buffer, resize);
+ }
+}
+
+void ImgRendererDist::drawRow (int row)
+{
+ for (typed::Iterator <TypedPointer <ImgRenderer> > it =
+ children->iterator (); it.hasNext (); ) {
+ TypedPointer <ImgRenderer> *tp = it.getNext ();
+ tp->getTypedValue()->drawRow (row);
+ }
+}
+
+
+} // namespace core
+} // namespace dw
diff --git a/dw/imgrenderer.hh b/dw/imgrenderer.hh
index 9c7c6525..1efeef8c 100644
--- a/dw/imgrenderer.hh
+++ b/dw/imgrenderer.hh
@@ -16,10 +16,40 @@ namespace core {
class ImgRenderer
{
public:
+ virtual ~ImgRenderer () { }
+
virtual void setBuffer (core::Imgbuf *buffer, bool resize = false) = 0;
virtual void drawRow (int row) = 0;
};
+/**
+ * \brief Implementation of ImgRenderer, which distributes all calls
+ * to a set of other implementations of ImgRenderer.
+ *
+ * The order of the call children is not defined, especially not
+ * identical to the order in which they have been added.
+ */
+class ImgRendererDist: public ImgRenderer
+{
+ lout::container::typed::HashSet <lout::object::TypedPointer <ImgRenderer> >
+ *children;
+
+public:
+ inline ImgRendererDist ()
+ { children = new lout::container::typed::HashSet
+ <lout::object::TypedPointer <ImgRenderer> > (true); }
+ ~ImgRendererDist () { delete children; }
+
+ void setBuffer (core::Imgbuf *buffer, bool resize);
+ void drawRow (int row);
+
+ void put (ImgRenderer *child)
+ { children->put (new lout::object::TypedPointer <ImgRenderer> (child)); }
+ void remove (ImgRenderer *child)
+ { lout::object::TypedPointer <ImgRenderer> tp (child);
+ children->remove (&tp); }
+};
+
} // namespace core
} // namespace dw
diff --git a/dw/style.cc b/dw/style.cc
index 6c0abda2..089faae2 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -48,6 +48,7 @@ void StyleAttrs::initValues ()
listStyleType = LIST_STYLE_TYPE_DISC;
valign = VALIGN_BASELINE;
backgroundColor = NULL;
+ backgroundImage = NULL;
width = height = lineHeight = LENGTH_AUTO;
textIndent = 0;
margin.setVal (0);
@@ -76,6 +77,7 @@ void StyleAttrs::resetValues ()
valign = VALIGN_BASELINE;
textAlignChar = '.';
backgroundColor = NULL;
+ backgroundImage = NULL;
width = LENGTH_AUTO;
height = LENGTH_AUTO;
@@ -116,6 +118,7 @@ bool StyleAttrs::equals (object::Object *other) {
textDecoration == otherAttrs->textDecoration &&
color == otherAttrs->color &&
backgroundColor == otherAttrs->backgroundColor &&
+ backgroundImage == otherAttrs->backgroundImage &&
textAlign == otherAttrs->textAlign &&
valign == otherAttrs->valign &&
textAlignChar == otherAttrs->textAlignChar &&
@@ -156,6 +159,7 @@ int StyleAttrs::hashValue () {
textDecoration +
(intptr_t) color +
(intptr_t) backgroundColor +
+ (intptr_t) backgroundImage +
textAlign +
valign +
textAlignChar +
@@ -205,6 +209,8 @@ Style::Style (StyleAttrs *attrs)
color->ref ();
if (backgroundColor)
backgroundColor->ref ();
+ if (backgroundImage)
+ backgroundImage->ref ();
if (borderColor.top)
borderColor.top->ref();
if (borderColor.bottom)
@@ -227,6 +233,8 @@ Style::~Style ()
color->unref ();
if (backgroundColor)
backgroundColor->unref ();
+ if (backgroundImage)
+ backgroundImage->unref ();
if (borderColor.top)
borderColor.top->unref();
if (borderColor.bottom)
@@ -248,6 +256,7 @@ void Style::copyAttrs (StyleAttrs *attrs)
textDecoration = attrs->textDecoration;
color = attrs->color;
backgroundColor = attrs->backgroundColor;
+ backgroundImage = attrs->backgroundImage;
textAlign = attrs->textAlign;
valign = attrs->valign;
textAlignChar = attrs->textAlignChar;
@@ -422,6 +431,42 @@ Tooltip *Tooltip::create (Layout *layout, const char *text)
// ----------------------------------------------------------------------
+void StyleImage::StyleImgRenderer::setBuffer (core::Imgbuf *buffer, bool resize)
+{
+ if (image->imgbuf)
+ image->imgbuf->unref ();
+
+ image->imgbuf = buffer;
+ if (image->imgbuf)
+ image->imgbuf->ref ();
+}
+
+void StyleImage::StyleImgRenderer::drawRow (int row)
+{
+ // Nothing to do.
+}
+
+StyleImage::StyleImage ()
+{
+ refCount = 0;
+ imgbuf = NULL;
+
+ imgRendererDist = new ImgRendererDist ();
+ styleImgRenderer = new StyleImgRenderer (this);
+ imgRendererDist->put (styleImgRenderer);
+}
+
+StyleImage::~StyleImage ()
+{
+ if (imgbuf)
+ imgbuf->unref ();
+
+ delete imgRendererDist;
+ delete styleImgRenderer;
+}
+
+// ----------------------------------------------------------------------
+
/*
* The drawBorder{Top,Bottom,Left,Right} functions are similar. They
* use a trapezium as draw polygon, or drawTypedLine() for dots and dashes.
@@ -867,8 +912,11 @@ void drawBackground (View *view, Rectangle *area,
Style *style, bool inverse)
{
Rectangle bgArea, intersection;
+ bool bgColor = style->backgroundColor != NULL;
+ bool bgImage = (style->backgroundImage != NULL &&
+ style->backgroundImage->getImgbuf() != NULL);
- if (style->backgroundColor) {
+ if (bgColor || bgImage) {
bgArea.x = x + style->margin.left + style->borderWidth.left;
bgArea.y = y + style->margin.top + style->borderWidth.top;
bgArea.width =
@@ -878,12 +926,21 @@ void drawBackground (View *view, Rectangle *area,
height - style->margin.top - style->borderWidth.top -
style->margin.bottom - style->borderWidth.bottom;
- if (area->intersectsWith (&bgArea, &intersection))
- view->drawRectangle (style->backgroundColor,
- inverse ?
- Color::SHADING_INVERSE : Color::SHADING_NORMAL,
- true, intersection.x, intersection.y,
- intersection.width, intersection.height);
+ if (area->intersectsWith (&bgArea, &intersection)) {
+ if (bgColor)
+ view->drawRectangle (style->backgroundColor,
+ inverse ?
+ Color::SHADING_INVERSE : Color::SHADING_NORMAL,
+ true, intersection.x, intersection.y,
+ intersection.width, intersection.height);
+
+ if (bgImage)
+ // TODO Just a very simple test, incomplete.
+ view->drawImage (style->backgroundImage->getImgbuf(),
+ bgArea.x, bgArea.y, intersection.x - bgArea.x,
+ intersection.y - bgArea.y, intersection.width,
+ intersection.height);
+ }
}
}
diff --git a/dw/style.hh b/dw/style.hh
index 7c00ac1f..754b9667 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -7,6 +7,8 @@
# error Do not include this file directly, use "core.hh" instead.
#endif
+#include "../lout/signal.hh"
+
namespace dw {
namespace core {
@@ -431,9 +433,10 @@ public:
}
};
+class Tooltip;
class Font;
class Color;
-class Tooltip;
+class StyleImage;
/**
* \sa dw::core::style
@@ -445,6 +448,7 @@ public:
int textDecoration; /* No TextDecoration because of problems converting
* TextDecoration <-> int */
Color *color, *backgroundColor;
+ StyleImage *backgroundImage;
TextAlignType textAlign;
VAlignType valign;
@@ -504,7 +508,8 @@ public:
}
inline int boxDiffHeight () { return boxOffsetY () + boxRestHeight (); }
- inline bool hasBackground () { return backgroundColor != NULL; }
+ inline bool hasBackground ()
+ { return backgroundColor != NULL || backgroundImage != NULL; }
bool equals (lout::object::Object *other);
int hashValue ();
@@ -677,6 +682,41 @@ public:
{ if (--refCount == 0) delete this; }
};
+
+class StyleImage: public lout::signal::ObservedObject
+{
+private:
+ class StyleImgRenderer: public ImgRenderer
+ {
+ private:
+ StyleImage *image;
+
+ public:
+ inline StyleImgRenderer (StyleImage *image) { this->image = image; }
+
+ void setBuffer (core::Imgbuf *buffer, bool resize);
+ void drawRow (int row);
+ };
+
+ int refCount;
+ Imgbuf *imgbuf;
+ ImgRendererDist *imgRendererDist;
+ StyleImgRenderer *styleImgRenderer;
+
+ StyleImage ();
+ ~StyleImage ();
+
+public:
+ static StyleImage *create () { return new StyleImage (); }
+
+ inline void ref () { refCount++; }
+ inline void unref ()
+ { if (--refCount == 0) delete this; }
+
+ inline Imgbuf *getImgbuf () { return imgbuf; }
+ inline ImgRenderer *getMainImgRenderer () { return imgRendererDist; }
+};
+
void drawBorder (View *view, Rectangle *area,
int x, int y, int width, int height,
Style *style, bool inverse);
diff --git a/test/Makefile.am b/test/Makefile.am
index 6a834acb..156c8667 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -9,6 +9,7 @@ noinst_PROGRAMS = \
dw-find-test \
dw-links \
dw-links2 \
+ dw-image-background \
dw-images-simple \
dw-images-scaled \
dw-images-scaled2 \
@@ -67,6 +68,14 @@ dw_links2_LDADD = \
$(top_builddir)/lout/liblout.a \
@LIBFLTK_LIBS@
+dw_image_background_SOURCES = dw_image_background.cc
+dw_image_background_LDADD = \
+ $(top_builddir)/dw/libDw-widgets.a \
+ $(top_builddir)/dw/libDw-fltk.a \
+ $(top_builddir)/dw/libDw-core.a \
+ $(top_builddir)/lout/liblout.a \
+ @LIBFLTK_LIBS@
+
dw_images_simple_SOURCES = dw_images_simple.cc
dw_images_simple_LDADD = \
$(top_builddir)/dw/libDw-widgets.a \
diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc
new file mode 100644
index 00000000..95264f6a
--- /dev/null
+++ b/test/dw_image_background.cc
@@ -0,0 +1,143 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2013 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+
+#include "../dw/core.hh"
+#include "../dw/fltkcore.hh"
+#include "../dw/fltkviewport.hh"
+#include "../dw/textblock.hh"
+#include "../dw/image.hh"
+
+using namespace dw;
+using namespace dw::core;
+using namespace dw::core::style;
+using namespace dw::fltk;
+
+static StyleImage *image;
+static Layout *layout;
+static int imgRow = 0;
+
+static void imageInitTimeout (void *data)
+{
+ Imgbuf *imgbuf = layout->createImgbuf (Imgbuf::RGB, 400, 200, 1);
+ image->getMainImgRenderer()->setBuffer (imgbuf, false);
+}
+
+static void imageDrawTimeout (void *data)
+{
+ Imgbuf *imgbuf = image->getImgbuf ();
+
+ if (imgbuf) {
+ for (int i = 0; i < 1; i++) {
+ byte buf[3 * 400];
+ for(int x = 0; x < 400; x++) {
+ buf[3 * x + 0] = x * 255 / 399;
+ buf[3 * x + 1] = (399 - x) * 255 / 399;
+ buf[3 * x + 2] = imgRow * 255 / 199;
+ }
+
+ imgbuf->copyRow (imgRow, buf);
+ image->getMainImgRenderer()->drawRow (imgRow);
+ imgRow++;
+ }
+ }
+
+ if(imgRow < 200)
+ Fl::repeat_timeout (0.5, imageDrawTimeout, NULL);
+}
+
+int main(int argc, char **argv)
+{
+ FltkPlatform *platform = new FltkPlatform ();
+ layout = new Layout (platform);
+
+ Fl_Window *window = new Fl_Window(200, 300, "Dw Example");
+ window->box(FL_NO_BOX);
+ window->begin();
+
+ FltkViewport *viewport = new FltkViewport (0, 0, 200, 300);
+ layout->attachView (viewport);
+
+ StyleAttrs styleAttrs;
+ styleAttrs.initValues ();
+ styleAttrs.margin.setVal (5);
+
+ FontAttrs fontAttrs;
+ fontAttrs.name = "Bitstream Charter";
+ fontAttrs.size = 14;
+ fontAttrs.weight = 400;
+ fontAttrs.style = FONT_STYLE_NORMAL;
+ fontAttrs.letterSpacing = 0;
+ fontAttrs.fontVariant = FONT_VARIANT_NORMAL;
+ styleAttrs.font = style::Font::create (layout, &fontAttrs);
+
+ styleAttrs.color = Color::create (layout, 0x000000);
+ styleAttrs.backgroundColor = Color::create (layout, 0xffffff);
+
+ image = styleAttrs.backgroundImage = StyleImage::create ();
+
+ Style *widgetStyle = Style::create (&styleAttrs);
+
+ Textblock *textblock = new Textblock (false);
+ textblock->setStyle (widgetStyle);
+ layout->setWidget (textblock);
+
+ widgetStyle->unref();
+
+ styleAttrs.margin.setVal (0);
+ styleAttrs.backgroundColor = NULL;
+ styleAttrs.backgroundImage = NULL;
+
+ Style *wordStyle = Style::create (&styleAttrs);
+
+ for(int i = 1; i <= 10; i++) {
+ char buf[4];
+ sprintf(buf, "%d.", i);
+
+ const char *words[] = { "This", "is", "the", buf, "paragraph.",
+ "Here", "comes", "some", "more", "text",
+ "to", "demonstrate", "word", "wrapping.",
+ NULL };
+
+ for(int j = 0; words[j]; j++) {
+ textblock->addText(words[j], wordStyle);
+ textblock->addSpace(wordStyle);
+ }
+
+ textblock->addParbreak(10, wordStyle);
+ }
+
+ wordStyle->unref();
+
+ textblock->flush ();
+
+ window->resizable(viewport);
+ window->show();
+
+ Fl::add_timeout (2.0, imageInitTimeout, NULL);
+ Fl::add_timeout (0.1, imageDrawTimeout, NULL);
+
+ int errorCode = Fl::run();
+
+ delete layout;
+
+ return errorCode;
+}