////////////////////////////////////////////////////////////////////////////// // Name: CSSStyleDeclaration.cpp // Purpose: // Author: Alex Thuering // Created: 2005/05/03 // RCS-ID: $Id: CSSStyleDeclaration.cpp,v 1.9 2006/07/20 07:34:47 ntalex Exp $ // Copyright: (c) 2005 Alex Thuering // Licence: wxWindows licence ////////////////////////////////////////////////////////////////////////////// #include "CSSStyleDeclaration.h" #include #include wxCSSPrimitiveValue* wxCSSStyleDeclaration::s_emptyCSSValue = new wxCSSPrimitiveValue; wxSVGColor* wxCSSStyleDeclaration::s_emptySVGColor = new wxSVGColor; wxSVGPaint* wxCSSStyleDeclaration::s_emptySVGPaint = new wxSVGPaint; wxSVGPaint* wxCSSStyleDeclaration::s_blackSVGPaint = new wxSVGPaint(0,0,0); wxCSSStyleDeclaration::~wxCSSStyleDeclaration() { iterator it; for (it = begin(); it != end(); ++it) delete it->second; } void wxCSSStyleDeclaration::Add(const wxCSSStyleDeclaration& style) { const_iterator it; for (it = style.begin(); it != style.end(); ++it) (*this)[it->first] = it->second->Clone(); } wxString wxCSSStyleDeclaration::GetCSSText() const { wxString text; const_iterator it; for (it = begin(); it != end(); ++it) text = text + GetPropertyName(it->first) + wxT(":") + it->second->GetCSSText() + wxT(";"); return text; } void wxCSSStyleDeclaration::SetCSSText(const wxString& text) { wxStringTokenizer tkz(text, wxT(";")); while (tkz.HasMoreTokens()) { wxString token = tkz.GetNextToken().Strip(wxString::both); int pos = token.find(wxT(':')); if (pos<=0) continue; SetProperty(token.substr(0,pos), token.substr(pos+1)); } } static wxSortedArrayString* s_cssProperties = NULL; #include "css_properties.cpp" inline void FillCSSProperties() { if (s_cssProperties == NULL) { s_cssProperties = new wxSortedArrayString; for (unsigned int i=0; iAdd(s_cssPropertyStrings[i]); } } wxCSS_PROPERTY wxCSSStyleDeclaration::GetPropertyId(const wxString& propertyName) { FillCSSProperties(); int id = s_cssProperties->Index(propertyName); if (id >= 0) return wxCSS_PROPERTY(id+1); return wxCSS_PROPERTY_UNKNOWN; } wxString wxCSSStyleDeclaration::GetPropertyName(wxCSS_PROPERTY propertyId) { FillCSSProperties(); if (propertyId == wxCSS_PROPERTY_UNKNOWN) return wxT(""); return (*s_cssProperties)[int(propertyId)-1]; } void wxCSSStyleDeclaration::SetProperty(wxCSS_PROPERTY propertyId, const wxString& svalue) { if (propertyId == wxCSS_PROPERTY_UNKNOWN) return; wxString value = svalue.Strip(wxString::both); wxCSSValue* cssValue = NULL; iterator it = find(propertyId); if (it != end()) cssValue = it->second; if (value == wxT("inherit")) { if (cssValue != NULL) erase(propertyId); return; } switch (propertyId) { case wxCSS_PROPERTY_UNKNOWN: break; // only idents case wxCSS_PROPERTY_ALIGNMENT_BASELINE: case wxCSS_PROPERTY_BASELINE_SHIFT: case wxCSS_PROPERTY_CLIP_RULE: case wxCSS_PROPERTY_COLOR_INTERPOLATION: case wxCSS_PROPERTY_COLOR_INTERPOLATION_FILTERS: case wxCSS_PROPERTY_COLOR_RENDERING: case wxCSS_PROPERTY_DIRECTION: case wxCSS_PROPERTY_DISPLAY: case wxCSS_PROPERTY_DOMINANT_BASELINE: case wxCSS_PROPERTY_ENABLE_BACKGROUND: case wxCSS_PROPERTY_FILL_RULE: case wxCSS_PROPERTY_FONT_STRETCH: case wxCSS_PROPERTY_FONT_STYLE: case wxCSS_PROPERTY_FONT_VARIANT: case wxCSS_PROPERTY_FONT_WEIGHT: case wxCSS_PROPERTY_IMAGE_RENDERING: case wxCSS_PROPERTY_OVERFLOW: case wxCSS_PROPERTY_POINTER_EVENTS: case wxCSS_PROPERTY_SHAPE_RENDERING: case wxCSS_PROPERTY_STROKE_LINECAP: case wxCSS_PROPERTY_STROKE_LINEJOIN: case wxCSS_PROPERTY_TEXT_ANCHOR: case wxCSS_PROPERTY_TEXT_DECORATION: case wxCSS_PROPERTY_TEXT_RENDERING: case wxCSS_PROPERTY_UNICODE_BIDI: case wxCSS_PROPERTY_VISIBILITY: case wxCSS_PROPERTY_WRITING_MODE: if (!cssValue) cssValue = new wxCSSPrimitiveValue; ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSSValue::GetValueId(value)); break; case wxCSS_PROPERTY_CLIP: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value == wxT("none")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_NONE); else ((wxCSSPrimitiveValue*)cssValue)->SetStringValue(wxCSS_STRING, value); break; // url or ident case wxCSS_PROPERTY_CLIP_PATH: case wxCSS_PROPERTY_CURSOR: case wxCSS_PROPERTY_FILTER: case wxCSS_PROPERTY_MARKER_END: case wxCSS_PROPERTY_MARKER_MID: case wxCSS_PROPERTY_MARKER_START: case wxCSS_PROPERTY_MASK: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value.Left(3) == wxT("url")) ((wxCSSPrimitiveValue*)cssValue)->SetStringValue(wxCSS_URI, value.AfterFirst(wxT('(')).BeforeFirst(wxT(')'))); else ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSSValue::GetValueId(value)); break; case wxCSS_PROPERTY_COLOR: if (!cssValue) cssValue = new wxCSSPrimitiveValue; ((wxCSSPrimitiveValue*)cssValue)->SetRGBColorValue(ParseColor(value)); break; case wxCSS_PROPERTY_COLOR_PROFILE: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value == wxT("auto")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_AUTO); else if (value == wxT("sRGB")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_SRGB); else if (value.Left(3) == wxT("url")) ((wxCSSPrimitiveValue*)cssValue)->SetStringValue(wxCSS_URI, value.AfterFirst(wxT('(')).BeforeFirst(wxT(')'))); else ((wxCSSPrimitiveValue*)cssValue)->SetStringValue(wxCSS_STRING, value); break; // number case wxCSS_PROPERTY_FILL_OPACITY: case wxCSS_PROPERTY_FLOOD_OPACITY: case wxCSS_PROPERTY_FONT_SIZE: case wxCSS_PROPERTY_GLYPH_ORIENTATION_HORIZONTAL: case wxCSS_PROPERTY_STROKE_DASHOFFSET: case wxCSS_PROPERTY_STROKE_MITERLIMIT: case wxCSS_PROPERTY_STROKE_OPACITY: case wxCSS_PROPERTY_STROKE_WIDTH: case wxCSS_PROPERTY_OPACITY: case wxCSS_PROPERTY_STOP_OPACITY: if (!cssValue) cssValue = new wxCSSPrimitiveValue; ((wxCSSPrimitiveValue*)cssValue)->SetFloatValue(wxCSS_NUMBER, ParseNumber(value)); break; // 'none' or number case wxCSS_PROPERTY_FONT_SIZE_ADJUST: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value == wxT("none")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_NONE); else ((wxCSSPrimitiveValue*)cssValue)->SetFloatValue(wxCSS_NUMBER, ParseNumber(value)); break; // 'auto' or number case wxCSS_PROPERTY_GLYPH_ORIENTATION_VERTICAL: case wxCSS_PROPERTY_KERNING: case wxCSS_PROPERTY_LETTER_SPACING: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value == wxT("auto")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_AUTO); else ((wxCSSPrimitiveValue*)cssValue)->SetFloatValue(wxCSS_NUMBER, ParseNumber(value)); break; // 'normal' or number case wxCSS_PROPERTY_WORD_SPACING: if (!cssValue) cssValue = new wxCSSPrimitiveValue; if (value == wxT("normal")) ((wxCSSPrimitiveValue*)cssValue)->SetIdentValue(wxCSS_VALUE_AUTO); else ((wxCSSPrimitiveValue*)cssValue)->SetFloatValue(wxCSS_NUMBER, ParseNumber(value)); break; // string case wxCSS_PROPERTY_FONT_FAMILY: case wxCSS_PROPERTY_STROKE_DASHARRAY: if (!cssValue) cssValue = new wxCSSPrimitiveValue; ((wxCSSPrimitiveValue*)cssValue)->SetStringValue(wxCSS_STRING, value); break; // case wxCSS_PROPERTY_FLOOD_COLOR: case wxCSS_PROPERTY_LIGHTING_COLOR: case wxCSS_PROPERTY_STOP_COLOR: if (!cssValue) cssValue = new wxSVGColor; ((wxSVGColor*)cssValue)->SetRGBColor(ParseColor(value)); break; // case wxCSS_PROPERTY_FILL: case wxCSS_PROPERTY_STROKE: if (!cssValue) cssValue = new wxSVGPaint; ParseSVGPaint(*(wxSVGPaint*)cssValue, value); break; } if (it == end()) (*this)[propertyId] = cssValue; } double wxCSSStyleDeclaration::ParseNumber(const wxString& value) { double val = 0; value.ToDouble(&val); return val; } static wxSortedArrayString* s_cssColors = NULL; #include "css_colors.cpp" inline void FillCSSColors() { if (s_cssColors == NULL) { s_cssColors = new wxSortedArrayString; for (unsigned int i=0; iAdd(s_cssNamedColors[i].name); } } wxRGBColor wxCSSStyleDeclaration::ParseColor(const wxString& value) { if (!value.length() || value == wxT("none")) return wxRGBColor(); else if (value.GetChar(0) == wxT('#')) { long r = 0, g = 0, b = 0; value.Mid(1,2).ToLong(&r,16); value.Mid(3,2).ToLong(&g,16); value.Mid(5,2).ToLong(&b,16); return wxRGBColor(r,g,b); } else if (value.Left(3) == wxT("rgb")) { wxStringTokenizer tkz(value.Mid(3), wxT(",()")); long rgb[3] = { 0, 0, 0 }; for (int i=0; tkz.HasMoreTokens() && i<3;) { wxString token = tkz.GetNextToken().Strip(wxString::both); if (token.length()) token.ToLong(&rgb[i++]); } return wxRGBColor(rgb[0], rgb[1], rgb[2]); } else { FillCSSColors(); int num = s_cssColors->Index(value); if (num>=0) return s_cssNamedColors[num].colour; } return wxRGBColor(); } void wxCSSStyleDeclaration::ParseSVGPaint(wxSVGPaint& cssValue, const wxString& value) { wxString val = value; if (val.Left(3) == wxT("url")) { cssValue.SetUri(value.AfterFirst(wxT('(')).BeforeFirst(wxT(')'))); val = value.AfterFirst(wxT(')')).Strip(wxString::both); } cssValue.SetRGBColor(ParseColor(val)); } ////////////////////////////////////////////////////////////////////////////// ///////////////////////// wxCSSStyleRef ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// wxCSSStyleRef::~wxCSSStyleRef() { while (size()) erase(begin()); } void wxCSSStyleRef::Add(const wxCSSStyleDeclaration& style) { const_iterator it; for (it = style.begin(); it != style.end(); ++it) (*this)[it->first] = it->second; }