Draw double/groove/ridge border styles

develop
Nimetu 3 years ago
parent 487f9f060e
commit 65edd9f95d

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

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

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

@ -571,12 +571,22 @@ namespace NLGUI
*dest = CSS_LINE_STYLE_NONE;
else if (value == "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")
*dest = CSS_LINE_STYLE_INSET;
else if (value == "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

Loading…
Cancel
Save