aboutsummaryrefslogtreecommitdiff
path: root/dw/style.cc
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/style.cc
parenta406f9d43bdc140fa7355be4e72aaef5081d7dd2 (diff)
Optimized drawing of very small background images.
Diffstat (limited to 'dw/style.cc')
-rw-r--r--dw/style.cc110
1 files changed, 85 insertions, 25 deletions
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 ();