From a6a818a88472dd157912c276080bb1d656ef1ee3 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 3 Nov 2015 10:49:57 +0300 Subject: [PATCH] fix DrawBuf.fill behavior - apply clipping rectangle --- examples/example1/example1.visualdproj | 6 +- examples/example1/src/example1.d | 2 + src/dlangui/graphics/drawbuf.d | 12 +- src/dlangui/graphics/gldrawbuf.d | 4 + src/dlangui/platforms/windows/win32drawbuf.d | 320 ++++++++++--------- 5 files changed, 182 insertions(+), 162 deletions(-) diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index e31a2a01..1a52df92 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -70,11 +70,11 @@ 1 $(IntDir)\$(TargetName).json 0 - + DebugFocus FontResources 0 EmbedStandardResources Unicode USE_FREETYPE 0 - 3 + 0 0 @@ -90,7 +90,7 @@ dlangui.lib phobos.lib ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib - ../../Debug ../../../DerelictOpenGL3/source + ../../Debug $(OutDir)\$(ProjectName).exe diff --git a/examples/example1/src/example1.d b/examples/example1/src/example1.d index 45a836ff..e0bebf50 100644 --- a/examples/example1/src/example1.d +++ b/examples/example1/src/example1.d @@ -190,6 +190,7 @@ extern (C) int UIAppMain(string[] args) { // always use trace, even for release builds Log.setLogLevel(LogLevel.Trace); + Log.setFileLogger(std.stdio.File("ui.log", "w")); // resource directory search paths // not required if only embedded resources are used @@ -875,6 +876,7 @@ void main() CanvasWidget canvas = new CanvasWidget("canvas"); canvas.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); canvas.onDrawListener = delegate(CanvasWidget canvas, DrawBuf buf, Rect rc) { + Log.w("canvas.onDrawListener clipRect=" ~ to!string(buf.clipRect)); buf.fill(0xFFFFFF); int x = rc.left; int y = rc.top; diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d index 2b6ce4cc..336a1385 100644 --- a/src/dlangui/graphics/drawbuf.d +++ b/src/dlangui/graphics/drawbuf.d @@ -21,7 +21,6 @@ public import dlangui.core.types; import dlangui.core.logger; import dlangui.graphics.colors; - /** * 9-patch image scaling information (see Android documentation). * @@ -120,6 +119,9 @@ class DrawBuf : RefCountedObject { void resetClipping() { _clipRect = Rect(0, 0, width, height); } + @property bool hasClipping() { + return _clipRect.left != 0 || _clipRect.top != 0 || _clipRect.right != width || _clipRect.bottom != height; + } /// returns clipping rectangle, when clipRect.isEmpty == true -- means no clipping. @property ref Rect clipRect() { return _clipRect; } /// returns clipping rectangle, or (0,0,dx,dy) when no clipping. @@ -736,6 +738,10 @@ class GrayDrawBuf : DrawBuf { resetClipping(); } override void fill(uint color) { + if (hasClipping) { + fillRect(_clipRect, color); + return; + } int len = _dx * _dy; ubyte * p = _buf.ptr; ubyte cl = rgbToGray(color); @@ -961,6 +967,10 @@ class ColorDrawBuf : ColorDrawBufBase { resetClipping(); } override void fill(uint color) { + if (hasClipping) { + fillRect(_clipRect, color); + return; + } int len = _dx * _dy; uint * p = _buf.ptr; for (int i = 0; i < len; i++) diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index ee613c12..d2580705 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -90,6 +90,10 @@ class GLDrawBuf : DrawBuf, GLConfigCallback { /// fill the whole buffer with solid color (no clipping applied) override void fill(uint color) { + if (hasClipping) { + fillRect(_clipRect, color); + return; + } assert(_scene !is null); _scene.add(new SolidRectSceneItem(Rect(0, 0, _dx, _dy), applyAlpha(color))); } diff --git a/src/dlangui/platforms/windows/win32drawbuf.d b/src/dlangui/platforms/windows/win32drawbuf.d index 7f5542e6..86507711 100644 --- a/src/dlangui/platforms/windows/win32drawbuf.d +++ b/src/dlangui/platforms/windows/win32drawbuf.d @@ -1,161 +1,165 @@ -// Written in the D programming language. - -/** - -This module contains drawing buffer implementation for Win32 platform - -Part of Win32 platform support. - -Usually you don't need to use this module directly. - - -Synopsis: - ----- -import dlangui.platforms.windows.win32drawbuf; ----- - -Copyright: Vadim Lopatin, 2014 -License: Boost License 1.0 -Authors: Vadim Lopatin, coolreader.org@gmail.com -*/ -module dlangui.platforms.windows.win32drawbuf; - -version(Windows): +// Written in the D programming language. -import win32.windows; -import dlangui.core.logger; -import dlangui.graphics.drawbuf; - -/// Win32 context ARGB drawing buffer -class Win32ColorDrawBuf : ColorDrawBufBase { - private uint * _pixels; - private HDC _drawdc; - private HBITMAP _drawbmp; - /// returns handle of win32 device context - @property HDC dc() { return _drawdc; } - /// returns handle of win32 bitmap - @property HBITMAP bmp() { return _drawdc; } - this(int width, int height) { - resize(width, height); - } - /// create resized copy of ColorDrawBuf - this(ColorDrawBuf v, int dx, int dy) { - this(dx, dy); - resetClipping(); - fill(0xFFFFFFFF); - if (_dx == dx && _dy == dy) - drawImage(0, 0, v); - else - drawRescaled(Rect(0, 0, dx, dy), v, Rect(0, 0, v.width, v.height)); - } - /// invert alpha in buffer content - void invertAlpha() { - for(int i = _dx * _dy - 1; i >= 0; i--) - _pixels[i] ^= 0xFF000000; - } - /// returns HBITMAP for alpha - HBITMAP createTransparencyBitmap() { - int hbytes = (((_dx + 7) / 8) + 1) & 0xFFFFFFFE; - static __gshared ubyte[] buf; - buf.length = hbytes * _dy * 2; - //for (int y = 0; y < _dy; y++) { - // uint * src = scanLine(y); - // ubyte * dst1 = buf.ptr + (_dy - 1 - y) * hbytes; - // ubyte * dst2 = buf.ptr + (_dy - 1 - y) * hbytes + hbytes * _dy; - // for (int x = 0; x < _dx; x++) { - // ubyte pixel1 = 0x80; //(src[x] >> 24) > 0x80 ? 0 : 0x80; - // ubyte pixel2 = (src[x] >> 24) < 0x80 ? 0 : 0x80; - // int xi = x >> 3; - // dst1[xi] |= (pixel1 >> (x & 7)); - // dst2[xi] |= (pixel2 >> (x & 7)); - // } - //} - // debug - for(int i = 0; i < hbytes * _dy; i++) - buf[i] = 0xFF; - for(int i = hbytes * _dy; i < buf.length; i++) - buf[i] = 0; //0xFF; - - BITMAP b; - b.bmWidth = _dx; - b.bmHeight = _dy; - b.bmWidthBytes = hbytes; - b.bmPlanes = 1; - b.bmBitsPixel = 1; - b.bmBits = buf.ptr; - return CreateBitmapIndirect(&b); - //return CreateBitmap(_dx, _dy, 1, 1, buf.ptr); - } - /// destroy object, but leave bitmap as is - HBITMAP destroyLeavingBitmap() { - HBITMAP res = _drawbmp; - _drawbmp = null; - destroy(this); - return res; - } - /// Returns pointer to scan line - override uint * scanLine(int y) { - if (y >= 0 && y < _dy) - return _pixels + _dx * (_dy - 1 - y); - return null; - } - ~this() { - clear(); - } - /// Clear buffer contents, set dimension to 0, 0 - override void clear() { - if (_drawbmp !is null || _drawdc !is null) { - if (_drawbmp) - DeleteObject(_drawbmp); - if (_drawdc) - DeleteObject(_drawdc); - _drawbmp = null; - _drawdc = null; - _pixels = null; - _dx = 0; - _dy = 0; - } - } - /// Change buffer size - override void resize(int width, int height) { - if (width< 0) - width = 0; - if (height < 0) - height = 0; - if (_dx == width && _dy == height) +/** + +This module contains drawing buffer implementation for Win32 platform + +Part of Win32 platform support. + +Usually you don't need to use this module directly. + + +Synopsis: + +---- +import dlangui.platforms.windows.win32drawbuf; +---- + +Copyright: Vadim Lopatin, 2014 +License: Boost License 1.0 +Authors: Vadim Lopatin, coolreader.org@gmail.com +*/ +module dlangui.platforms.windows.win32drawbuf; + +version(Windows): + +import win32.windows; +import dlangui.core.logger; +import dlangui.graphics.drawbuf; + +/// Win32 context ARGB drawing buffer +class Win32ColorDrawBuf : ColorDrawBufBase { + private uint * _pixels; + private HDC _drawdc; + private HBITMAP _drawbmp; + /// returns handle of win32 device context + @property HDC dc() { return _drawdc; } + /// returns handle of win32 bitmap + @property HBITMAP bmp() { return _drawdc; } + this(int width, int height) { + resize(width, height); + } + /// create resized copy of ColorDrawBuf + this(ColorDrawBuf v, int dx, int dy) { + this(dx, dy); + resetClipping(); + fill(0xFFFFFFFF); + if (_dx == dx && _dy == dy) + drawImage(0, 0, v); + else + drawRescaled(Rect(0, 0, dx, dy), v, Rect(0, 0, v.width, v.height)); + } + /// invert alpha in buffer content + void invertAlpha() { + for(int i = _dx * _dy - 1; i >= 0; i--) + _pixels[i] ^= 0xFF000000; + } + /// returns HBITMAP for alpha + HBITMAP createTransparencyBitmap() { + int hbytes = (((_dx + 7) / 8) + 1) & 0xFFFFFFFE; + static __gshared ubyte[] buf; + buf.length = hbytes * _dy * 2; + //for (int y = 0; y < _dy; y++) { + // uint * src = scanLine(y); + // ubyte * dst1 = buf.ptr + (_dy - 1 - y) * hbytes; + // ubyte * dst2 = buf.ptr + (_dy - 1 - y) * hbytes + hbytes * _dy; + // for (int x = 0; x < _dx; x++) { + // ubyte pixel1 = 0x80; //(src[x] >> 24) > 0x80 ? 0 : 0x80; + // ubyte pixel2 = (src[x] >> 24) < 0x80 ? 0 : 0x80; + // int xi = x >> 3; + // dst1[xi] |= (pixel1 >> (x & 7)); + // dst2[xi] |= (pixel2 >> (x & 7)); + // } + //} + // debug + for(int i = 0; i < hbytes * _dy; i++) + buf[i] = 0xFF; + for(int i = hbytes * _dy; i < buf.length; i++) + buf[i] = 0; //0xFF; + + BITMAP b; + b.bmWidth = _dx; + b.bmHeight = _dy; + b.bmWidthBytes = hbytes; + b.bmPlanes = 1; + b.bmBitsPixel = 1; + b.bmBits = buf.ptr; + return CreateBitmapIndirect(&b); + //return CreateBitmap(_dx, _dy, 1, 1, buf.ptr); + } + /// destroy object, but leave bitmap as is + HBITMAP destroyLeavingBitmap() { + HBITMAP res = _drawbmp; + _drawbmp = null; + destroy(this); + return res; + } + /// Returns pointer to scan line + override uint * scanLine(int y) { + if (y >= 0 && y < _dy) + return _pixels + _dx * (_dy - 1 - y); + return null; + } + ~this() { + clear(); + } + /// Clear buffer contents, set dimension to 0, 0 + override void clear() { + if (_drawbmp !is null || _drawdc !is null) { + if (_drawbmp) + DeleteObject(_drawbmp); + if (_drawdc) + DeleteObject(_drawdc); + _drawbmp = null; + _drawdc = null; + _pixels = null; + _dx = 0; + _dy = 0; + } + } + /// Change buffer size + override void resize(int width, int height) { + if (width< 0) + width = 0; + if (height < 0) + height = 0; + if (_dx == width && _dy == height) + return; + clear(); + _dx = width; + _dy = height; + if (_dx > 0 && _dy > 0) { + BITMAPINFO bmi; + //memset( &bmi, 0, sizeof(bmi) ); + bmi.bmiHeader.biSize = (bmi.bmiHeader.sizeof); + bmi.bmiHeader.biWidth = _dx; + bmi.bmiHeader.biHeight = _dy; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 1024; + bmi.bmiHeader.biYPelsPerMeter = 1024; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + _drawbmp = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS, cast(void**)(&_pixels), NULL, 0 ); + _drawdc = CreateCompatibleDC(NULL); + SelectObject(_drawdc, _drawbmp); + } + } + /// fill with solid color + override void fill(uint color) { + if (hasClipping) { + fillRect(_clipRect, color); return; - clear(); - _dx = width; - _dy = height; - if (_dx > 0 && _dy > 0) { - BITMAPINFO bmi; - //memset( &bmi, 0, sizeof(bmi) ); - bmi.bmiHeader.biSize = (bmi.bmiHeader.sizeof); - bmi.bmiHeader.biWidth = _dx; - bmi.bmiHeader.biHeight = _dy; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = 0; - bmi.bmiHeader.biXPelsPerMeter = 1024; - bmi.bmiHeader.biYPelsPerMeter = 1024; - bmi.bmiHeader.biClrUsed = 0; - bmi.bmiHeader.biClrImportant = 0; - _drawbmp = CreateDIBSection( NULL, &bmi, DIB_RGB_COLORS, cast(void**)(&_pixels), NULL, 0 ); - _drawdc = CreateCompatibleDC(NULL); - SelectObject(_drawdc, _drawbmp); } - } - /// fill with solid color - override void fill(uint color) { - int len = _dx * _dy; - //for (int i = 0; i < len; i++) - // _pixels[i] = color; - _pixels[0 .. len - 1] = color; - } - /// draw to win32 device context - void drawTo(HDC dc, int x, int y) { - BitBlt(dc, x, y, _dx, _dy, _drawdc, 0, 0, SRCCOPY); - } -} + int len = _dx * _dy; + //for (int i = 0; i < len; i++) + // _pixels[i] = color; + _pixels[0 .. len - 1] = color; + } + /// draw to win32 device context + void drawTo(HDC dc, int x, int y) { + BitBlt(dc, x, y, _dx, _dy, _drawdc, 0, 0, SRCCOPY); + } +}