diff --git a/code/nel/include/nel/3d/text_context.h b/code/nel/include/nel/3d/text_context.h index 156ea9f79..a95916da4 100644 --- a/code/nel/include/nel/3d/text_context.h +++ b/code/nel/include/nel/3d/text_context.h @@ -88,7 +88,7 @@ public: void setShadeOutline (bool b) { _ShadeOutline = b; } - void setShadeExtent (float shext) { _ShadeExtent = shext; } + void setShadeExtent (float x, float y) { _ShadeExtentX = x; _ShadeExtentY = y; } /// The alpha of the shade is multiplied at each draw with the alpha of the color. Default: (0,0,0,255) void setShadeColor (NLMISC::CRGBA color) { _ShadeColor = color; } @@ -157,19 +157,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2D(*_Driver, x+rext, z-rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-rext, z-rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-rext, z+rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x+rext, z+rext, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x+_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x-_ShadeExtent, z, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); - rCS.render2D(*_Driver, x, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2D(*_Driver, x+rextX, z-rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-rextX, z-rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-rextX, z+rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+rextX, z+rextY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+_ShadeExtentX, z, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x-_ShadeExtentX, z, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } else { - rCS.render2D(*_Driver, x+_ShadeExtent, z-_ShadeExtent, _HotSpot, _ScaleX, _ScaleZ); + rCS.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } rCS.Color= bkup; } @@ -190,19 +191,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z-rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z-rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-rext, z+rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x+rext, z+rext, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtent, z, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x, z+_ShadeExtent, xmin, ymin, xmax, ymax); - rCS.render2DClip(*_Driver, rdrBuffer, x, z-_ShadeExtent, xmin, ymin, xmax, ymax); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2DClip(*_Driver, rdrBuffer, x+rextX, z-rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-rextX, z-rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-rextX, z+rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+rextX, z+rextY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtentX, z, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x-_ShadeExtentX, z, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x, z+_ShadeExtentY, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x, z-_ShadeExtentY, xmin, ymin, xmax, ymax); } else { - rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtent, z-_ShadeExtent, xmin, ymin, xmax, ymax); + rCS.render2DClip(*_Driver, rdrBuffer, x+_ShadeExtentX, z-_ShadeExtentY, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -223,19 +225,20 @@ public: rCS.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y-rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y-rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rext, y+rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rext, y+rext, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtent, y, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y+_ShadeExtent, depth, xmin, ymin, xmax, ymax); - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rextX, y-rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rextX, y-rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-rextX, y+rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+rextX, y+rextY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtentX, y, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x-_ShadeExtentX, y, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y+_ShadeExtentY, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x, y-_ShadeExtentY, depth, xmin, ymin, xmax, ymax); } else { - rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtent, y-_ShadeExtent, depth, xmin, ymin, xmax, ymax); + rCS.render2DUnProjected (*_Driver, renderBuffer, frustum, scaleMatrix, x+_ShadeExtentX, y-_ShadeExtentY, depth, xmin, ymin, xmax, ymax); } rCS.Color= bkup; } @@ -258,19 +261,20 @@ public: _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - _TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + _TempString.render2D(*_Driver,x+rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z+_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z-_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); } else { - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } _TempString.Color = bkup; } @@ -297,19 +301,20 @@ public: _TempString.Color.A = (uint8)((uint(bkup.A) * uint(_ShadeColor.A)+1)>>8); if (_ShadeOutline) { - float rext = _ShadeExtent * 0.7071f; - _TempString.render2D(*_Driver,x+rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z-rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+rext,z+rext,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x+_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x-_ShadeExtent,z,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z+_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); - _TempString.render2D(*_Driver,x,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + float rextX = _ShadeExtentX * 0.7071f; + float rextY = _ShadeExtentY * 0.7071f; + _TempString.render2D(*_Driver,x+rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z-rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+rextX,z+rextY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x+_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x-_ShadeExtentX,z,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z+_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver,x,z-_ShadeExtentY,_HotSpot,_ScaleX,_ScaleZ); } else { - _TempString.render2D(*_Driver,x+_ShadeExtent,z-_ShadeExtent,_HotSpot,_ScaleX,_ScaleZ); + _TempString.render2D(*_Driver, x+_ShadeExtentX, z-_ShadeExtentY, _HotSpot, _ScaleX, _ScaleZ); } _TempString.Color = bkup; } @@ -412,7 +417,8 @@ private: bool _ShadeOutline; /// shade's extent (shadow size) - float _ShadeExtent; + float _ShadeExtentX; + float _ShadeExtentY; /// Shade color (default is black) NLMISC::CRGBA _ShadeColor; diff --git a/code/nel/include/nel/3d/text_context_user.h b/code/nel/include/nel/3d/text_context_user.h index b05238dbf..15e93c3f2 100644 --- a/code/nel/include/nel/3d/text_context_user.h +++ b/code/nel/include/nel/3d/text_context_user.h @@ -80,7 +80,7 @@ public: bool getShaded() const; void setShadeOutline(bool b); bool getShadeOutline() const; - void setShadeExtent(float shext) ; + void setShadeExtent(float x, float y); void setShadeColor (NLMISC::CRGBA sc); NLMISC::CRGBA getShadeColor () const; void setKeep800x600Ratio(bool keep); diff --git a/code/nel/include/nel/3d/u_text_context.h b/code/nel/include/nel/3d/u_text_context.h index 0aa9ea2f9..4c1dfea47 100644 --- a/code/nel/include/nel/3d/u_text_context.h +++ b/code/nel/include/nel/3d/u_text_context.h @@ -205,7 +205,7 @@ public: * set the shadow's size * \param the shade extent */ - virtual void setShadeExtent (float shext) = 0; + virtual void setShadeExtent (float x, float y) = 0; /** * set the shadow's color * The alpha of the shade is multiplied at each draw with the alpha of the color. Default: (0,0,0,255) diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index 0ccd227b7..811cd3503 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -75,11 +75,26 @@ namespace NLGUI }; static SWebOptions options; - + + // text-shadow + struct STextShadow + { + public: + STextShadow(bool enabled = false, bool outline = false, sint32 x=1, sint32 y=1, NLMISC::CRGBA color=NLMISC::CRGBA::Black) + : Enabled(enabled), Outline(outline), X(x), Y(y), Color(color) + { } + + bool Enabled; + bool Outline; + sint32 X; + sint32 Y; + NLMISC::CRGBA Color; + }; + class CStyleParams { public: - CStyleParams () : FontFamily(""), TextColor(255,255,255,255) + CStyleParams () : FontFamily(""), TextColor(255,255,255,255), TextShadow() { FontSize=10; FontWeight=400; @@ -97,6 +112,7 @@ namespace NLGUI bool FontOblique; std::string FontFamily; NLMISC::CRGBA TextColor; + STextShadow TextShadow; bool GlobalColor; bool Underlined; bool StrikeThrough; @@ -595,6 +611,14 @@ namespace NLGUI return _TR.back(); } + std::vector _TextShadow; + inline STextShadow getTextShadow() const + { + if (_TextShadow.empty()) + return STextShadow(); + return _TextShadow.back(); + } + // Forms class CForm { diff --git a/code/nel/include/nel/gui/view_text.h b/code/nel/include/nel/gui/view_text.h index 8b8e1a7cf..cf53b5207 100644 --- a/code/nel/include/nel/gui/view_text.h +++ b/code/nel/include/nel/gui/view_text.h @@ -88,6 +88,7 @@ namespace NLGUI void setShadow (bool bShadow); void setShadowOutline (bool bShadowOutline); void setShadowColor (const NLMISC::CRGBA &color); + void setShadowOffset (sint x, sint y); void setLineMaxW (sint nMaxW, bool invalidate=true); void setMultiLine (bool bMultiLine); void setMultiLineSpace (sint nMultiLineSpace); @@ -112,6 +113,7 @@ namespace NLGUI bool getShadow() { return _Shadow; } bool getShadowOutline() { return _ShadowOutline; } NLMISC::CRGBA getShadowColor() { return _ShadowColor; } + void getShadowOffset(sint &x, sint &y) { x = _ShadowX; y = _ShadowY; } sint getLineMaxW() const { return _LineMaxW; } bool getMultiLine() const { return _MultiLine; } sint getMultiLineSpace() const { return _MultiLineSpace; } @@ -247,6 +249,8 @@ namespace NLGUI /// the shadow mode bool _Shadow; bool _ShadowOutline; + sint32 _ShadowX; + sint32 _ShadowY; /// the case mode TCaseMode _CaseMode; /// the text shadow color diff --git a/code/nel/src/3d/text_context.cpp b/code/nel/src/3d/text_context.cpp index 8cee144ca..5fcc43daa 100644 --- a/code/nel/src/3d/text_context.cpp +++ b/code/nel/src/3d/text_context.cpp @@ -47,7 +47,8 @@ CTextContext::CTextContext() _Shaded = false; _ShadeOutline = false; - _ShadeExtent = 0.001f; + _ShadeExtentX = 0.001f; + _ShadeExtentY = 0.001f; _ShadeColor = NLMISC::CRGBA(0,0,0); _Keep800x600Ratio= true; diff --git a/code/nel/src/3d/text_context_user.cpp b/code/nel/src/3d/text_context_user.cpp index 1834a93ce..ae2cc2417 100644 --- a/code/nel/src/3d/text_context_user.cpp +++ b/code/nel/src/3d/text_context_user.cpp @@ -187,11 +187,11 @@ bool CTextContextUser::getShadeOutline() const return _TextContext.getShadeOutline(); } -void CTextContextUser::setShadeExtent(float shext) +void CTextContextUser::setShadeExtent(float x, float y) { H_AUTO2; - _TextContext.setShadeExtent(shext); + _TextContext.setShadeExtent(x, y); } void CTextContextUser::setShadeColor (NLMISC::CRGBA sc) { diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 970178947..e8a2ac889 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -1057,6 +1057,29 @@ namespace NLGUI _CellParams.push_back (cellParams); \ } + static bool scanCssLength(const std::string& str, uint32 &px) + { + if (fromString(str, px)) + return true; + + if (str == "thin") + { + px = 1; + return true; + } + if (str == "medium") + { + px = 3; + return true; + } + if (str == "thick") + { + px = 5; + return true; + } + + return false; + } static bool isHexa(char c) { @@ -2378,6 +2401,7 @@ namespace NLGUI _Style.FontWeight = FONT_WEIGHT_NORMAL; _Style.FontOblique = false; _Style.FontSize = TextFontSize; + _Style.TextShadow = STextShadow(true); if (present[MY_HTML_TEXTAREA_STYLE] && value[MY_HTML_TEXTAREA_STYLE]) getStyleParams(value[MY_HTML_TEXTAREA_STYLE], _Style); @@ -4351,8 +4375,17 @@ namespace NLGUI if (_CurrentViewLink) { bool skipLine = !_CurrentViewLink->getText().empty() && *(_CurrentViewLink->getText().rbegin()) == (ucchar) '\n'; + bool sameShadow = _Style.TextShadow.Enabled && _CurrentViewLink->getShadow(); + if (sameShadow && _Style.TextShadow.Enabled) + { + sint sx, sy; + _CurrentViewLink->getShadowOffset(sx, sy); + sameShadow = (_Style.TextShadow.Color == _CurrentViewLink->getShadowColor()); + sameShadow = sameShadow && (_Style.TextShadow.Outline == _CurrentViewLink->getShadowOutline()); + sameShadow = sameShadow && (_Style.TextShadow.X == sx) && (_Style.TextShadow.Y == sy); + } // Compatible with current parameters ? - if (!skipLine && + if (!skipLine && sameShadow && (_Style.TextColor == _CurrentViewLink->getColor()) && (_Style.FontFamily == _CurrentViewLink->getFontName()) && (_Style.FontSize == (uint)_CurrentViewLink->getFontSize()) && @@ -4431,6 +4464,13 @@ namespace NLGUI newLink->setMultiLineSpace((uint)((float)(_Style.FontSize)*LineSpaceFontFactor)); newLink->setMultiLine(true); newLink->setModulateGlobalColor(_Style.GlobalColor); + if (_Style.TextShadow.Enabled) + { + newLink->setShadow(true); + newLink->setShadowColor(_Style.TextShadow.Color); + newLink->setShadowOutline(_Style.TextShadow.Outline); + newLink->setShadowOffset(_Style.TextShadow.X, _Style.TextShadow.Y); + } // newLink->setLineAtBottom (true); registerAnchor(newLink); @@ -4553,6 +4593,14 @@ namespace NLGUI templateParams.push_back (std::pair ("enter_recover_focus", "false")); if (maxlength > 0) templateParams.push_back (std::pair ("max_num_chars", toString(maxlength))); + templateParams.push_back (std::pair ("shadow", toString(_Style.TextShadow.Enabled))); + if (_Style.TextShadow.Enabled) + { + templateParams.push_back (std::pair ("shadow_x", toString(_Style.TextShadow.X))); + templateParams.push_back (std::pair ("shadow_y", toString(_Style.TextShadow.Y))); + templateParams.push_back (std::pair ("shadow_color", _Style.TextShadow.Color.toString())); + templateParams.push_back (std::pair ("shadow_outline", toString(_Style.TextShadow.Outline))); + } CInterfaceGroup *textArea = CWidgetManager::getInstance()->getParser()->createGroupInstance (templateName.c_str(), getParagraph()->getId(), templateParams.empty()?NULL:&(templateParams[0]), (uint)templateParams.size()); @@ -6229,6 +6277,115 @@ namespace NLGUI style.StrikeThrough = (prop.find("line-through") != std::string::npos); } else + if (it->first == "text-stroke" || it->first == "-webkit-text-stroke") + { + // text-stroke: length || color + bool success = false; + uint px = 0; + CRGBA color; + std::vector parts; + NLMISC::splitString(it->second, " ", parts); + if (parts.size() == 1) + { + success = scanCssLength(parts[0], px); + if (!success) + success = scanHTMLColor(parts[0].c_str(), color); + } + else if (parts.size() == 2) + { + success = scanCssLength(parts[0], px); + if (success) + success = scanHTMLColor(parts[1].c_str(), color); + else + { + success = scanHTMLColor(parts[0].c_str(), color); + success = success && scanCssLength(parts[1], px); + } + } + + // do not disable shadow if one is already set + if (success) + { + style.TextShadow.Enabled = (px > 0); + style.TextShadow.Color = color; + style.TextShadow.X = px; + style.TextShadow.Y = px; + style.TextShadow.Outline = true; + } + } + else + if (it->first == "text-shadow") + { + if (it->second == "none") + style.TextShadow = STextShadow(false); + else + if (it->second == "inherit") + style.TextShadow = current.TextShadow; + else + { + // text-shadow: offset-x offset-y | blur | #color + // text-shadow: #color | offset-x offset-y + bool success = true; + std::string prop(it->second); + size_t pos; + pos = prop.find_first_of(",\n\r"); + if (pos != std::string::npos) + prop = prop.substr(0, pos); + + std::vector parts; + NLMISC::splitString(prop, " ", parts); + switch(parts.size()) + { + case 1: + { + success = scanHTMLColor(it->second.c_str(), style.TextShadow.Color); + break; + } + // no case 2: + case 3: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + } + else + { + success = fromString(parts[1], style.TextShadow.Y); + success = success && scanHTMLColor(parts[2].c_str(), style.TextShadow.Color); + } + break; + } + case 4: + { + if (!fromString(parts[0], style.TextShadow.X)) + { + success = scanHTMLColor(parts[0].c_str(), style.TextShadow.Color); + success = success && fromString(parts[1], style.TextShadow.X); + success = success && fromString(parts[2], style.TextShadow.Y); + // ignore blur [3] + } + else + { + success = fromString(parts[0], style.TextShadow.X); + success = success && fromString(parts[1], style.TextShadow.Y); + // ignore blur [2] + success = success && scanHTMLColor(parts[3].c_str(), style.TextShadow.Color); + } + break; + } + default: + { + // unsupported rule + break; + } + } + + style.TextShadow.Enabled = success; + } + } + else if (it->first == "width") getPercentage(style.Width, tmpf, it->second.c_str()); else diff --git a/code/nel/src/gui/view_text.cpp b/code/nel/src/gui/view_text.cpp index c14a7f9a1..bd10afbb9 100644 --- a/code/nel/src/gui/view_text.cpp +++ b/code/nel/src/gui/view_text.cpp @@ -72,6 +72,8 @@ namespace NLGUI _Shadow = false; _ShadowOutline = false; _ShadowColor = CRGBA(0,0,0,255); + _ShadowX = 1; + _ShadowY = 1; _MultiLine = false; _TextMode = DontClipWord; @@ -955,6 +957,19 @@ namespace NLGUI ((_YReal) > (ClipY+ClipH)) || ((_YReal+_HReal) < ClipY)) return; + // hack: allow shadow to overflow outside parent box. + // In CGroupHTML context, clip is set for row + if (std::abs(_ShadowX) > 0) + { + ClipX -= 3; + ClipW += 3; + } + if (std::abs(_ShadowY) > 0) + { + ClipY -= 3; + ClipH += 3; + } + // *** Screen Minimized? uint32 w, h; float oow, ooh; @@ -992,6 +1007,7 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); + TextContext->setShadeExtent (_ShadowX*oow, _ShadowY*ooh); TextContext->setFontSize (_FontSize); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -1119,6 +1135,7 @@ namespace NLGUI TextContext->setShaded (_Shadow); TextContext->setShadeOutline (_ShadowOutline); TextContext->setShadeColor (shcol); + TextContext->setShadeExtent (_ShadowX*oow, _ShadowY*ooh); TextContext->setFontSize (_FontSize); TextContext->setEmbolden (_Embolden); TextContext->setOblique (_Oblique); @@ -1339,6 +1356,13 @@ namespace NLGUI _ShadowColor = color; } + // *************************************************************************** + void CViewText::setShadowOffset(sint32 x, sint32 y) + { + _ShadowX = x; + _ShadowY = y; + } + // *************************************************************************** void CViewText::setLineMaxW (sint nMaxW, bool invalidate) {