aboutsummaryrefslogtreecommitdiff
path: root/dw
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2013-11-18 20:16:42 +0100
committerSebastian Geerken <devnull@localhost>2013-11-18 20:16:42 +0100
commit9ec54d30159139ef7e66eefd24fbe601d7544b99 (patch)
tree6ae74cccd930cfef738cf162215b72c8eb852919 /dw
parenta406f9d43bdc140fa7355be4e72aaef5081d7dd2 (diff)
Optimized drawing of very small background images.
Diffstat (limited to 'dw')
-rw-r--r--dw/fltkimgbuf.cc31
-rw-r--r--dw/fltkimgbuf.hh3
-rw-r--r--dw/imgbuf.hh13
-rw-r--r--dw/layout.cc2
-rw-r--r--dw/style.cc110
-rw-r--r--dw/style.hh10
6 files changed, 140 insertions, 29 deletions
diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc
index 81d2dc2d..e526ad60 100644
--- a/dw/fltkimgbuf.cc
+++ b/dw/fltkimgbuf.cc
@@ -427,6 +427,37 @@ int FltkImgbuf::getRootHeight ()
return root ? root->height : height;
}
+core::Imgbuf *FltkImgbuf::createSimilarBuf (int width, int height)
+{
+ return new FltkImgbuf (type, width, height, gamma);
+}
+
+void FltkImgbuf::copyTo (Imgbuf *dest, int xDestRoot, int yDestRoot,
+ int xSrc, int ySrc, int widthSrc, int heightSrc)
+{
+ FltkImgbuf *fDest = (FltkImgbuf*)dest;
+ assert (bpp == fDest->bpp);
+
+ int xSrc2 = lout::misc::min (xSrc + widthSrc, fDest->width - xDestRoot);
+ int ySrc2 = lout::misc::min (ySrc + heightSrc, fDest->height - yDestRoot);
+
+ //printf ("copying from (%d, %d), %d x %d to (%d, %d) (root) => "
+ // "xSrc2 = %d, ySrc2 = %d\n",
+ // xSrc, ySrc, widthSrc, heightSrc, xDestRoot, yDestRoot,
+ // xSrc2, ySrc2);
+
+ for (int x = xSrc; x < xSrc2; x++)
+ for (int y = ySrc; y < ySrc2; y++) {
+ int iSrc = x + width * y;
+ int iDest = xDestRoot + x + fDest->width * (yDestRoot + y);
+
+ //printf (" (%d, %d): %d -> %d\n", x, y, iSrc, iDest);
+
+ for (int b = 0; b < bpp; b++)
+ fDest->rawdata[bpp * iDest + b] = rawdata[bpp * iSrc + b];
+ }
+}
+
void FltkImgbuf::ref ()
{
refCount++;
diff --git a/dw/fltkimgbuf.hh b/dw/fltkimgbuf.hh
index ee5ae922..0b8b5549 100644
--- a/dw/fltkimgbuf.hh
+++ b/dw/fltkimgbuf.hh
@@ -73,6 +73,9 @@ public:
void getRowArea (int row, dw::core::Rectangle *area);
int getRootWidth ();
int getRootHeight ();
+ core::Imgbuf *createSimilarBuf (int width, int height);
+ void copyTo (Imgbuf *dest, int xDestRoot, int yDestRoot,
+ int xSrc, int ySrc, int widthSrc, int heightSrc);
void ref ();
void unref ();
diff --git a/dw/imgbuf.hh b/dw/imgbuf.hh
index 02ba9087..3ccbe3c5 100644
--- a/dw/imgbuf.hh
+++ b/dw/imgbuf.hh
@@ -178,6 +178,19 @@ public:
virtual int getRootWidth () = 0;
virtual int getRootHeight () = 0;
+
+ /**
+ * Creates an image buffer with same parameters (type, gamma etc.)
+ * except size.
+ */
+ virtual Imgbuf *createSimilarBuf (int width, int height) = 0;
+
+ /**
+ * Copies another image buffer into this image buffer.
+ */
+ virtual void copyTo (Imgbuf *dest, int xDestRoot, int yDestRoot,
+ int xSrc, int ySrc, int widthSrc, int heightSrc) = 0;
+
/*
* Reference counting.
*/
diff --git a/dw/layout.cc b/dw/layout.cc
index 8e1f065c..89361881 100644
--- a/dw/layout.cc
+++ b/dw/layout.cc
@@ -580,7 +580,7 @@ void Layout::draw (View *view, Rectangle *area)
// First of all, draw background image. (Unlike background *color*,
// this is not a feature of the views.)
- if (bgImage != NULL && bgImage->getImgbuf() != NULL)
+ if (bgImage != NULL && bgImage->getImgbufSrc() != NULL)
style::drawBackgroundImage (view, bgImage, bgRepeat, bgAttachment,
bgPositionX, bgPositionY,
area->x, area->y, area->width,
diff --git a/dw/style.cc b/dw/style.cc
index 4a8325d8..3b57ffcf 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -36,6 +36,11 @@ namespace style {
const bool drawBackgroundLineByLine = true;
+const int MIN_BG_IMG_W = 10;
+const int MIN_BG_IMG_H = 10;
+const int OPT_BG_IMG_W = 50;
+const int OPT_BG_IMG_H = 50;
+
static void calcBackgroundRelatedValues (StyleImage *backgroundImage,
BackgroundRepeat backgroundRepeat,
BackgroundAttachment
@@ -469,17 +474,59 @@ 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 ();
+ if (image->imgbufSrc)
+ image->imgbufSrc->unref ();
+ if (image->imgbufTiled)
+ image->imgbufTiled->unref ();
+
+ image->imgbufTiled = NULL;
+
+ image->imgbufSrc = buffer;
+ if (image->imgbufSrc) {
+ image->imgbufSrc->ref ();
+
+ // If the image is too small, drawing a background will cause
+ // many calls of View::drawImgbuf. For this reason, we create
+ // another image buffer, the "tiled" image buffer, which is
+ // larger (the "optimal" size is defined as OPT_BG_IMG_W *
+ // OPT_BG_IMG_H) and contains the "source" buffer several times.
+
+ if (image->imgbufSrc->getRootWidth() * image->imgbufSrc->getRootHeight()
+ < MIN_BG_IMG_W * MIN_BG_IMG_H) {
+ image->tilesX =
+ misc::max (OPT_BG_IMG_W / image->imgbufSrc->getRootWidth(), 1);
+ image->tilesY =
+ misc::max (OPT_BG_IMG_H / image->imgbufSrc->getRootHeight(), 1);
+ image->imgbufTiled =
+ image->imgbufSrc->createSimilarBuf
+ (image->tilesX * image->imgbufSrc->getRootWidth(),
+ image->tilesY * image->imgbufSrc->getRootHeight());
+ }
+ }
}
void StyleImage::StyleImgRenderer::drawRow (int row)
{
- // Nothing to do.
+ if (image->imgbufTiled) {
+ // A row of data has been copied to the source buffer, here it
+ // is copied into the tiled buffer.
+
+ // Unfortunately, this code may be called *after* some other
+ // implementations of ImgRenderer::drawRow, which actually
+ // *draw* the tiled buffer, which is so not up to date
+ // (ImgRendererDist does not define an order). OTOH, these
+ // drawing implementations calle Widget::queueResize, so the
+ // actual drawing (and so access to the tiled buffer) is done
+ // later.
+
+ int w = image->imgbufSrc->getRootWidth ();
+ int h = image->imgbufSrc->getRootHeight ();
+
+ for (int x = 0; x < image->tilesX; x++)
+ for (int y = 0; y < image->tilesX; y++)
+ image->imgbufSrc->copyTo (image->imgbufTiled, x * w, y * h,
+ 0, row, w, 1);
+ }
}
void StyleImage::StyleImgRenderer::finish ()
@@ -497,7 +544,8 @@ StyleImage::StyleImage ()
//printf ("new StyleImage %p\n", this);
refCount = 0;
- imgbuf = NULL;
+ imgbufSrc = NULL;
+ imgbufTiled = NULL;
imgRendererDist = new ImgRendererDist ();
styleImgRenderer = new StyleImgRenderer (this);
@@ -508,8 +556,10 @@ StyleImage::~StyleImage ()
{
//printf ("delete StyleImage %p\n", this);
- if (imgbuf)
- imgbuf->unref ();
+ if (imgbufSrc)
+ imgbufSrc->unref ();
+ if (imgbufTiled)
+ imgbufTiled->unref ();
delete imgRendererDist;
delete styleImgRenderer;
@@ -528,7 +578,7 @@ void StyleImage::ExternalImgRenderer::drawRow (int row)
if (readyToDraw () && (backgroundImage = getBackgroundImage ())) {
// All single rows are drawn.
- Imgbuf *imgbuf = backgroundImage->getImgbuf();
+ Imgbuf *imgbuf = backgroundImage->getImgbufSrc();
int imgWidth = imgbuf->getRootWidth ();
int imgHeight = imgbuf->getRootHeight ();
@@ -1093,7 +1143,7 @@ void drawBackground (View *view, Layout *layout, Rectangle *area,
// has to be compared, ...
(!atTop || layout->getBgColor () != style->backgroundColor);
bool bgImage = (style->backgroundImage != NULL &&
- style->backgroundImage->getImgbuf() != NULL) &&
+ style->backgroundImage->getImgbufSrc() != NULL) &&
// ... but for backgrounds, it would be rather complicated. To handle the
// two cases (normal HTML in a viewport, where the layout background
// image is set, and contents of <button> within a flat view, where the
@@ -1144,10 +1194,6 @@ void drawBackgroundImage (View *view, StyleImage *backgroundImage,
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 ("drawBackgroundImage (..., [img: %d, %d], ..., (%d, %d), %d x %d, "
// "(%d, %d), %d x %d)\n", imgWidth, imgHeight, x, y, width, height,
// xRef, yRef, widthRef, heightRef);
@@ -1165,19 +1211,33 @@ void drawBackgroundImage (View *view, StyleImage *backgroundImage,
//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;
+ if (doDraw) {
+ // Drawing is done with the "tiled" buffer, but all calculations
+ // before have been done with the "source" buffer.
+
+ Imgbuf *imgbufS = backgroundImage->getImgbufSrc();
+ int imgWidthS = imgbufS->getRootWidth ();
+ int imgHeightS = imgbufS->getRootHeight ();
+
+ Imgbuf *imgbufT = backgroundImage->getImgbufTiled();
+ int imgWidthT = imgbufT->getRootWidth ();
+ int imgHeightT = imgbufT->getRootHeight ();
+ int tilesX = backgroundImage->getTilesX ();
+ int tilesY = backgroundImage->getTilesY ();
+
+ for (int tileX = tileX1; tileX <= tileX2; tileX += tilesX)
+ for (int tileY = tileY1; tileY <= tileY2; tileY += tilesY) {
+ int xt = origX + tileX * imgWidthS;
int x1 = misc::max (xt, x);
- int x2 = misc::min (xt + imgWidth, x + width);
- int yt = origY + tileY * imgHeight;
+ int x2 = misc::min (xt + imgWidthT, x + width);
+ int yt = origY + tileY * imgHeightS;
int y1 = misc::max (yt, y);
- int y2 = misc::min (yt + imgHeight, y + height);
+ int y2 = misc::min (yt + imgHeightT, y + height);
- view->drawImage (imgbuf, xt, yt, x1 - xt, y1 - yt,
+ view->drawImage (imgbufT, xt, yt, x1 - xt, y1 - yt,
x2 - x1, y2 - y1);
}
+ }
}
void calcBackgroundRelatedValues (StyleImage *backgroundImage,
@@ -1192,7 +1252,7 @@ void calcBackgroundRelatedValues (StyleImage *backgroundImage,
int *tileX1, int *tileX2, int *tileY1,
int *tileY2, bool *doDraw)
{
- Imgbuf *imgbuf = backgroundImage->getImgbuf();
+ Imgbuf *imgbuf = backgroundImage->getImgbufSrc();
int imgWidth = imgbuf->getRootWidth ();
int imgHeight = imgbuf->getRootHeight ();
diff --git a/dw/style.hh b/dw/style.hh
index 752f6a64..ce8e2e6f 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -748,8 +748,8 @@ private:
void fatal ();
};
- int refCount;
- Imgbuf *imgbuf;
+ int refCount, tilesX, tilesY;
+ Imgbuf *imgbufSrc, *imgbufTiled;
ImgRendererDist *imgRendererDist;
StyleImgRenderer *styleImgRenderer;
@@ -826,7 +826,11 @@ public:
inline void unref ()
{ if (--refCount == 0) delete this; }
- inline Imgbuf *getImgbuf () { return imgbuf; }
+ inline Imgbuf *getImgbufSrc () { return imgbufSrc; }
+ inline Imgbuf *getImgbufTiled ()
+ { return imgbufTiled ? imgbufTiled : imgbufSrc; }
+ inline int getTilesX () { return imgbufTiled ? tilesX : 1; }
+ inline int getTilesY () { return imgbufTiled ? tilesY : 1; }
inline ImgRenderer *getMainImgRenderer () { return imgRendererDist; }
/**