From 434aae7b0402f0779b42ad6e64cfc1ff75023a58 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Fri, 7 Mar 2014 14:34:37 +0400 Subject: [PATCH] nine patch drawing is working --- src/dlangui/graphics/drawbuf.d | 68 +++++++++++++++++++++++++++++++++- src/dlangui/graphics/images.d | 7 ++-- src/dlangui/widgets/widget.d | 6 +++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d index a571ac78..87380a0f 100644 --- a/src/dlangui/graphics/drawbuf.d +++ b/src/dlangui/graphics/drawbuf.d @@ -250,6 +250,7 @@ class ColorDrawBufBase : DrawBuf { } /// draw source buffer rectangle contents to destination buffer rectangle applying rescaling override void drawRescaled(Rect dstrect, DrawBuf src, Rect srcrect) { + //Log.d("drawRescaled ", dstrect, " <- ", srcrect); if (applyClipping(dstrect, srcrect)) { int[] xmap = createMap(dstrect.left, dstrect.right, srcrect.left, srcrect.right); int[] ymap = createMap(dstrect.top, dstrect.bottom, srcrect.top, srcrect.bottom); @@ -427,9 +428,11 @@ class SolidFillDrawable : Drawable { class ImageDrawable : Drawable { protected DrawBufRef _image; protected bool _tiled; - this(ref DrawBufRef image, bool tiled = false) { + this(ref DrawBufRef image, bool tiled = false, bool ninePatch = false) { _image = image; _tiled = tiled; + if (ninePatch) + _image.detectNinePatch(); } @property override int width() { if (_image.isNull) @@ -450,11 +453,74 @@ class ImageDrawable : Drawable { return _image.ninePatch.padding; return Rect(0,0,0,0); } + private static void correctFrameBounds(ref int n1, ref int n2) { + if (n1 > n2) { + int middle = (n1 + n2) / 2; + n1 = n2 = middle; + } + } override void drawTo(DrawBuf buf, Rect rc, int tilex0 = 0, int tiley0 = 0) { if (_image.isNull) return; if (_image.hasNinePatch) { // draw nine patch + const NinePatch * p = _image.ninePatch; + //Log.d("drawing nine patch image with frame ", p.frame, " padding ", p.padding); + int w = width; + int h = height; + Rect dstrect = rc; + Rect srcrect = Rect(1, 1, w + 1, h + 1); + if (buf.applyClipping(dstrect, srcrect)) { + int x0 = srcrect.left; + int x1 = 1 + p.frame.left; + int x2 = w - p.frame.right; + int x3 = srcrect.right; + int y0 = srcrect.top; + int y1 = 1 + p.frame.top; + int y2 = h - p.frame.bottom; + int y3 = srcrect.bottom; + int dstx0 = rc.left; + int dstx1 = rc.left + p.frame.left; + int dstx2 = rc.right - p.frame.right; + int dstx3 = rc.right; + int dsty0 = rc.top; + int dsty1 = rc.top + p.frame.top; + int dsty2 = rc.bottom - p.frame.bottom; + int dsty3 = rc.bottom; + //Log.d("src x bounds: ", x0, ", ", x1, ", ", x2, ", ", x3, " dst ", dstx0, ", ", dstx1, ", ", dstx2, ", ", dstx3); + //Log.d("src y bounds: ", y0, ", ", y1, ", ", y2, ", ", y3, " dst ", dsty0, ", ", dsty1, ", ", dsty2, ", ", dsty3); + correctFrameBounds(x1, x2); + correctFrameBounds(y1, y2); + correctFrameBounds(dstx1, dstx2); + correctFrameBounds(dsty1, dsty2); + if (y0 < y1 && dsty0 < dsty1) { + // top row + if (x0 < x1 && dstx0 < dstx1) + buf.drawFragment(dstx0, dsty0, _image.get, Rect(x0, y0, x1, y1)); // top left + if (x1 < x2 && dstx1 < dstx2) + buf.drawRescaled(Rect(dstx1, dsty0, dstx2, dsty1), _image.get, Rect(x1, y0, x2, y1)); // top center + if (x2 < x3 && dstx2 < dstx3) + buf.drawFragment(dstx2, dsty0, _image.get, Rect(x2, y0, x3, y1)); // top right + } + if (y1 < y2 && dsty1 < dsty2) { + // middle row + if (x0 < x1 && dstx0 < dstx1) + buf.drawRescaled(Rect(dstx0, dsty1, dstx1, dsty2), _image.get, Rect(x0, y1, x1, y2)); // middle center + if (x1 < x2 && dstx1 < dstx2) + buf.drawRescaled(Rect(dstx1, dsty1, dstx2, dsty2), _image.get, Rect(x1, y1, x2, y2)); // center + if (x2 < x3 && dstx2 < dstx3) + buf.drawRescaled(Rect(dstx2, dsty1, dstx3, dsty2), _image.get, Rect(x2, y1, x3, y2)); // middle center + } + if (y2 < y3 && dsty2 < dsty3) { + // bottom row + if (x0 < x1 && dstx0 < dstx1) + buf.drawFragment(dstx0, dsty2, _image.get, Rect(x0, y2, x1, y3)); // bottom left + if (x1 < x2 && dstx1 < dstx2) + buf.drawRescaled(Rect(dstx1, dsty2, dstx2, dsty3), _image.get, Rect(x1, y2, x2, y3)); // bottom center + if (x2 < x3 && dstx2 < dstx3) + buf.drawFragment(dstx2, dsty2, _image.get, Rect(x2, y2, x3, y3)); // bottom right + } + } } else if (_tiled) { // tiled } else { diff --git a/src/dlangui/graphics/images.d b/src/dlangui/graphics/images.d index 490ecab4..ad88fbe8 100644 --- a/src/dlangui/graphics/images.d +++ b/src/dlangui/graphics/images.d @@ -122,9 +122,10 @@ class DrawableCache { if (_filename !is null) { // reload from file DrawBufRef image = imageCache.get(_filename); - if (!image.isNull) - _drawable = new ImageDrawable(image, _tiled); - else + if (!image.isNull) { + bool ninePatch = _filename.endsWith(".9.png"); + _drawable = new ImageDrawable(image, _tiled, ninePatch); + } else _error = true; } return _drawable; diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index e5721139..ae761afb 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -155,6 +155,12 @@ class Widget { DrawableRef img = drawableCache.get("exit"); if (!img.isNull) img.drawTo(buf, Rect(50, 50, 50+64, 50+64)); + img = drawableCache.get("btn_default_normal"); + if (!img.isNull) { + img.drawTo(buf, Rect(150, 150, 150+100, 150+50)); + img.drawTo(buf, Rect(250, 250, 250+60, 250+150)); + img.drawTo(buf, Rect(50, 50, 50+30, 50+30)); + } _needDraw = false; } /// Applies alignment for content of size sz - set rectangle rc to aligned value of content inside of initial value of rc.