GUI: Add drawTabClip()

This commit is contained in:
Alexander Tkachev 2016-06-29 21:07:12 +06:00 committed by Eugene Sandulenko
parent ee00156d54
commit 80412a4139
6 changed files with 339 additions and 5 deletions

View File

@ -218,6 +218,7 @@ public:
* @param r Radius of the corners of the tab (0 for squared tabs). * @param r Radius of the corners of the tab (0 for squared tabs).
*/ */
virtual void drawTab(int x, int y, int r, int w, int h) = 0; virtual void drawTab(int x, int y, int r, int w, int h) = 0;
virtual void drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) = 0;
/** /**
@ -404,10 +405,10 @@ public:
drawBeveledSquareClip(x, y, w, h, _bevel, clip); drawBeveledSquareClip(x, y, w, h, _bevel, clip);
} }
void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO void drawCallback_TAB(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
uint16 x, y, w, h; uint16 x, y, w, h;
stepGetPositions(step, area, x, y, w, h); stepGetPositions(step, area, x, y, w, h);
drawTab(x, y, stepGetRadius(step, area), w, h); drawTabClip(x, y, stepGetRadius(step, area), w, h, clip);
} }
void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO void drawCallback_BITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO

View File

@ -1425,6 +1425,66 @@ drawTab(int x, int y, int r, int w, int h) {
} }
} }
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
return;
Common::Rect backup = _clippingArea;
_clippingArea = clipping;
bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
if (r == 0 && Base::_bevel > 0) {
if (useClippingVersions)
drawBevelTabAlgClip(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
else
drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
_clippingArea = backup;
return;
}
if (r == 0) {
_clippingArea = backup;
return;
}
switch (Base::_fillMode) {
case kFillDisabled:
// FIXME: Implement this
_clippingArea = backup;
return;
case kFillGradient:
case kFillBackground:
// FIXME: This is broken for the AA renderer.
// See the rounded rect alg for how to fix it. (The border should
// be drawn before the interior, both inside drawTabAlg.)
if (useClippingVersions) {
drawTabShadowClip(x, y, w - 2, h, r);
drawTabAlgClip(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
if (Base::_strokeWidth)
drawTabAlgClip(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
} else {
drawTabShadow(x, y, w - 2, h, r);
drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
if (Base::_strokeWidth)
drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
}
break;
case kFillForeground:
if (useClippingVersions)
drawTabAlgClip(x, y, w, h, r, _fgColor, Base::_fillMode);
else
drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
break;
}
_clippingArea = backup;
}
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::
drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
@ -1685,6 +1745,120 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
} }
} }
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTabAlgClip(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
// Don't draw anything for empty rects.
if (w <= 0 || h <= 0) {
return;
}
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int sw = 0, sp = 0, hp = 0;
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
int tl_x = x1 + r, tl_y = y1 + r;
int tr_x = x1 + w - r, tr_y = y1 + r;
int fill_x = x1, fill_y = y1;
int real_radius = r;
int short_h = h - r + 2;
int long_h = h;
if (fill_m == kFillDisabled) {
while (sw++ < Base::_strokeWidth) {
colorFillClip<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, fill_x + r, fill_y + sp/pitch, _clippingArea);
colorFillClip<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, fill_x + r, fill_y + hp / pitch - sp / pitch, _clippingArea);
sp += pitch;
BE_RESET();
r--;
while (x++ < y) {
BE_ALGORITHM();
BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
if (Base::_strokeWidth > 1)
BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px - pitch, py, tr_x, tr_y, tl_x, tl_y);
}
}
ptr_fill += pitch * real_radius;
fill_y += real_radius;
while (short_h--) {
colorFillClip<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color, fill_x, fill_y, _clippingArea);
colorFillClip<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, fill_x + w - Base::_strokeWidth + 1, fill_y, _clippingArea);
ptr_fill += pitch;
++fill_y;
}
if (baseLeft) {
sw = 0;
ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
fill_x = x1;
fill_y = y1 + h + 1;
while (sw++ < Base::_strokeWidth) {
colorFillClip<PixelType>(ptr_fill - baseLeft, ptr_fill, color, fill_x - baseLeft, fill_y, _clippingArea);
ptr_fill += pitch;
++fill_y;
}
}
if (baseRight) {
sw = 0;
ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
fill_x = x1 + w;
fill_y = y1 + h + 1;
while (sw++ < Base::_strokeWidth) {
colorFillClip<PixelType>(ptr_fill, ptr_fill + baseRight, color, fill_x, fill_y, _clippingArea);
ptr_fill += pitch;
++fill_y;
}
}
} else {
BE_RESET();
precalcGradient(long_h);
PixelType color1, color2;
color1 = color2 = color;
while (x++ < y) {
BE_ALGORITHM();
if (fill_m == kFillGradient) {
color1 = calcGradient(real_radius - x, long_h);
color2 = calcGradient(real_radius - y, long_h);
gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y, tl_x - x, tl_y - y);
gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x, tl_x - y, tl_y - x);
BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
} else {
colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color, tl_x - x, tl_y - y, _clippingArea);
colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color, tl_x - y, tl_y - x, _clippingArea);
BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
}
}
ptr_fill += pitch * r;
fill_y += r;
while (short_h--) {
if (fill_m == kFillGradient) {
gradientFillClip(ptr_fill, w + 1, x1, real_radius++, fill_x, fill_y);
} else {
colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color, fill_x, fill_y, _clippingArea);
}
ptr_fill += pitch;
++fill_y;
}
}
}
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::
@ -1747,6 +1921,72 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
} }
} }
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTabShadowClip(int x1, int y1, int w, int h, int r) {
int offset = 3;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
uint8 expFactor = 3;
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
int xstart = x1;
int ystart = y1;
int width = w;
int height = h + offset + 1;
for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y;
int x, y, px, py;
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
int tl_x = xstart + r, tl_y = ystart + r;
int fill_x = xstart, fill_y = ystart;
int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0);
BE_RESET();
// HACK: As we are drawing circles exploting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;
while (x++ < y) {
BE_ALGORITHM();
if (((1 << x) & hb) == 0) {
blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, tl_x - y, tl_y - x);
hb |= (1 << x);
}
if (((1 << y) & hb) == 0) {
blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, tl_x - x, tl_y - y);
hb |= (1 << y);
}
}
ptr_fill += pitch * r;
fill_y += r;
while (short_h--) {
blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha, fill_x, fill_y);
ptr_fill += pitch;
++fill_y;
}
// Move shadow one pixel upward each iteration
xstart += 1;
// Multiply with expfactor
alpha = (alpha * (expFactor << 8)) >> 9;
}
}
/** BEVELED TABS FOR CLASSIC THEME **/ /** BEVELED TABS FOR CLASSIC THEME **/
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::
@ -1791,6 +2031,57 @@ drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, Pixe
} }
} }
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawBevelTabAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;
PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
int ptr_x = x, ptr_y = y;
i = bevel;
while (i--) {
colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
ptr_left += pitch;
++ptr_y;
}
if (baseLeft > 0) {
i = h - bevel;
ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
ptr_x = x; ptr_y = y;
while (i--) {
colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
ptr_left += pitch;
++ptr_y;
}
}
i = h - bevel;
j = bevel - 1;
ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
ptr_x = x + w - bevel; ptr_y = y;
while (i--) {
colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
if (j > 0) j--;
ptr_left += pitch;
++ptr_y;
}
i = bevel;
ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
ptr_x = x + w - bevel; ptr_y = y + h - bevel;
while (i--) {
colorFillClip<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color, ptr_x, ptr_y, _clippingArea);
if (baseLeft)
colorFillClip<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color, ptr_x - w - baseLeft + bevel, ptr_y, _clippingArea);
ptr_left += pitch;
++ptr_y;
}
}
/** SQUARE ALGORITHM **/ /** SQUARE ALGORITHM **/
template<typename PixelType> template<typename PixelType>
void VectorRendererSpec<PixelType>:: void VectorRendererSpec<PixelType>::

View File

@ -60,7 +60,8 @@ public:
void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch); void drawRoundedSquareClip(int x, int y, int r, int w, int h, int cx, int cy, int cw, int ch);
void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient); void drawTriangle(int x, int y, int base, int height, TriangleOrientation orient);
void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping); void drawTriangleClip(int x, int y, int base, int height, TriangleOrientation orient, Common::Rect clipping);
void drawTab(int x, int y, int r, int w, int h); //TODO void drawTab(int x, int y, int r, int w, int h);
void drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping);
void drawBeveledSquare(int x, int y, int w, int h, int bevel) { void drawBeveledSquare(int x, int y, int w, int h, int bevel) {
drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled); drawBevelSquareAlg(x, y, w, h, bevel, _bevelColor, _fgColor, Base::_fillMode != kFillDisabled);
} }
@ -223,12 +224,22 @@ protected:
PixelType color, VectorRenderer::FillMode fill_m, PixelType color, VectorRenderer::FillMode fill_m,
int baseLeft = 0, int baseRight = 0); int baseLeft = 0, int baseRight = 0);
virtual void drawTabAlgClip(int x, int y, int w, int h, int r,
PixelType color, VectorRenderer::FillMode fill_m,
int baseLeft = 0, int baseRight = 0);
virtual void drawTabShadow(int x, int y, int w, int h, int r); virtual void drawTabShadow(int x, int y, int w, int h, int r);
virtual void drawTabShadowClip(int x, int y, int w, int h, int r);
virtual void drawBevelTabAlg(int x, int y, int w, int h, virtual void drawBevelTabAlg(int x, int y, int w, int h,
int bevel, PixelType topColor, PixelType bottomColor, int bevel, PixelType topColor, PixelType bottomColor,
int baseLeft = 0, int baseRight = 0); int baseLeft = 0, int baseRight = 0);
virtual void drawBevelTabAlgClip(int x, int y, int w, int h,
int bevel, PixelType topColor, PixelType bottomColor,
int baseLeft = 0, int baseRight = 0);
/** /**
* SHADOW DRAWING ALGORITHMS * SHADOW DRAWING ALGORITHMS
* *

View File

@ -1351,6 +1351,34 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co
} }
} }
void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
if (!ready())
return;
queueDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip);
for (int i = 0; i < (int)tabs.size(); ++i) {
if (i == active)
continue;
if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
continue;
Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
queueDDClip(kDDTabInactive, tabRect, clip);
queueDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
}
if (active >= 0 &&
(r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
const uint16 tabLeft = active * tabWidth;
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
queueDDClip(kDDTabActive, tabRect, clip, (tabLeft << 16) | (tabRight & 0xFFFF));
queueDDTextClip(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, clip, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
}
}
void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) { void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
if (!ready()) if (!ready())
return; return;

View File

@ -365,6 +365,9 @@ public:
void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
const Common::Array<Common::String> &tabs, int active, uint16 hints, const Common::Array<Common::String> &tabs, int active, uint16 hints,
int titleVPad, WidgetStateInfo state = kStateEnabled); int titleVPad, WidgetStateInfo state = kStateEnabled);
void drawTabClip(const Common::Rect &r, const Common::Rect &clippingRect, int tabHeight, int tabWidth,
const Common::Array<Common::String> &tabs, int active, uint16 hints,
int titleVPad, WidgetStateInfo state = kStateEnabled);
void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
ScrollbarState, WidgetStateInfo state = kStateEnabled); ScrollbarState, WidgetStateInfo state = kStateEnabled);

View File

@ -308,9 +308,9 @@ void TabWidget::drawWidget() {
for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) { for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) {
tabs.push_back(_tabs[i].title); tabs.push_back(_tabs[i].title);
} }
g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), _bodyBackgroundType); g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), getBossClipRect(), _bodyBackgroundType);
g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad); g_gui.theme()->drawTabClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
} }
void TabWidget::draw() { void TabWidget::draw() {