Draw double/groove/ridge border styles

develop
Nimetu 3 years ago
parent 487f9f060e
commit 65edd9f95d

@ -35,22 +35,24 @@ namespace NLGUI
{ {
private: private:
// parent element screen coordinates // parent element screen coordinates
sint32 _XReal, _YReal; sint32 m_XReal, m_YReal;
sint32 _WReal, _HReal; sint32 m_WReal, m_HReal;
NLMISC::CQuadUV _QuadT; struct SDrawBorder
NLMISC::CQuadUV _QuadR; {
NLMISC::CQuadUV _QuadB; NLMISC::CQuadUV Quad;
NLMISC::CQuadUV _QuadL; NLMISC::CRGBA Color;
};
std::vector<SDrawBorder> m_DrawBorders;
sint8 _RenderLayer; sint8 m_RenderLayer;
bool _ModulateGlobalColor; bool m_ModulateGlobalColor;
// if true, then updateCoords() is called from draw() // if true, then updateCoords() is called from draw()
bool _Dirty; bool m_Dirty;
// if true, then at least one border is set // if true, then at least one border is set
bool _Border; bool m_Border;
bool _BorderTop, _BorderRight, _BorderBottom, _BorderLeft; bool m_BorderTop, m_BorderRight, m_BorderBottom, m_BorderLeft;
public: public:
uint32 TopWidth, RightWidth, BottomWidth, LeftWidth; uint32 TopWidth, RightWidth, BottomWidth, LeftWidth;
@ -73,8 +75,8 @@ namespace NLGUI
void setColor(const NLMISC::CRGBA &top, const NLMISC::CRGBA &right, const NLMISC::CRGBA &bottom, const NLMISC::CRGBA &left); void setColor(const NLMISC::CRGBA &top, const NLMISC::CRGBA &right, const NLMISC::CRGBA &bottom, const NLMISC::CRGBA &left);
void updateCoords(); void updateCoords();
void invalidateCoords() { _Dirty = _Border = true; } void invalidateCoords() { m_Dirty = m_Border = true; }
void invalidateContent() { _Dirty = _Border = true; }; void invalidateContent() { m_Dirty = m_Border = true; };
uint32 getTopWidth() const; uint32 getTopWidth() const;
uint32 getRightWidth() const; uint32 getRightWidth() const;
@ -84,6 +86,8 @@ namespace NLGUI
uint32 getLeftRightWidth() const; uint32 getLeftRightWidth() const;
uint32 getTopBottomWidth() const; uint32 getTopBottomWidth() const;
bool hasInnerShape(CSSLineStyle style) const;
void draw(); void draw();
}; // CSSBorderRenderer }; // CSSBorderRenderer

@ -30,7 +30,12 @@ namespace NLGUI
enum CSSLineStyle { enum CSSLineStyle {
CSS_LINE_STYLE_NONE = 0, CSS_LINE_STYLE_NONE = 0,
CSS_LINE_STYLE_HIDDEN, CSS_LINE_STYLE_HIDDEN,
CSS_LINE_STYLE_DOTTED,
CSS_LINE_STYLE_DASHED,
CSS_LINE_STYLE_SOLID, CSS_LINE_STYLE_SOLID,
CSS_LINE_STYLE_DOUBLE,
CSS_LINE_STYLE_GROOVE,
CSS_LINE_STYLE_RIDGE,
CSS_LINE_STYLE_INSET, CSS_LINE_STYLE_INSET,
CSS_LINE_STYLE_OUTSET CSS_LINE_STYLE_OUTSET
}; };

@ -29,8 +29,6 @@ using namespace NLMISC;
namespace NLGUI namespace NLGUI
{ {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
CSSBorderRenderer::CSSBorderRenderer() CSSBorderRenderer::CSSBorderRenderer()
{ {
@ -39,56 +37,39 @@ namespace NLGUI
TopStyle = RightStyle = BottomStyle = LeftStyle = CSS_LINE_STYLE_SOLID; TopStyle = RightStyle = BottomStyle = LeftStyle = CSS_LINE_STYLE_SOLID;
CurrentAlpha = 255; CurrentAlpha = 255;
_RenderLayer = 0; m_RenderLayer = 0;
_ModulateGlobalColor = false; m_ModulateGlobalColor = false;
_Border = true; m_Border = true;
_Dirty = true; m_Dirty = true;
_BorderTop = _BorderRight = _BorderBottom = _BorderLeft = false; m_BorderTop = m_BorderRight = m_BorderBottom = m_BorderLeft = false;
m_XReal = 0;
// m_YReal = 0;
_QuadT.Uv0.set(0.f, 0.f); m_WReal = 0;
_QuadT.Uv1.set(0.f, 0.f); m_HReal = 0;
_QuadT.Uv2.set(1.f, 1.f);
_QuadT.Uv3.set(0.f, 1.f);
//
_QuadR.Uv0.set(0.f, 0.f);
_QuadR.Uv1.set(0.f, 0.f);
_QuadR.Uv2.set(1.f, 1.f);
_QuadR.Uv3.set(0.f, 1.f);
//
_QuadB.Uv0.set(0.f, 0.f);
_QuadB.Uv1.set(0.f, 0.f);
_QuadB.Uv2.set(1.f, 1.f);
_QuadB.Uv3.set(0.f, 1.f);
//
_QuadL.Uv0.set(0.f, 0.f);
_QuadL.Uv1.set(0.f, 0.f);
_QuadL.Uv2.set(1.f, 1.f);
_QuadL.Uv3.set(0.f, 1.f);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CSSBorderRenderer::setRenderLayer(sint layer) void CSSBorderRenderer::setRenderLayer(sint layer)
{ {
_RenderLayer = layer; m_RenderLayer = layer;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CSSBorderRenderer::setModulateGlobalColor(bool s) void CSSBorderRenderer::setModulateGlobalColor(bool s)
{ {
_ModulateGlobalColor = s; m_ModulateGlobalColor = s;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CSSBorderRenderer::setRect(sint32 x, sint32 y, sint32 w, sint32 h) void CSSBorderRenderer::setRect(sint32 x, sint32 y, sint32 w, sint32 h)
{ {
_XReal = x; m_XReal = x;
_YReal = y; m_YReal = y;
_WReal = w; m_WReal = w;
_HReal = h; m_HReal = h;
_Dirty = _Border = (w > 0 && h > 0); m_Dirty = m_Border = (w > 0 && h > 0);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -99,7 +80,7 @@ namespace NLGUI
BottomWidth = bottom; BottomWidth = bottom;
LeftWidth = left; LeftWidth = left;
_Dirty = _Border = (top > 0 || right > 0 || bottom > 0 || left > 0); m_Dirty = m_Border = (top > 0 || right > 0 || bottom > 0 || left > 0);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -110,7 +91,7 @@ namespace NLGUI
BottomStyle = bottom; BottomStyle = bottom;
LeftStyle = left; LeftStyle = left;
_Dirty = _Border = true; m_Dirty = m_Border = true;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -121,7 +102,7 @@ namespace NLGUI
BottomColor = bottom; BottomColor = bottom;
LeftColor = left; LeftColor = left;
_Dirty = true; m_Dirty = true;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -173,146 +154,232 @@ namespace NLGUI
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void CSSBorderRenderer::updateCoords() bool CSSBorderRenderer::hasInnerShape(CSSLineStyle style) const
{ {
_Dirty = false; return style == CSS_LINE_STYLE_DOUBLE ||
if (!_Border) return; style == CSS_LINE_STYLE_GROOVE ||
style == CSS_LINE_STYLE_RIDGE;
}
sint dTop = getTopWidth(); _BorderTop = dTop > 0; // ----------------------------------------------------------------------------
sint dRight = getRightWidth(); _BorderRight = dRight > 0; void CSSBorderRenderer::updateCoords()
sint dBottom = getBottomWidth(); _BorderBottom = dBottom > 0; {
sint dLeft = getLeftWidth(); _BorderLeft = dLeft > 0; m_Dirty = false;
m_DrawBorders.clear();
if (!m_Border) return;
sint dTop = getTopWidth(); m_BorderTop = dTop > 0;
sint dRight = getRightWidth(); m_BorderRight = dRight > 0;
sint dBottom = getBottomWidth(); m_BorderBottom = dBottom > 0;
sint dLeft = getLeftWidth(); m_BorderLeft = dLeft > 0;
m_Border = m_BorderTop || m_BorderRight || m_BorderBottom || m_BorderLeft;
if (!m_Border) return;
sint xTop = m_YReal + m_HReal;
sint xRight = m_XReal + m_WReal;
sint bLeft = m_XReal + dLeft;
sint bRight = xRight - dRight;
sint bTop = xTop - dTop;
sint bBottom = m_YReal + dBottom;
SDrawBorder shape;
shape.Quad.Uv0.set(0.f, 0.f);
shape.Quad.Uv1.set(1.f, 0.f);
shape.Quad.Uv2.set(1.f, 1.f);
shape.Quad.Uv3.set(0.f, 1.f);
// V3 - top-left
// V2 - top-right
// V1 - bottom-right
// V0 - bottom-left
if (m_BorderTop)
{
if (TopStyle == CSS_LINE_STYLE_INSET || TopStyle == CSS_LINE_STYLE_GROOVE)
shape.Color = blend(TopColor, CRGBA::Black, 0.5f);
else
shape.Color = TopColor;
shape.Quad.V3.x = m_XReal; shape.Quad.V3.y = xTop;
shape.Quad.V2.x = xRight; shape.Quad.V2.y = xTop;
shape.Quad.V1.x = bRight; shape.Quad.V1.y = bTop;
shape.Quad.V0.x = bLeft; shape.Quad.V0.y = bTop;
m_DrawBorders.push_back(shape);
if (hasInnerShape(TopStyle))
{
float iLeft, iTop, iRight;
if (TopStyle == CSS_LINE_STYLE_DOUBLE)
{
iLeft = 2*dLeft / 3.f;
iTop = 2*dBottom / 3.f;
iRight = 2*dRight / 3.f;
} else {
iLeft = dLeft / 2.f;
iTop = dTop / 2.f;
iRight = dRight / 2.f;
}
_Border = _BorderTop || _BorderRight || _BorderBottom || _BorderLeft; if (TopStyle == CSS_LINE_STYLE_RIDGE)
if (!_Border) return; shape.Color = blend(TopColor, CRGBA::Black, 0.5f);
else
shape.Color = TopColor;
// create inner border shape and remove overlapping from outer shape
m_DrawBorders.back().Quad.V0.x -= iLeft; m_DrawBorders.back().Quad.V0.y += iTop;
m_DrawBorders.back().Quad.V1.x += iRight; m_DrawBorders.back().Quad.V1.y += iTop;
shape.Quad.V3.x += iLeft; shape.Quad.V3.y -= iTop;
shape.Quad.V2.x -= iRight; shape.Quad.V2.y -= iTop;
m_DrawBorders.push_back(shape);
}
}
if (_BorderTop) if (m_BorderBottom)
{
if (BottomStyle == CSS_LINE_STYLE_OUTSET || BottomStyle == CSS_LINE_STYLE_RIDGE)
shape.Color = blend(BottomColor, CRGBA::Black, 0.5f);
else
shape.Color = BottomColor;
shape.Quad.V3.x = bLeft; shape.Quad.V3.y = bBottom;
shape.Quad.V2.x = bRight; shape.Quad.V2.y = bBottom;
shape.Quad.V1.x = xRight; shape.Quad.V1.y = m_YReal;
shape.Quad.V0.x = m_XReal; shape.Quad.V0.y = m_YReal;
m_DrawBorders.push_back(shape);
if (hasInnerShape(BottomStyle))
{ {
// top-left float iLeft, iBottom, iRight;
_QuadT.V3.x = _XReal; if (BottomStyle == CSS_LINE_STYLE_DOUBLE)
_QuadT.V3.y = _YReal + _HReal; {
// top-right iLeft = 2*dLeft / 3.f;
_QuadT.V2.x = _XReal + _WReal; iBottom = 2*dBottom / 3.f;
_QuadT.V2.y = _YReal + _HReal; iRight = 2*dRight / 3.f;
// bottom-right
_QuadT.V1.x = _XReal + _WReal - dRight;
_QuadT.V1.y = _YReal + _HReal - dTop;
// bottom-left
_QuadT.V0.x = _XReal + dLeft;
_QuadT.V0.y = _YReal + _HReal - dTop;
} }
else
if (_BorderRight)
{ {
// top-left iLeft = dLeft / 2.f;
_QuadR.V3.x = _XReal + _WReal - dRight; iBottom = dBottom / 2.f;
_QuadR.V3.y = _YReal + _HReal - dTop; iRight = dRight / 2.f;
// top-right
_QuadR.V2.x = _XReal + _WReal;
_QuadR.V2.y = _YReal + _HReal;
// bottom-right
_QuadR.V1.x = _XReal + _WReal;
_QuadR.V1.y = _YReal;
// bottom-left
_QuadR.V0.x = _XReal + _WReal - dRight;
_QuadR.V0.y = _YReal + dBottom;
} }
if (_BorderBottom) if (BottomStyle == CSS_LINE_STYLE_GROOVE)
{ shape.Color = blend(shape.Color, CRGBA::Black, 0.5f);
// top-left else
_QuadB.V3.x = _XReal + dLeft; shape.Color = BottomColor;
_QuadB.V3.y = _YReal + dBottom;
// top-right m_DrawBorders.back().Quad.V2.x += iRight; m_DrawBorders.back().Quad.V2.y -= iBottom;
_QuadB.V2.x = _XReal + _WReal - dRight; m_DrawBorders.back().Quad.V3.x -= iLeft; m_DrawBorders.back().Quad.V3.y -= iBottom;
_QuadB.V2.y = _YReal + dBottom; shape.Quad.V1.x -= iRight; shape.Quad.V1.y += iBottom;
// bottom-right shape.Quad.V0.x += iLeft; shape.Quad.V0.y += iBottom;
_QuadB.V1.x = _XReal + _WReal; m_DrawBorders.push_back(shape);
_QuadB.V1.y = _YReal; }
// bottom-left
_QuadB.V0.x = _XReal;
_QuadB.V0.y = _YReal;
} }
if (_BorderLeft) if (m_BorderRight)
{
if (RightStyle == CSS_LINE_STYLE_OUTSET || RightStyle == CSS_LINE_STYLE_RIDGE)
shape.Color = blend(RightColor, CRGBA::Black, 0.5f);
else
shape.Color = RightColor;
shape.Quad.V3.x = bRight; shape.Quad.V3.y = bTop;
shape.Quad.V2.x = xRight; shape.Quad.V2.y = xTop;
shape.Quad.V1.x = xRight; shape.Quad.V1.y = m_YReal;
shape.Quad.V0.x = bRight; shape.Quad.V0.y = bBottom;
m_DrawBorders.push_back(shape);
if (hasInnerShape(RightStyle))
{ {
// top-left float iTop, iRight, iBottom;
_QuadL.V3.x = _XReal; if (RightStyle == CSS_LINE_STYLE_DOUBLE)
_QuadL.V3.y = _YReal + _HReal; {
// top-right iTop = 2*dTop / 3.f;
_QuadL.V2.x = _XReal + dLeft; iRight = 2*dRight / 3.f;
_QuadL.V2.y = _YReal + _HReal - dTop; iBottom = 2*dBottom / 3.f;
// bottom-right } else {
_QuadL.V1.x = _XReal + dLeft; iTop = dTop / 2.f;
_QuadL.V1.y = _YReal + dBottom; iRight = dRight / 2.f;
// bottom-left iBottom = dBottom / 2.f;
_QuadL.V0.x = _XReal; }
_QuadL.V0.y = _YReal;
if (RightStyle == CSS_LINE_STYLE_GROOVE)
shape.Color = blend(shape.Color, CRGBA::Black, 0.5f);
else
shape.Color = RightColor;
m_DrawBorders.back().Quad.V3.x += iRight; m_DrawBorders.back().Quad.V3.y += iTop;
m_DrawBorders.back().Quad.V0.x += iRight; m_DrawBorders.back().Quad.V0.y -= iBottom;
shape.Quad.V2.x -= iRight; shape.Quad.V2.y -= iTop;
shape.Quad.V1.x -= iRight; shape.Quad.V1.y += iBottom;
m_DrawBorders.push_back(shape);
} }
} }
// ---------------------------------------------------------------------------- if (m_BorderLeft)
void CSSBorderRenderer::draw() { {
if (_Dirty) updateCoords(); if (LeftStyle == CSS_LINE_STYLE_INSET || LeftStyle == CSS_LINE_STYLE_GROOVE)
if (!_Border) return; shape.Color = blend(LeftColor, CRGBA::Black, 0.5f);
else
shape.Color = LeftColor;
CViewRenderer &rVR = *CViewRenderer::getInstance(); shape.Quad.V3.x = m_XReal; shape.Quad.V3.y = xTop;
shape.Quad.V2.x = bLeft; shape.Quad.V2.y = bTop;
shape.Quad.V1.x = bLeft; shape.Quad.V1.y = bBottom;
shape.Quad.V0.x = m_XReal; shape.Quad.V0.y = m_YReal;
// TODO: no need for widget manager, if global color is set from parent m_DrawBorders.push_back(shape);
CRGBA globalColor;
if (_ModulateGlobalColor)
globalColor = CWidgetManager::getInstance()->getGlobalColor();
// TODO: monitor ModulateGlobalColor and CurrentAlpha in table checkCoords and recalculate colors on change only if (hasInnerShape(LeftStyle))
// OUTSET - bottom/right darker than normal (default table style)
// INSET - top/left darker than normal
if (_BorderTop)
{ {
CRGBA borderColorT = TopColor; if (LeftStyle == CSS_LINE_STYLE_RIDGE)
if (TopStyle == CSS_LINE_STYLE_INSET) shape.Color = blend(LeftColor, CRGBA::Black, 0.5f);
borderColorT = blend(borderColorT, CRGBA::Black, 0.5f); else
shape.Color = LeftColor;
if (_ModulateGlobalColor) float iTop, iLeft, iBottom;
borderColorT.modulateFromColor (borderColorT, globalColor); if (LeftStyle == CSS_LINE_STYLE_DOUBLE)
{
iTop = 2*dTop / 3.f;
iLeft = 2*dLeft / 3.f;
iBottom = 2*dBottom / 3.f;
} else {
iTop = dTop / 2.f;
iLeft = dLeft / 2.f;
dBottom = dBottom / 2.f;
}
borderColorT.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorT.A) >> 8); m_DrawBorders.back().Quad.V2.x -= iLeft; m_DrawBorders.back().Quad.V2.y += iTop;
rVR.drawQuad(_RenderLayer, _QuadT, rVR.getBlankTextureId(), borderColorT, false); m_DrawBorders.back().Quad.V1.x -= iLeft; m_DrawBorders.back().Quad.V1.y -= iBottom;
shape.Quad.V3.x += iLeft; shape.Quad.V3.y -= iTop;
shape.Quad.V0.x += iLeft; shape.Quad.V0.y += iBottom;
m_DrawBorders.push_back(shape);
}
}
} }
if (_BorderRight)
{
CRGBA borderColorR = RightColor;
if (RightStyle == CSS_LINE_STYLE_OUTSET)
borderColorR = blend(borderColorR, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor) // ----------------------------------------------------------------------------
borderColorR.modulateFromColor (borderColorR, globalColor); void CSSBorderRenderer::draw() {
if (m_Dirty) updateCoords();
if (!m_Border) return;
borderColorR.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorR.A) >> 8); CViewRenderer &rVR = *CViewRenderer::getInstance();
rVR.drawQuad(_RenderLayer, _QuadR, rVR.getBlankTextureId(), borderColorR, false);
}
if (_BorderBottom)
{
CRGBA borderColorB = BottomColor;
if (BottomStyle == CSS_LINE_STYLE_OUTSET)
borderColorB = blend(borderColorB, CRGBA::Black, 0.5f);
if (_ModulateGlobalColor) // TODO: no need for widget manager, if global color is set from parent
borderColorB.modulateFromColor (borderColorB, globalColor); CRGBA globalColor;
if (m_ModulateGlobalColor)
globalColor = CWidgetManager::getInstance()->getGlobalColor();
borderColorB.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorB.A) >> 8); sint32 texId = rVR.getBlankTextureId();
rVR.drawQuad(_RenderLayer, _QuadB, rVR.getBlankTextureId(), borderColorB, false); for(uint i = 0; i < m_DrawBorders.size(); ++i)
}
if (_BorderLeft)
{ {
CRGBA borderColorL = LeftColor; CRGBA color = m_DrawBorders[i].Color;
if (LeftStyle == CSS_LINE_STYLE_INSET) if (m_ModulateGlobalColor)
borderColorL = blend(borderColorL, CRGBA::Black, 0.5f); color.modulateFromColor (color, globalColor);
if (_ModulateGlobalColor)
borderColorL.modulateFromColor (borderColorL, globalColor);
borderColorL.A = (uint8) (((uint16) CurrentAlpha * (uint16) borderColorL.A) >> 8); color.A = (uint8) (((uint16) CurrentAlpha * (uint16) color.A) >> 8);
rVR.drawQuad(_RenderLayer, _QuadL, rVR.getBlankTextureId(), borderColorL, false); rVR.drawQuad(m_RenderLayer, m_DrawBorders[i].Quad, texId, color, false);
} }
} }

@ -571,12 +571,22 @@ namespace NLGUI
*dest = CSS_LINE_STYLE_NONE; *dest = CSS_LINE_STYLE_NONE;
else if (value == "hidden") else if (value == "hidden")
*dest = CSS_LINE_STYLE_HIDDEN; *dest = CSS_LINE_STYLE_HIDDEN;
else if (value == "dotted")
*dest = CSS_LINE_STYLE_DOTTED;
else if (value == "dashed")
*dest = CSS_LINE_STYLE_DASHED;
else if (value == "solid")
*dest = CSS_LINE_STYLE_SOLID;
else if (value == "double")
*dest = CSS_LINE_STYLE_DOUBLE;
else if (value == "groove")
*dest = CSS_LINE_STYLE_GROOVE;
else if (value == "ridge")
*dest = CSS_LINE_STYLE_RIDGE;
else if (value == "inset") else if (value == "inset")
*dest = CSS_LINE_STYLE_INSET; *dest = CSS_LINE_STYLE_INSET;
else if (value == "outset") else if (value == "outset")
*dest = CSS_LINE_STYLE_OUTSET; *dest = CSS_LINE_STYLE_OUTSET;
else if (value == "solid")
*dest = CSS_LINE_STYLE_SOLID;
} }
void CCssStyle::applyPaddingWidth(const std::string &value, uint32 *dest, const uint32 currentPadding, uint32 fontSize) const void CCssStyle::applyPaddingWidth(const std::string &value, uint32 *dest, const uint32 currentPadding, uint32 fontSize) const

Loading…
Cancel
Save