From 06f5833b8f41196bc427c06e39ed21d431c1e665 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 10 Sep 2013 21:00:58 +0200 Subject: Some refactoring: the image decoding code now only accesses dw::core::ImgRenderer, not dw::Image (which now implements the former) anymore. --- dw/Makefile.am | 1 + dw/core.hh | 1 + dw/image.hh | 2 +- dw/imgrenderer.hh | 28 ++++++++++++++++++++++++++++ src/dicache.c | 7 ++++--- src/form.cc | 8 ++++++-- src/html.cc | 25 ++++++++++++++++++------- src/image.cc | 13 +++++++------ src/image.hh | 4 ++-- src/imgbuf.cc | 6 +++--- src/imgbuf.hh | 2 +- 11 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 dw/imgrenderer.hh diff --git a/dw/Makefile.am b/dw/Makefile.am index e108da60..06a7af51 100644 --- a/dw/Makefile.am +++ b/dw/Makefile.am @@ -14,6 +14,7 @@ libDw_core_a_SOURCES = \ findtext.cc \ findtext.hh \ imgbuf.hh \ + imgrenderer.hh \ iterator.cc \ iterator.hh \ layout.cc \ diff --git a/dw/core.hh b/dw/core.hh index f39c38cc..022574b1 100644 --- a/dw/core.hh +++ b/dw/core.hh @@ -44,6 +44,7 @@ class ResourceFactory; #include "types.hh" #include "events.hh" #include "imgbuf.hh" +#include "imgrenderer.hh" #include "style.hh" #include "view.hh" #include "platform.hh" diff --git a/dw/image.hh b/dw/image.hh index a8314d4f..7ac05c20 100644 --- a/dw/image.hh +++ b/dw/image.hh @@ -116,7 +116,7 @@ public: * * \sa\ref dw-images-and-backgrounds */ -class Image: public core::Widget +class Image: public core::Widget, public core::ImgRenderer { private: char *altText; diff --git a/dw/imgrenderer.hh b/dw/imgrenderer.hh new file mode 100644 index 00000000..9c7c6525 --- /dev/null +++ b/dw/imgrenderer.hh @@ -0,0 +1,28 @@ +#ifndef __DW_IMGRENDERER_HH__ +#define __DW_IMGRENDERER_HH__ + +#ifndef __INCLUDED_FROM_DW_CORE_HH__ +# error Do not include this file directly, use "core.hh" instead. +#endif + +namespace dw { +namespace core { + +/** + * \brief ... + * + * \sa \ref dw-images-and-backgrounds + */ +class ImgRenderer +{ +public: + virtual void setBuffer (core::Imgbuf *buffer, bool resize = false) = 0; + virtual void drawRow (int row) = 0; +}; + +} // namespace core +} // namespace dw + +#endif // __DW_IMGRENDERER_HH__ + + diff --git a/src/dicache.c b/src/dicache.c index 55232846..673d5907 100644 --- a/src/dicache.c +++ b/src/dicache.c @@ -276,7 +276,8 @@ void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, /* BUG: there's just one image-type now */ #define I_RGB 0 - DicEntry->v_imgbuf = a_Imgbuf_new(Image->dw, I_RGB, width, height, gamma); + DicEntry->v_imgbuf = + a_Imgbuf_new(Image->layout, I_RGB, width, height, gamma); DicEntry->TotalSize = width * height * 3; DicEntry->width = width; @@ -402,7 +403,7 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, dReturn_val_if_fail(MimeType && Ptr, NULL); if (!web->Image) { - web->Image = a_Image_new(NULL, web->bgColor); + web->Image = a_Image_new(NULL, NULL, web->bgColor); a_Image_ref(web->Image); } @@ -429,7 +430,7 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, *Data = DicEntry->DecoderData; *Call = (CA_Callback_t) a_Dicache_callback; - return (web->Image->dw); + return (web->Image->img_rnd); } /* diff --git a/src/form.cc b/src/form.cc index f756a1c9..7c747c5a 100644 --- a/src/form.cc +++ b/src/form.cc @@ -2004,10 +2004,14 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize) /* create new image and add it to the button */ a_Html_image_attrs(html, tag, tagsize); if ((Image = a_Html_image_new(html, tag, tagsize))) { - IM2DW(Image)->setStyle (html->styleEngine->backgroundStyle ()); + // At this point, we know that Image->ir represents an image + // widget. Notice that the order of the casts matters, because + // of multiple inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rnd; + dwi->setStyle (html->styleEngine->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); ComplexButtonResource *complex_b_r = - factory->createComplexButtonResource(IM2DW(Image), false); + factory->createComplexButtonResource(dwi, false); button = new Embed(complex_b_r); HT2TB(html)->addWidget (button, html->styleEngine->style ()); } diff --git a/src/html.cc b/src/html.cc index adfd818e..e8aeb12d 100644 --- a/src/html.cc +++ b/src/html.cc @@ -2195,7 +2195,9 @@ DilloImage *a_Html_image_new(DilloHtml *html, const char *tag, int tagsize) alt_ptr = dStrdup("[IMG]"); // Place holder for img_off mode } - image = a_Image_new(alt_ptr, 0); + dw::Image *dw = new dw::Image(alt_ptr); + image = + a_Image_new(html->dw->getLayout(), (void*)(dw::core::ImgRenderer*)dw, 0); if (HT2TB(html)->getBgColor()) image->bg_color = HT2TB(html)->getBgColor()->getColor(); @@ -2272,11 +2274,15 @@ static void Html_tag_content_img(DilloHtml *html, const char *tag, int tagsize) /* TODO: usemap URLs outside of the document are not used. */ usemap_url = a_Html_url_new(html, attrbuf, NULL, 0); - HT2TB(html)->addWidget((Widget*)Image->dw, html->styleEngine->style()); + // At this point, we know that Image->ir represents an image + // widget. Notice that the order of the casts matters, because of + // multiple inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rnd; + HT2TB(html)->addWidget(dwi, html->styleEngine->style()); /* Image maps */ if (a_Html_get_attr(html, tag, tagsize, "ismap")) { - ((::dw::Image*)Image->dw)->setIsMap(); + dwi->setIsMap(); _MSG(" Html_tag_open_img: server-side map (ISMAP)\n"); } else if (html->styleEngine->style ()->x_link != -1 && usemap_url == NULL) { @@ -2286,8 +2292,7 @@ static void Html_tag_content_img(DilloHtml *html, const char *tag, int tagsize) } if (usemap_url) { - ((::dw::Image*)Image->dw)->setUseMap(&html->maps, - new ::object::String(URL_STR(usemap_url))); + dwi->setUseMap(&html->maps, new ::object::String(URL_STR(usemap_url))); a_Url_free (usemap_url); } } @@ -2330,8 +2335,14 @@ static void Html_tag_close_map(DilloHtml *html) for (int i = 0; i < html->images->size(); i++) { DilloImage *img = html->images->get(i)->image; - if (img) - ((dw::Image*) img->dw)->forceMapRedraw(); + if (img) { + // At this point, we know that img->ir represents an image + // widget. (Really? Is this assumtion safe?) Notice that the + // order of the casts matters, because of multiple + // inheritance. + dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)img->img_rnd; + dwi->forceMapRedraw(); + } } html->InFlags &= ~IN_MAP; } diff --git a/src/image.cc b/src/image.cc index c499d977..570c012a 100644 --- a/src/image.cc +++ b/src/image.cc @@ -23,19 +23,20 @@ using namespace dw::core; -// Image to Object-Image macro -#define I2DW(Image) ((dw::Image*)(Image->dw)) +// Image to Object-ImgRenderer macro +#define I2IR(Image) ((dw::core::ImgRenderer*)(Image->img_rnd)) /* * Create and initialize a new image structure. */ -DilloImage *a_Image_new(const char *alt_text, int32_t bg_color) +DilloImage *a_Image_new(void *layout, void *img_rnd, int32_t bg_color) { DilloImage *Image; Image = dNew(DilloImage, 1); - Image->dw = (void*) new dw::Image(alt_text); + Image->layout = layout; + Image->img_rnd = img_rnd; Image->width = 0; Image->height = 0; Image->bg_color = bg_color; @@ -88,7 +89,7 @@ void a_Image_set_parms(DilloImage *Image, void *v_imgbuf, DilloUrl *url, _MSG("a_Image_set_parms: width=%d height=%d\n", width, height); bool resize = (Image->width != width || Image->height != height); - I2DW(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); + I2IR(Image)->setBuffer((Imgbuf*)v_imgbuf, resize); if (!Image->BitVec) Image->BitVec = a_Bitvec_new(height); @@ -106,7 +107,7 @@ void a_Image_write(DilloImage *Image, uint_t y) dReturn_if_fail ( y < Image->height ); /* Update the row in DwImage */ - I2DW(Image)->drawRow(y); + I2IR(Image)->drawRow(y); a_Bitvec_set_bit(Image->BitVec, y); Image->State = IMG_Write; } diff --git a/src/image.hh b/src/image.hh index a66edaae..80f23461 100644 --- a/src/image.hh +++ b/src/image.hh @@ -44,7 +44,7 @@ typedef enum { } ImageState; struct _DilloImage { - void *dw; + void *layout, *img_rnd; /* Parameters as told by image data */ uint_t width; @@ -62,7 +62,7 @@ struct _DilloImage { /* * Function prototypes */ -DilloImage *a_Image_new(const char *alt_text, int32_t bg_color); +DilloImage *a_Image_new(void *layout, void *img_rnd, int32_t bg_color); void a_Image_ref(DilloImage *Image); void a_Image_unref(DilloImage *Image); diff --git a/src/imgbuf.cc b/src/imgbuf.cc index 16eb5c31..48e6bde5 100644 --- a/src/imgbuf.cc +++ b/src/imgbuf.cc @@ -90,10 +90,9 @@ void a_Imgbuf_unref(void *v_imgbuf) /* * Create a new Imgbuf */ -void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, +void *a_Imgbuf_new(void *layout, int img_type, uint_t width, uint_t height, double gamma) { - Layout *layout = ((Widget*)v_dw)->getLayout(); if (!layout) { MSG_ERR("a_Imgbuf_new: layout is NULL.\n"); exit(1); @@ -104,7 +103,8 @@ void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, linebuf = (uchar_t*) dRealloc(linebuf, linebuf_size); } - return (void*)layout->createImgbuf(Imgbuf::RGB, width, height, gamma); + return (void*)((Layout*)layout)->createImgbuf(Imgbuf::RGB, width, height, + gamma); } /* diff --git a/src/imgbuf.hh b/src/imgbuf.hh index af0bf9a6..efa1b48c 100644 --- a/src/imgbuf.hh +++ b/src/imgbuf.hh @@ -16,7 +16,7 @@ extern "C" { */ void a_Imgbuf_ref(void *v_imgbuf); void a_Imgbuf_unref(void *v_imgbuf); -void *a_Imgbuf_new(void *v_dw, int img_type, uint_t width, uint_t height, +void *a_Imgbuf_new(void *v_ir, int img_type, uint_t width, uint_t height, double gamma); int a_Imgbuf_last_reference(void *v_imgbuf); void a_Imgbuf_update(void *v_imgbuf, const uchar_t *buf, DilloImgType type, -- cgit v1.2.3 From 7173e6047f26d71718502570836ef0ab158deab2 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 12 Sep 2013 10:52:03 +0200 Subject: Added basic functionality for background images to dw::style. Drawing still very incomplete. --- dw/Makefile.am | 1 + dw/imgrenderer.cc | 29 +++++++++ dw/imgrenderer.hh | 30 ++++++++++ dw/style.cc | 71 +++++++++++++++++++--- dw/style.hh | 44 +++++++++++++- test/Makefile.am | 9 +++ test/dw_image_background.cc | 143 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 318 insertions(+), 9 deletions(-) create mode 100644 dw/imgrenderer.cc create mode 100644 test/dw_image_background.cc 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 > it = + children->iterator (); it.hasNext (); ) { + TypedPointer *tp = it.getNext (); + tp->getTypedValue()->setBuffer (buffer, resize); + } +} + +void ImgRendererDist::drawRow (int row) +{ + for (typed::Iterator > it = + children->iterator (); it.hasNext (); ) { + TypedPointer *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 > + *children; + +public: + inline ImgRendererDist () + { children = new lout::container::typed::HashSet + > (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 (child)); } + void remove (ImgRenderer *child) + { lout::object::TypedPointer 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 + * + * 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 . + */ + +#include +#include + +#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; +} -- cgit v1.2.3 From 280994c5459fdd99e2dc0b9f791ccfdfdb8589ad Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 12 Sep 2013 17:58:18 +0200 Subject: Some cleanup and fixes for recent changes. --- dw/style.cc | 25 ++++++++++++++++++++----- dw/style.hh | 6 +++--- dw/widget.cc | 33 +++++++++------------------------ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index 089faae2..373ffa8d 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -869,7 +869,7 @@ static void drawBorderRight(View *view, Style *style, * * Used by dw::core::Widget::drawBox and dw::core::Widget::drawWidgetBox. */ -void drawBorder (View *view, Rectangle *area, +void drawBorder (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse) { @@ -906,17 +906,32 @@ void drawBorder (View *view, Rectangle *area, * according to style. * * Used by dw::core::Widget::drawBox and dw::core::Widget::drawWidgetBox. + * + * "atTop" should be true, only if the area is drawn directly on the + * canvas, not on top of other areas; this is only true for the + * toplevel widget itself (not parts of its contents). Toplevel widget + * background colors are already set as viewport background color, so + * that drawing again is is not neccessary, but some time can be + * saved. + * + * Otherwise, the caller should not try to increase the performance by + * doing some tests befre; this is all done in this method. */ -void drawBackground (View *view, Rectangle *area, +void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, - Style *style, bool inverse) + Style *style, bool inverse, bool atTop) { - Rectangle bgArea, intersection; - bool bgColor = style->backgroundColor != NULL; + bool bgColor = style->backgroundColor != NULL && + (!atTop || layout->getBgColor () != style->backgroundColor); bool bgImage = (style->backgroundImage != NULL && style->backgroundImage->getImgbuf() != NULL); + // Since widgets are always drawn from top to bottom, it is *not* + // necessary to draw the background if background color and image + // are not set (NULL), i. e. shining through. + if (bgColor || bgImage) { + Rectangle bgArea, intersection; bgArea.x = x + style->margin.left + style->borderWidth.left; bgArea.y = y + style->margin.top + style->borderWidth.top; bgArea.width = diff --git a/dw/style.hh b/dw/style.hh index 754b9667..187cd6be 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -717,12 +717,12 @@ public: inline ImgRenderer *getMainImgRenderer () { return imgRendererDist; } }; -void drawBorder (View *view, Rectangle *area, +void drawBorder (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, Style *style, bool inverse); -void drawBackground (View *view, Rectangle *area, +void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, - Style *style, bool inverse); + Style *style, bool inverse, bool atTop); void numtostr (int num, char *buf, int buflen, ListStyleType listStyleType); } // namespace style diff --git a/dw/widget.cc b/dw/widget.cc index 9c6fe380..648f629b 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -346,14 +346,13 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, viewArea.width = area->width; viewArea.height = area->height; - style::drawBorder (view, &viewArea, allocation.x + x, allocation.y + y, + style::drawBorder (view, layout, &viewArea, + allocation.x + x, allocation.y + y, width, height, style, inverse); - /** \todo Background images? */ - if (style->backgroundColor) - style::drawBackground (view, &viewArea, - allocation.x + x, allocation.y + y, width, height, - style, inverse); + style::drawBackground (view, layout, &viewArea, + allocation.x + x, allocation.y + y, width, height, + style, inverse, false); } /** @@ -370,26 +369,12 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) viewArea.width = area->width; viewArea.height = area->height; - style::drawBorder (view, &viewArea, allocation.x, allocation.y, + style::drawBorder (view, layout, &viewArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); - /** \todo Adjust following comment from the old dw sources. */ - /* - * - Toplevel widget background colors are set as viewport - * background color. This is not crucial for the rendering, but - * looks a bit nicer when scrolling. Furthermore, the viewport - * does anything else in this case. - * - * - Since widgets are always drawn from top to bottom, it is - * *not* necessary to draw the background if - * widget->style->background_color is NULL (shining through). - */ - /** \todo Background images? */ - - if (style->backgroundColor && - (parent || layout->getBgColor () != style->backgroundColor)) - style::drawBackground (view, &viewArea, allocation.x, allocation.y, - allocation.width, getHeight (), style, inverse); + style::drawBackground (view, layout, &viewArea, allocation.x, allocation.y, + allocation.width, getHeight (), style, inverse, + parent == NULL); } /* -- cgit v1.2.3 From 3599a4762e8a62c0c8c32f0e9d9ec3e37730d271 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 12 Sep 2013 19:47:23 +0200 Subject: Meaningful renaming. --- dw/widget.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dw/widget.cc b/dw/widget.cc index 648f629b..31c69f4c 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -340,17 +340,17 @@ style::Color *Widget::getBgColor () void Widget::drawBox (View *view, style::Style *style, Rectangle *area, int x, int y, int width, int height, bool inverse) { - Rectangle viewArea; - viewArea.x = area->x + allocation.x; - viewArea.y = area->y + allocation.y; - viewArea.width = area->width; - viewArea.height = area->height; + Rectangle canvasArea; + canvasArea.x = area->x + allocation.x; + canvasArea.y = area->y + allocation.y; + canvasArea.width = area->width; + canvasArea.height = area->height; - style::drawBorder (view, layout, &viewArea, + style::drawBorder (view, layout, &canvasArea, allocation.x + x, allocation.y + y, width, height, style, inverse); - style::drawBackground (view, layout, &viewArea, + style::drawBackground (view, layout, &canvasArea, allocation.x + x, allocation.y + y, width, height, style, inverse, false); } @@ -363,16 +363,16 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, */ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) { - Rectangle viewArea; - viewArea.x = area->x + allocation.x; - viewArea.y = area->y + allocation.y; - viewArea.width = area->width; - viewArea.height = area->height; + Rectangle canvasArea; + canvasArea.x = area->x + allocation.x; + canvasArea.y = area->y + allocation.y; + canvasArea.width = area->width; + canvasArea.height = area->height; - style::drawBorder (view, layout, &viewArea, allocation.x, allocation.y, + style::drawBorder (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); - style::drawBackground (view, layout, &viewArea, allocation.x, allocation.y, + style::drawBackground (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse, parent == NULL); } -- cgit v1.2.3 From 76a23c134dfd1d98923830b35a9ee630924b2250 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 12 Sep 2013 20:19:27 +0200 Subject: Some clarifications. --- dw/style.cc | 9 +++++++++ dw/style.hh | 1 + dw/widget.cc | 16 +++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index 373ffa8d..4409bb43 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -868,6 +868,9 @@ static void drawBorderRight(View *view, Style *style, * \brief Draw the border of a region in window, according to style. * * Used by dw::core::Widget::drawBox and dw::core::Widget::drawWidgetBox. + * + * "area" is the area to be drawn, "x", "y", "width" and "height" + * define the box itself. All are given in canvas coordinates. */ void drawBorder (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, @@ -907,6 +910,11 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, * * Used by dw::core::Widget::drawBox and dw::core::Widget::drawWidgetBox. * + * "area" is the area to be drawn, "x", "y", "width" and "height" + * define the box itself. "xRef", "yRef", "widthRef" and "heightRef" + * define the reference area, which is important for background + * images. All are given in canvas coordinates. + * * "atTop" should be true, only if the area is drawn directly on the * canvas, not on top of other areas; this is only true for the * toplevel widget itself (not parts of its contents). Toplevel widget @@ -919,6 +927,7 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, */ void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, + int xRef, int yRef, int widthRef, int heightRef, Style *style, bool inverse, bool atTop) { bool bgColor = style->backgroundColor != NULL && diff --git a/dw/style.hh b/dw/style.hh index 187cd6be..6c82be8d 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -722,6 +722,7 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, Style *style, bool inverse); void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, + int xRef, int yRef, int widthRef, int heightRef, Style *style, bool inverse, bool atTop); void numtostr (int num, char *buf, int buflen, ListStyleType listStyleType); diff --git a/dw/widget.cc b/dw/widget.cc index 31c69f4c..766d2500 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -350,9 +350,14 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, allocation.x + x, allocation.y + y, width, height, style, inverse); + /** + * \todo Reference should be the containing block (which will be + * introduced later), not the widget allocation. + */ style::drawBackground (view, layout, &canvasArea, allocation.x + x, allocation.y + y, width, height, - style, inverse, false); + allocation.x, allocation.y, allocation.width, + getHeight (), style, inverse, false); } /** @@ -372,9 +377,14 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) style::drawBorder (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); + /** + * \todo Reference should be the containing block (which will be + * introduced later), not the widget allocation. + */ style::drawBackground (view, layout, &canvasArea, allocation.x, allocation.y, - allocation.width, getHeight (), style, inverse, - parent == NULL); + allocation.width, getHeight (), allocation.x, + allocation.y, allocation.width, getHeight (), + style, inverse, parent == NULL); } /* -- cgit v1.2.3 From 7ccdc7ac47628f347315e4fd84eb2854ff5e780c Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 12 Sep 2013 22:52:20 +0200 Subject: Remaning style attributes. --- dw/style.cc | 20 ++++++++++++++++++++ dw/style.hh | 16 ++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/dw/style.cc b/dw/style.cc index 4409bb43..1ea0a9c4 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -49,6 +49,10 @@ void StyleAttrs::initValues () valign = VALIGN_BASELINE; backgroundColor = NULL; backgroundImage = NULL; + backgroundRepeat = BACKGROUND_REPEAT; + backgroundAttachment = BACKGROUND_ATTACHMENT_SCROLL; + backgroundPositionX = createPerLength (0); + backgroundPositionY = createPerLength (0); width = height = lineHeight = LENGTH_AUTO; textIndent = 0; margin.setVal (0); @@ -78,6 +82,10 @@ void StyleAttrs::resetValues () textAlignChar = '.'; backgroundColor = NULL; backgroundImage = NULL; + backgroundRepeat = BACKGROUND_REPEAT; + backgroundAttachment = BACKGROUND_ATTACHMENT_SCROLL; + backgroundPositionX = createPerLength (0); + backgroundPositionY = createPerLength (0); width = LENGTH_AUTO; height = LENGTH_AUTO; @@ -119,6 +127,10 @@ bool StyleAttrs::equals (object::Object *other) { color == otherAttrs->color && backgroundColor == otherAttrs->backgroundColor && backgroundImage == otherAttrs->backgroundImage && + backgroundRepeat == otherAttrs->backgroundRepeat && + backgroundAttachment == otherAttrs->backgroundAttachment && + backgroundPositionX == otherAttrs->backgroundPositionX && + backgroundPositionY == otherAttrs->backgroundPositionY && textAlign == otherAttrs->textAlign && valign == otherAttrs->valign && textAlignChar == otherAttrs->textAlignChar && @@ -160,6 +172,10 @@ int StyleAttrs::hashValue () { (intptr_t) color + (intptr_t) backgroundColor + (intptr_t) backgroundImage + + backgroundRepeat + + backgroundAttachment + + backgroundPositionX + + backgroundPositionY + textAlign + valign + textAlignChar + @@ -257,6 +273,10 @@ void Style::copyAttrs (StyleAttrs *attrs) color = attrs->color; backgroundColor = attrs->backgroundColor; backgroundImage = attrs->backgroundImage; + backgroundRepeat = attrs->backgroundRepeat; + backgroundAttachment = attrs->backgroundAttachment; + backgroundPositionX = attrs->backgroundPositionX; + backgroundPositionY = attrs->backgroundPositionY; textAlign = attrs->textAlign; valign = attrs->valign; textAlignChar = attrs->textAlignChar; diff --git a/dw/style.hh b/dw/style.hh index 6c82be8d..c09a52f0 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -230,6 +230,18 @@ enum BorderStyle { BORDER_OUTSET }; +enum BackgroundRepeat { + BACKGROUND_REPEAT, + BACKGROUND_REPEAT_X, + BACKGROUND_REPEAT_Y, + BACKGROUND_NO_REPEAT +}; + +enum BackgroundAttachment { + BACKGROUND_ATTACHMENT_SCROLL, + BACKGROUND_ATTACHMENT_FIXED +}; + enum TextAlignType { TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, @@ -449,6 +461,10 @@ public: * TextDecoration <-> int */ Color *color, *backgroundColor; StyleImage *backgroundImage; + BackgroundRepeat backgroundRepeat; + BackgroundAttachment backgroundAttachment; + Length backgroundPositionX; // "left" defiened by "0%" etc. (see CSS spec) + Length backgroundPositionY; // "top" defiened by "0%" etc. (see CSS spec) TextAlignType textAlign; VAlignType valign; -- cgit v1.2.3 From 196446a333575404057077a07d7c3673a941cce9 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 13 Sep 2013 15:26:22 +0200 Subject: dw::style::drawBackground much more complete. --- .hgignore | 1 + dw/style.cc | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/.hgignore b/.hgignore index 2a169cd4..9ab76864 100644 --- a/.hgignore +++ b/.hgignore @@ -27,6 +27,7 @@ ^test/dw-border-test$ ^test/dw-example$ ^test/dw-find-test$ +^test/dw-image-background$ ^test/dw-images-scaled$ ^test/dw-images-scaled2$ ^test/dw-images-simple$ diff --git a/dw/style.cc b/dw/style.cc index 1ea0a9c4..f0fa360b 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -935,6 +935,9 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, * define the reference area, which is important for background * images. All are given in canvas coordinates. * + * \todo Does "reference" area include margin and padding? Does + * currently, but should probably not. + * * "atTop" should be true, only if the area is drawn directly on the * canvas, not on top of other areas; this is only true for the * toplevel widget itself (not parts of its contents). Toplevel widget @@ -942,6 +945,9 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, * that drawing again is is not neccessary, but some time can be * saved. * + * \todo The same should not only be applied to background colors, but + * also to background images. + * * Otherwise, the caller should not try to increase the performance by * doing some tests befre; this is all done in this method. */ @@ -978,12 +984,68 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, 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); + if (bgImage) { + Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); + int imgWidth = imgbuf->getRootWidth (); + int imgHeight = imgbuf->getRootHeight (); + + /** \todo "background-repeat" not yet used. */ + bool repeatX = + style->backgroundRepeat == BACKGROUND_REPEAT || + style->backgroundRepeat == BACKGROUND_REPEAT_X; + bool repeatY = + style->backgroundRepeat == BACKGROUND_REPEAT || + style->backgroundRepeat == BACKGROUND_REPEAT_Y; + + int origX = xRef + + (isPerLength (style->backgroundPositionX) ? + perLengthVal (style->backgroundPositionX) * (widthRef - + imgWidth) : + absLengthVal (style->backgroundPositionX)); + int origY = yRef + + (isPerLength (style->backgroundPositionY) ? + perLengthVal (style->backgroundPositionY) * (heightRef - + imgHeight) : + absLengthVal (style->backgroundPositionY)); + + int tileX1 = intersection.x < origX ? + - (origX - intersection.x + imgWidth - 1) / imgWidth : + (intersection.x - origX) / imgWidth; + int tileX2 = origX < intersection.x + intersection.width ? + (intersection.x + intersection.width - origX - 1) / imgWidth : + - (origX - (intersection.x + intersection.width) + + imgWidth - 1) / imgWidth; + int tileY1 = intersection.y < origY ? + - (origY - intersection.y + imgHeight - 1) / imgHeight : + (intersection.y - origY) / imgHeight; + int tileY2 = origY < intersection.y + intersection.height ? + (intersection.y + intersection.height - origY - 1) / imgHeight : + - (origY - (intersection.y + intersection.height) + + imgHeight - 1) / imgHeight; + + //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", + // tileX1, tileX2, tileY1, tileY2); + + for (int tileX = tileX1; tileX <= tileX2; tileX++) + for (int tileY = tileY1; tileY <= tileY2; tileY++) { + int x = origX + tileX * imgWidth; + int x1 = misc::max (x, intersection.x); + int x2 = misc::min (x + imgWidth, + intersection.x + intersection.width); + int y = origY + tileY * imgHeight; + int y1 = misc::max (y, intersection.y); + int y2 = misc::min (y + imgHeight, + intersection.y + intersection.height); + + //printf (" (%d, %d) => (%d, %d - %d) / (%d, %d - %d)\n", + // tileX, tileY, x, x1, x2, y, y1, y2); + //printf (" => drawImage (%d, %d, %d, %d, %d, %d)\n", + // x, y, x - x, y1 - y, x2 - x1, y2 - y1); + + view->drawImage (imgbuf, x, y, x1 - x, y1 - y, + x2 - x1, y2 - y1); + } + } } } } -- cgit v1.2.3 From e0162c58c6b8d427bdb66023104cb65cee5177f0 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 13 Sep 2013 20:03:26 +0200 Subject: Some more tests. --- test/dw_image_background.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc index 95264f6a..ccb59479 100644 --- a/test/dw_image_background.cc +++ b/test/dw_image_background.cc @@ -93,6 +93,9 @@ int main(int argc, char **argv) styleAttrs.backgroundColor = Color::create (layout, 0xffffff); image = styleAttrs.backgroundImage = StyleImage::create (); + styleAttrs.backgroundRepeat = BACKGROUND_REPEAT_Y; + styleAttrs.backgroundPositionX = createPerLength (0.5); + styleAttrs.backgroundPositionY = createAbsLength (30); Style *widgetStyle = Style::create (&styleAttrs); -- cgit v1.2.3 From 0ab5863987ec411ebf1ead15ff64de4b7766666e Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 13 Sep 2013 21:27:13 +0200 Subject: "background-repeat" implemented. --- dw/style.cc | 58 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index f0fa360b..fca8d5d1 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -1026,25 +1026,45 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", // tileX1, tileX2, tileY1, tileY2); - for (int tileX = tileX1; tileX <= tileX2; tileX++) - for (int tileY = tileY1; tileY <= tileY2; tileY++) { - int x = origX + tileX * imgWidth; - int x1 = misc::max (x, intersection.x); - int x2 = misc::min (x + imgWidth, - intersection.x + intersection.width); - int y = origY + tileY * imgHeight; - int y1 = misc::max (y, intersection.y); - int y2 = misc::min (y + imgHeight, - intersection.y + intersection.height); - - //printf (" (%d, %d) => (%d, %d - %d) / (%d, %d - %d)\n", - // tileX, tileY, x, x1, x2, y, y1, y2); - //printf (" => drawImage (%d, %d, %d, %d, %d, %d)\n", - // x, y, x - x, y1 - y, x2 - x1, y2 - y1); - - view->drawImage (imgbuf, x, y, x1 - x, y1 - y, - x2 - x1, y2 - y1); - } + bool doDraw = true; + if (!repeatX) { + // Only center tile (tileX = 0) is drawn, ... + if (tileX1 <= 0 && tileX2 >= 0) + // ... and is visible. + tileX1 = tileX2 = 0; + else + // ... but is not visible. + doDraw = false; + } + + if (!repeatY) { + // Analogue. + if (tileY1 <= 0 && tileY2 >= 0) + tileY1 = tileY2 = 0; + else + doDraw = false; + } + + if (doDraw) + for (int tileX = tileX1; tileX <= tileX2; tileX++) + for (int tileY = tileY1; tileY <= tileY2; tileY++) { + int x = origX + tileX * imgWidth; + int x1 = misc::max (x, intersection.x); + int x2 = misc::min (x + imgWidth, + intersection.x + intersection.width); + int y = origY + tileY * imgHeight; + int y1 = misc::max (y, intersection.y); + int y2 = misc::min (y + imgHeight, + intersection.y + intersection.height); + + //printf (" (%d, %d) => (%d, %d - %d) / (%d, %d - %d)\n", + // tileX, tileY, x, x1, x2, y, y1, y2); + //printf (" => drawImage (%d, %d, %d, %d, %d, %d)\n", + // x, y, x - x, y1 - y, x2 - x1, y2 - y1); + + view->drawImage (imgbuf, x, y, x1 - x, y1 - y, + x2 - x1, y2 - y1); + } } } } -- cgit v1.2.3 From 2435de82b60cadb0283ef1636fbe078cf2beac0f Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 15 Sep 2013 14:59:06 +0200 Subject: Very simple implementation of ExternalImgRenderer (used to immediately draw imgbuf updates); concretization for widgets. --- dw/style.cc | 22 ++++++++++++++++++++ dw/style.hh | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ dw/widget.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- dw/widget.hh | 22 ++++++++++++++++++++ 4 files changed, 162 insertions(+), 2 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index fca8d5d1..2328c1e4 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -485,6 +485,28 @@ StyleImage::~StyleImage () delete styleImgRenderer; } +void StyleImage::ExternalImgRenderer::setBuffer (core::Imgbuf *buffer, + bool resize) +{ + // Nothing to do? +} + +void StyleImage::ExternalImgRenderer::drawRow (int row) +{ + // Extremely simple implementation + Style *style; + if (readyToDraw () && (style = getStyle ())) { + int x, y, width, height; + getArea (&x, &y, &width, &height); + draw (x + style->margin.left + style->borderWidth.left, + y + style->margin.top + style->borderWidth.top, + width - style->margin.left - style->borderWidth.left + - style->margin.right - style->borderWidth.right, + height - style->margin.top - style->borderWidth.top + - style->margin.bottom - style->borderWidth.bottom); + } +} + // ---------------------------------------------------------------------- /* diff --git a/dw/style.hh b/dw/style.hh index c09a52f0..217ed4b8 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -723,6 +723,48 @@ private: ~StyleImage (); public: + /** + * \brief Useful (but not mandatory) base class for updates of + * areas with background images. + */ + class ExternalImgRenderer: public ImgRenderer + { + public: + void setBuffer (core::Imgbuf *buffer, bool resize); + void drawRow (int row); + + /** + * \brief If this method returns false, nothing is done at all. + */ + virtual bool readyToDraw () = 0; + + /** + * \brief Return the total area this background image is + * attached to, in canvas coordinates. + */ + virtual void getArea (int *x, int *y, int *width, int *height) = 0; + + /** + * \brief Return the "reference area". + * + * See comment of "drawBackground". + */ + virtual void getRefArea (int *xRef, int *yRef, int *widthRef, + int *heightRef) = 0; + + + /** + * \brief Return the style this background image is part of. + */ + virtual Style *getStyle () = 0; + + /** + * \brief Draw (or queue for drawing) an area, which is given in + * canvas coordinates. + */ + virtual void draw (int x, int y, int width, int height) = 0; + }; + static StyleImage *create () { return new StyleImage (); } inline void ref () { refCount++; } @@ -731,6 +773,19 @@ public: inline Imgbuf *getImgbuf () { return imgbuf; } inline ImgRenderer *getMainImgRenderer () { return imgRendererDist; } + + /** + * \brief Add an additional ImgRenderer, especially used for + * drawing. + */ + inline void putExternalImgRenderer (ImgRenderer *ir) + { imgRendererDist->put (ir); } + + /** + * \brief Remove a previously added additional ImgRenderer. + */ + inline void removeExternalImgRenderer (ImgRenderer *ir) + { imgRendererDist->remove (ir); } }; void drawBorder (View *view, Layout *layout, Rectangle *area, diff --git a/dw/widget.cc b/dw/widget.cc index 766d2500..317d5eeb 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -32,6 +32,46 @@ namespace core { // ---------------------------------------------------------------------- +bool Widget::WidgetImgRenderer::readyToDraw () +{ + return widget->wasAllocated (); +} + +void Widget::WidgetImgRenderer::getArea (int *x, int *y, int *width, + int *height) +{ + *x = widget->allocation.x; + *y = widget->allocation.y; + *width = widget->allocation.width; + *height = widget->getHeight (); +} + +void Widget::WidgetImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, + int *heightRef) +{ + /** + * \todo Reference should be the containing block (which will be + * introduced later), not the widget allocation. + */ + *xRef = widget->allocation.x; + *yRef = widget->allocation.y; + *widthRef = widget->allocation.width; + *heightRef = widget->getHeight (); +} + +style::Style *Widget::WidgetImgRenderer::getStyle () +{ + return widget->getStyle (); +} + +void Widget::WidgetImgRenderer::draw (int x, int y, int width, int height) +{ + widget->queueDrawArea (x - widget->allocation.x, y - widget->allocation.y, + width, height); +} + +// ---------------------------------------------------------------------- + int Widget::CLASS_ID = -1; Widget::Widget () @@ -55,6 +95,8 @@ Widget::Widget () deleteCallbackData = NULL; deleteCallbackFunc = NULL; + + widgetImgRenderer = NULL; } Widget::~Widget () @@ -62,6 +104,12 @@ Widget::~Widget () if (deleteCallbackFunc) deleteCallbackFunc (deleteCallbackData); + if (widgetImgRenderer) { + if (style && style->backgroundImage) + style->backgroundImage->removeExternalImgRenderer (widgetImgRenderer); + delete widgetImgRenderer; + } + if (style) style->unref (); @@ -281,6 +329,10 @@ void Widget::setStyle (style::Style *style) { bool sizeChanged; + if (widgetImgRenderer && this->style && this->style->backgroundImage) + this->style->backgroundImage->removeExternalImgRenderer + (widgetImgRenderer); + style->ref (); if (this->style) { @@ -291,6 +343,15 @@ void Widget::setStyle (style::Style *style) this->style = style; + if (style && style->backgroundImage) { + // Create instance of WidgetImgRenderer when needed. Until this + // widget is deleted, "widgetImgRenderer" will be kept, since it + // is not specific to the style, but only to this widget. + if (widgetImgRenderer == NULL) + widgetImgRenderer = new WidgetImgRenderer (this); + style->backgroundImage->putExternalImgRenderer (widgetImgRenderer); + } + if (layout != NULL) { layout->updateCursor (); } @@ -352,7 +413,7 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, /** * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. + * introduced later), not the widget allocation. */ style::drawBackground (view, layout, &canvasArea, allocation.x + x, allocation.y + y, width, height, @@ -379,7 +440,7 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) /** * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. + * introduced later), not the widget allocation. */ style::drawBackground (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), allocation.x, diff --git a/dw/widget.hh b/dw/widget.hh index 6942221b..c836d117 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -74,6 +74,28 @@ protected: BLOCK_LEVEL = 1 << 6, }; + /** + * \brief Implementation which represents the whole widget. + * + * The only instance is set created needed. + */ + class WidgetImgRenderer: public style::StyleImage::ExternalImgRenderer + { + private: + Widget *widget; + + public: + inline WidgetImgRenderer (Widget *widget) { this->widget = widget; } + + bool readyToDraw (); + void getArea (int *x, int *y, int *width, int *height); + void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); + style::Style *getStyle (); + void draw (int x, int y, int width, int height); + }; + + WidgetImgRenderer *widgetImgRenderer; + private: /** * \brief The parent widget, NULL for top-level widgets. -- cgit v1.2.3 From f381101ed63aeb3575abfb015a4cc4af52c35742 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 15 Sep 2013 15:46:16 +0200 Subject: Whitespaces. --- dw/style.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/dw/style.hh b/dw/style.hh index 217ed4b8..88e4a290 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -752,7 +752,6 @@ public: virtual void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) = 0; - /** * \brief Return the style this background image is part of. */ -- cgit v1.2.3 From 3ff154af28b5f1d6f3b808d846a464a733ddea71 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 15 Sep 2013 15:47:43 +0200 Subject: Removed obsolete comment. --- dw/style.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/dw/style.cc b/dw/style.cc index 2328c1e4..3161b7c2 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -1011,7 +1011,6 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, int imgWidth = imgbuf->getRootWidth (); int imgHeight = imgbuf->getRootHeight (); - /** \todo "background-repeat" not yet used. */ bool repeatX = style->backgroundRepeat == BACKGROUND_REPEAT || style->backgroundRepeat == BACKGROUND_REPEAT_X; -- cgit v1.2.3 From 260dc9e27d4212e08c8a87ae8eaedb172e6134a5 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 15 Sep 2013 16:18:52 +0200 Subject: Some refactoring. --- dw/style.cc | 128 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index 3161b7c2..cd61d7ea 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -34,6 +34,14 @@ namespace dw { namespace core { namespace style { +static void calcBackgroundRelatedValues (Style *style, int xDraw, int yDraw, + int widthDraw, int heightDraw, + int xRef, int yRef, int widthRef, + int heightRef, bool *repeatX, + bool *repeatY, int *origX, int *origY, + int *tileX1, int *tileX2, int *tileY1, + int *tileY2, bool *doDraw); + void StyleAttrs::initValues () { x_link = -1; @@ -1010,62 +1018,20 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); int imgWidth = imgbuf->getRootWidth (); int imgHeight = imgbuf->getRootHeight (); - - bool repeatX = - style->backgroundRepeat == BACKGROUND_REPEAT || - style->backgroundRepeat == BACKGROUND_REPEAT_X; - bool repeatY = - style->backgroundRepeat == BACKGROUND_REPEAT || - style->backgroundRepeat == BACKGROUND_REPEAT_Y; - - int origX = xRef + - (isPerLength (style->backgroundPositionX) ? - perLengthVal (style->backgroundPositionX) * (widthRef - - imgWidth) : - absLengthVal (style->backgroundPositionX)); - int origY = yRef + - (isPerLength (style->backgroundPositionY) ? - perLengthVal (style->backgroundPositionY) * (heightRef - - imgHeight) : - absLengthVal (style->backgroundPositionY)); - - int tileX1 = intersection.x < origX ? - - (origX - intersection.x + imgWidth - 1) / imgWidth : - (intersection.x - origX) / imgWidth; - int tileX2 = origX < intersection.x + intersection.width ? - (intersection.x + intersection.width - origX - 1) / imgWidth : - - (origX - (intersection.x + intersection.width) - + imgWidth - 1) / imgWidth; - int tileY1 = intersection.y < origY ? - - (origY - intersection.y + imgHeight - 1) / imgHeight : - (intersection.y - origY) / imgHeight; - int tileY2 = origY < intersection.y + intersection.height ? - (intersection.y + intersection.height - origY - 1) / imgHeight : - - (origY - (intersection.y + intersection.height) - + imgHeight - 1) / imgHeight; + + bool repeatX, repeatY, doDraw; + int origX, origY, tileX1, tileX2, tileY1, tileY2; + + calcBackgroundRelatedValues (style, intersection.x, intersection.y, + intersection.width, + intersection.height, xRef, yRef, + widthRef, heightRef, &repeatX, + &repeatY, &origX, &origY, &tileX1, + &tileX2, &tileY1, &tileY2, &doDraw); //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", // tileX1, tileX2, tileY1, tileY2); - bool doDraw = true; - if (!repeatX) { - // Only center tile (tileX = 0) is drawn, ... - if (tileX1 <= 0 && tileX2 >= 0) - // ... and is visible. - tileX1 = tileX2 = 0; - else - // ... but is not visible. - doDraw = false; - } - - if (!repeatY) { - // Analogue. - if (tileY1 <= 0 && tileY2 >= 0) - tileY1 = tileY2 = 0; - else - doDraw = false; - } - if (doDraw) for (int tileX = tileX1; tileX <= tileX2; tileX++) for (int tileY = tileY1; tileY <= tileY2; tileY++) { @@ -1091,6 +1057,64 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, } } +void calcBackgroundRelatedValues (Style *style, int xDraw, int yDraw, + int widthDraw, int heightDraw, int xRef, + int yRef, int widthRef, int heightRef, + bool *repeatX, bool *repeatY, int *origX, + int *origY, int *tileX1, int *tileX2, + int *tileY1, int *tileY2, bool *doDraw) +{ + Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); + int imgWidth = imgbuf->getRootWidth (); + int imgHeight = imgbuf->getRootHeight (); + + *repeatX = style->backgroundRepeat == BACKGROUND_REPEAT || + style->backgroundRepeat == BACKGROUND_REPEAT_X; + *repeatY = style->backgroundRepeat == BACKGROUND_REPEAT || + style->backgroundRepeat == BACKGROUND_REPEAT_Y; + + *origX = xRef + + (isPerLength (style->backgroundPositionX) ? + perLengthVal (style->backgroundPositionX) * (widthRef - imgWidth) : + absLengthVal (style->backgroundPositionX)); + *origY = yRef + + (isPerLength (style->backgroundPositionY) ? + perLengthVal (style->backgroundPositionY) * (heightRef - imgHeight) : + absLengthVal (style->backgroundPositionY)); + + *tileX1 = xDraw < *origX ? + - (*origX - xDraw + imgWidth - 1) / imgWidth : + (xDraw - *origX) / imgWidth; + *tileX2 = *origX < xDraw + widthDraw ? + (xDraw + widthDraw - *origX - 1) / imgWidth : + - (*origX - (xDraw + widthDraw) + imgWidth - 1) / imgWidth; + *tileY1 = yDraw < *origY ? + - (*origY - yDraw + imgHeight - 1) / imgHeight : + (yDraw - *origY) / imgHeight; + *tileY2 = *origY < yDraw + heightDraw ? + (yDraw + heightDraw - *origY - 1) / imgHeight : + - (*origY - (yDraw + heightDraw) + imgHeight - 1) / imgHeight; + + *doDraw = true; + if (!*repeatX) { + // Only center tile (tileX = 0) is drawn, ... + if (*tileX1 <= 0 && *tileX2 >= 0) + // ... and is visible. + *tileX1 = *tileX2 = 0; + else + // ... but is not visible. + *doDraw = false; + } + + if (!*repeatY) { + // Analogue. + if (*tileY1 <= 0 && *tileY2 >= 0) + *tileY1 = *tileY2 = 0; + else + *doDraw = false; + } +} + // ---------------------------------------------------------------------- static const char -- cgit v1.2.3 From 3331bb0ed3cc7ffb4d283170659c151abd5fa884 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 15 Sep 2013 16:37:55 +0200 Subject: StyleImage::ExternalImgRenderer::drawRow now only draws single rows. --- dw/style.cc | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index cd61d7ea..160d0444 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -501,17 +501,49 @@ void StyleImage::ExternalImgRenderer::setBuffer (core::Imgbuf *buffer, void StyleImage::ExternalImgRenderer::drawRow (int row) { - // Extremely simple implementation Style *style; if (readyToDraw () && (style = getStyle ())) { + // All single rows are drawn. + + Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); + int imgWidth = imgbuf->getRootWidth (); + int imgHeight = imgbuf->getRootHeight (); + int x, y, width, height; getArea (&x, &y, &width, &height); - draw (x + style->margin.left + style->borderWidth.left, - y + style->margin.top + style->borderWidth.top, - width - style->margin.left - style->borderWidth.left - - style->margin.right - style->borderWidth.right, - height - style->margin.top - style->borderWidth.top - - style->margin.bottom - style->borderWidth.bottom); + int xDraw = x + style->margin.left + style->borderWidth.left; + int yDraw = y + style->margin.top + style->borderWidth.top; + int widthDraw = width - style->margin.left - style->borderWidth.left + - style->margin.right - style->borderWidth.right; + int heightDraw = height - style->margin.top - style->borderWidth.top + - style->margin.bottom - style->borderWidth.bottom; + + int xRef, yRef, widthRef, heightRef; + getRefArea (&xRef, &yRef, &widthRef, &heightRef); + + bool repeatX, repeatY, doDraw; + int origX, origY, tileX1, tileX2, tileY1, tileY2; + + calcBackgroundRelatedValues (style, xDraw, yDraw, widthDraw, heightDraw, + xRef, yRef, widthRef, heightRef, &repeatX, + &repeatY, &origX, &origY, &tileX1, &tileX2, + &tileY1, &tileY2, &doDraw); + + //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", + // tileX1, tileX2, tileY1, tileY2); + + if (doDraw) + // Only iterate over y, because the rows can be combined + // horizontically. + for (int tileY = tileY1; tileY <= tileY2; tileY++) { + int x1 = misc::max (origX + tileX1 * imgWidth, xDraw); + int x2 = misc::min (origX + (tileX2 + 1) * imgWidth, + xDraw + widthDraw); + + int y = origY + tileY * imgHeight + row; + if (y >= yDraw && y < yDraw + heightDraw) + draw (x1, y, x2 - x1, 1); + } } } -- cgit v1.2.3 From c8a4d1e1da9534f030908c792e8922d8509eb2a4 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 16 Sep 2013 12:49:03 +0200 Subject: Extended test for bg images. --- test/dw_image_background.cc | 71 +++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc index ccb59479..4e91cde0 100644 --- a/test/dw_image_background.cc +++ b/test/dw_image_background.cc @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#include + #include #include @@ -31,36 +33,54 @@ using namespace dw::core; using namespace dw::core::style; using namespace dw::fltk; -static StyleImage *image; +static StyleImage *image1 = NULL, *image2 = NULL; static Layout *layout; -static int imgRow = 0; +static int imgRow1 = 0, imgRow2 = 0; static void imageInitTimeout (void *data) { - Imgbuf *imgbuf = layout->createImgbuf (Imgbuf::RGB, 400, 200, 1); - image->getMainImgRenderer()->setBuffer (imgbuf, false); + if (image1) { + Imgbuf *imgbuf1 = layout->createImgbuf (Imgbuf::RGB, 400, 200, 1); + image1->getMainImgRenderer()->setBuffer (imgbuf1, false); + } + + if (image2) { + Imgbuf *imgbuf2 = layout->createImgbuf (Imgbuf::RGB, 100, 100, 1); + image2->getMainImgRenderer()->setBuffer (imgbuf2, 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++; + Imgbuf *imgbuf1 = image1 ? image1->getImgbuf () : NULL; + Imgbuf *imgbuf2 = image2 ? image2->getImgbuf () : NULL; + + if (imgbuf1 && imgRow1 < 200) { + byte buf[3 * 400]; + for(int x = 0; x < 400; x++) { + buf[3 * x + 0] = 128 + x * 127 / 399; + buf[3 * x + 1] = 128 + (399 - x) * 127 / 399; + buf[3 * x + 2] = 128 + imgRow1 * 127 / 199; + } + + imgbuf1->copyRow (imgRow1, buf); + image1->getMainImgRenderer()->drawRow (imgRow1); + imgRow1++; + } + + if (imgbuf2 && imgRow2 < 100) { + byte buf[3 * 100]; + for(int x = 0; x < 100; x++) { + int r = 128 + rand () % 127; + buf[3 * x + 0] = buf[3 * x + 1] = buf[3 * x + 2] = r; } + + imgbuf2->copyRow (imgRow2, buf); + image2->getMainImgRenderer()->drawRow (imgRow2); + imgRow2++; } - if(imgRow < 200) + if(imgRow1 < 200 || imgRow2 < 100) Fl::repeat_timeout (0.5, imageDrawTimeout, NULL); } @@ -92,7 +112,7 @@ int main(int argc, char **argv) styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); - image = styleAttrs.backgroundImage = StyleImage::create (); + image1 = styleAttrs.backgroundImage = StyleImage::create (); styleAttrs.backgroundRepeat = BACKGROUND_REPEAT_Y; styleAttrs.backgroundPositionX = createPerLength (0.5); styleAttrs.backgroundPositionY = createAbsLength (30); @@ -111,6 +131,12 @@ int main(int argc, char **argv) Style *wordStyle = Style::create (&styleAttrs); + image2 = styleAttrs.backgroundImage = StyleImage::create (); + styleAttrs.backgroundRepeat = BACKGROUND_REPEAT; + styleAttrs.backgroundPositionX = createPerLength (0); + styleAttrs.backgroundPositionY = createPerLength (0); + Style *wordStyleBg = Style::create (&styleAttrs); + for(int i = 1; i <= 10; i++) { char buf[4]; sprintf(buf, "%d.", i); @@ -121,7 +147,7 @@ int main(int argc, char **argv) NULL }; for(int j = 0; words[j]; j++) { - textblock->addText(words[j], wordStyle); + textblock->addText(words[j], j == 3 ? wordStyleBg : wordStyle); textblock->addSpace(wordStyle); } @@ -129,13 +155,14 @@ int main(int argc, char **argv) } wordStyle->unref(); + wordStyleBg->unref(); textblock->flush (); window->resizable(viewport); window->show(); - Fl::add_timeout (2.0, imageInitTimeout, NULL); + Fl::add_timeout (1.0, imageInitTimeout, NULL); Fl::add_timeout (0.1, imageDrawTimeout, NULL); int errorCode = Fl::run(); -- cgit v1.2.3 From 679c1ff1091a0f2d2c401a3951af8bef9d76d553 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 16 Sep 2013 22:01:15 +0200 Subject: ExternalImgRenderer for textblock works. (Unfortunately, still crashes.) --- dw/textblock.cc | 122 +++++++++++++++++++++++++++++++++++++++++++ dw/textblock.hh | 41 +++++++++++++++ dw/textblock_linebreaking.cc | 10 ++++ 3 files changed, 173 insertions(+) diff --git a/dw/textblock.cc b/dw/textblock.cc index d7e1704e..035bb4d0 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -41,6 +41,85 @@ namespace dw { int Textblock::CLASS_ID = -1; +Textblock::WordImgRenderer::WordImgRenderer (Textblock *textblock, + Word *word) +{ + //printf ("new WordImgRenderer %p\n", this); + + this->textblock = textblock; + this->word = word; + dataSet = false; +} + +Textblock::WordImgRenderer::~WordImgRenderer () +{ + //printf ("delete WordImgRenderer %p\n", this); +} + +void Textblock::WordImgRenderer::setData (int xWordWidget, int lineNo) +{ + dataSet = true; + this->xWordWidget = xWordWidget; + this->lineNo = lineNo; +} + +bool Textblock::WordImgRenderer::readyToDraw () +{ + return dataSet && textblock->wasAllocated () + && lineNo < textblock->lines->size(); +} + +void Textblock::WordImgRenderer::getArea (int *x, int *y, int *width, + int *height) +{ + Line *line = textblock->lines->getRef (lineNo); + *x = textblock->allocation.x + this->xWordWidget; + *y = textblock->lineYOffsetCanvas (line); + *width = word->size.width; + *height = line->boxAscent + line->boxDescent; +} + +void Textblock::WordImgRenderer::getRefArea (int *xRef, int *yRef, + int *widthRef, int *heightRef) +{ + /** + * \todo Reference should be the containing block (which will be + * introduced later), not the widget allocation. (And also, + * there should be one single method for this.) + */ + *xRef = textblock->allocation.x; + *yRef = textblock->allocation.y; + *widthRef = textblock->allocation.width; + *heightRef = textblock->getHeight (); +} + +core::style::Style *Textblock::WordImgRenderer::getStyle () +{ + return word->style; +} + +void Textblock::WordImgRenderer::draw (int x, int y, int width, int height) +{ + textblock->queueDrawArea (x - textblock->allocation.x, + y - textblock->allocation.y, width, height); + +} + +void Textblock::SpaceImgRenderer::getArea (int *x, int *y, int *width, + int *height) +{ + WordImgRenderer::getArea (x, y, width, height); + *x += *width; + *width = word->effSpace; +} + +core::style::Style *Textblock::SpaceImgRenderer::getStyle () +{ + return word->spaceStyle; +} + +// ---------------------------------------------------------------------- + Textblock::DivChar Textblock::divChars[NUM_DIV_CHARS] = { // soft hyphen (U+00AD) { "\xc2\xad", true, false, true, PENALTY_HYPHEN, -1 }, @@ -181,8 +260,22 @@ Textblock::~Textblock () for (int i = 0; i < words->size(); i++) { Word *word = words->getRef (i); + if (word->content.type == core::Content::WIDGET) delete word->content.widget; + + if (word->wordImgRenderer) { + word->style->backgroundImage->removeExternalImgRenderer + (word->wordImgRenderer); + delete word->wordImgRenderer; + } + + if (word->spaceImgRenderer) { + word->spaceStyle->backgroundImage->removeExternalImgRenderer + (word->spaceImgRenderer); + delete word->spaceImgRenderer; + } + word->style->unref (); word->spaceStyle->unref (); } @@ -1365,6 +1458,21 @@ void Textblock::fillWord (Word *word, int width, int ascent, int descent, word->style = style; word->spaceStyle = style; + + if (word->style->backgroundImage) { + word->wordImgRenderer = new WordImgRenderer (this, word); + word->style->backgroundImage->putExternalImgRenderer + (word->wordImgRenderer); + } else + word->wordImgRenderer = NULL; + + if (word->spaceStyle->backgroundImage) { + word->spaceImgRenderer = new SpaceImgRenderer (this, word); + word->spaceStyle->backgroundImage->putExternalImgRenderer + (word->spaceImgRenderer); + } else + word->spaceImgRenderer = NULL; + style->ref (); style->ref (); } @@ -1894,9 +2002,23 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", wordIndex, // word->content.space); + + if (word->spaceImgRenderer) { + word->spaceStyle->backgroundImage->removeExternalImgRenderer + (word->spaceImgRenderer); + delete word->spaceImgRenderer; + } + word->spaceStyle->unref (); word->spaceStyle = style; style->ref (); + + if (word->spaceStyle->backgroundImage) { + word->spaceImgRenderer = new SpaceImgRenderer (this, word); + word->spaceStyle->backgroundImage->putExternalImgRenderer + (word->spaceImgRenderer); + } else + word->spaceImgRenderer = NULL; } } diff --git a/dw/textblock.hh b/dw/textblock.hh index aae0edad..33bb5dbc 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -237,6 +237,42 @@ private: static const char *hyphenDrawChar; protected: + struct Word; + + /** + * \brief Implementation used for words. + */ + class WordImgRenderer: public core::style::StyleImage::ExternalImgRenderer + { + protected: + Textblock *textblock; + Word *word; + bool dataSet; + int xWordWidget, lineNo; + + public: + WordImgRenderer (Textblock *textblock, Word *word); + ~WordImgRenderer (); + + void setData (int xWordWidget, int lineNo); + + bool readyToDraw (); + void getArea (int *x, int *y, int *width, int *height); + void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); + core::style::Style *getStyle (); + void draw (int x, int y, int width, int height); + }; + + class SpaceImgRenderer: public WordImgRenderer + { + public: + inline SpaceImgRenderer (Textblock *textblock, Word *word) : + WordImgRenderer (textblock, word) { } + + void getArea (int *x, int *y, int *width, int *height); + core::style::Style *getStyle (); + }; + struct Paragraph { int firstWord; /* first word's index in word vector */ @@ -349,6 +385,11 @@ protected: core::style::Style *style; core::style::Style *spaceStyle; /* initially the same as of the word, later set by a_Dw_page_add_space */ + + // These two are used rarely, so there is perhaps a way to store + // them which is consuming less memory. + WordImgRenderer *wordImgRenderer; + SpaceImgRenderer *spaceImgRenderer; }; void printWordShort (Word *word); diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index d1b0df85..bf47140e 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -418,6 +418,16 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord, //printf (": "); //words->getRef(line->lastWord)->badnessAndPenalty.print (); //printf ("\n"); + + int xWidget = lineXOffsetWidget(line); + for (int i = firstWord; i <= lastWord; i++) { + Word *word = words->getRef (i); + if (word->wordImgRenderer) + word->wordImgRenderer->setData (xWidget, lines->size () - 1); + if (word->spaceImgRenderer) + word->spaceImgRenderer->setData (xWidget, lines->size () - 1); + xWidget += word->size.width + word->effSpace; + } return line; } -- cgit v1.2.3 From 1dd550cc0b1b1a7afef91f0a22031d29e5e70ba8 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 17 Sep 2013 11:32:15 +0200 Subject: Some refactoring (Widget::getBgRefArea). --- dw/textblock.cc | 10 +--------- dw/widget.cc | 47 ++++++++++++++++++++++++++--------------------- dw/widget.hh | 2 ++ 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/dw/textblock.cc b/dw/textblock.cc index 035bb4d0..6cb02726 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -82,15 +82,7 @@ void Textblock::WordImgRenderer::getArea (int *x, int *y, int *width, void Textblock::WordImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) { - /** - * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. (And also, - * there should be one single method for this.) - */ - *xRef = textblock->allocation.x; - *yRef = textblock->allocation.y; - *widthRef = textblock->allocation.width; - *heightRef = textblock->getHeight (); + textblock->getBgRefArea (xRef, yRef, widthRef, heightRef); } core::style::Style *Textblock::WordImgRenderer::getStyle () diff --git a/dw/widget.cc b/dw/widget.cc index 317d5eeb..719f1263 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -49,14 +49,7 @@ void Widget::WidgetImgRenderer::getArea (int *x, int *y, int *width, void Widget::WidgetImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) { - /** - * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. - */ - *xRef = widget->allocation.x; - *yRef = widget->allocation.y; - *widthRef = widget->allocation.width; - *heightRef = widget->getHeight (); + widget->getBgRefArea (xRef, yRef, widthRef, heightRef); } style::Style *Widget::WidgetImgRenderer::getStyle () @@ -411,14 +404,12 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, allocation.x + x, allocation.y + y, width, height, style, inverse); - /** - * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. - */ + int xRef, yRef, widthRef, heightRef; + getBgRefArea (&xRef, &yRef, &widthRef, &heightRef); style::drawBackground (view, layout, &canvasArea, allocation.x + x, allocation.y + y, width, height, - allocation.x, allocation.y, allocation.width, - getHeight (), style, inverse, false); + xRef, yRef, widthRef, heightRef, style, inverse, + false); } /** @@ -438,14 +429,11 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) style::drawBorder (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); - /** - * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. - */ + int xRef, yRef, widthRef, heightRef; + getBgRefArea (&xRef, &yRef, &widthRef, &heightRef); style::drawBackground (view, layout, &canvasArea, allocation.x, allocation.y, - allocation.width, getHeight (), allocation.x, - allocation.y, allocation.width, getHeight (), - style, inverse, parent == NULL); + allocation.width, getHeight (), xRef, yRef, widthRef, + heightRef, style, inverse, parent == NULL); } /* @@ -589,6 +577,23 @@ void Widget::scrollTo (HPosition hpos, VPosition vpos, x + allocation.x, y + allocation.y, width, height); } +/** + * \brief Return the "reference area" for backgrounds. + * + * See comment of "style::drawBackground". + */ +void Widget::getBgRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) +{ + /** + * \todo Reference should be the containing block (which will be + * introduced later), not the widget allocation. + */ + *xRef = allocation.x; + *yRef = allocation.y; + *widthRef = allocation.width; + *heightRef = getHeight (); +} + void Widget::getExtremesImpl (Extremes *extremes) { /* Simply return the requisition width */ diff --git a/dw/widget.hh b/dw/widget.hh index c836d117..fb16bf90 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -311,6 +311,8 @@ public: void scrollTo (HPosition hpos, VPosition vpos, int x, int y, int width, int height); + void getBgRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); + /** * \brief Return an iterator for this widget. * -- cgit v1.2.3 From 4a98456a5f0430c6f49a05cd85a941b3e705a336 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 17 Sep 2013 16:53:10 +0200 Subject: Fixed a problem in the test. --- dw/style.cc | 4 ++++ test/dw_image_background.cc | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/dw/style.cc b/dw/style.cc index 160d0444..e443ab61 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -476,6 +476,8 @@ void StyleImage::StyleImgRenderer::drawRow (int row) StyleImage::StyleImage () { + //printf ("new StyleImage %p\n", this); + refCount = 0; imgbuf = NULL; @@ -486,6 +488,8 @@ StyleImage::StyleImage () StyleImage::~StyleImage () { + //printf ("delete StyleImage %p\n", this); + if (imgbuf) imgbuf->unref (); diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc index 4e91cde0..3b692901 100644 --- a/test/dw_image_background.cc +++ b/test/dw_image_background.cc @@ -28,14 +28,33 @@ #include "../dw/textblock.hh" #include "../dw/image.hh" +using namespace lout::signal; +using namespace lout::misc; using namespace dw; using namespace dw::core; using namespace dw::core::style; using namespace dw::fltk; +class ImageStyleDeletionReceiver: public ObservedObject::DeletionReceiver +{ +public: + void deleted (ObservedObject *object); +}; + static StyleImage *image1 = NULL, *image2 = NULL; static Layout *layout; static int imgRow1 = 0, imgRow2 = 0; +static ImageStyleDeletionReceiver isdr; + +void ImageStyleDeletionReceiver::deleted (ObservedObject *object) +{ + if ((StyleImage*)object == image1) + image1 = NULL; + else if ((StyleImage*)object == image2) + image2 = NULL; + else + assertNotReached (); +} static void imageInitTimeout (void *data) { @@ -113,6 +132,7 @@ int main(int argc, char **argv) styleAttrs.backgroundColor = Color::create (layout, 0xffffff); image1 = styleAttrs.backgroundImage = StyleImage::create (); + image1->connectDeletion (&isdr); styleAttrs.backgroundRepeat = BACKGROUND_REPEAT_Y; styleAttrs.backgroundPositionX = createPerLength (0.5); styleAttrs.backgroundPositionY = createAbsLength (30); @@ -132,6 +152,7 @@ int main(int argc, char **argv) Style *wordStyle = Style::create (&styleAttrs); image2 = styleAttrs.backgroundImage = StyleImage::create (); + image2->connectDeletion (&isdr); styleAttrs.backgroundRepeat = BACKGROUND_REPEAT; styleAttrs.backgroundPositionX = createPerLength (0); styleAttrs.backgroundPositionY = createPerLength (0); -- cgit v1.2.3 From c758502505223216b6e335e6a3283447435a2aa2 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 17 Sep 2013 17:39:20 +0200 Subject: Replacing Word* by word index (int) in WordImgRenderer; this seems to fix the segfaults. (There should still be problems with hyphenation.) --- dw/textblock.cc | 31 ++++++++++++++++++------------- dw/textblock.hh | 15 ++++++--------- dw/textblock_linebreaking.cc | 4 ++-- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/dw/textblock.cc b/dw/textblock.cc index 6cb02726..fbff3e23 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -42,12 +42,12 @@ namespace dw { int Textblock::CLASS_ID = -1; Textblock::WordImgRenderer::WordImgRenderer (Textblock *textblock, - Word *word) + int wordNo) { //printf ("new WordImgRenderer %p\n", this); this->textblock = textblock; - this->word = word; + this->wordNo = wordNo; dataSet = false; } @@ -66,6 +66,7 @@ void Textblock::WordImgRenderer::setData (int xWordWidget, int lineNo) bool Textblock::WordImgRenderer::readyToDraw () { return dataSet && textblock->wasAllocated () + && wordNo < textblock->words->size() && lineNo < textblock->lines->size(); } @@ -75,7 +76,7 @@ void Textblock::WordImgRenderer::getArea (int *x, int *y, int *width, Line *line = textblock->lines->getRef (lineNo); *x = textblock->allocation.x + this->xWordWidget; *y = textblock->lineYOffsetCanvas (line); - *width = word->size.width; + *width = textblock->words->getRef(wordNo)->size.width; *height = line->boxAscent + line->boxDescent; } @@ -87,7 +88,7 @@ void Textblock::WordImgRenderer::getRefArea (int *xRef, int *yRef, core::style::Style *Textblock::WordImgRenderer::getStyle () { - return word->style; + return textblock->words->getRef(wordNo)->style; } void Textblock::WordImgRenderer::draw (int x, int y, int width, int height) @@ -102,12 +103,12 @@ void Textblock::SpaceImgRenderer::getArea (int *x, int *y, int *width, { WordImgRenderer::getArea (x, y, width, height); *x += *width; - *width = word->effSpace; + *width = textblock->words->getRef(wordNo)->effSpace; } core::style::Style *Textblock::SpaceImgRenderer::getStyle () { - return word->spaceStyle; + return textblock->words->getRef(wordNo)->spaceStyle; } // ---------------------------------------------------------------------- @@ -1432,13 +1433,15 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, { words->increase (); Word *word = words->getLastRef (); - fillWord (word, width, ascent, descent, flags, style); + fillWord (words->size () - 1, width, ascent, descent, flags, style); return word; } -void Textblock::fillWord (Word *word, int width, int ascent, int descent, +void Textblock::fillWord (int wordNo, int width, int ascent, int descent, short flags, core::style::Style *style) { + Word *word = words->getRef (wordNo); + word->size.width = width; word->size.ascent = ascent; word->size.descent = descent; @@ -1452,14 +1455,14 @@ void Textblock::fillWord (Word *word, int width, int ascent, int descent, word->spaceStyle = style; if (word->style->backgroundImage) { - word->wordImgRenderer = new WordImgRenderer (this, word); + word->wordImgRenderer = new WordImgRenderer (this, wordNo); word->style->backgroundImage->putExternalImgRenderer (word->wordImgRenderer); } else word->wordImgRenderer = NULL; if (word->spaceStyle->backgroundImage) { - word->spaceImgRenderer = new SpaceImgRenderer (this, word); + word->spaceImgRenderer = new SpaceImgRenderer (this, wordNo); word->spaceStyle->backgroundImage->putExternalImgRenderer (word->spaceImgRenderer); } else @@ -1939,7 +1942,7 @@ void Textblock::addSpace (core::style::Style *style) { int wordIndex = words->size () - 1; if (wordIndex >= 0) { - fillSpace (words->getRef(wordIndex), style); + fillSpace (wordIndex, style); accumulateWordData (wordIndex); correctLastWordExtremes (); } @@ -1961,7 +1964,7 @@ void Textblock::addBreakOption (core::style::Style *style, bool forceBreak) } } -void Textblock::fillSpace (Word *word, core::style::Style *style) +void Textblock::fillSpace (int wordNo, core::style::Style *style) { // Old comment: // @@ -1977,6 +1980,8 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) // // TODO: Re-evaluate again. + Word *word = words->getRef (wordNo); + // TODO: This line does not work: addBreakOption (word, style); // Do not override a previously set break penalty. @@ -2006,7 +2011,7 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) style->ref (); if (word->spaceStyle->backgroundImage) { - word->spaceImgRenderer = new SpaceImgRenderer (this, word); + word->spaceImgRenderer = new SpaceImgRenderer (this, wordNo); word->spaceStyle->backgroundImage->putExternalImgRenderer (word->spaceImgRenderer); } else diff --git a/dw/textblock.hh b/dw/textblock.hh index 33bb5dbc..572080fd 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -237,8 +237,6 @@ private: static const char *hyphenDrawChar; protected: - struct Word; - /** * \brief Implementation used for words. */ @@ -246,12 +244,11 @@ protected: { protected: Textblock *textblock; - Word *word; + int wordNo, xWordWidget, lineNo; bool dataSet; - int xWordWidget, lineNo; public: - WordImgRenderer (Textblock *textblock, Word *word); + WordImgRenderer (Textblock *textblock, int wordNo); ~WordImgRenderer (); void setData (int xWordWidget, int lineNo); @@ -266,8 +263,8 @@ protected: class SpaceImgRenderer: public WordImgRenderer { public: - inline SpaceImgRenderer (Textblock *textblock, Word *word) : - WordImgRenderer (textblock, word) { } + inline SpaceImgRenderer (Textblock *textblock, int wordNo) : + WordImgRenderer (textblock, wordNo) { } void getArea (int *x, int *y, int *width, int *height); core::style::Style *getStyle (); @@ -518,9 +515,9 @@ protected: Word *addWord (int width, int ascent, int descent, short flags, core::style::Style *style); - void fillWord (Word *word, int width, int ascent, int descent, + void fillWord (int wordNo, int width, int ascent, int descent, short flags, core::style::Style *style); - void fillSpace (Word *word, core::style::Style *style); + void fillSpace (int wordNo, core::style::Style *style); void setBreakOption (Word *word, core::style::Style *style, int breakPenalty1, int breakPenalty2, bool forceBreak); bool isBreakAllowed (Word *word); diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index bf47140e..d1e4488d 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -892,7 +892,7 @@ int Textblock::hyphenateWord (int wordIndex) for (int i = 0; i < numBreaks + 1; i++) { Word *w = words->getRef (wordIndex + i); - fillWord (w, wordSize[i].width, wordSize[i].ascent, + fillWord (wordIndex + i, wordSize[i].width, wordSize[i].ascent, wordSize[i].descent, false, origWord.style); // TODO There should be a method fillText0. @@ -931,7 +931,7 @@ int Textblock::hyphenateWord (int wordIndex) PRINTF (" [%d] + hyphen\n", wordIndex + i); } else { if (origWord.content.space) { - fillSpace (w, origWord.spaceStyle); + fillSpace (wordIndex + i, origWord.spaceStyle); PRINTF (" [%d] + space\n", wordIndex + i); } else { PRINTF (" [%d] + nothing\n", wordIndex + i); -- cgit v1.2.3 From ebd938d548840aefe8f30837ff987e4b726cd5bf Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 17 Sep 2013 17:51:19 +0200 Subject: Comment. --- dw/textblock.hh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dw/textblock.hh b/dw/textblock.hh index 572080fd..b094b5ec 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -239,6 +239,9 @@ private: protected: /** * \brief Implementation used for words. + * + * \todo The word index must be updated when, through hyphenation, + * words are added before. */ class WordImgRenderer: public core::style::StyleImage::ExternalImgRenderer { -- cgit v1.2.3 From fae1427770c3484970798e2e3f9f074f4af6599c Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 20 Sep 2013 09:29:24 +0200 Subject: Refactoring: some useful shortcuts in DilloHtml. --- src/cssparser.hh | 3 +- src/form.cc | 26 ++++++------ src/html.cc | 119 +++++++++++++++++++++++++---------------------------- src/html_common.hh | 14 +++++++ src/table.cc | 20 ++++----- 5 files changed, 96 insertions(+), 86 deletions(-) diff --git a/src/cssparser.hh b/src/cssparser.hh index 8609877b..30d02eee 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -2,7 +2,8 @@ #define __CSSPARSER_HH__ #include "css.hh" -#include "html_common.hh" + +class DilloHtml; class CssParser { private: diff --git a/src/form.cc b/src/form.cc index 7c747c5a..af25bcb9 100644 --- a/src/form.cc +++ b/src/form.cc @@ -340,7 +340,7 @@ void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize) char *charset, *first; const char *attrbuf; - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); if (html->InFlags & IN_FORM) { BUG_MSG("nested forms\n"); @@ -566,7 +566,7 @@ void Html_tag_open_input(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, attrbuf); } - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle()); + HT2TB(html)->addWidget (embed, html->backgroundStyle()); } dFree(type); dFree(name); @@ -599,17 +599,17 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) html->charset); html->InFlags |= IN_FORM; - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "prompt"))) - HT2TB(html)->addText(attrbuf, html->styleEngine->wordStyle ()); + HT2TB(html)->addText(attrbuf, html->wordStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); EntryResource *entryResource = factory->createEntryResource (20,false,NULL); embed = new Embed (entryResource); Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); a_Url_free(action); html->InFlags &= ~IN_FORM; @@ -674,7 +674,7 @@ void Html_tag_content_textarea(DilloHtml *html, const char *tag, int tagsize) textres->setEditable(false); Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); dFree(name); } @@ -765,7 +765,7 @@ void Html_tag_open_select(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint (PROPERTY_X_TOOLTIP, CSS_TYPE_STRING, attrbuf); } - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); Html_add_input(html, type, embed, name, NULL, false); a_Html_stash_init(html); @@ -937,16 +937,16 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize) * but it caused 100% CPU usage. */ page = new Textblock (false); - page->setStyle (html->styleEngine->backgroundStyle ()); + page->setStyle (html->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); Resource *resource = factory->createComplexButtonResource(page, true); embed = new Embed(resource); // a_Dw_button_set_sensitive (DW_BUTTON (button), FALSE); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); - HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ()); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); + HT2TB(html)->addWidget (embed, html->backgroundStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); S_TOP(html)->textblock = html->dw = page; @@ -2008,12 +2008,12 @@ static Embed *Html_input_image(DilloHtml *html, const char *tag, int tagsize) // widget. Notice that the order of the casts matters, because // of multiple inheritance. dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rnd; - dwi->setStyle (html->styleEngine->backgroundStyle ()); + dwi->setStyle (html->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); ComplexButtonResource *complex_b_r = factory->createComplexButtonResource(dwi, false); button = new Embed(complex_b_r); - HT2TB(html)->addWidget (button, html->styleEngine->style ()); + HT2TB(html)->addWidget (button, html->style ()); } if (!button) MSG("Html_input_image: unable to create image submit.\n"); diff --git a/src/html.cc b/src/html.cc index e8aeb12d..527d7c79 100644 --- a/src/html.cc +++ b/src/html.cc @@ -354,9 +354,9 @@ static void Html_add_textblock(DilloHtml *html, int space) { Textblock *textblock = new Textblock (prefs.limit_text_width); - HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ()); - HT2TB(html)->addWidget (textblock, html->styleEngine->style ()); - HT2TB(html)->addParbreak (space, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (space, html->wordStyle ()); + HT2TB(html)->addWidget (textblock, html->style ()); + HT2TB(html)->addParbreak (space, html->wordStyle ()); S_TOP(html)->textblock = html->dw = textblock; S_TOP(html)->hand_over_break = true; } @@ -1034,11 +1034,11 @@ static void Html_process_space_pre_line(DilloHtml *html, const char *space, breakCnt++; html->PrevWasCR = (space[i] == '\r'); - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); } } if (breakCnt == 0) { - HT2TB(html)->addSpace(html->styleEngine->wordStyle ()); + HT2TB(html)->addSpace(html->wordStyle ()); } } @@ -1071,12 +1071,11 @@ static void Html_process_space(DilloHtml *html, const char *space, if (spaceCnt) { spc = dStrnfill(spaceCnt, ' '); - HT2TB(html)->addText (spc, spaceCnt, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText (spc, spaceCnt, html->wordStyle ()); dFree(spc); spaceCnt = 0; } - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); html->pre_column = 0; } html->PreFirstChar = false; @@ -1104,20 +1103,19 @@ static void Html_process_space(DilloHtml *html, const char *space, if (spaceCnt) { // add break possibility for the white-space:pre-wrap case - HT2TB(html)->addBreakOption (html->styleEngine->wordStyle (), false); + HT2TB(html)->addBreakOption (html->wordStyle (), false); spc = dStrnfill(spaceCnt, ' '); - HT2TB(html)->addText (spc, spaceCnt, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (spc, spaceCnt, html->wordStyle ()); dFree(spc); } } else { if (SGML_SPCDEL) { /* SGML_SPCDEL ignores white space immediately after an open tag */ - } else if (html->styleEngine->wordStyle ()->whiteSpace == - WHITE_SPACE_PRE_LINE) { + } else if (html->wordStyle ()->whiteSpace == WHITE_SPACE_PRE_LINE) { Html_process_space_pre_line(html, space, spacesize); } else { - HT2TB(html)->addSpace(html->styleEngine->wordStyle ()); + HT2TB(html)->addSpace(html->wordStyle ()); } if (parse_mode == DILLO_HTML_PARSE_MODE_STASH_AND_BODY) @@ -1170,8 +1168,7 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) Html_process_space(html, Pword + start, i - start); } else { while (Pword[++i] && !isspace(Pword[i])) ; - HT2TB(html)->addText(Pword + start, i - start, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText(Pword + start, i - start, html->wordStyle ()); html->pre_column += i - start; html->PreFirstChar = false; } @@ -1209,20 +1206,18 @@ static void Html_process_word(DilloHtml *html, const char *word, int size) Html_process_space(html, word2 + start, i - start); } else if (!strncmp(word2+i, utf8_zero_width_space, 3)) { i += 3; - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), false); + HT2TB(html)->addBreakOption(html->wordStyle (), false); } else if (a_Utf8_ideographic(word2+i, beyond_word2, &len)) { i += len; - HT2TB(html)->addText(word2 + start, i - start, - html->styleEngine->wordStyle ()); - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), false); + HT2TB(html)->addText(word2 + start, i - start, html->wordStyle ()); + HT2TB(html)->addBreakOption(html->wordStyle (), false); } else { do { i += len; } while (word2[i] && !isspace(word2[i]) && strncmp(word2+i, utf8_zero_width_space, 3) && (!a_Utf8_ideographic(word2+i, beyond_word2, &len))); - HT2TB(html)->addText(word2 + start, i - start, - html->styleEngine->wordStyle ()); + HT2TB(html)->addText(word2 + start, i - start, html->wordStyle ()); } } if (Pword == word2) @@ -1256,7 +1251,7 @@ static void Html_eventually_pop_dw(DilloHtml *html, bool hand_over_break) { if (html->dw != S_TOP(html)->textblock) { if (hand_over_break) - HT2TB(html)->handOverBreak (html->styleEngine->style ()); + HT2TB(html)->handOverBreak (html->style ()); HT2TB(html)->flush (); html->dw = S_TOP(html)->textblock; } @@ -1284,7 +1279,7 @@ static void Html_push_tag(DilloHtml *html, int tag_idx) */ static void Html_force_push_tag(DilloHtml *html, int tag_idx) { - html->styleEngine->startElement (tag_idx); + html->startElement (tag_idx); Html_push_tag(html, tag_idx); } @@ -1842,7 +1837,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) CSS_TYPE_COLOR, color); } - html->styleEngine->restyle (); + html->restyle (); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "link"))) html->non_css_link_color = a_Html_color_parse(html, attrbuf, -1); @@ -1850,7 +1845,7 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "vlink"))) html->non_css_visited_color = a_Html_color_parse(html, attrbuf, -1); - html->dw->setStyle (html->styleEngine->style ()); + html->dw->setStyle (html->style ()); bgColor = html->styleEngine->backgroundColor (); @@ -1863,22 +1858,22 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) * On reload style including color for visited links is computed properly * according to CSS. */ - html->styleEngine->startElement (tag_index_a); + html->startElement (tag_index_a); html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) { html->styleEngine->setNonCssHint (CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, html->non_css_visited_color); } - html->visited_color = html->styleEngine->style ()->color->getColor (); + html->visited_color = html->style ()->color->getColor (); html->styleEngine->endElement (tag_index_a); if (prefs.contrast_visited_color) { /* get a color that has a "safe distance" from text, link and bg */ html->visited_color = a_Color_vc(html->visited_color, - html->styleEngine->style ()->color->getColor(), + html->style ()->color->getColor(), html->non_css_link_color, - html->styleEngine->backgroundStyle()->backgroundColor->getColor()); + html->backgroundStyle()->backgroundColor->getColor()); } @@ -1950,28 +1945,28 @@ static void src = dStrdup(attrbuf); - textblock->addParbreak (5, html->styleEngine->wordStyle ()); + textblock->addParbreak (5, html->wordStyle ()); bullet = new Bullet(); - textblock->addWidget(bullet, html->styleEngine->wordStyle ()); - textblock->addSpace(html->styleEngine->wordStyle ()); + textblock->addWidget(bullet, html->wordStyle ()); + textblock->addSpace(html->wordStyle ()); if (D_ASCII_TOLOWER(tag[1]) == 'i') { /* IFRAME usually comes with very long advertising/spying URLS, * to not break rendering we will force name="IFRAME" */ - textblock->addText ("IFRAME", html->styleEngine->wordStyle ()); + textblock->addText ("IFRAME", html->wordStyle ()); } else { /* FRAME: * If 'name' tag is present use it, if not use 'src' value */ if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) { - textblock->addText (src, html->styleEngine->wordStyle ()); + textblock->addText (src, html->wordStyle ()); } else { - textblock->addText (attrbuf, html->styleEngine->wordStyle ()); + textblock->addText (attrbuf, html->wordStyle ()); } } - textblock->addParbreak (5, html->styleEngine->wordStyle ()); + textblock->addParbreak (5, html->wordStyle ()); dFree(src); } @@ -1984,8 +1979,8 @@ static void static void Html_tag_content_frameset (DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); - HT2TB(html)->addText("--FRAME--", html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); + HT2TB(html)->addText("--FRAME--", html->wordStyle ()); Html_add_textblock(html, 5); } @@ -2006,7 +2001,7 @@ static void Html_tag_open_h(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_content_br(DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addLinebreak (html->styleEngine->wordStyle ()); + HT2TB(html)->addLinebreak (html->wordStyle ()); } /* @@ -2278,13 +2273,13 @@ static void Html_tag_content_img(DilloHtml *html, const char *tag, int tagsize) // widget. Notice that the order of the casts matters, because of // multiple inheritance. dw::Image *dwi = (dw::Image*)(dw::core::ImgRenderer*)Image->img_rnd; - HT2TB(html)->addWidget(dwi, html->styleEngine->style()); + HT2TB(html)->addWidget(dwi, html->style()); /* Image maps */ if (a_Html_get_attr(html, tag, tagsize, "ismap")) { dwi->setIsMap(); _MSG(" Html_tag_open_img: server-side map (ISMAP)\n"); - } else if (html->styleEngine->style ()->x_link != -1 && + } else if (html->style ()->x_link != -1 && usemap_url == NULL) { /* For simple links, we have to suppress the "image_pressed" signal. * This is overridden for USEMAP images. */ @@ -2485,7 +2480,7 @@ static void Html_tag_open_object(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint(PROPERTY_X_LINK, CSS_TYPE_INTEGER, Html_set_new_link(html, &url)); - HT2TB(html)->addText("[OBJECT]", html->styleEngine->wordStyle ()); + HT2TB(html)->addText("[OBJECT]", html->wordStyle ()); } a_Url_free(base_url); } @@ -2519,7 +2514,7 @@ static const char* Html_get_javascript_link(DilloHtml *html) static void Html_add_anchor(DilloHtml *html, const char *name) { _MSG("Registering ANCHOR: %s\n", name); - if (!HT2TB(html)->addAnchor (name, html->styleEngine->style ())) + if (!HT2TB(html)->addAnchor (name, html->style ())) BUG_MSG("Anchor names must be unique within the document ('%s')\n",name); /* * According to Sec. 12.2.1 of the HTML 4.01 spec, "anchor names that @@ -2628,7 +2623,7 @@ static void Html_tag_open_q(DilloHtml *html, const char *tag, int tagsize) const char *U201C = "\xe2\x80\x9c"; html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addText (U201C, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (U201C, html->wordStyle ()); } /* @@ -2639,7 +2634,7 @@ static void Html_tag_close_q(DilloHtml *html) /* Right Double Quotation Mark */ const char *U201D = "\xe2\x80\x9d"; - HT2TB(html)->addText (U201D, html->styleEngine->wordStyle ()); + HT2TB(html)->addText (U201D, html->wordStyle ()); } /* @@ -2679,7 +2674,7 @@ static void Html_tag_open_ul(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_open_dir(DilloHtml *html, const char *tag, int tagsize) { html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); S_TOP(html)->list_type = HTML_LIST_UNORDERED; S_TOP(html)->list_number = 0; @@ -2739,7 +2734,7 @@ static void Html_tag_open_ol(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_open_li(DilloHtml *html, const char *tag, int tagsize) { - Style *style = html->styleEngine->style (); + Style *style = html->style (); int *list_number; const char *attrbuf; @@ -2827,12 +2822,12 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_content_hr(DilloHtml *html, const char *tag, int tagsize) { Widget *hruler; - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); hruler = new Ruler(); - hruler->setStyle (html->styleEngine->style ()); - HT2TB(html)->addWidget (hruler, html->styleEngine->style ()); - HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); + hruler->setStyle (html->style ()); + HT2TB(html)->addWidget (hruler, html->style ()); + HT2TB(html)->addParbreak (5, html->wordStyle ()); } /* @@ -2842,7 +2837,7 @@ static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) { /* may want to actually do some stuff here. */ html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -2851,7 +2846,7 @@ static void Html_tag_open_dl(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_open_dt(DilloHtml *html, const char *tag, int tagsize) { html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -2868,7 +2863,7 @@ static void Html_tag_open_dd(DilloHtml *html, const char *tag, int tagsize) static void Html_tag_open_pre(DilloHtml *html, const char *tag, int tagsize) { html->styleEngine->inheritBackgroundColor (); - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); html->InFlags |= IN_PRE; } @@ -3200,7 +3195,7 @@ static void Html_tag_open_div(DilloHtml *html, const char *tag, int tagsize) */ static void Html_tag_close_par(DilloHtml *html) { - HT2TB(html)->addParbreak (9, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (9, html->wordStyle ()); } /* @@ -3208,7 +3203,7 @@ static void Html_tag_close_par(DilloHtml *html) */ static void Html_tag_content_wbr(DilloHtml *html, const char *tag, int tagsize) { - HT2TB(html)->addBreakOption(html->styleEngine->wordStyle (), true); + HT2TB(html)->addBreakOption(html->wordStyle (), true); } @@ -3643,8 +3638,8 @@ static void Html_display_block(DilloHtml *html) static void Html_display_listitem(DilloHtml *html) { - Style *style = html->styleEngine->style (); - Style *wordStyle = html->styleEngine->wordStyle (); + Style *style = html->style (); + Style *wordStyle = html->wordStyle (); Widget **ref_list_item; ListItem *list_item; int *list_number; @@ -3728,7 +3723,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) /* Push the tag into the stack */ Html_push_tag(html, ni); - html->styleEngine->startElement (ni); + html->startElement (ni); _MSG("Open : %*s%s\n", html->stack->size(), " ", Tags[ni].name); /* Parse attributes that can appear on any tag */ @@ -3739,7 +3734,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) Tags[ni].open (html, tag, tagsize); if (! S_TOP(html)->display_none) { - switch (html->styleEngine->style ()->display) { + switch (html->style ()->display) { case DISPLAY_BLOCK: Html_display_block(html); break; @@ -3766,8 +3761,8 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize) if (S_TOP(html)->parse_mode == DILLO_HTML_PARSE_MODE_VERBATIM) { /* don't change anything */ } else if (S_TOP(html)->parse_mode != DILLO_HTML_PARSE_MODE_PRE && - (html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE || - html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE_WRAP)) { + (html->style ()->whiteSpace == WHITE_SPACE_PRE || + html->style ()->whiteSpace == WHITE_SPACE_PRE_WRAP)) { S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_PRE; html->pre_column = 0; html->PreFirstChar = true; diff --git a/src/html_common.hh b/src/html_common.hh index 6c5d4807..a2d13bf1 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -218,6 +218,20 @@ public: bool_t unloadedImages(); void loadImages (const DilloUrl *pattern); void addCssUrl(const DilloUrl *url); + + // useful shortcuts + inline void startElement (int tag) { styleEngine->startElement (tag); } + inline void startElement (const char *tagname) + { styleEngine->startElement (tagname); } + + inline dw::core::style::Style *backgroundStyle () + { return styleEngine->backgroundStyle (); } + inline dw::core::style::Style *style () { return styleEngine->style (); } + inline dw::core::style::Style *wordStyle () + { return styleEngine->wordStyle (); } + + inline void restyle () { styleEngine->restyle (); } + }; /* diff --git a/src/table.cc b/src/table.cc index 41f2b686..b11dde4d 100644 --- a/src/table.cc +++ b/src/table.cc @@ -100,7 +100,7 @@ void Html_tag_open_table(DilloHtml *html, const char *tag, int tagsize) CSS_TYPE_COLOR, bgcolor); } - html->styleEngine->style (); // evaluate now, so we can build non-css hints for the cells + html->style (); // evaluate now, so we can build non-css hints for the cells /* The style for the cells */ html->styleEngine->clearNonCssHints (); @@ -141,10 +141,10 @@ void Html_tag_content_table(DilloHtml *html, const char *tag, int tagsize) { dw::core::Widget *table; - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); + HT2TB(html)->addParbreak (0, html->wordStyle ()); table = new dw::Table(prefs.limit_text_width); - HT2TB(html)->addWidget (table, html->styleEngine->style ()); - HT2TB(html)->addParbreak (0, html->styleEngine->wordStyle ()); + HT2TB(html)->addWidget (table, html->style ()); + HT2TB(html)->addParbreak (0, html->wordStyle ()); S_TOP(html)->table_mode = DILLO_HTML_TABLE_MODE_TOP; S_TOP(html)->table_border_mode = DILLO_HTML_TABLE_BORDER_SEPARATE; @@ -205,7 +205,7 @@ void Html_tag_content_tr(DilloHtml *html, const char *tag, int tagsize) case DILLO_HTML_TABLE_MODE_TOP: case DILLO_HTML_TABLE_MODE_TR: case DILLO_HTML_TABLE_MODE_TD: - ((dw::Table*)S_TOP(html)->table)->addRow (html->styleEngine->style ()); + ((dw::Table*)S_TOP(html)->table)->addRow (html->style ()); default: break; } @@ -286,10 +286,10 @@ static void Html_set_collapsing_border_model(DilloHtml *html, Widget *col_tb) int borderWidth, marginWidth; tableStyle = ((dw::Table*)S_TOP(html)->table)->getStyle (); - borderWidth = html->styleEngine->style ()->borderWidth.top; + borderWidth = html->style ()->borderWidth.top; marginWidth = tableStyle->margin.top; - collapseCellAttrs = *(html->styleEngine->style ()); + collapseCellAttrs = *(html->style ()); collapseCellAttrs.margin.setVal (0); collapseCellAttrs.borderWidth.left = 0; collapseCellAttrs.borderWidth.top = 0; @@ -328,7 +328,7 @@ static void Html_set_separate_border_model(DilloHtml *html, Widget *col_tb) dw::core::style::Style *separateStyle; dw::core::style::StyleAttrs separateCellAttrs; - separateCellAttrs = *(html->styleEngine->style ()); + separateCellAttrs = *(html->style ()); /* CSS2 17.5: Internal table elements do not have margins */ separateCellAttrs.margin.setVal (0); separateStyle = Style::create(&separateCellAttrs); @@ -417,7 +417,7 @@ static void Html_tag_content_table_cell(DilloHtml *html, /* TODO: check errors? */ if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "rowspan"))) rowspan = MAX(1, strtol (attrbuf, NULL, 10)); - if (html->styleEngine->style ()->textAlign + if (html->style ()->textAlign == TEXT_ALIGN_STRING) col_tb = new dw::TableCell ( ((dw::Table*)S_TOP(html)->table)->getCellRef (), @@ -425,7 +425,7 @@ static void Html_tag_content_table_cell(DilloHtml *html, else col_tb = new Textblock (prefs.limit_text_width); - if (html->styleEngine->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ + if (html->style()->borderCollapse == BORDER_MODEL_COLLAPSE){ Html_set_collapsing_border_model(html, col_tb); } else { Html_set_separate_border_model(html, col_tb); -- cgit v1.2.3 From f815ca9e7f27a8fc4a8230413ecac8ad2b2e0621 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 20 Sep 2013 09:40:14 +0200 Subject: Added BrowserWindow and DilloURL (base URL) to StyleEngine::apply and related. --- src/html_common.hh | 14 ++++++++------ src/plain.cc | 7 ++++--- src/styleengine.cc | 32 +++++++++++++++++--------------- src/styleengine.hh | 25 ++++++++++++++----------- src/web.cc | 4 ++-- 5 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/html_common.hh b/src/html_common.hh index a2d13bf1..a43d91b7 100644 --- a/src/html_common.hh +++ b/src/html_common.hh @@ -220,17 +220,19 @@ public: void addCssUrl(const DilloUrl *url); // useful shortcuts - inline void startElement (int tag) { styleEngine->startElement (tag); } + inline void startElement (int tag) + { styleEngine->startElement (tag, bw, base_url); } inline void startElement (const char *tagname) - { styleEngine->startElement (tagname); } + { styleEngine->startElement (tagname, bw, base_url); } inline dw::core::style::Style *backgroundStyle () - { return styleEngine->backgroundStyle (); } - inline dw::core::style::Style *style () { return styleEngine->style (); } + { return styleEngine->backgroundStyle (bw, base_url); } + inline dw::core::style::Style *style () + { return styleEngine->style (bw, base_url); } inline dw::core::style::Style *wordStyle () - { return styleEngine->wordStyle (); } + { return styleEngine->wordStyle (bw, base_url); } - inline void restyle () { styleEngine->restyle (); } + inline void restyle () { styleEngine->restyle (bw, base_url); } }; diff --git a/src/plain.cc b/src/plain.cc index d63ce6cf..d09f6d79 100644 --- a/src/plain.cc +++ b/src/plain.cc @@ -97,9 +97,10 @@ DilloPlain::DilloPlain(BrowserWindow *p_bw) Layout *layout = (Layout*) bw->render_layout; StyleEngine styleEngine (layout); - styleEngine.startElement ("body"); - styleEngine.startElement ("pre"); - widgetStyle = styleEngine.wordStyle (); + // TODO (3x) No URL? + styleEngine.startElement ("body", bw, NULL); + styleEngine.startElement ("pre", bw, NULL); + widgetStyle = styleEngine.wordStyle (bw, NULL); widgetStyle->ref (); /* The context menu */ diff --git a/src/styleengine.cc b/src/styleengine.cc index 47bf6240..af5623c2 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -92,8 +92,8 @@ void StyleEngine::stackPop () { /** * \brief tell the styleEngine that a new html element has started. */ -void StyleEngine::startElement (int element) { - style (); // ensure that style of current node is computed +void StyleEngine::startElement (int element, BrowserWindow *bw, DilloUrl *url) { + style (bw, url); // ensure that style of current node is computed stackPush (); Node *n = stack->getLastRef (); @@ -103,8 +103,9 @@ void StyleEngine::startElement (int element) { n->doctreeNode = dn; } -void StyleEngine::startElement (const char *tagname) { - startElement (a_Html_tag_index (tagname)); +void StyleEngine::startElement (const char *tagname, BrowserWindow *bw, + DilloUrl *url) { + startElement (a_Html_tag_index (tagname), bw, url); } void StyleEngine::setId (const char *id) { @@ -281,7 +282,8 @@ void StyleEngine::postprocessAttrs (dw::core::style::StyleAttrs *attrs) { /** * \brief Make changes to StyleAttrs attrs according to CssPropertyList props. */ -void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props) { +void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, + BrowserWindow *bw, DilloUrl *url) { FontAttrs fontAttrs = *attrs->font; Font *parentFont = stack->get (i - 1).style->font; char *c, *fontName; @@ -706,9 +708,9 @@ void StyleEngine::computeBorderWidth (int *dest, CssProperty *p, * A normal style might have backgroundColor == NULL to indicate a transparent * background. This method ensures that backgroundColor is set. */ -Style * StyleEngine::backgroundStyle () { +Style * StyleEngine::backgroundStyle (BrowserWindow *bw, DilloUrl *url) { if (!stack->getRef (stack->size () - 1)->backgroundStyle) { - StyleAttrs attrs = *style (); + StyleAttrs attrs = *style (bw, url); for (int i = stack->size () - 1; i >= 0 && ! attrs.backgroundColor; i--) attrs.backgroundColor = stack->getRef (i)->style->backgroundColor; @@ -725,7 +727,7 @@ Style * StyleEngine::backgroundStyle () { * HTML elements and the nonCssProperties that have been set. * This method is private. Call style() to get a current style object. */ -Style * StyleEngine::style0 (int i) { +Style * StyleEngine::style0 (int i, BrowserWindow *bw, DilloUrl *url) { CssPropertyList props, *styleAttrProperties, *styleAttrPropertiesImportant; CssPropertyList *nonCssProperties; // get previous style from the stack @@ -753,7 +755,7 @@ Style * StyleEngine::style0 (int i) { nonCssProperties); // apply style - apply (i, &attrs, &props); + apply (i, &attrs, &props, bw, url); postprocessAttrs (&attrs); @@ -762,14 +764,14 @@ Style * StyleEngine::style0 (int i) { return stack->getRef (i)->style; } -Style * StyleEngine::wordStyle0 () { - StyleAttrs attrs = *style (); +Style * StyleEngine::wordStyle0 (BrowserWindow *bw, DilloUrl *url) { + StyleAttrs attrs = *style (bw, url); attrs.resetValues (); if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) - attrs.backgroundColor = style ()->backgroundColor; + attrs.backgroundColor = style (bw, url)->backgroundColor; - attrs.valign = style ()->valign; + attrs.valign = style (bw, url)->valign; stack->getRef(stack->size() - 1)->wordStyle = Style::create(&attrs); return stack->getRef (stack->size () - 1)->wordStyle; @@ -782,7 +784,7 @@ Style * StyleEngine::wordStyle0 () { * and thereby after the HTML-element has been opened. * Note that restyle() does not change any styles in the widget tree. */ -void StyleEngine::restyle () { +void StyleEngine::restyle (BrowserWindow *bw, DilloUrl *url) { for (int i = 1; i < stack->size (); i++) { Node *n = stack->getRef (i); if (n->style) { @@ -798,7 +800,7 @@ void StyleEngine::restyle () { n->backgroundStyle = NULL; } - style0 (i); + style0 (i, bw, url); } } diff --git a/src/styleengine.hh b/src/styleengine.hh index 237008a6..14222f35 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -40,8 +40,8 @@ class StyleEngine { void stackPop (); void buildUserAgentStyle (); void buildUserStyle (); - dw::core::style::Style *style0 (int i); - dw::core::style::Style *wordStyle0 (); + dw::core::style::Style *style0 (int i, BrowserWindow *bw, DilloUrl *url); + dw::core::style::Style *wordStyle0 (BrowserWindow *bw, DilloUrl *url); inline void setNonCssHint(CssPropertyName name, CssValueType type, CssPropertyValue value) { Node *n = stack->getRef (stack->size () - 1); @@ -52,7 +52,8 @@ class StyleEngine { } void preprocessAttrs (dw::core::style::StyleAttrs *attrs); void postprocessAttrs (dw::core::style::StyleAttrs *attrs); - void apply (int i, dw::core::style::StyleAttrs *attrs, CssPropertyList *props); + void apply (int i, dw::core::style::StyleAttrs *attrs, + CssPropertyList *props, BrowserWindow *bw, DilloUrl *url); bool computeValue (int *dest, CssLength value, dw::core::style::Font *font); bool computeValue (int *dest, CssLength value, @@ -68,8 +69,8 @@ class StyleEngine { void parse (DilloHtml *html, DilloUrl *url, const char *buf, int buflen, CssOrigin origin); - void startElement (int tag); - void startElement (const char *tagname); + void startElement (int tag, BrowserWindow *bw, DilloUrl *url); + void startElement (const char *tagname, BrowserWindow *bw, DilloUrl *url); void setId (const char *id); const char * getId () { return doctree->top ()->id; }; void setClass (const char *klass); @@ -91,25 +92,27 @@ class StyleEngine { } void inheritNonCssHints (); void clearNonCssHints (); - void restyle (); + void restyle (BrowserWindow *bw, DilloUrl *url); void inheritBackgroundColor (); /* \todo get rid of this somehow */ - dw::core::style::Style *backgroundStyle (); + dw::core::style::Style *backgroundStyle (BrowserWindow *bw, + DilloUrl *url); dw::core::style::Color *backgroundColor (); - inline dw::core::style::Style *style () { + inline dw::core::style::Style *style (BrowserWindow *bw, DilloUrl *url) { dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style; if (s) return s; else - return style0 (stack->size () - 1); + return style0 (stack->size () - 1, bw, url); }; - inline dw::core::style::Style *wordStyle () { + inline dw::core::style::Style *wordStyle (BrowserWindow *bw, + DilloUrl *url) { dw::core::style::Style *s = stack->getRef(stack->size()-1)->wordStyle; if (s) return s; else - return wordStyle0 (); + return wordStyle0 (bw, url); }; }; diff --git a/src/web.cc b/src/web.cc index fcc65af8..a469ccb2 100644 --- a/src/web.cc +++ b/src/web.cc @@ -70,13 +70,13 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, /* Set a style for the widget */ StyleEngine styleEngine (layout); - styleEngine.startElement ("body"); + styleEngine.startElement ("body", Web->bw, Web->url); dw = (Widget*) viewer(Type, Web, Call, Data); if (dw == NULL) return -1; - dw->setStyle (styleEngine.style ()); + dw->setStyle (styleEngine.style (Web->bw, Web->url)); /* This method frees the old dw if any */ layout->setWidget(dw); -- cgit v1.2.3 From c2eb8db9a1a7f98d228dc4402f234525621b4e8e Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 20 Sep 2013 09:41:44 +0200 Subject: First attempt to integrate 'background-image'. --- src/cssparser.cc | 3 ++- src/styleengine.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index eda45472..b60f49d1 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -141,7 +141,8 @@ static const char *const Css_word_spacing_enum_vals[] = { const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-attachment", {CSS_TYPE_UNUSED}, NULL}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, - {"background-image", {CSS_TYPE_UNUSED}, NULL}, + /** todo 'background-image' os of type , which is not yet defined. */ + {"background-image", {CSS_TYPE_STRING, CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, diff --git a/src/styleengine.cc b/src/styleengine.cc index af5623c2..363e9b02 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -15,6 +15,8 @@ #include "misc.h" #include "html_common.hh" #include "styleengine.hh" +#include "web.hh" +#include "capi.h" using namespace lout::misc; using namespace dw::core::style; @@ -450,6 +452,30 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, attrs->backgroundColor = Color::create(layout, prefs.white_bg_replacement); break; + case CSS_PROPERTY_BACKGROUND_IMAGE: + { + DilloUrl *imgUrl = + a_Url_new (p->value.strVal, a_Url_str (url)); + + attrs->backgroundImage = StyleImage::create(); + DilloImage *image = + a_Image_new(layout, + (void*)attrs->backgroundImage + ->getMainImgRenderer(), + 0xffffff); + + DilloWeb *web = a_Web_new(bw, imgUrl, url); + web->Image = image; + a_Image_ref(image); + web->flags |= WEB_Image; + + int clientKey; + if ((clientKey = a_Capi_open_url(web, NULL, NULL)) != 0) { + a_Bw_add_client(bw, clientKey, 0); + a_Bw_add_url(bw, url); + } + } + break; case CSS_PROPERTY_BORDER_COLLAPSE: attrs->borderCollapse = (BorderCollapse) p->value.intVal; break; -- cgit v1.2.3 From 7947111ed07f65821435d9e323fba8754f308202 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 22 Sep 2013 12:30:22 +0200 Subject: CSS type implemented; applied to 'background-image'. --- src/css.hh | 1 + src/cssparser.cc | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/css.hh b/src/css.hh index 6b142827..ea16703b 100644 --- a/src/css.hh +++ b/src/css.hh @@ -45,6 +45,7 @@ typedef enum { opposed to CSS_TYPE_ENUM and CSS_TYPE_MULTI_ENUM). Used for 'font-family'. */ + CSS_TYPE_URI, /* */ CSS_TYPE_UNUSED /* Not yet used. Will itself get unused some day. */ } CssValueType; diff --git a/src/cssparser.cc b/src/cssparser.cc index b60f49d1..d5840f07 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -141,8 +141,7 @@ static const char *const Css_word_spacing_enum_vals[] = { const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-attachment", {CSS_TYPE_UNUSED}, NULL}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, - /** todo 'background-image' os of type , which is not yet defined. */ - {"background-image", {CSS_TYPE_STRING, CSS_TYPE_UNUSED}, NULL}, + {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, @@ -735,6 +734,12 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) } break; + case CSS_TYPE_URI: + if (ttype == CSS_TK_SYMBOL && + dStrAsciiCasecmp(tval, "url") == 0) + return true; + break; + case CSS_TYPE_UNUSED: case CSS_TYPE_INTEGER: /* Not used for parser values. */ @@ -1005,6 +1010,15 @@ bool CssParser::parseValue(CssPropertyName prop, } break; + case CSS_TYPE_URI: + if (ttype == CSS_TK_SYMBOL && + dStrAsciiCasecmp(tval, "url") == 0) { + val->strVal = parseUrl(); + ret = true; + nextToken(); + } + break; + case CSS_TYPE_UNUSED: /* nothing */ break; -- cgit v1.2.3 From b033268e6b7c83d3b1ffcb4f8e79769dc8d9c39c Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Sun, 22 Sep 2013 13:03:05 +0200 Subject: Check url in CSS parser. --- src/cssparser.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index d5840f07..5383ab1a 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1014,8 +1014,9 @@ bool CssParser::parseValue(CssPropertyName prop, if (ttype == CSS_TK_SYMBOL && dStrAsciiCasecmp(tval, "url") == 0) { val->strVal = parseUrl(); - ret = true; nextToken(); + if (val->strVal) + ret = true; } break; -- cgit v1.2.3 From 37507ce8b1188c040afca07390504cd162f5111f Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 23 Sep 2013 14:55:21 +0200 Subject: CSS attribute 'background-repeat'. --- src/cssparser.cc | 7 ++++++- src/styleengine.cc | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index 5383ab1a..19eb95a5 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -47,6 +47,10 @@ typedef struct { const char *const *enum_symbols; } CssPropertyInfo; +static const char *const Css_background_repeat_enum_vals[] = { + "repeat", "repeat-x", "repeat-y", "no-repeat", NULL +}; + static const char *const Css_border_collapse_enum_vals[] = { "separate", "collapse", NULL }; @@ -143,7 +147,8 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, - {"background-repeat", {CSS_TYPE_UNUSED}, NULL}, + {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_background_repeat_enum_vals}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, Css_border_color_enum_vals}, {"border-bottom-style", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, diff --git a/src/styleengine.cc b/src/styleengine.cc index 363e9b02..2cdb6e2c 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -476,6 +476,9 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, } } break; + case CSS_PROPERTY_BACKGROUND_REPEAT: + attrs->backgroundRepeat = (BackgroundRepeat) p->value.intVal; + break; case CSS_PROPERTY_BORDER_COLLAPSE: attrs->borderCollapse = (BorderCollapse) p->value.intVal; break; -- cgit v1.2.3 From 9bdbab27811d631db9c321380dea0842ec0af392 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 25 Sep 2013 11:57:00 +0200 Subject: CSS attribute 'background-attachment' (not implemented in dw::core::style). --- src/cssparser.cc | 7 ++++++- src/styleengine.cc | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index 19eb95a5..a67e98d3 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -47,6 +47,10 @@ typedef struct { const char *const *enum_symbols; } CssPropertyInfo; +static const char *const Css_background_attachment_enum_vals[] = { + "scroll", "fixed", NULL +}; + static const char *const Css_background_repeat_enum_vals[] = { "repeat", "repeat-x", "repeat-y", "no-repeat", NULL }; @@ -143,7 +147,8 @@ static const char *const Css_word_spacing_enum_vals[] = { }; const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { - {"background-attachment", {CSS_TYPE_UNUSED}, NULL}, + {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, + Css_background_attachment_enum_vals}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, {"background-position", {CSS_TYPE_UNUSED}, NULL}, diff --git a/src/styleengine.cc b/src/styleengine.cc index 2cdb6e2c..6b35e33c 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -445,6 +445,10 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, switch (p->name) { /* \todo missing cases */ + case CSS_PROPERTY_BACKGROUND_ATTACHMENT: + attrs->backgroundAttachment = + (BackgroundAttachment) p->value.intVal; + break; case CSS_PROPERTY_BACKGROUND_COLOR: if (prefs.allow_white_bg || p->value.intVal != 0xffffff) attrs->backgroundColor = Color::create(layout, p->value.intVal); -- cgit v1.2.3 From c789b39fea45e2d950b8feb4fd03bd380de1f0e5 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 26 Sep 2013 10:22:34 +0200 Subject: CSS attribute 'background-position'. --- src/css.hh | 6 ++++- src/cssparser.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/styleengine.cc | 19 ++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/css.hh b/src/css.hh index ea16703b..b05a18bc 100644 --- a/src/css.hh +++ b/src/css.hh @@ -143,7 +143,7 @@ typedef enum { CSS_PROPERTY_BACKGROUND_ATTACHMENT, CSS_PROPERTY_BACKGROUND_COLOR, CSS_PROPERTY_BACKGROUND_IMAGE, - CSS_PROPERTY_BACKGROUND_POSITION, + // 'background-position' is handled as a shorthand. CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BORDER_BOTTOM_COLOR, CSS_PROPERTY_BORDER_BOTTOM_STYLE, @@ -223,6 +223,10 @@ typedef enum { CSS_PROPERTY_X_LINK, CSS_PROPERTY_X_COLSPAN, CSS_PROPERTY_X_ROWSPAN, + // The following two are internal properties for 'background-position'; see + // more at equivalent definition in Css_property_info. + CSS_PROPERTY_X_BACKGROUND_POSITION_X, + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, PROPERTY_X_LINK, PROPERTY_X_LANG, PROPERTY_X_IMG, diff --git a/src/cssparser.cc b/src/cssparser.cc index a67e98d3..aa049659 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -146,12 +146,20 @@ static const char *const Css_word_spacing_enum_vals[] = { "normal", NULL }; +static const char *const Css_x_background_position_x_enum_vals[] = { + "left", "center", "right", NULL +}; + +static const char *const Css_x_background_position_y_enum_vals[] = { + "top", "center", "bottom", NULL +}; + const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_background_attachment_enum_vals}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, - {"background-position", {CSS_TYPE_UNUSED}, NULL}, + // 'background-position' is handled as a shorthand. {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_background_repeat_enum_vals}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, @@ -258,6 +266,17 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"x-link", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, {"x-colspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, {"x-rowspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, + + // The following two are internal properties for 'background-position'. They + // are not set directly, but by the 'background-position' shortcut. Here, + // both , , as well as symbolic values ("right", "top" + // etc.) are possible. + {"x-background-position-x", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH_PERCENTAGE, + CSS_TYPE_UNUSED}, + Css_x_background_position_x_enum_vals}, + {"x-background-position-y", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH_PERCENTAGE, + CSS_TYPE_UNUSED}, + Css_x_background_position_y_enum_vals}, {"last", {CSS_TYPE_UNUSED}, NULL}, }; @@ -269,6 +288,8 @@ typedef struct { CSS_SHORTHAND_DIRECTIONS, /* {1,4} */ CSS_SHORTHAND_BORDER, /* special, used for 'border' */ CSS_SHORTHAND_FONT, /* special, used for 'font' */ + CSS_SHORTHAND_BACKGROUND_POSITION, + /* special, used for 'background-position' */ } type; const CssPropertyName * properties;/* CSS_SHORTHAND_MULTIPLE: * must be terminated by -1 @@ -285,7 +306,14 @@ const CssPropertyName Css_background_properties[] = { CSS_PROPERTY_BACKGROUND_IMAGE, CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BACKGROUND_ATTACHMENT, - CSS_PROPERTY_BACKGROUND_POSITION, + CSS_PROPERTY_X_BACKGROUND_POSITION_X, + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, + (CssPropertyName) - 1 +}; + +const CssPropertyName Css_background_position_properties[] = { + CSS_PROPERTY_X_BACKGROUND_POSITION_X, + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, (CssPropertyName) - 1 }; @@ -393,6 +421,8 @@ const CssPropertyName Css_font_properties[] = { static const CssShorthandInfo Css_shorthand_info[] = { {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, Css_background_properties}, + {"background-position", CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION, + Css_background_position_properties}, {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER, Css_border_properties}, {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, @@ -1218,6 +1248,49 @@ void CssParser::parseDeclaration(CssPropertyList * props, } } while (found); break; + + case CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION: + // 'background-position' consists of one or two values: + // vertical and horizontal position; in most cases in this + // order. However, as long it is unambigous, the order can be + // switched: "10px left" and "left 10px" are both possible + // and have the same effect. For this reason, we test both + // possible orders: i = 0 means vertical/horizontal, i = 1 + // means horizontal/vertical. + for (found = false, i = 0; !found && i < 2; i++) { + int i1 = i, i2 = 1 - i; + if (tokenMatchesProperty( + Css_shorthand_info[sh_index].properties[i1], &type) + && parseValue( + Css_shorthand_info[sh_index].properties[i1], + type, &val)) { + found = true; + props->set(Css_shorthand_info[sh_index].properties[i1], + type, val); + + if (tokenMatchesProperty( + Css_shorthand_info[sh_index].properties[i2], + &type)) { + if (parseValue( + Css_shorthand_info[sh_index].properties[i2], + type, &val)) + props->set( + Css_shorthand_info[sh_index].properties[i2], + type, val); + // else: Should be an error. + } else { + // Second value not set: assume 'center', whose + // enum index is 1 in both cases (horizontal and + // vertical). + CssPropertyValue val = { 1 }; + props->set( + Css_shorthand_info[sh_index].properties[i2], + CSS_TYPE_ENUM, val); + } + } + } + // Error, if !found? At least one value should be set. + break; } } } diff --git a/src/styleengine.cc b/src/styleengine.cc index 6b35e33c..4c1a315c 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -629,6 +629,25 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, else if (attrs->wordSpacing < -1000) attrs->wordSpacing = -1000; break; + case CSS_PROPERTY_X_BACKGROUND_POSITION_X: + if (p->type == CSS_TYPE_ENUM) + // Enums are sorted: 0 = left = 0%; 1 = center = 50%; + // 2 = right = 100%. + attrs->backgroundPositionX = + createPerLength (0.5 * (double)p->value.intVal); + else + computeLength (&attrs->backgroundPositionX, p->value.intVal, + attrs->font); + break; + case CSS_PROPERTY_X_BACKGROUND_POSITION_Y: + if (p->type == CSS_TYPE_ENUM) + // See comment above. + attrs->backgroundPositionY = + createPerLength (0.5 * (double)p->value.intVal); + else + computeLength (&attrs->backgroundPositionY, p->value.intVal, + attrs->font); + break; case PROPERTY_X_LINK: attrs->x_link = p->value.intVal; break; -- cgit v1.2.3 From 2aac3c8d2edf41ac12980c2d25f8b42e76a8ce90 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Thu, 26 Sep 2013 23:27:37 +0200 Subject: Handle 'background' correctly (a bit complicated because of ). --- src/cssparser.cc | 172 +++++++++++++++++++++++++++++++++++++++---------------- src/cssparser.hh | 2 + 2 files changed, 126 insertions(+), 48 deletions(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index aa049659..85abb55a 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -288,6 +288,7 @@ typedef struct { CSS_SHORTHAND_DIRECTIONS, /* {1,4} */ CSS_SHORTHAND_BORDER, /* special, used for 'border' */ CSS_SHORTHAND_FONT, /* special, used for 'font' */ + CSS_SHORTHAND_BACKGROUND, /* special, used for 'background' */ CSS_SHORTHAND_BACKGROUND_POSITION, /* special, used for 'background-position' */ } type; @@ -311,12 +312,6 @@ const CssPropertyName Css_background_properties[] = { (CssPropertyName) - 1 }; -const CssPropertyName Css_background_position_properties[] = { - CSS_PROPERTY_X_BACKGROUND_POSITION_X, - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, - (CssPropertyName) - 1 -}; - const CssPropertyName Css_border_bottom_properties[] = { CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_PROPERTY_BORDER_BOTTOM_STYLE, @@ -419,10 +414,14 @@ const CssPropertyName Css_font_properties[] = { }; static const CssShorthandInfo Css_shorthand_info[] = { - {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, + {"background", CssShorthandInfo::CSS_SHORTHAND_BACKGROUND, Css_background_properties}, + // For 'background-position', no properties are needed, because + // these (CSS_PROPERTY_X_BACKGROUND_POSITION_X and + // CSS_PROPERTY_X_BACKGROUND_POSITION_Y) are handled explicitely + // and specially. {"background-position", CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION, - Css_background_position_properties}, + NULL}, {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER, Css_border_properties}, {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, @@ -1249,47 +1248,74 @@ void CssParser::parseDeclaration(CssPropertyList * props, } while (found); break; + case CssShorthandInfo::CSS_SHORTHAND_BACKGROUND: + // This is mostly a copy of CSS_SHORTHAND_MULTIPLE, with the + // exception of the special handling of + // CSS_PROPERTY_X_BACKGROUND_POSITION_X and + // CSS_PROPERTY_X_BACKGROUND_POSITION_Y, which are part of + // . Simply applying + // CSS_SHORTHAND_MULTIPLE would result in some problems: + // + // (i) It would be allowed that both parts of + // are seperated by other parts, + // which is invalid CSS. Not a real issue, since valid + // CSS would still be parsed. + // + // (ii) CSS_SHORTHAND_MULTIPLE allows to use a property + // multiple times; example: for "10px 20px", first + // "10px", then "20px" would be assigned to + // CSS_PROPERTY_X_BACKGROUND_POSITION_X, but nothing at + // all to CSS_PROPERTY_X_BACKGROUND_POSITION_Y. + // + // (iii) If only one value is set, the other defaults to + // "center", according to the CSS spec; this cannot be + // handled by CSS_SHORTHAND_MULTIPLE. + // + // (And probably more subtleties.) + + do { + for (found = false, i = 0; + !found && + Css_shorthand_info[sh_index].properties[i] != -1; + i++) + if (tokenMatchesProperty(Css_shorthand_info[sh_index]. + properties[i], &type)) { + found = true; + DEBUG_MSG(DEBUG_PARSE_LEVEL, + "will assign to '%s'\n", + Css_property_info + [Css_shorthand_info[sh_index] + .properties[i]].symbol); + + if (Css_shorthand_info[sh_index].properties[i] + == CSS_PROPERTY_X_BACKGROUND_POSITION_X || + Css_shorthand_info[sh_index].properties[i] + == CSS_PROPERTY_X_BACKGROUND_POSITION_Y) + // CSS_PROPERTY_X_BACKGROUND_POSITION_X and + // CSS_PROPERTY_X_BACKGROUND_POSITION_Y are + // handles specially. + parseShorthandBackgroundPosition (sh_index, + props); + else { + // Other values: like CSS_SHORTHAND_MULTIPLE. + if (parseValue(Css_shorthand_info[sh_index] + .properties[i], type, &val)) { + weight = parseWeight(); + if (weight && importantProps) + importantProps-> + set(Css_shorthand_info[sh_index]. + properties[i], type, val); + else + props->set(Css_shorthand_info[sh_index]. + properties[i], type, val); + } + } + } + } while (found); + break; + case CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION: - // 'background-position' consists of one or two values: - // vertical and horizontal position; in most cases in this - // order. However, as long it is unambigous, the order can be - // switched: "10px left" and "left 10px" are both possible - // and have the same effect. For this reason, we test both - // possible orders: i = 0 means vertical/horizontal, i = 1 - // means horizontal/vertical. - for (found = false, i = 0; !found && i < 2; i++) { - int i1 = i, i2 = 1 - i; - if (tokenMatchesProperty( - Css_shorthand_info[sh_index].properties[i1], &type) - && parseValue( - Css_shorthand_info[sh_index].properties[i1], - type, &val)) { - found = true; - props->set(Css_shorthand_info[sh_index].properties[i1], - type, val); - - if (tokenMatchesProperty( - Css_shorthand_info[sh_index].properties[i2], - &type)) { - if (parseValue( - Css_shorthand_info[sh_index].properties[i2], - type, &val)) - props->set( - Css_shorthand_info[sh_index].properties[i2], - type, val); - // else: Should be an error. - } else { - // Second value not set: assume 'center', whose - // enum index is 1 in both cases (horizontal and - // vertical). - CssPropertyValue val = { 1 }; - props->set( - Css_shorthand_info[sh_index].properties[i2], - CSS_TYPE_ENUM, val); - } - } - } - // Error, if !found? At least one value should be set. + parseShorthandBackgroundPosition (sh_index, props); break; } } @@ -1307,6 +1333,56 @@ void CssParser::parseDeclaration(CssPropertyList * props, nextToken(); } +/** + * Parse (consisting of one or two parts), either for the + * 'background-position' property itself, or within 'background'. + */ +void CssParser::parseShorthandBackgroundPosition (int sh_index, + CssPropertyList * props) +{ + // 'background-position' consists of one or two values: vertical and + // horizontal position; in most cases in this order. However, as long it is + // unambigous, the order can be switched: "10px left" and "left 10px" are + // both possible and have the same effect. For this reason, we test both + // possible orders: i = 0 means vertical/horizontal, i = 1 means + // horizontal/vertical. + + // TODO Still not fully working. + + CssValueType type = CSS_TYPE_UNUSED; + CssPropertyValue val; + bool found; + int i; + CssPropertyName prop1, prop2; + + for (found = false, i = 0; !found && i < 2; i++) { + if (i == 0) { + prop1 = CSS_PROPERTY_X_BACKGROUND_POSITION_X; + prop2 = CSS_PROPERTY_X_BACKGROUND_POSITION_Y; + } else { + prop1 = CSS_PROPERTY_X_BACKGROUND_POSITION_Y; + prop2 = CSS_PROPERTY_X_BACKGROUND_POSITION_X; + } + + if (tokenMatchesProperty(prop1, &type) && parseValue(prop1, type, &val)) { + found = true; + props->set(prop1, type, val); + + if (tokenMatchesProperty(prop2, &type)) { + if (parseValue(prop2, type, &val)) + props->set(prop2, type, val); + // else: Should be an error. + } else { + // Second value not set: assume 'center', whose enum index is 1 in + // both cases (horizontal and vertical). + CssPropertyValue val = { 1 }; + props->set(prop2, CSS_TYPE_ENUM, val); + } + } + } + // Error, if !found? At least one value should be set. +} + bool CssParser::parseSimpleSelector(CssSimpleSelector *selector) { CssSimpleSelector::SelectType selectType; diff --git a/src/cssparser.hh b/src/cssparser.hh index 30d02eee..561d4dcf 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -38,6 +38,8 @@ class CssParser { bool parseRgbColor(int32_t *c); void parseDeclaration(CssPropertyList * props, CssPropertyList * importantProps); + void parseShorthandBackgroundPosition (int sh_index, + CssPropertyList * props); bool parseSimpleSelector(CssSimpleSelector *selector); char *parseUrl(); void parseImport(DilloHtml *html, DilloUrl *url); -- cgit v1.2.3 From 80e0cbce7a726a898905d6116e4e237d3af5432b Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 27 Sep 2013 12:50:33 +0200 Subject: Typo (confusing dimensions!). --- src/cssparser.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index 85abb55a..c84a0721 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1344,8 +1344,8 @@ void CssParser::parseShorthandBackgroundPosition (int sh_index, // horizontal position; in most cases in this order. However, as long it is // unambigous, the order can be switched: "10px left" and "left 10px" are // both possible and have the same effect. For this reason, we test both - // possible orders: i = 0 means vertical/horizontal, i = 1 means - // horizontal/vertical. + // possible orders: i = 0 means horizontal/vertical, i = 1 means + // vertical/horizontal. // TODO Still not fully working. -- cgit v1.2.3 From 50c1c525fcb7ffa6384e9f5d6afae96370556ca1 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 27 Sep 2013 15:09:35 +0200 Subject: is now parsed correctly. --- src/cssparser.cc | 93 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index c84a0721..12e14779 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1343,44 +1343,71 @@ void CssParser::parseShorthandBackgroundPosition (int sh_index, // 'background-position' consists of one or two values: vertical and // horizontal position; in most cases in this order. However, as long it is // unambigous, the order can be switched: "10px left" and "left 10px" are - // both possible and have the same effect. For this reason, we test both - // possible orders: i = 0 means horizontal/vertical, i = 1 means - // vertical/horizontal. + // both possible and have the same effect. For this reason, all possibilities + // are tested parrallel. + + CssValueType typeH1, typeV1, typeH2, typeV2; + CssPropertyValue val1, val2; + bool h1, h2, v1, v2; + + // Test both for the first value. + h1 = tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_X, &typeH1); + v1 = tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, &typeV1); + + if (!h1 && !v1) { + // No match at all. Should raise an error. + return; + } - // TODO Still not fully working. + // If both fit (h1 && v1), values can be exchanged later; so setting + // a value as CSS_PROPERTY_X_BACKGROUND_POSITION_Y later, which has been + // parsed here as CSS_PROPERTY_X_BACKGROUND_POSITION_X, causes no problem. + if (!parseValue (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, + h1 ? typeH1 : typeV1, &val1)) { + // Should raise an error. + return; + } - CssValueType type = CSS_TYPE_UNUSED; - CssPropertyValue val; - bool found; - int i; - CssPropertyName prop1, prop2; - - for (found = false, i = 0; !found && i < 2; i++) { - if (i == 0) { - prop1 = CSS_PROPERTY_X_BACKGROUND_POSITION_X; - prop2 = CSS_PROPERTY_X_BACKGROUND_POSITION_Y; - } else { - prop1 = CSS_PROPERTY_X_BACKGROUND_POSITION_Y; - prop2 = CSS_PROPERTY_X_BACKGROUND_POSITION_X; + // Test both for the second value, but exclude already the cases + // horizontal/horizontal and vertical/vertical. + h2 = v1 && + tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_X, &typeH2); + v2 = h1 && + tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, &typeV2); + + if (!h2 && !v2) { + // Second value not set. Prefer horizontal for the first one. + props->set (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, + h1 ? typeH1 : typeV1, val1); + + // Set the second value to 'center', whose enum index is 1 in both cases + // (horizontal and vertical). + val2.intVal = 1; + props->set (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_Y : + CSS_PROPERTY_X_BACKGROUND_POSITION_X, + CSS_TYPE_ENUM, val2); + } else { + // See comment above. + if (!parseValue (h2 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : + CSS_PROPERTY_X_BACKGROUND_POSITION_Y, + h2 ? typeH2 : typeV2, &val2)) { + // Should raise an error. + return; } - - if (tokenMatchesProperty(prop1, &type) && parseValue(prop1, type, &val)) { - found = true; - props->set(prop1, type, val); - - if (tokenMatchesProperty(prop2, &type)) { - if (parseValue(prop2, type, &val)) - props->set(prop2, type, val); - // else: Should be an error. - } else { - // Second value not set: assume 'center', whose enum index is 1 in - // both cases (horizontal and vertical). - CssPropertyValue val = { 1 }; - props->set(prop2, CSS_TYPE_ENUM, val); - } + + // It can be assumed (see above): h2 implies v1, v2 implies h1. + // Prefer v2, i. e. vertical for the second value. + if (v2) { + props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_X, typeH1, val1); + props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, typeV2, val2); + } else { + // !v2 implies h2, since !h2 && !v2 has been excluded. + props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, typeV1, val1); + props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_X, typeH2, val2); } } - // Error, if !found? At least one value should be set. } bool CssParser::parseSimpleSelector(CssSimpleSelector *selector) -- cgit v1.2.3 From b2fd371c4311d5d6abe7c724c8025a37c534942b Mon Sep 17 00:00:00 2001 From: Johannes Hofmann Date: Mon, 30 Sep 2013 20:34:03 +0200 Subject: New type for (incomplete). --- src/css.hh | 8 ++++++++ src/cssparser.cc | 20 ++++++++++++++++---- src/styleengine.cc | 12 +++++------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/css.hh b/src/css.hh index b05a18bc..1dcc41cc 100644 --- a/src/css.hh +++ b/src/css.hh @@ -46,6 +46,7 @@ typedef enum { CSS_TYPE_MULTI_ENUM). Used for 'font-family'. */ CSS_TYPE_URI, /* */ + CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED /* Not yet used. Will itself get unused some day. */ } CssValueType; @@ -143,6 +144,7 @@ typedef enum { CSS_PROPERTY_BACKGROUND_ATTACHMENT, CSS_PROPERTY_BACKGROUND_COLOR, CSS_PROPERTY_BACKGROUND_IMAGE, + CSS_PROPERTY_BACKGROUND_POSITION, // 'background-position' is handled as a shorthand. CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BORDER_BOTTOM_COLOR, @@ -234,9 +236,15 @@ typedef enum { CSS_PROPERTY_LAST } CssPropertyName; +typedef struct { + int32_t posX; + int32_t posY; +} CssBackgroundPosition; + typedef union { int32_t intVal; char *strVal; + CssBackgroundPosition *posVal; } CssPropertyValue; typedef enum { diff --git a/src/cssparser.cc b/src/cssparser.cc index 12e14779..6e414e78 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -159,7 +159,7 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { Css_background_attachment_enum_vals}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, - // 'background-position' is handled as a shorthand. + {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED}, NULL}, {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_background_repeat_enum_vals}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, @@ -307,8 +307,7 @@ const CssPropertyName Css_background_properties[] = { CSS_PROPERTY_BACKGROUND_IMAGE, CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BACKGROUND_ATTACHMENT, - CSS_PROPERTY_X_BACKGROUND_POSITION_X, - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, + CSS_PROPERTY_BACKGROUND_POSITION, (CssPropertyName) - 1 }; @@ -414,7 +413,7 @@ const CssPropertyName Css_font_properties[] = { }; static const CssShorthandInfo Css_shorthand_info[] = { - {"background", CssShorthandInfo::CSS_SHORTHAND_BACKGROUND, + {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, Css_background_properties}, // For 'background-position', no properties are needed, because // these (CSS_PROPERTY_X_BACKGROUND_POSITION_X and @@ -733,6 +732,7 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) } break; + case CSS_TYPE_BACKGROUND_POSITION: case CSS_TYPE_LENGTH_PERCENTAGE: case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER: case CSS_TYPE_LENGTH: @@ -1059,6 +1059,18 @@ bool CssParser::parseValue(CssPropertyName prop, } break; + case CSS_TYPE_BACKGROUND_POSITION: + CssPropertyValue posX, posY; + if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posX) && + parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posY)) { + CssBackgroundPosition *position = (CssBackgroundPosition *) malloc(sizeof(CssBackgroundPosition)); + position->posX = posX.intVal; + position->posY = posY.intVal; + val->posVal = position; + ret = true; + } + break; + case CSS_TYPE_UNUSED: /* nothing */ break; diff --git a/src/styleengine.cc b/src/styleengine.cc index 4c1a315c..8d425371 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -629,23 +629,21 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, else if (attrs->wordSpacing < -1000) attrs->wordSpacing = -1000; break; - case CSS_PROPERTY_X_BACKGROUND_POSITION_X: + case CSS_PROPERTY_BACKGROUND_POSITION: if (p->type == CSS_TYPE_ENUM) // Enums are sorted: 0 = left = 0%; 1 = center = 50%; // 2 = right = 100%. attrs->backgroundPositionX = - createPerLength (0.5 * (double)p->value.intVal); + createPerLength (0.5 * (double)p->value.posVal->posX); else - computeLength (&attrs->backgroundPositionX, p->value.intVal, + computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, attrs->font); - break; - case CSS_PROPERTY_X_BACKGROUND_POSITION_Y: if (p->type == CSS_TYPE_ENUM) // See comment above. attrs->backgroundPositionY = - createPerLength (0.5 * (double)p->value.intVal); + createPerLength (0.5 * (double)p->value.posVal->posY); else - computeLength (&attrs->backgroundPositionY, p->value.intVal, + computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, attrs->font); break; case PROPERTY_X_LINK: -- cgit v1.2.3 From 1bc80ace64c68cad386bdcb3efc37fd9a8ccc558 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 30 Sep 2013 21:09:16 +0200 Subject: Cleaned up Johannes' patch. --- src/css.hh | 5 -- src/cssparser.cc | 178 +---------------------------------------------------- src/cssparser.hh | 2 - src/styleengine.cc | 19 ++---- 4 files changed, 6 insertions(+), 198 deletions(-) diff --git a/src/css.hh b/src/css.hh index 1dcc41cc..d2c75808 100644 --- a/src/css.hh +++ b/src/css.hh @@ -145,7 +145,6 @@ typedef enum { CSS_PROPERTY_BACKGROUND_COLOR, CSS_PROPERTY_BACKGROUND_IMAGE, CSS_PROPERTY_BACKGROUND_POSITION, - // 'background-position' is handled as a shorthand. CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BORDER_BOTTOM_COLOR, CSS_PROPERTY_BORDER_BOTTOM_STYLE, @@ -225,10 +224,6 @@ typedef enum { CSS_PROPERTY_X_LINK, CSS_PROPERTY_X_COLSPAN, CSS_PROPERTY_X_ROWSPAN, - // The following two are internal properties for 'background-position'; see - // more at equivalent definition in Css_property_info. - CSS_PROPERTY_X_BACKGROUND_POSITION_X, - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, PROPERTY_X_LINK, PROPERTY_X_LANG, PROPERTY_X_IMG, diff --git a/src/cssparser.cc b/src/cssparser.cc index 6e414e78..ed90f275 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -146,20 +146,13 @@ static const char *const Css_word_spacing_enum_vals[] = { "normal", NULL }; -static const char *const Css_x_background_position_x_enum_vals[] = { - "left", "center", "right", NULL -}; - -static const char *const Css_x_background_position_y_enum_vals[] = { - "top", "center", "bottom", NULL -}; - const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"background-attachment", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_background_attachment_enum_vals}, {"background-color", {CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, NULL}, {"background-image", {CSS_TYPE_URI, CSS_TYPE_UNUSED}, NULL}, - {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED}, NULL}, + {"background-position", {CSS_TYPE_BACKGROUND_POSITION, CSS_TYPE_UNUSED}, + NULL}, {"background-repeat", {CSS_TYPE_ENUM, CSS_TYPE_UNUSED}, Css_background_repeat_enum_vals}, {"border-bottom-color", {CSS_TYPE_ENUM, CSS_TYPE_COLOR, CSS_TYPE_UNUSED}, @@ -266,17 +259,6 @@ const CssPropertyInfo Css_property_info[CSS_PROPERTY_LAST] = { {"x-link", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, {"x-colspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, {"x-rowspan", {CSS_TYPE_INTEGER, CSS_TYPE_UNUSED}, NULL}, - - // The following two are internal properties for 'background-position'. They - // are not set directly, but by the 'background-position' shortcut. Here, - // both , , as well as symbolic values ("right", "top" - // etc.) are possible. - {"x-background-position-x", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH_PERCENTAGE, - CSS_TYPE_UNUSED}, - Css_x_background_position_x_enum_vals}, - {"x-background-position-y", {CSS_TYPE_ENUM, CSS_TYPE_LENGTH_PERCENTAGE, - CSS_TYPE_UNUSED}, - Css_x_background_position_y_enum_vals}, {"last", {CSS_TYPE_UNUSED}, NULL}, }; @@ -288,9 +270,6 @@ typedef struct { CSS_SHORTHAND_DIRECTIONS, /* {1,4} */ CSS_SHORTHAND_BORDER, /* special, used for 'border' */ CSS_SHORTHAND_FONT, /* special, used for 'font' */ - CSS_SHORTHAND_BACKGROUND, /* special, used for 'background' */ - CSS_SHORTHAND_BACKGROUND_POSITION, - /* special, used for 'background-position' */ } type; const CssPropertyName * properties;/* CSS_SHORTHAND_MULTIPLE: * must be terminated by -1 @@ -415,12 +394,6 @@ const CssPropertyName Css_font_properties[] = { static const CssShorthandInfo Css_shorthand_info[] = { {"background", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, Css_background_properties}, - // For 'background-position', no properties are needed, because - // these (CSS_PROPERTY_X_BACKGROUND_POSITION_X and - // CSS_PROPERTY_X_BACKGROUND_POSITION_Y) are handled explicitely - // and specially. - {"background-position", CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION, - NULL}, {"border", CssShorthandInfo::CSS_SHORTHAND_BORDER, Css_border_properties}, {"border-bottom", CssShorthandInfo::CSS_SHORTHAND_MULTIPLE, @@ -1259,76 +1232,6 @@ void CssParser::parseDeclaration(CssPropertyList * props, } } while (found); break; - - case CssShorthandInfo::CSS_SHORTHAND_BACKGROUND: - // This is mostly a copy of CSS_SHORTHAND_MULTIPLE, with the - // exception of the special handling of - // CSS_PROPERTY_X_BACKGROUND_POSITION_X and - // CSS_PROPERTY_X_BACKGROUND_POSITION_Y, which are part of - // . Simply applying - // CSS_SHORTHAND_MULTIPLE would result in some problems: - // - // (i) It would be allowed that both parts of - // are seperated by other parts, - // which is invalid CSS. Not a real issue, since valid - // CSS would still be parsed. - // - // (ii) CSS_SHORTHAND_MULTIPLE allows to use a property - // multiple times; example: for "10px 20px", first - // "10px", then "20px" would be assigned to - // CSS_PROPERTY_X_BACKGROUND_POSITION_X, but nothing at - // all to CSS_PROPERTY_X_BACKGROUND_POSITION_Y. - // - // (iii) If only one value is set, the other defaults to - // "center", according to the CSS spec; this cannot be - // handled by CSS_SHORTHAND_MULTIPLE. - // - // (And probably more subtleties.) - - do { - for (found = false, i = 0; - !found && - Css_shorthand_info[sh_index].properties[i] != -1; - i++) - if (tokenMatchesProperty(Css_shorthand_info[sh_index]. - properties[i], &type)) { - found = true; - DEBUG_MSG(DEBUG_PARSE_LEVEL, - "will assign to '%s'\n", - Css_property_info - [Css_shorthand_info[sh_index] - .properties[i]].symbol); - - if (Css_shorthand_info[sh_index].properties[i] - == CSS_PROPERTY_X_BACKGROUND_POSITION_X || - Css_shorthand_info[sh_index].properties[i] - == CSS_PROPERTY_X_BACKGROUND_POSITION_Y) - // CSS_PROPERTY_X_BACKGROUND_POSITION_X and - // CSS_PROPERTY_X_BACKGROUND_POSITION_Y are - // handles specially. - parseShorthandBackgroundPosition (sh_index, - props); - else { - // Other values: like CSS_SHORTHAND_MULTIPLE. - if (parseValue(Css_shorthand_info[sh_index] - .properties[i], type, &val)) { - weight = parseWeight(); - if (weight && importantProps) - importantProps-> - set(Css_shorthand_info[sh_index]. - properties[i], type, val); - else - props->set(Css_shorthand_info[sh_index]. - properties[i], type, val); - } - } - } - } while (found); - break; - - case CssShorthandInfo::CSS_SHORTHAND_BACKGROUND_POSITION: - parseShorthandBackgroundPosition (sh_index, props); - break; } } } @@ -1345,83 +1248,6 @@ void CssParser::parseDeclaration(CssPropertyList * props, nextToken(); } -/** - * Parse (consisting of one or two parts), either for the - * 'background-position' property itself, or within 'background'. - */ -void CssParser::parseShorthandBackgroundPosition (int sh_index, - CssPropertyList * props) -{ - // 'background-position' consists of one or two values: vertical and - // horizontal position; in most cases in this order. However, as long it is - // unambigous, the order can be switched: "10px left" and "left 10px" are - // both possible and have the same effect. For this reason, all possibilities - // are tested parrallel. - - CssValueType typeH1, typeV1, typeH2, typeV2; - CssPropertyValue val1, val2; - bool h1, h2, v1, v2; - - // Test both for the first value. - h1 = tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_X, &typeH1); - v1 = tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, &typeV1); - - if (!h1 && !v1) { - // No match at all. Should raise an error. - return; - } - - // If both fit (h1 && v1), values can be exchanged later; so setting - // a value as CSS_PROPERTY_X_BACKGROUND_POSITION_Y later, which has been - // parsed here as CSS_PROPERTY_X_BACKGROUND_POSITION_X, causes no problem. - if (!parseValue (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, - h1 ? typeH1 : typeV1, &val1)) { - // Should raise an error. - return; - } - - // Test both for the second value, but exclude already the cases - // horizontal/horizontal and vertical/vertical. - h2 = v1 && - tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_X, &typeH2); - v2 = h1 && - tokenMatchesProperty (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, &typeV2); - - if (!h2 && !v2) { - // Second value not set. Prefer horizontal for the first one. - props->set (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, - h1 ? typeH1 : typeV1, val1); - - // Set the second value to 'center', whose enum index is 1 in both cases - // (horizontal and vertical). - val2.intVal = 1; - props->set (h1 ? CSS_PROPERTY_X_BACKGROUND_POSITION_Y : - CSS_PROPERTY_X_BACKGROUND_POSITION_X, - CSS_TYPE_ENUM, val2); - } else { - // See comment above. - if (!parseValue (h2 ? CSS_PROPERTY_X_BACKGROUND_POSITION_X : - CSS_PROPERTY_X_BACKGROUND_POSITION_Y, - h2 ? typeH2 : typeV2, &val2)) { - // Should raise an error. - return; - } - - // It can be assumed (see above): h2 implies v1, v2 implies h1. - // Prefer v2, i. e. vertical for the second value. - if (v2) { - props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_X, typeH1, val1); - props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, typeV2, val2); - } else { - // !v2 implies h2, since !h2 && !v2 has been excluded. - props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_Y, typeV1, val1); - props->set (CSS_PROPERTY_X_BACKGROUND_POSITION_X, typeH2, val2); - } - } -} - bool CssParser::parseSimpleSelector(CssSimpleSelector *selector) { CssSimpleSelector::SelectType selectType; diff --git a/src/cssparser.hh b/src/cssparser.hh index 561d4dcf..30d02eee 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -38,8 +38,6 @@ class CssParser { bool parseRgbColor(int32_t *c); void parseDeclaration(CssPropertyList * props, CssPropertyList * importantProps); - void parseShorthandBackgroundPosition (int sh_index, - CssPropertyList * props); bool parseSimpleSelector(CssSimpleSelector *selector); char *parseUrl(); void parseImport(DilloHtml *html, DilloUrl *url); diff --git a/src/styleengine.cc b/src/styleengine.cc index 8d425371..01ba71f8 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -630,21 +630,10 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, attrs->wordSpacing = -1000; break; case CSS_PROPERTY_BACKGROUND_POSITION: - if (p->type == CSS_TYPE_ENUM) - // Enums are sorted: 0 = left = 0%; 1 = center = 50%; - // 2 = right = 100%. - attrs->backgroundPositionX = - createPerLength (0.5 * (double)p->value.posVal->posX); - else - computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, - attrs->font); - if (p->type == CSS_TYPE_ENUM) - // See comment above. - attrs->backgroundPositionY = - createPerLength (0.5 * (double)p->value.posVal->posY); - else - computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, - attrs->font); + computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, + attrs->font); + computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, + attrs->font); break; case PROPERTY_X_LINK: attrs->x_link = p->value.intVal; -- cgit v1.2.3 From 8ef9399d0e4f92ebb00d7cc6c0ec273c4b5ca4bd Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 1 Oct 2013 14:57:30 +0200 Subject: Parsing of is complete. --- src/cssparser.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 8 deletions(-) diff --git a/src/cssparser.cc b/src/cssparser.cc index ed90f275..ce6225dd 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -706,6 +706,14 @@ bool CssParser::tokenMatchesProperty(CssPropertyName prop, CssValueType *type) break; case CSS_TYPE_BACKGROUND_POSITION: + if (ttype == CSS_TK_SYMBOL && + (dStrAsciiCasecmp(tval, "center") == 0 || + dStrAsciiCasecmp(tval, "left") == 0 || + dStrAsciiCasecmp(tval, "right") == 0 || + dStrAsciiCasecmp(tval, "top") == 0 || + dStrAsciiCasecmp(tval, "bottom") == 0)) + return true; + // Fall Through (lenght and percentage) case CSS_TYPE_LENGTH_PERCENTAGE: case CSS_TYPE_LENGTH_PERCENTAGE_NUMBER: case CSS_TYPE_LENGTH: @@ -1033,14 +1041,95 @@ bool CssParser::parseValue(CssPropertyName prop, break; case CSS_TYPE_BACKGROUND_POSITION: - CssPropertyValue posX, posY; - if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posX) && - parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &posY)) { - CssBackgroundPosition *position = (CssBackgroundPosition *) malloc(sizeof(CssBackgroundPosition)); - position->posX = posX.intVal; - position->posY = posY.intVal; - val->posVal = position; - ret = true; + // 'background-position' consists of one or two values: vertical and + // horizontal position; in most cases in this order. However, as long it + // is unambigous, the order can be switched: "10px left" and "left 10px" + // are both possible and have the same effect. For this reason, all + // possibilities are tested parrallel. + + bool h[2], v[2]; + int pos[2]; + h[0] = v[0] = h[1] = v[1] = false; + + // First: collect values in pos[0] and pos[1], and determine whether + // they can be used for a horizontal (h[i]) or vertical (v[i]) position + // (or both). When neither h[i] or v[i] is set, pos[i] is undefined. + for (i = 0; i < 2; i++) { + CssValueType typeTmp; + // tokenMatchesProperty will, for CSS_PROPERTY_BACKGROUND_POSITION, + // work on both parts, since they are exchangable. + if (tokenMatchesProperty (CSS_PROPERTY_BACKGROUND_POSITION, + &typeTmp)) { + h[i] = ttype != CSS_TK_SYMBOL || + (dStrAsciiCasecmp(tval, "top") != 0 && + dStrAsciiCasecmp(tval, "bottom") != 0); + v[i] = ttype != CSS_TK_SYMBOL || + (dStrAsciiCasecmp(tval, "left") != 0 && + dStrAsciiCasecmp(tval, "right") != 0); + } else + // No match. + h[i] = v[i] = false; + + if (h[i] || v[i]) { + // Calculate values. + if (ttype == CSS_TK_SYMBOL) { + if (dStrAsciiCasecmp(tval, "top") == 0 || + dStrAsciiCasecmp(tval, "left") == 0) { + pos[i] = CSS_CREATE_LENGTH (0.0, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else if (dStrAsciiCasecmp(tval, "center") == 0) { + pos[i] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else if (dStrAsciiCasecmp(tval, "bottom") == 0 || + dStrAsciiCasecmp(tval, "right") == 0) { + pos[i] = CSS_CREATE_LENGTH (1.0, CSS_LENGTH_TYPE_PERCENTAGE); + nextToken(); + } else + // tokenMatchesProperty should have returned "false" already. + lout::misc::assertNotReached (); + } else { + // We can assume or here ... + CssPropertyValue valTmp; + if (parseValue(prop, CSS_TYPE_LENGTH_PERCENTAGE, &valTmp)) { + pos[i] = valTmp.intVal; + ret = true; + } else + // ... but something may still fail. + h[i] = v[i] = false; + } + } + + // If the first value cannot be read, do not read the second. + if (!h[i] && !v[i]) + break; + } + + // Second: Create the final value. Order will be determined here. + if (v[0] || h[0]) { + // If second value is not set, it is set to "center", i. e. 50%, (see + // CSS specification), which is suitable for both dimensions. + if (!h[1] && !v[1]) { + pos[1] = CSS_CREATE_LENGTH (0.5, CSS_LENGTH_TYPE_PERCENTAGE); + h[1] = v[1] = true; + } + + // Only valid, when a combination h/v or v/h is possible. + if ((h[0] && v[1]) || (v[0] && h[1])) { + ret = true; + CssBackgroundPosition *position = + (CssBackgroundPosition *) malloc(sizeof(CssBackgroundPosition)); + val->posVal = position; + + // Prefer combination h/v: + if (h[0] && v[1]) { + position->posX = pos[0]; + position->posY = pos[1]; + } else { + // This should be v/h: + position->posX = pos[1]; + position->posY = pos[0]; + } + } } break; -- cgit v1.2.3 From b786927adfaaee3eddc3c73033edbddd7f646f2a Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 1 Oct 2013 14:58:17 +0200 Subject: Cleanup. --- src/styleengine.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/styleengine.cc b/src/styleengine.cc index 01ba71f8..f3fd2934 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -480,6 +480,12 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, } } break; + case CSS_PROPERTY_BACKGROUND_POSITION: + computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, + attrs->font); + computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, + attrs->font); + break; case CSS_PROPERTY_BACKGROUND_REPEAT: attrs->backgroundRepeat = (BackgroundRepeat) p->value.intVal; break; @@ -629,12 +635,6 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, else if (attrs->wordSpacing < -1000) attrs->wordSpacing = -1000; break; - case CSS_PROPERTY_BACKGROUND_POSITION: - computeLength (&attrs->backgroundPositionX, p->value.posVal->posX, - attrs->font); - computeLength (&attrs->backgroundPositionY, p->value.posVal->posY, - attrs->font); - break; case PROPERTY_X_LINK: attrs->x_link = p->value.intVal; break; -- cgit v1.2.3 From e8f04035f76c6a31f42ec3465902854569905c1d Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 2 Oct 2013 11:10:40 +0200 Subject: Typo in comment. --- dw/style.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dw/style.hh b/dw/style.hh index 88e4a290..27bcf579 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -463,8 +463,8 @@ public: StyleImage *backgroundImage; BackgroundRepeat backgroundRepeat; BackgroundAttachment backgroundAttachment; - Length backgroundPositionX; // "left" defiened by "0%" etc. (see CSS spec) - Length backgroundPositionY; // "top" defiened by "0%" etc. (see CSS spec) + Length backgroundPositionX; // "left" defined by "0%" etc. (see CSS spec) + Length backgroundPositionY; // "top" defined by "0%" etc. (see CSS spec) TextAlignType textAlign; VAlignType valign; -- cgit v1.2.3 From 8ef6e194f3c77f6f21ffbe9fea5a5961b502541e Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 4 Oct 2013 16:00:53 +0200 Subject: Background image for view(port)s; no updates yet. --- dw/layout.cc | 38 +++++++++++ dw/layout.hh | 9 +++ dw/style.cc | 155 ++++++++++++++++++++++++++------------------ dw/style.hh | 7 ++ test/dw_image_background.cc | 14 ++-- 5 files changed, 154 insertions(+), 69 deletions(-) diff --git a/dw/layout.cc b/dw/layout.cc index 3f493d8a..61ff8a38 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -189,6 +189,7 @@ Layout::Layout (Platform *platform) DBG_OBJ_CREATE (this, "DwRenderLayout"); bgColor = NULL; + bgImage = NULL; cursor = style::CURSOR_DEFAULT; canvasWidth = canvasAscent = canvasDescent = 0; @@ -228,6 +229,8 @@ Layout::~Layout () platform->removeIdle (resizeIdleId); if (bgColor) bgColor->unref (); + if (bgImage) + bgImage->unref (); if (topLevel) { Widget *w = topLevel; topLevel = NULL; @@ -508,6 +511,23 @@ void Layout::draw (View *view, Rectangle *area) { Rectangle widgetArea, intersection, widgetDrawArea; + // First of all, draw background image. (Unlike background *color*, + // this is not a feature of the views.) + if (bgImage != NULL && bgImage->getImgbuf() != NULL) + style::drawBackgroundImage (view, bgImage, bgRepeat, bgAttachment, + bgPositionX, bgPositionY, + area->x, area->y, area->width, + area->height, 0, 0, + // Reference area: maximum of canvas size and + // viewport size. + misc::max (viewportWidth + - (canvasHeightGreater ? + vScrollbarThickness : 0), + canvasWidth), + misc::max (viewportHeight + - hScrollbarThickness, + canvasAscent + canvasDescent)); + if (scrollIdleId != -1) { /* scroll is pending, defer draw until after scrollIdle() */ drawAfterScrollReq = true; @@ -650,6 +670,24 @@ void Layout::setBgColor (style::Color *color) view->setBgColor (bgColor); } +void Layout::setBgImage (style::StyleImage *bgImage, + style::BackgroundRepeat bgRepeat, + style::BackgroundAttachment bgAttachment, + style::Length bgPositionX, style::Length bgPositionY) +{ + bgImage->ref (); + + if (this->bgImage) + this->bgImage->unref (); + + this->bgImage = bgImage; + this->bgRepeat = bgRepeat; + this->bgAttachment = bgAttachment; + this->bgPositionX = bgPositionX; + this->bgPositionY = bgPositionY; +} + + void Layout::resizeIdle () { //static int calls = 0; diff --git a/dw/layout.hh b/dw/layout.hh index 51d764a4..9687a2da 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -135,6 +135,11 @@ private: /* The state, which must be projected into the view. */ style::Color *bgColor; + style::StyleImage *bgImage; + style::BackgroundRepeat bgRepeat; + style::BackgroundAttachment bgAttachment; + style::Length bgPositionX, bgPositionY; + style::Cursor cursor; int canvasWidth, canvasAscent, canvasDescent; @@ -386,6 +391,10 @@ public: inline void resetSearch () { findtextState.resetSearch (); } void setBgColor (style::Color *color); + void setBgImage (style::StyleImage *bgImage, + style::BackgroundRepeat bgRepeat, + style::BackgroundAttachment bgAttachment, + style::Length bgPositionX, style::Length bgPositionY); inline style::Color* getBgColor () { return bgColor; } }; diff --git a/dw/style.cc b/dw/style.cc index e443ab61..cc885a59 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -34,11 +34,17 @@ namespace dw { namespace core { namespace style { -static void calcBackgroundRelatedValues (Style *style, int xDraw, int yDraw, - int widthDraw, int heightDraw, - int xRef, int yRef, int widthRef, - int heightRef, bool *repeatX, - bool *repeatY, int *origX, int *origY, +static void calcBackgroundRelatedValues (StyleImage *backgroundImage, + BackgroundRepeat backgroundRepeat, + BackgroundAttachment + backgroundAttachment, + Length backgroundPositionX, + Length backgroundPositionY, + int xDraw, int yDraw, int widthDraw, + int heightDraw, int xRef, int yRef, + int widthRef, int heightRef, + bool *repeatX, bool *repeatY, + int *origX, int *origY, int *tileX1, int *tileX2, int *tileY1, int *tileY2, bool *doDraw); @@ -528,7 +534,12 @@ void StyleImage::ExternalImgRenderer::drawRow (int row) bool repeatX, repeatY, doDraw; int origX, origY, tileX1, tileX2, tileY1, tileY2; - calcBackgroundRelatedValues (style, xDraw, yDraw, widthDraw, heightDraw, + calcBackgroundRelatedValues (style->backgroundImage, + style->backgroundRepeat, + style->backgroundAttachment, + style->backgroundPositionX, + style->backgroundPositionY, + xDraw, yDraw, widthDraw, heightDraw, xRef, yRef, widthRef, heightRef, &repeatX, &repeatY, &origX, &origY, &tileX1, &tileX2, &tileY1, &tileY2, &doDraw); @@ -1050,73 +1061,93 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, true, intersection.x, intersection.y, intersection.width, intersection.height); - if (bgImage) { - Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); - int imgWidth = imgbuf->getRootWidth (); - int imgHeight = imgbuf->getRootHeight (); - - bool repeatX, repeatY, doDraw; - int origX, origY, tileX1, tileX2, tileY1, tileY2; - - calcBackgroundRelatedValues (style, intersection.x, intersection.y, - intersection.width, - intersection.height, xRef, yRef, - widthRef, heightRef, &repeatX, - &repeatY, &origX, &origY, &tileX1, - &tileX2, &tileY1, &tileY2, &doDraw); - - //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", - // tileX1, tileX2, tileY1, tileY2); - - if (doDraw) - for (int tileX = tileX1; tileX <= tileX2; tileX++) - for (int tileY = tileY1; tileY <= tileY2; tileY++) { - int x = origX + tileX * imgWidth; - int x1 = misc::max (x, intersection.x); - int x2 = misc::min (x + imgWidth, - intersection.x + intersection.width); - int y = origY + tileY * imgHeight; - int y1 = misc::max (y, intersection.y); - int y2 = misc::min (y + imgHeight, - intersection.y + intersection.height); - - //printf (" (%d, %d) => (%d, %d - %d) / (%d, %d - %d)\n", - // tileX, tileY, x, x1, x2, y, y1, y2); - //printf (" => drawImage (%d, %d, %d, %d, %d, %d)\n", - // x, y, x - x, y1 - y, x2 - x1, y2 - y1); - - view->drawImage (imgbuf, x, y, x1 - x, y1 - y, - x2 - x1, y2 - y1); - } - } + if (bgImage) + drawBackgroundImage (view, style->backgroundImage, + style->backgroundRepeat, + style->backgroundAttachment, + style->backgroundPositionX, + style->backgroundPositionY, + intersection.x, intersection.y, + intersection.width, intersection.height, + xRef, yRef, widthRef, heightRef); + } } } -void calcBackgroundRelatedValues (Style *style, int xDraw, int yDraw, - int widthDraw, int heightDraw, int xRef, - int yRef, int widthRef, int heightRef, - bool *repeatX, bool *repeatY, int *origX, - int *origY, int *tileX1, int *tileX2, - int *tileY1, int *tileY2, bool *doDraw) +void drawBackgroundImage (View *view, StyleImage *backgroundImage, + BackgroundRepeat backgroundRepeat, + BackgroundAttachment backgroundAttachment, + Length backgroundPositionX, + Length backgroundPositionY, + int x, int y, int width, int height, + int xRef, int yRef, int widthRef, int heightRef) +{ + Imgbuf *imgbuf = backgroundImage->getImgbuf(); + int imgWidth = imgbuf->getRootWidth (); + int imgHeight = imgbuf->getRootHeight (); + + //printf ("drawBackrgoundImage (..., [img: %d, %d], ..., (%d, %d), %d x %d, " + // "(%d, %d), %d x %d)\n", imgWidth, imgHeight, x, y, width, height, + // xRef, yRef, widthRef, heightRef); + + bool repeatX, repeatY, doDraw; + int origX, origY, tileX1, tileX2, tileY1, tileY2; + + calcBackgroundRelatedValues (backgroundImage, backgroundRepeat, + backgroundAttachment, backgroundPositionX, + backgroundPositionY, x, y, width, height, + xRef, yRef, widthRef, heightRef, + &repeatX, &repeatY, &origX, &origY, + &tileX1, &tileX2, &tileY1, &tileY2, &doDraw); + + //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", + // tileX1, tileX2, tileY1, tileY2); + + if (doDraw) + for (int tileX = tileX1; tileX <= tileX2; tileX++) + for (int tileY = tileY1; tileY <= tileY2; tileY++) { + int xt = origX + tileX * imgWidth; + int x1 = misc::max (xt, x); + int x2 = misc::min (xt + imgWidth, x + width); + int yt = origY + tileY * imgHeight; + int y1 = misc::max (yt, y); + int y2 = misc::min (yt + imgHeight, y + height); + + view->drawImage (imgbuf, xt, yt, x1 - xt, y1 - yt, + x2 - x1, y2 - y1); + } +} + +void calcBackgroundRelatedValues (StyleImage *backgroundImage, + BackgroundRepeat backgroundRepeat, + BackgroundAttachment backgroundAttachment, + Length backgroundPositionX, + Length backgroundPositionY, + int xDraw, int yDraw, int widthDraw, + int heightDraw, int xRef, int yRef, + int widthRef, int heightRef, bool *repeatX, + bool *repeatY, int *origX, int *origY, + int *tileX1, int *tileX2, int *tileY1, + int *tileY2, bool *doDraw) { - Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); + Imgbuf *imgbuf = backgroundImage->getImgbuf(); int imgWidth = imgbuf->getRootWidth (); int imgHeight = imgbuf->getRootHeight (); - *repeatX = style->backgroundRepeat == BACKGROUND_REPEAT || - style->backgroundRepeat == BACKGROUND_REPEAT_X; - *repeatY = style->backgroundRepeat == BACKGROUND_REPEAT || - style->backgroundRepeat == BACKGROUND_REPEAT_Y; + *repeatX = backgroundRepeat == BACKGROUND_REPEAT || + backgroundRepeat == BACKGROUND_REPEAT_X; + *repeatY = backgroundRepeat == BACKGROUND_REPEAT || + backgroundRepeat == BACKGROUND_REPEAT_Y; *origX = xRef + - (isPerLength (style->backgroundPositionX) ? - perLengthVal (style->backgroundPositionX) * (widthRef - imgWidth) : - absLengthVal (style->backgroundPositionX)); + (isPerLength (backgroundPositionX) ? + perLengthVal (backgroundPositionX) * (widthRef - imgWidth) : + absLengthVal (backgroundPositionX)); *origY = yRef + - (isPerLength (style->backgroundPositionY) ? - perLengthVal (style->backgroundPositionY) * (heightRef - imgHeight) : - absLengthVal (style->backgroundPositionY)); + (isPerLength (backgroundPositionY) ? + perLengthVal (backgroundPositionY) * (heightRef - imgHeight) : + absLengthVal (backgroundPositionY)); *tileX1 = xDraw < *origX ? - (*origX - xDraw + imgWidth - 1) / imgWidth : diff --git a/dw/style.hh b/dw/style.hh index 27bcf579..fbc726ef 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -794,6 +794,13 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, int xRef, int yRef, int widthRef, int heightRef, Style *style, bool inverse, bool atTop); +void drawBackgroundImage (View *view, StyleImage *backgroundImage, + BackgroundRepeat backgroundRepeat, + BackgroundAttachment backgroundAttachment, + Length backgroundPositionX, + Length backgroundPositionY, + int x, int y, int width, int height, + int xRef, int yRef, int widthRef, int heightRef); void numtostr (int num, char *buf, int buflen, ListStyleType listStyleType); } // namespace style diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc index 3b692901..391d6fe1 100644 --- a/test/dw_image_background.cc +++ b/test/dw_image_background.cc @@ -115,6 +115,12 @@ int main(int argc, char **argv) FltkViewport *viewport = new FltkViewport (0, 0, 200, 300); layout->attachView (viewport); + image1 = StyleImage::create (); + image1->connectDeletion (&isdr); + layout->setBgImage (image1, BACKGROUND_REPEAT_Y, + BACKGROUND_ATTACHMENT_SCROLL, createPerLength (0.5), + createAbsLength (30)); + StyleAttrs styleAttrs; styleAttrs.initValues (); styleAttrs.margin.setVal (5); @@ -129,13 +135,7 @@ int main(int argc, char **argv) styleAttrs.font = style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); - styleAttrs.backgroundColor = Color::create (layout, 0xffffff); - - image1 = styleAttrs.backgroundImage = StyleImage::create (); - image1->connectDeletion (&isdr); - styleAttrs.backgroundRepeat = BACKGROUND_REPEAT_Y; - styleAttrs.backgroundPositionX = createPerLength (0.5); - styleAttrs.backgroundPositionY = createAbsLength (30); + //styleAttrs.backgroundColor = Color::create (layout, 0xffffff); Style *widgetStyle = Style::create (&styleAttrs); -- cgit v1.2.3 From 727dd780fddcf423400df4283c1587618ced0ed0 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 4 Oct 2013 21:49:22 +0200 Subject: Some refactoring. --- dw/style.cc | 93 +++++++++++++++++++++++++++++++++++++++++---------------- dw/style.hh | 40 ++++++++++++++++++++----- dw/textblock.hh | 3 +- dw/widget.hh | 2 +- 4 files changed, 104 insertions(+), 34 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index cc885a59..39d8858b 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -511,22 +511,16 @@ void StyleImage::ExternalImgRenderer::setBuffer (core::Imgbuf *buffer, void StyleImage::ExternalImgRenderer::drawRow (int row) { - Style *style; - if (readyToDraw () && (style = getStyle ())) { + StyleImage *backgroundImage; + if (readyToDraw () && (backgroundImage = getBackgroundImage ())) { // All single rows are drawn. - Imgbuf *imgbuf = style->backgroundImage->getImgbuf(); + Imgbuf *imgbuf = backgroundImage->getImgbuf(); int imgWidth = imgbuf->getRootWidth (); int imgHeight = imgbuf->getRootHeight (); int x, y, width, height; - getArea (&x, &y, &width, &height); - int xDraw = x + style->margin.left + style->borderWidth.left; - int yDraw = y + style->margin.top + style->borderWidth.top; - int widthDraw = width - style->margin.left - style->borderWidth.left - - style->margin.right - style->borderWidth.right; - int heightDraw = height - style->margin.top - style->borderWidth.top - - style->margin.bottom - style->borderWidth.bottom; + getPaddingArea (&x, &y, &width, &height); int xRef, yRef, widthRef, heightRef; getRefArea (&xRef, &yRef, &widthRef, &heightRef); @@ -534,15 +528,15 @@ void StyleImage::ExternalImgRenderer::drawRow (int row) bool repeatX, repeatY, doDraw; int origX, origY, tileX1, tileX2, tileY1, tileY2; - calcBackgroundRelatedValues (style->backgroundImage, - style->backgroundRepeat, - style->backgroundAttachment, - style->backgroundPositionX, - style->backgroundPositionY, - xDraw, yDraw, widthDraw, heightDraw, - xRef, yRef, widthRef, heightRef, &repeatX, - &repeatY, &origX, &origY, &tileX1, &tileX2, - &tileY1, &tileY2, &doDraw); + calcBackgroundRelatedValues (backgroundImage, + getBackgroundRepeat (), + getBackgroundAttachment (), + getBackgroundPositionX (), + getBackgroundPositionY (), + x, y, width, height, xRef, yRef, widthRef, + heightRef, &repeatX, &repeatY, &origX, + &origY, &tileX1, &tileX2, &tileY1, &tileY2, + &doDraw); //printf ("tileX1 = %d, tileX2 = %d, tileY1 = %d, tileY2 = %d\n", // tileX1, tileX2, tileY1, tileY2); @@ -551,19 +545,68 @@ void StyleImage::ExternalImgRenderer::drawRow (int row) // Only iterate over y, because the rows can be combined // horizontically. for (int tileY = tileY1; tileY <= tileY2; tileY++) { - int x1 = misc::max (origX + tileX1 * imgWidth, xDraw); - int x2 = misc::min (origX + (tileX2 + 1) * imgWidth, - xDraw + widthDraw); + int x1 = misc::max (origX + tileX1 * imgWidth, x); + int x2 = misc::min (origX + (tileX2 + 1) * imgWidth, x + width); - int y = origY + tileY * imgHeight + row; - if (y >= yDraw && y < yDraw + heightDraw) - draw (x1, y, x2 - x1, 1); + int yt = origY + tileY * imgHeight + row; + if (yt >= y && yt < y + height) + draw (x1, yt, x2 - x1, 1); } } } // ---------------------------------------------------------------------- +void StyleImage::ExternalWidgetImgRenderer::getPaddingArea (int *x, int *y, + int *width, + int *height) +{ + Style *style = getStyle (); + assert (style != NULL); + + int x0, y0, width0, height0; + getArea (&x0, &y0, &width0, &height0); + *x = x0 + style->margin.left + style->borderWidth.left; + *y = y0 + style->margin.top + style->borderWidth.top; + *width = width0 - style->margin.left - style->borderWidth.left + - style->margin.right - style->borderWidth.right; + *height = height0 - style->margin.top - style->borderWidth.top + - style->margin.bottom - style->borderWidth.bottom; +} + +StyleImage *StyleImage::ExternalWidgetImgRenderer::getBackgroundImage () +{ + Style *style = getStyle (); + return style ? style->backgroundImage : NULL; +} + +BackgroundRepeat StyleImage::ExternalWidgetImgRenderer::getBackgroundRepeat () +{ + Style *style = getStyle (); + return style ? style->backgroundRepeat : BACKGROUND_REPEAT; +} + +BackgroundAttachment + StyleImage::ExternalWidgetImgRenderer::getBackgroundAttachment () +{ + Style *style = getStyle (); + return style ? style->backgroundAttachment : BACKGROUND_ATTACHMENT_SCROLL; +} + +Length StyleImage::ExternalWidgetImgRenderer::getBackgroundPositionX () +{ + Style *style = getStyle (); + return style ? style->backgroundPositionX : createPerLength (0); +} + +Length StyleImage::ExternalWidgetImgRenderer::getBackgroundPositionY () +{ + Style *style = getStyle (); + return style ? style->backgroundPositionY : createPerLength (0); +} + +// ---------------------------------------------------------------------- + /* * The drawBorder{Top,Bottom,Left,Right} functions are similar. They * use a trapezium as draw polygon, or drawTypedLine() for dots and dashes. diff --git a/dw/style.hh b/dw/style.hh index fbc726ef..04380dde 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -739,10 +739,9 @@ public: virtual bool readyToDraw () = 0; /** - * \brief Return the total area this background image is - * attached to, in canvas coordinates. + * \brief ... */ - virtual void getArea (int *x, int *y, int *width, int *height) = 0; + virtual void getPaddingArea (int *x, int *y, int *width, int *height) = 0; /** * \brief Return the "reference area". @@ -752,10 +751,11 @@ public: virtual void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) = 0; - /** - * \brief Return the style this background image is part of. - */ - virtual Style *getStyle () = 0; + virtual StyleImage *getBackgroundImage () = 0; + virtual BackgroundRepeat getBackgroundRepeat () = 0; + virtual BackgroundAttachment getBackgroundAttachment () = 0; + virtual Length getBackgroundPositionX () = 0; + virtual Length getBackgroundPositionY () = 0; /** * \brief Draw (or queue for drawing) an area, which is given in @@ -764,6 +764,32 @@ public: virtual void draw (int x, int y, int width, int height) = 0; }; + /** + * \brief Suitable for widgets and parts of widgets. + */ + class ExternalWidgetImgRenderer: public ExternalImgRenderer + { + public: + void getPaddingArea (int *x, int *y, int *width, int *height); + + StyleImage *getBackgroundImage (); + BackgroundRepeat getBackgroundRepeat (); + BackgroundAttachment getBackgroundAttachment (); + Length getBackgroundPositionX (); + Length getBackgroundPositionY (); + + /** + * \brief Return the total area this background image is + * attached to, in canvas coordinates. + */ + virtual void getArea (int *x, int *y, int *width, int *height) = 0; + + /** + * \brief Return the style this background image is part of. + */ + virtual Style *getStyle () = 0; + }; + static StyleImage *create () { return new StyleImage (); } inline void ref () { refCount++; } diff --git a/dw/textblock.hh b/dw/textblock.hh index b094b5ec..e61d2961 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -243,7 +243,8 @@ protected: * \todo The word index must be updated when, through hyphenation, * words are added before. */ - class WordImgRenderer: public core::style::StyleImage::ExternalImgRenderer + class WordImgRenderer: + public core::style::StyleImage::ExternalWidgetImgRenderer { protected: Textblock *textblock; diff --git a/dw/widget.hh b/dw/widget.hh index fb16bf90..ad36df92 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -79,7 +79,7 @@ protected: * * The only instance is set created needed. */ - class WidgetImgRenderer: public style::StyleImage::ExternalImgRenderer + class WidgetImgRenderer: public style::StyleImage::ExternalWidgetImgRenderer { private: Widget *widget; -- cgit v1.2.3 From 79c24d20a6dfa62e72085a45a29e148ad86d7009 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 4 Oct 2013 22:25:52 +0200 Subject: Background images for view(port)s are now updated. --- dw/layout.cc | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dw/layout.hh | 21 ++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/dw/layout.cc b/dw/layout.cc index 61ff8a38..7fa93046 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -32,6 +32,65 @@ using namespace lout::object; namespace dw { namespace core { +bool Layout::LayoutImgRenderer::readyToDraw () +{ + return true; +} + +void Layout::LayoutImgRenderer::getPaddingArea (int *x, int *y, int *width, + int *height) +{ + // TODO Actually not padding area, but visible area? + getRefArea (x, y, width, height); +} + +void Layout::LayoutImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, + int *heightRef) +{ + *xRef = 0; + *yRef = 0; + *widthRef = misc::max (layout->viewportWidth + - (layout->canvasHeightGreater ? + layout->vScrollbarThickness : 0), + layout->canvasWidth); + *heightRef = misc::max (layout->viewportHeight + - layout->hScrollbarThickness, + layout->canvasAscent + layout->canvasDescent); +} + +style::StyleImage *Layout::LayoutImgRenderer::getBackgroundImage () +{ + return layout->bgImage; +} + +style::BackgroundRepeat Layout::LayoutImgRenderer::getBackgroundRepeat () +{ + return layout->bgRepeat; +} + +style::BackgroundAttachment + Layout::LayoutImgRenderer::getBackgroundAttachment () +{ + return layout->bgAttachment; +} + +style::Length Layout::LayoutImgRenderer::getBackgroundPositionX () +{ + return layout->bgPositionX; +} + +style::Length Layout::LayoutImgRenderer::getBackgroundPositionY () +{ + return layout->bgPositionY; +} + +void Layout::LayoutImgRenderer::draw (int x, int y, int width, int height) +{ + layout->queueDraw (x, y, width, height); +} + +// ---------------------------------------------------------------------- + void Layout::Receiver::canvasSizeChanged (int width, int ascent, int descent) { } @@ -217,6 +276,8 @@ Layout::Layout (Platform *platform) platform->setLayout (this); selectionState.setLayout(this); + + layoutImgRenderer = NULL; } Layout::~Layout () @@ -240,6 +301,12 @@ Layout::~Layout () delete view; delete anchorsTable; delete textZone; + + if (layoutImgRenderer) { + if (bgImage) + bgImage->removeExternalImgRenderer (layoutImgRenderer); + delete layoutImgRenderer; + } } void Layout::addWidget (Widget *widget) @@ -675,6 +742,9 @@ void Layout::setBgImage (style::StyleImage *bgImage, style::BackgroundAttachment bgAttachment, style::Length bgPositionX, style::Length bgPositionY) { + if (layoutImgRenderer && this->bgImage) + this->bgImage->removeExternalImgRenderer (layoutImgRenderer); + bgImage->ref (); if (this->bgImage) @@ -685,6 +755,15 @@ void Layout::setBgImage (style::StyleImage *bgImage, this->bgAttachment = bgAttachment; this->bgPositionX = bgPositionX; this->bgPositionY = bgPositionY; + + if (bgImage) { + // Create instance of LayoutImgRenderer when needed. Until this + // layout is deleted, "layoutImgRenderer" will be kept, since it + // is not specific to the style, but only to this layout. + if (layoutImgRenderer == NULL) + layoutImgRenderer = new LayoutImgRenderer (this); + bgImage->putExternalImgRenderer (layoutImgRenderer); + } } diff --git a/dw/layout.hh b/dw/layout.hh index 9687a2da..abc763b1 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -17,6 +17,27 @@ class Layout: public lout::object::Object { friend class Widget; +private: + class LayoutImgRenderer: public style::StyleImage::ExternalImgRenderer + { + Layout *layout; + + public: + LayoutImgRenderer (Layout *layout) { this->layout = layout; } + + bool readyToDraw (); + void getPaddingArea (int *x, int *y, int *width, int *height); + void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); + style::StyleImage *getBackgroundImage (); + style::BackgroundRepeat getBackgroundRepeat (); + style::BackgroundAttachment getBackgroundAttachment (); + style::Length getBackgroundPositionX (); + style::Length getBackgroundPositionY (); + void draw (int x, int y, int width, int height); + }; + + LayoutImgRenderer *layoutImgRenderer; + public: /** * \brief Receiver interface different signals. -- cgit v1.2.3 From cfdf262f3ffe5f818ebf318d68d03b698ff3e363 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 7 Oct 2013 11:36:31 +0200 Subject: Cache client is stopped when StyleImage is deleted. --- src/styleengine.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/styleengine.cc b/src/styleengine.cc index f3fd2934..efd4d629 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -21,6 +21,44 @@ using namespace lout::misc; using namespace dw::core::style; +/** + * Signal handler for "delete": This handles the case when an instance + * of StyleImage is deleted, possibly when the cache client is still + * active. + * + * \todo Not neccessary for dw::Image? (dw::Image also implements + * lout::signal::ObservedObject.) + */ +class StyleImageDeletionReceiver: + public lout::signal::ObservedObject::DeletionReceiver +{ + int clientKey; + +public: + StyleImageDeletionReceiver (int clientKey); + ~StyleImageDeletionReceiver (); + + void deleted (lout::signal::ObservedObject *object); +}; + +StyleImageDeletionReceiver::StyleImageDeletionReceiver (int clientKey) +{ + this->clientKey = clientKey; +} + +StyleImageDeletionReceiver::~StyleImageDeletionReceiver () +{ + printf ("StyleImageDeletionReceiver deleted.\n"); +} + +void StyleImageDeletionReceiver::deleted (lout::signal::ObservedObject *object) +{ + a_Capi_stop_client (clientKey, 0); + delete this; +} + +// ---------------------------------------------------------------------- + StyleEngine::StyleEngine (dw::core::Layout *layout) { StyleAttrs style_attrs; FontAttrs font_attrs; @@ -477,6 +515,8 @@ void StyleEngine::apply (int i, StyleAttrs *attrs, CssPropertyList *props, if ((clientKey = a_Capi_open_url(web, NULL, NULL)) != 0) { a_Bw_add_client(bw, clientKey, 0); a_Bw_add_url(bw, url); + attrs->backgroundImage->connectDeletion + (new StyleImageDeletionReceiver (clientKey)); } } break; -- cgit v1.2.3 From c4a148796a7597db7bb3ca1b0d1a2623e1373ce8 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 7 Oct 2013 21:30:34 +0200 Subject: View(port) background now set by HTML parser. --- dw/style.cc | 10 +++++++++- src/html.cc | 11 ++++++++++- src/styleengine.cc | 20 ++++++++++++++++++++ src/styleengine.hh | 5 +++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index 39d8858b..abb5c84b 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -1077,9 +1077,17 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, Style *style, bool inverse, bool atTop) { bool bgColor = style->backgroundColor != NULL && + // The test for background colors is rather simple, since only the color + // has to be compared, ... (!atTop || layout->getBgColor () != style->backgroundColor); bool bgImage = (style->backgroundImage != NULL && - style->backgroundImage->getImgbuf() != NULL); + style->backgroundImage->getImgbuf() != NULL) && + // ... but for backgrounds, it would be rather complicated. However, + // since the background of the viewport should always be the background + // of the toplevel widget, it is not worth the extra work; so the + // background image of top level widgets is ignored here. (The test for + // the background *color* above is equally useless.) + !atTop; // Since widgets are always drawn from top to bottom, it is *not* // necessary to draw the background if background color and image diff --git a/src/html.cc b/src/html.cc index 527d7c79..2ff6a2c7 100644 --- a/src/html.cc +++ b/src/html.cc @@ -1805,6 +1805,10 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) int32_t color; int tag_index_a = a_Html_tag_index ("a"); style::Color *bgColor; + style::StyleImage *bgImage; + style::BackgroundRepeat bgRepeat; + style::BackgroundAttachment bgAttachment; + style::Length bgPositionX, bgPositionY; _MSG("Html_tag_open_body Num_BODY=%d\n", html->Num_BODY); if (!(html->InFlags & IN_BODY)) @@ -1848,10 +1852,15 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) html->dw->setStyle (html->style ()); bgColor = html->styleEngine->backgroundColor (); - if (bgColor) HT2LT(html)->setBgColor(bgColor); + bgImage = html->styleEngine->backgroundImage (&bgRepeat, &bgAttachment, + &bgPositionX, &bgPositionY); + if (bgImage) + HT2LT(html)->setBgImage(bgImage, bgRepeat, bgAttachment, bgPositionX, + bgPositionY); + /* Determine a color for visited links. * This color is computed once per page and used for immediate feedback * when clicking a link. diff --git a/src/styleengine.cc b/src/styleengine.cc index efd4d629..90ef718e 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -248,6 +248,26 @@ dw::core::style::Color *StyleEngine::backgroundColor () { return NULL; } +dw::core::style::StyleImage *StyleEngine::backgroundImage + (dw::core::style::BackgroundRepeat *bgRepeat, + dw::core::style::BackgroundAttachment *bgAttachment, + dw::core::style::Length *bgPositionX, + dw::core::style::Length *bgPositionY) { + for (int i = 1; i < stack->size (); i++) { + Node *n = stack->getRef (i); + + if (n->style && n->style->backgroundImage) { + *bgRepeat = n->style->backgroundRepeat; + *bgAttachment = n->style->backgroundAttachment; + *bgPositionX = n->style->backgroundPositionX; + *bgPositionY = n->style->backgroundPositionY; + return n->style->backgroundImage; + } + } + + return NULL; +} + /** * \brief set the CSS pseudo class :link. */ diff --git a/src/styleengine.hh b/src/styleengine.hh index 14222f35..714553ff 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -97,6 +97,11 @@ class StyleEngine { dw::core::style::Style *backgroundStyle (BrowserWindow *bw, DilloUrl *url); dw::core::style::Color *backgroundColor (); + dw::core::style::StyleImage *backgroundImage + (dw::core::style::BackgroundRepeat *bgRepeat, + dw::core::style::BackgroundAttachment *bgAttachment, + dw::core::style::Length *bgPositionX, + dw::core::style::Length *bgPositionY); inline dw::core::style::Style *style (BrowserWindow *bw, DilloUrl *url) { dw::core::style::Style *s = stack->getRef (stack->size () - 1)->style; -- cgit v1.2.3 From 10b15cd3300df05c9bd913212a05fbca4dc86130 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 7 Oct 2013 22:53:11 +0200 Subject: Removed printf. --- src/styleengine.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/styleengine.cc b/src/styleengine.cc index 90ef718e..f29b1a05 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -48,7 +48,6 @@ StyleImageDeletionReceiver::StyleImageDeletionReceiver (int clientKey) StyleImageDeletionReceiver::~StyleImageDeletionReceiver () { - printf ("StyleImageDeletionReceiver deleted.\n"); } void StyleImageDeletionReceiver::deleted (lout::signal::ObservedObject *object) -- cgit v1.2.3 From 770d42709c33d55cfd3d650efbb95abdc7c2cc65 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 8 Oct 2013 11:43:05 +0200 Subject: Comment. --- dw/style.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index abb5c84b..721e6c81 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -1051,12 +1051,13 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, * Used by dw::core::Widget::drawBox and dw::core::Widget::drawWidgetBox. * * "area" is the area to be drawn, "x", "y", "width" and "height" - * define the box itself. "xRef", "yRef", "widthRef" and "heightRef" - * define the reference area, which is important for background - * images. All are given in canvas coordinates. - * - * \todo Does "reference" area include margin and padding? Does - * currently, but should probably not. + * define the box itself (padding box). "xRef", "yRef", "widthRef" and + * "heightRef" define the reference area, which is important for the + * tiling of background images (for position 0%/0%, a tile is set at + * xRef/yRef; for position 100%/100%, a tile is set at xRef + + * widthRef/yRef + widthRef). See calls for more informations; in most + * cases, these boxes are identical (padding box). All these + * coordinates are given in canvas coordinates. * * "atTop" should be true, only if the area is drawn directly on the * canvas, not on top of other areas; this is only true for the -- cgit v1.2.3 From ff920593c94fe192775811b7d9c7ab340a883c3a Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Tue, 8 Oct 2013 15:03:36 +0200 Subject: Cleaned up "reference area" of background images; confirms now to CSS spec. --- dw/layout.cc | 4 ++-- dw/layout.hh | 2 +- dw/style.cc | 31 +++++--------------------- dw/style.hh | 10 ++------- dw/textblock.cc | 14 ++++++------ dw/textblock.hh | 4 ++-- dw/widget.cc | 67 +++++++++++++++++++++++++++++++-------------------------- dw/widget.hh | 4 ++-- 8 files changed, 59 insertions(+), 77 deletions(-) diff --git a/dw/layout.cc b/dw/layout.cc index 7fa93046..f0470748 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -37,8 +37,8 @@ bool Layout::LayoutImgRenderer::readyToDraw () return true; } -void Layout::LayoutImgRenderer::getPaddingArea (int *x, int *y, int *width, - int *height) +void Layout::LayoutImgRenderer::getBgArea (int *x, int *y, int *width, + int *height) { // TODO Actually not padding area, but visible area? getRefArea (x, y, width, height); diff --git a/dw/layout.hh b/dw/layout.hh index abc763b1..65fe2312 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -26,7 +26,7 @@ private: LayoutImgRenderer (Layout *layout) { this->layout = layout; } bool readyToDraw (); - void getPaddingArea (int *x, int *y, int *width, int *height); + void getBgArea (int *x, int *y, int *width, int *height); void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); style::StyleImage *getBackgroundImage (); style::BackgroundRepeat getBackgroundRepeat (); diff --git a/dw/style.cc b/dw/style.cc index 721e6c81..cda61845 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -520,7 +520,7 @@ void StyleImage::ExternalImgRenderer::drawRow (int row) int imgHeight = imgbuf->getRootHeight (); int x, y, width, height; - getPaddingArea (&x, &y, &width, &height); + getBgArea (&x, &y, &width, &height); int xRef, yRef, widthRef, heightRef; getRefArea (&xRef, &yRef, &widthRef, &heightRef); @@ -557,23 +557,6 @@ void StyleImage::ExternalImgRenderer::drawRow (int row) // ---------------------------------------------------------------------- -void StyleImage::ExternalWidgetImgRenderer::getPaddingArea (int *x, int *y, - int *width, - int *height) -{ - Style *style = getStyle (); - assert (style != NULL); - - int x0, y0, width0, height0; - getArea (&x0, &y0, &width0, &height0); - *x = x0 + style->margin.left + style->borderWidth.left; - *y = y0 + style->margin.top + style->borderWidth.top; - *width = width0 - style->margin.left - style->borderWidth.left - - style->margin.right - style->borderWidth.right; - *height = height0 - style->margin.top - style->borderWidth.top - - style->margin.bottom - style->borderWidth.bottom; -} - StyleImage *StyleImage::ExternalWidgetImgRenderer::getBackgroundImage () { Style *style = getStyle (); @@ -1096,14 +1079,10 @@ void drawBackground (View *view, Layout *layout, Rectangle *area, if (bgColor || bgImage) { Rectangle bgArea, intersection; - bgArea.x = x + style->margin.left + style->borderWidth.left; - bgArea.y = y + style->margin.top + style->borderWidth.top; - bgArea.width = - width - style->margin.left - style->borderWidth.left - - style->margin.right - style->borderWidth.right; - bgArea.height = - height - style->margin.top - style->borderWidth.top - - style->margin.bottom - style->borderWidth.bottom; + bgArea.x = x; + bgArea.y = y; + bgArea.width = width; + bgArea.height = height; if (area->intersectsWith (&bgArea, &intersection)) { if (bgColor) diff --git a/dw/style.hh b/dw/style.hh index 04380dde..361741be 100644 --- a/dw/style.hh +++ b/dw/style.hh @@ -739,9 +739,9 @@ public: virtual bool readyToDraw () = 0; /** - * \brief ... + * \brief Return the area covered by the background image. */ - virtual void getPaddingArea (int *x, int *y, int *width, int *height) = 0; + virtual void getBgArea (int *x, int *y, int *width, int *height) = 0; /** * \brief Return the "reference area". @@ -778,12 +778,6 @@ public: Length getBackgroundPositionX (); Length getBackgroundPositionY (); - /** - * \brief Return the total area this background image is - * attached to, in canvas coordinates. - */ - virtual void getArea (int *x, int *y, int *width, int *height) = 0; - /** * \brief Return the style this background image is part of. */ diff --git a/dw/textblock.cc b/dw/textblock.cc index fbff3e23..6538ed1e 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -70,9 +70,10 @@ bool Textblock::WordImgRenderer::readyToDraw () && lineNo < textblock->lines->size(); } -void Textblock::WordImgRenderer::getArea (int *x, int *y, int *width, - int *height) +void Textblock::WordImgRenderer::getBgArea (int *x, int *y, int *width, + int *height) { + // TODO Subtract margin and border (padding box)? Line *line = textblock->lines->getRef (lineNo); *x = textblock->allocation.x + this->xWordWidget; *y = textblock->lineYOffsetCanvas (line); @@ -83,7 +84,8 @@ void Textblock::WordImgRenderer::getArea (int *x, int *y, int *width, void Textblock::WordImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) { - textblock->getBgRefArea (xRef, yRef, widthRef, heightRef); + // See comment in Widget::drawBox about the reference area.q + textblock->getPaddingArea (xRef, yRef, widthRef, heightRef); } core::style::Style *Textblock::WordImgRenderer::getStyle () @@ -98,10 +100,10 @@ void Textblock::WordImgRenderer::draw (int x, int y, int width, int height) } -void Textblock::SpaceImgRenderer::getArea (int *x, int *y, int *width, - int *height) +void Textblock::SpaceImgRenderer::getBgArea (int *x, int *y, int *width, + int *height) { - WordImgRenderer::getArea (x, y, width, height); + WordImgRenderer::getBgArea (x, y, width, height); *x += *width; *width = textblock->words->getRef(wordNo)->effSpace; } diff --git a/dw/textblock.hh b/dw/textblock.hh index e61d2961..2bd85917 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -258,7 +258,7 @@ protected: void setData (int xWordWidget, int lineNo); bool readyToDraw (); - void getArea (int *x, int *y, int *width, int *height); + void getBgArea (int *x, int *y, int *width, int *height); void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); core::style::Style *getStyle (); void draw (int x, int y, int width, int height); @@ -270,7 +270,7 @@ protected: inline SpaceImgRenderer (Textblock *textblock, int wordNo) : WordImgRenderer (textblock, wordNo) { } - void getArea (int *x, int *y, int *width, int *height); + void getBgArea (int *x, int *y, int *width, int *height); core::style::Style *getStyle (); }; diff --git a/dw/widget.cc b/dw/widget.cc index 719f1263..415da6bc 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -37,19 +37,16 @@ bool Widget::WidgetImgRenderer::readyToDraw () return widget->wasAllocated (); } -void Widget::WidgetImgRenderer::getArea (int *x, int *y, int *width, - int *height) +void Widget::WidgetImgRenderer::getBgArea (int *x, int *y, int *width, + int *height) { - *x = widget->allocation.x; - *y = widget->allocation.y; - *width = widget->allocation.width; - *height = widget->getHeight (); + widget->getPaddingArea (x, y, width, height); } void Widget::WidgetImgRenderer::getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) { - widget->getBgRefArea (xRef, yRef, widthRef, heightRef); + widget->getPaddingArea (xRef, yRef, widthRef, heightRef); } style::Style *Widget::WidgetImgRenderer::getStyle () @@ -404,12 +401,21 @@ void Widget::drawBox (View *view, style::Style *style, Rectangle *area, allocation.x + x, allocation.y + y, width, height, style, inverse); - int xRef, yRef, widthRef, heightRef; - getBgRefArea (&xRef, &yRef, &widthRef, &heightRef); - style::drawBackground (view, layout, &canvasArea, - allocation.x + x, allocation.y + y, width, height, - xRef, yRef, widthRef, heightRef, style, inverse, - false); + // This method is used for inline elements, where the CSS 2 specification + // does not define what here is called "reference area". To make it look + // smoothly, the widget padding box is used. + + int xPad, yPad, widthPad, heightPad; + getPaddingArea (&xPad, &yPad, &widthPad, &heightPad); + style::drawBackground + (view, layout, &canvasArea, + allocation.x + x + style->margin.left + style->borderWidth.left, + allocation.y + y + style->margin.top + style->borderWidth.top, + width - style->margin.left - style->borderWidth.left + - style->margin.right - style->borderWidth.right, + height - style->margin.top - style->borderWidth.top + - style->margin.bottom - style->borderWidth.bottom, + xPad, yPad, widthPad, heightPad, style, inverse, false); } /** @@ -429,11 +435,12 @@ void Widget::drawWidgetBox (View *view, Rectangle *area, bool inverse) style::drawBorder (view, layout, &canvasArea, allocation.x, allocation.y, allocation.width, getHeight (), style, inverse); - int xRef, yRef, widthRef, heightRef; - getBgRefArea (&xRef, &yRef, &widthRef, &heightRef); - style::drawBackground (view, layout, &canvasArea, allocation.x, allocation.y, - allocation.width, getHeight (), xRef, yRef, widthRef, - heightRef, style, inverse, parent == NULL); + int xPad, yPad, widthPad, heightPad; + getPaddingArea (&xPad, &yPad, &widthPad, &heightPad); + style::drawBackground (view, layout, &canvasArea, + xPad, yPad, widthPad, heightPad, + xPad, yPad, widthPad, heightPad, + style, inverse, parent == NULL); } /* @@ -578,20 +585,20 @@ void Widget::scrollTo (HPosition hpos, VPosition vpos, } /** - * \brief Return the "reference area" for backgrounds. + * \brief Return the padding area (content plus padding). * - * See comment of "style::drawBackground". + * Used as "reference area" (ee comment of "style::drawBackground") + * for backgrounds. */ -void Widget::getBgRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef) -{ - /** - * \todo Reference should be the containing block (which will be - * introduced later), not the widget allocation. - */ - *xRef = allocation.x; - *yRef = allocation.y; - *widthRef = allocation.width; - *heightRef = getHeight (); +void Widget::getPaddingArea (int *xPad, int *yPad, int *widthPad, + int *heightPad) +{ + *xPad = allocation.x + style->margin.left + style->borderWidth.left; + *yPad = allocation.y + style->margin.top + style->borderWidth.top; + *widthPad = allocation.width - style->margin.left - style->borderWidth.left + - style->margin.right - style->borderWidth.right; + *heightPad = getHeight () - style->margin.top - style->borderWidth.top + - style->margin.bottom - style->borderWidth.bottom; } void Widget::getExtremesImpl (Extremes *extremes) diff --git a/dw/widget.hh b/dw/widget.hh index ad36df92..34b35efa 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -88,7 +88,7 @@ protected: inline WidgetImgRenderer (Widget *widget) { this->widget = widget; } bool readyToDraw (); - void getArea (int *x, int *y, int *width, int *height); + void getBgArea (int *x, int *y, int *width, int *height); void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); style::Style *getStyle (); void draw (int x, int y, int width, int height); @@ -311,7 +311,7 @@ public: void scrollTo (HPosition hpos, VPosition vpos, int x, int y, int width, int height); - void getBgRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); + void getPaddingArea (int *xPad, int *yPad, int *widthPad, int *heightPad); /** * \brief Return an iterator for this widget. -- cgit v1.2.3 From c49ced3a29f1f2f318d9fcd873abc3ffeff30e54 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 9 Oct 2013 12:22:20 +0200 Subject: Comments. --- dw/style.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dw/style.cc b/dw/style.cc index cda61845..cd5136a5 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -1049,11 +1049,8 @@ void drawBorder (View *view, Layout *layout, Rectangle *area, * that drawing again is is not neccessary, but some time can be * saved. * - * \todo The same should not only be applied to background colors, but - * also to background images. - * * Otherwise, the caller should not try to increase the performance by - * doing some tests befre; this is all done in this method. + * doing some tests before; this is all done in this method. */ void drawBackground (View *view, Layout *layout, Rectangle *area, int x, int y, int width, int height, -- cgit v1.2.3 From 3db296631dfd8101066847cd552422da0c26f02f Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 9 Oct 2013 21:58:16 +0200 Subject: Some cleanup. --- dw/textblock.cc | 123 +++++++++++++++++++++++++++++++------------ dw/textblock.hh | 9 ++++ dw/textblock_linebreaking.cc | 1 - test/dw_image_background.cc | 6 ++- 4 files changed, 101 insertions(+), 38 deletions(-) diff --git a/dw/textblock.cc b/dw/textblock.cc index 6538ed1e..0c7a6108 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -65,6 +65,9 @@ void Textblock::WordImgRenderer::setData (int xWordWidget, int lineNo) bool Textblock::WordImgRenderer::readyToDraw () { + //print (); + //printf ("\n"); + return dataSet && textblock->wasAllocated () && wordNo < textblock->words->size() && lineNo < textblock->lines->size(); @@ -100,6 +103,16 @@ void Textblock::WordImgRenderer::draw (int x, int y, int width, int height) } +void Textblock::WordImgRenderer::print () +{ + printf ("%p: word #%d, ", this, wordNo); + if (wordNo < textblock->words->size()) + textblock->printWordShort (textblock->words->getRef(wordNo)); + else + printf ("", wordNo); + printf (", data set: %s", dataSet ? "yes" : "no"); +} + void Textblock::SpaceImgRenderer::getBgArea (int *x, int *y, int *width, int *height) { @@ -113,6 +126,16 @@ core::style::Style *Textblock::SpaceImgRenderer::getStyle () return textblock->words->getRef(wordNo)->spaceStyle; } +void Textblock::SpaceImgRenderer::print () +{ + printf ("%p: word FOR SPACE #%d, ", this, wordNo); + if (wordNo < textblock->words->size()) + textblock->printWordShort (textblock->words->getRef(wordNo)); + else + printf ("", wordNo); + printf (", data set: %s", dataSet ? "yes" : "no"); +} + // ---------------------------------------------------------------------- Textblock::DivChar Textblock::divChars[NUM_DIV_CHARS] = { @@ -259,17 +282,8 @@ Textblock::~Textblock () if (word->content.type == core::Content::WIDGET) delete word->content.widget; - if (word->wordImgRenderer) { - word->style->backgroundImage->removeExternalImgRenderer - (word->wordImgRenderer); - delete word->wordImgRenderer; - } - - if (word->spaceImgRenderer) { - word->spaceStyle->backgroundImage->removeExternalImgRenderer - (word->spaceImgRenderer); - delete word->spaceImgRenderer; - } + removeWordImgRenderer (i); + removeSpaceImgRenderer (i); word->style->unref (); word->spaceStyle->unref (); @@ -1439,22 +1453,32 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, return word; } -void Textblock::fillWord (int wordNo, int width, int ascent, int descent, - short flags, core::style::Style *style) +/** + * Basic initialization, which is neccessary before fillWord. + */ +void Textblock::initWord (int wordNo) { Word *word = words->getRef (wordNo); - word->size.width = width; - word->size.ascent = ascent; - word->size.descent = descent; - word->origSpace = word->effSpace = 0; - word->hyphenWidth = 0; - word->badnessAndPenalty.setPenalty (PENALTY_PROHIBIT_BREAK); - word->content.space = false; - word->flags = flags; + word->wordImgRenderer = NULL; + word->spaceImgRenderer = NULL; +} - word->style = style; - word->spaceStyle = style; +void Textblock::removeWordImgRenderer (int wordNo) +{ + Word *word = words->getRef (wordNo); + + if (word->wordImgRenderer) { + word->style->backgroundImage->removeExternalImgRenderer + (word->wordImgRenderer); + delete word->wordImgRenderer; + word->wordImgRenderer = NULL; + } +} + +void Textblock::setWordImgRenderer (int wordNo) +{ + Word *word = words->getRef (wordNo); if (word->style->backgroundImage) { word->wordImgRenderer = new WordImgRenderer (this, wordNo); @@ -1462,6 +1486,23 @@ void Textblock::fillWord (int wordNo, int width, int ascent, int descent, (word->wordImgRenderer); } else word->wordImgRenderer = NULL; +} + +void Textblock::removeSpaceImgRenderer (int wordNo) +{ + Word *word = words->getRef (wordNo); + + if (word->spaceImgRenderer) { + word->spaceStyle->backgroundImage->removeExternalImgRenderer + (word->spaceImgRenderer); + delete word->spaceImgRenderer; + word->spaceImgRenderer = NULL; + } +} + +void Textblock::setSpaceImgRenderer (int wordNo) +{ + Word *word = words->getRef (wordNo); if (word->spaceStyle->backgroundImage) { word->spaceImgRenderer = new SpaceImgRenderer (this, wordNo); @@ -1469,6 +1510,27 @@ void Textblock::fillWord (int wordNo, int width, int ascent, int descent, (word->spaceImgRenderer); } else word->spaceImgRenderer = NULL; +} + +void Textblock::fillWord (int wordNo, int width, int ascent, int descent, + short flags, core::style::Style *style) +{ + Word *word = words->getRef (wordNo); + + word->size.width = width; + word->size.ascent = ascent; + word->size.descent = descent; + word->origSpace = word->effSpace = 0; + word->hyphenWidth = 0; + word->badnessAndPenalty.setPenalty (PENALTY_PROHIBIT_BREAK); + word->content.space = false; + word->flags = flags; + + word->style = style; + word->spaceStyle = style; + + setWordImgRenderer (wordNo); + setSpaceImgRenderer (wordNo); style->ref (); style->ref (); @@ -2002,22 +2064,13 @@ void Textblock::fillSpace (int wordNo, core::style::Style *style) // word->content.space); - if (word->spaceImgRenderer) { - word->spaceStyle->backgroundImage->removeExternalImgRenderer - (word->spaceImgRenderer); - delete word->spaceImgRenderer; - } + removeSpaceImgRenderer (wordNo); word->spaceStyle->unref (); word->spaceStyle = style; style->ref (); - - if (word->spaceStyle->backgroundImage) { - word->spaceImgRenderer = new SpaceImgRenderer (this, wordNo); - word->spaceStyle->backgroundImage->putExternalImgRenderer - (word->spaceImgRenderer); - } else - word->spaceImgRenderer = NULL; + + setSpaceImgRenderer (wordNo); } } diff --git a/dw/textblock.hh b/dw/textblock.hh index 2bd85917..be8cdfee 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -262,6 +262,8 @@ protected: void getRefArea (int *xRef, int *yRef, int *widthRef, int *heightRef); core::style::Style *getStyle (); void draw (int x, int y, int width, int height); + + virtual void print (); }; class SpaceImgRenderer: public WordImgRenderer @@ -272,6 +274,8 @@ protected: void getBgArea (int *x, int *y, int *width, int *height); core::style::Style *getStyle (); + + void print (); }; struct Paragraph @@ -519,6 +523,11 @@ protected: Word *addWord (int width, int ascent, int descent, short flags, core::style::Style *style); + void initWord (int wordNo); + void removeWordImgRenderer (int wordNo); + void setWordImgRenderer (int wordNo); + void removeSpaceImgRenderer (int wordNo); + void setSpaceImgRenderer (int wordNo); void fillWord (int wordNo, int width, int ascent, int descent, short flags, core::style::Style *style); void fillSpace (int wordNo, core::style::Style *style); diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index d1e4488d..9352744d 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -891,7 +891,6 @@ int Textblock::hyphenateWord (int wordIndex) for (int i = 0; i < numBreaks + 1; i++) { Word *w = words->getRef (wordIndex + i); - fillWord (wordIndex + i, wordSize[i].width, wordSize[i].ascent, wordSize[i].descent, false, origWord.style); diff --git a/test/dw_image_background.cc b/test/dw_image_background.cc index 391d6fe1..ad50924d 100644 --- a/test/dw_image_background.cc +++ b/test/dw_image_background.cc @@ -124,6 +124,8 @@ int main(int argc, char **argv) StyleAttrs styleAttrs; styleAttrs.initValues (); styleAttrs.margin.setVal (5); + styleAttrs.x_lang[0] = 'e'; + styleAttrs.x_lang[1] = 'n'; FontAttrs fontAttrs; fontAttrs.name = "Bitstream Charter"; @@ -158,7 +160,7 @@ int main(int argc, char **argv) styleAttrs.backgroundPositionY = createPerLength (0); Style *wordStyleBg = Style::create (&styleAttrs); - for(int i = 1; i <= 10; i++) { + for(int i = 1; i <= 1; i++) { char buf[4]; sprintf(buf, "%d.", i); @@ -168,7 +170,7 @@ int main(int argc, char **argv) NULL }; for(int j = 0; words[j]; j++) { - textblock->addText(words[j], j == 3 ? wordStyleBg : wordStyle); + textblock->addText(words[j], j == 11 ? wordStyleBg : wordStyle); textblock->addSpace(wordStyle); } -- cgit v1.2.3 From 543269017e29ecc6fcde020c78b563aeb43ee018 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 9 Oct 2013 22:21:47 +0200 Subject: Correct initialization of words. --- dw/textblock.cc | 15 ++++++++++----- dw/textblock_linebreaking.cc | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/dw/textblock.cc b/dw/textblock.cc index 0c7a6108..7950ba96 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1448,9 +1448,10 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, short flags, core::style::Style *style) { words->increase (); - Word *word = words->getLastRef (); - fillWord (words->size () - 1, width, ascent, descent, flags, style); - return word; + int wordNo = words->size () - 1; + initWord (wordNo); + fillWord (wordNo, width, ascent, descent, flags, style); + return words->getRef (wordNo);; } /** @@ -1460,6 +1461,7 @@ void Textblock::initWord (int wordNo) { Word *word = words->getRef (wordNo); + word->style = word->spaceStyle = NULL; word->wordImgRenderer = NULL; word->spaceImgRenderer = NULL; } @@ -1468,7 +1470,7 @@ void Textblock::removeWordImgRenderer (int wordNo) { Word *word = words->getRef (wordNo); - if (word->wordImgRenderer) { + if (word->style && word->wordImgRenderer) { word->style->backgroundImage->removeExternalImgRenderer (word->wordImgRenderer); delete word->wordImgRenderer; @@ -1492,7 +1494,7 @@ void Textblock::removeSpaceImgRenderer (int wordNo) { Word *word = words->getRef (wordNo); - if (word->spaceImgRenderer) { + if (word->spaceStyle && word->spaceImgRenderer) { word->spaceStyle->backgroundImage->removeExternalImgRenderer (word->spaceImgRenderer); delete word->spaceImgRenderer; @@ -1526,6 +1528,9 @@ void Textblock::fillWord (int wordNo, int width, int ascent, int descent, word->content.space = false; word->flags = flags; + removeWordImgRenderer (wordNo); + removeSpaceImgRenderer (wordNo); + word->style = style; word->spaceStyle = style; diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index 9352744d..58b8c494 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -880,6 +880,8 @@ int Textblock::hyphenateWord (int wordIndex) PRINTF ("[%p] %d words ...\n", this, words->size ()); words->insert (wordIndex, numBreaks); + for (int i = 0; i < numBreaks; i++) + initWord (wordIndex + i); PRINTF ("[%p] ... => %d words\n", this, words->size ()); // Adjust anchor indexes. -- cgit v1.2.3 From ea02d9d78a3b945e1650a4ff38e2c70f252b1e02 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 9 Oct 2013 22:23:09 +0200 Subject: Removed obsolete comment. --- dw/textblock.hh | 3 --- 1 file changed, 3 deletions(-) diff --git a/dw/textblock.hh b/dw/textblock.hh index be8cdfee..0f5ae38e 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -239,9 +239,6 @@ private: protected: /** * \brief Implementation used for words. - * - * \todo The word index must be updated when, through hyphenation, - * words are added before. */ class WordImgRenderer: public core::style::StyleImage::ExternalWidgetImgRenderer -- cgit v1.2.3 From de124c423740eb25bdceb0ea6939336d9dc096c7 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Fri, 11 Oct 2013 14:32:32 +0200 Subject: Background images for inline elements. --- src/styleengine.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/styleengine.cc b/src/styleengine.cc index f29b1a05..5b3b34f0 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -298,6 +298,16 @@ void StyleEngine::preprocessAttrs (dw::core::style::StyleAttrs *attrs) { if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) { attrs->backgroundColor = stack->getRef (stack->size () - 2)->style->backgroundColor; + attrs->backgroundImage = + stack->getRef (stack->size () - 2)->style->backgroundImage; + attrs->backgroundRepeat = + stack->getRef (stack->size () - 2)->style->backgroundRepeat; + attrs->backgroundAttachment = + stack->getRef (stack->size () - 2)->style->backgroundAttachment; + attrs->backgroundPositionX = + stack->getRef (stack->size () - 2)->style->backgroundPositionX; + attrs->backgroundPositionY = + stack->getRef (stack->size () - 2)->style->backgroundPositionY; attrs->valign = stack->getRef (stack->size () - 2)->style->valign; } @@ -866,8 +876,14 @@ Style * StyleEngine::wordStyle0 (BrowserWindow *bw, DilloUrl *url) { StyleAttrs attrs = *style (bw, url); attrs.resetValues (); - if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) + if (stack->getRef (stack->size() - 1)->inheritBackgroundColor) { attrs.backgroundColor = style (bw, url)->backgroundColor; + attrs.backgroundImage = style (bw, url)->backgroundImage; + attrs.backgroundRepeat = style (bw, url)->backgroundRepeat; + attrs.backgroundAttachment = style (bw, url)->backgroundAttachment; + attrs.backgroundPositionX = style (bw, url)->backgroundPositionX; + attrs.backgroundPositionY = style (bw, url)->backgroundPositionY; + } attrs.valign = style (bw, url)->valign; -- cgit v1.2.3 From 2201fbb06e12a240f8ccb3347311f586c1fa6574 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Mon, 14 Oct 2013 19:06:23 +0200 Subject: 'background-image' now also works for