From 90aa9bbb4932cab361fb12d7b5a17e7b19e0f45a Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 1 Apr 2014 23:13:00 +0400 Subject: [PATCH] clipping fixes --- src/dlangui/graphics/drawbuf.d | 28 +++++++++++++++------- src/dlangui/platforms/windows/win32fonts.d | 10 +++++++- src/dlangui/widgets/controls.d | 8 +++---- src/dlangui/widgets/layouts.d | 4 ++-- src/dlangui/widgets/lists.d | 2 +- src/dlangui/widgets/tabs.d | 2 +- 6 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/dlangui/graphics/drawbuf.d b/src/dlangui/graphics/drawbuf.d index 100c93dd..f8cd4874 100644 --- a/src/dlangui/graphics/drawbuf.d +++ b/src/dlangui/graphics/drawbuf.d @@ -94,9 +94,19 @@ class DrawBuf : RefCountedObject { /// 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. + @property Rect clipOrFullRect() { return _clipRect.empty ? Rect(0,0,width,height) : _clipRect; } /// sets new clipping rectangle, when clipRect.isEmpty == true -- means no clipping. @property void clipRect(const ref Rect rect) { - _clipRect = rect; + _clipRect = rect; + _clipRect.intersect(Rect(0, 0, width, height)); + } + /// sets new clipping rectangle, when clipRect.isEmpty == true -- means no clipping. + @property void intersectClipRect(const ref Rect rect) { + if (_clipRect.empty) + _clipRect = rect; + else + _clipRect.intersect(rect); _clipRect.intersect(Rect(0, 0, width, height)); } /// apply clipRect and buffer bounds clipping to rectangle @@ -131,8 +141,8 @@ class DrawBuf : RefCountedObject { rc2.top += _clipRect.top - rc.top; rc.top = _clipRect.top; } - if (rc.right > _clipRect.left) { - rc2.right -= rc.right - _clipRect.left; + if (rc.right > _clipRect.right) { + rc2.right -= rc.right - _clipRect.right; rc.right = _clipRect.right; } if (rc.bottom > _clipRect.bottom) { @@ -171,8 +181,8 @@ class DrawBuf : RefCountedObject { rc2.top += (_clipRect.top - rc.top) * srcdy / dstdy; rc.top = _clipRect.top; } - if (rc.right > _clipRect.left) { - rc2.right -= (rc.right - _clipRect.left) * srcdx / dstdx; + if (rc.right > _clipRect.right) { + rc2.right -= (rc.right - _clipRect.right) * srcdx / dstdx; rc.right = _clipRect.right; } if (rc.bottom > _clipRect.bottom) { @@ -235,12 +245,12 @@ alias DrawBufRef = Ref!DrawBuf; /// RAII setting/restoring of clip rectangle struct ClipRectSaver { - DrawBuf _buf; - Rect _oldClipRect; - this(DrawBuf buf, Rect newClipRect) { + private DrawBuf _buf; + private Rect _oldClipRect; + this(DrawBuf buf, ref Rect newClipRect) { _buf = buf; _oldClipRect = buf.clipRect; - buf.clipRect = newClipRect; + buf.intersectClipRect(newClipRect); } ~this() { _buf.clipRect = _oldClipRect; diff --git a/src/dlangui/platforms/windows/win32fonts.d b/src/dlangui/platforms/windows/win32fonts.d index f8407a33..1b2f5a07 100644 --- a/src/dlangui/platforms/windows/win32fonts.d +++ b/src/dlangui/platforms/windows/win32fonts.d @@ -189,13 +189,21 @@ class Win32Font : Font { override void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color) { int[] widths; int charsMeasured = measureText(text, widths, 3000); + Rect clip = buf.clipOrFullRect; + if (y + height < clip.top || y >= clip.bottom) + return; for (int i = 0; i < charsMeasured; i++) { int xx = (i > 0) ? widths[i - 1] : 0; + if (x + xx > clip.right) + break; Glyph * glyph = getCharGlyph(text[i]); if (glyph is null) continue; if ( glyph.blackBoxX && glyph.blackBoxY ) { - buf.drawGlyph( x + xx + glyph.originX, + int gx = x + xx + glyph.originX; + if (gx + glyph.blackBoxX < clip.left) + continue; + buf.drawGlyph( gx, y + _baseline - glyph.originY, glyph, color); diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d index 0891a03e..a1c66cb3 100644 --- a/src/dlangui/widgets/controls.d +++ b/src/dlangui/widgets/controls.d @@ -50,7 +50,7 @@ class TextWidget : Widget { super.onDraw(buf); Rect rc = _pos; applyMargins(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); applyPadding(rc); FontRef font = font(); Point sz = font.textSize(text); @@ -110,7 +110,7 @@ class ImageWidget : Widget { super.onDraw(buf); Rect rc = _pos; applyMargins(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); applyPadding(rc); DrawableRef img = drawable; if (!img.isNull) { @@ -156,7 +156,7 @@ class Button : Widget { applyMargins(rc); buf.fillRect(_pos, backgroundColor); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); FontRef font = font(); Point sz = font.textSize(text); applyAlign(rc, sz); @@ -572,7 +572,7 @@ class ScrollBar : AbstractSlider, OnClickHandler { Rect rc = _pos; applyMargins(rc); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); _btnForward.onDraw(buf); _btnBack.onDraw(buf); _pageUp.onDraw(buf); diff --git a/src/dlangui/widgets/layouts.d b/src/dlangui/widgets/layouts.d index b877aabc..6f1c8936 100644 --- a/src/dlangui/widgets/layouts.d +++ b/src/dlangui/widgets/layouts.d @@ -271,7 +271,7 @@ class LinearLayout : WidgetGroup { Rect rc = _pos; applyMargins(rc); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); for (int i = 0; i < _children.count; i++) { Widget item = _children.get(i); if (item.visibility != Visibility.Visible) @@ -352,7 +352,7 @@ class FrameLayout : WidgetGroup { Rect rc = _pos; applyMargins(rc); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); for (int i = 0; i < _children.count; i++) { Widget item = _children.get(i); if (item.visibility != Visibility.Visible) diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index 8e9141e1..99f58e07 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -369,7 +369,7 @@ class ListWidget : WidgetGroup, OnScrollHandler { Rect rc = _pos; applyMargins(rc); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); // draw scrollbar if (_needScrollbar) _scrollbar.onDraw(buf); diff --git a/src/dlangui/widgets/tabs.d b/src/dlangui/widgets/tabs.d index 0ed57104..d8054c1d 100644 --- a/src/dlangui/widgets/tabs.d +++ b/src/dlangui/widgets/tabs.d @@ -306,7 +306,7 @@ class TabControl : WidgetGroup { Rect rc = _pos; applyMargins(rc); applyPadding(rc); - ClipRectSaver(buf, rc); + auto saver = ClipRectSaver(buf, rc); for (int i = 0; i < _children.count; i++) { Widget item = _children.get(i); if (item.visibility != Visibility.Visible)