aboutsummaryrefslogtreecommitdiff
path: root/src/styleengine.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/styleengine.cc')
-rw-r--r--src/styleengine.cc156
1 files changed, 107 insertions, 49 deletions
diff --git a/src/styleengine.cc b/src/styleengine.cc
index b9f30054..8653ed68 100644
--- a/src/styleengine.cc
+++ b/src/styleengine.cc
@@ -41,6 +41,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) {
font_attrs.weight = 400;
font_attrs.style = FONT_STYLE_NORMAL;
font_attrs.letterSpacing = 0;
+ font_attrs.fontVariant = FONT_VARIANT_NORMAL;
style_attrs.initValues ();
style_attrs.font = Font::create (layout, &font_attrs);
@@ -49,7 +50,8 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) {
n->style = Style::create (layout, &style_attrs);
n->wordStyle = NULL;
- n->styleAttribute = NULL;
+ n->styleAttrProperties = NULL;
+ n->nonCssProperties = NULL;
n->inheritBackgroundColor = false;
}
@@ -66,13 +68,14 @@ StyleEngine::~StyleEngine () {
*/
void StyleEngine::startElement (int element) {
if (stack->getRef (stack->size () - 1)->style == NULL)
- style0 ();
+ style0 (stack->size () - 1);
stack->increase ();
Node *n = stack->getRef (stack->size () - 1);
+ n->styleAttrProperties = NULL;
+ n->nonCssProperties = NULL;
n->style = NULL;
n->wordStyle = NULL;
- n->styleAttribute = NULL;
n->inheritBackgroundColor = false;
DoctreeNode *dn = doctree->push ();
@@ -120,20 +123,45 @@ void StyleEngine::setClass (const char *klass) {
dn->klass = splitStr (klass, ' ');
};
-void StyleEngine::setStyle (const char *style) {
+void StyleEngine::setStyle (const char *styleAttr) {
Node *n = stack->getRef (stack->size () - 1);
- assert (n->styleAttribute == NULL);
- n->styleAttribute = dStrdup (style);
+ assert (n->styleAttrProperties == NULL);
+ // parse style information from style="" attribute, if it exists
+ if (styleAttr && prefs.parse_embedded_css)
+ n->styleAttrProperties =
+ CssParser::parseDeclarationBlock (styleAttr,
+ strlen (styleAttr));
};
/**
* \brief set properties that were definded using (mostly deprecated) HTML
* attributes (e.g. bgColor).
*/
-void StyleEngine::setNonCssHints (CssPropertyList *nonCssHints) {
- if (stack->getRef (stack->size () - 1)->style)
- stack->getRef (stack->size () - 1)->style->unref ();
- style0 (nonCssHints); // evaluate now, so caller can free nonCssHints
+void StyleEngine::setNonCssHint (CssPropertyName name, CssValueType type,
+ CssPropertyValue value) {
+ Node *n = stack->getRef (stack->size () - 1);
+
+ if (!n->nonCssProperties)
+ n->nonCssProperties = new CssPropertyList (true);
+
+ n->nonCssProperties->set(name, type, value);
+}
+
+void StyleEngine::inheritNonCssHints () {
+ Node *pn = stack->getRef (stack->size () - 2);
+ Node *n = stack->getRef (stack->size () - 1);
+
+ if (pn->nonCssProperties)
+ n->nonCssProperties = new CssPropertyList (*pn->nonCssProperties);
+}
+
+void StyleEngine::clearNonCssHints () {
+ Node *n = stack->getRef (stack->size () - 1);
+
+ if (n->nonCssProperties) {
+ delete n->nonCssProperties;
+ n->nonCssProperties = NULL;
+ }
}
/**
@@ -171,17 +199,55 @@ void StyleEngine::endElement (int element) {
Node *n = stack->getRef (stack->size () - 1);
+ if (n->styleAttrProperties)
+ delete n->styleAttrProperties;
+ if (n->nonCssProperties)
+ delete n->nonCssProperties;
if (n->style)
n->style->unref ();
if (n->wordStyle)
n->wordStyle->unref ();
- if (n->styleAttribute)
- dFree ((void*) n->styleAttribute);
doctree->pop ();
stack->setSize (stack->size () - 1);
}
+void StyleEngine::preprocessAttrs (dw::core::style::StyleAttrs *attrs) {
+ /* workaround for styling of inline elements */
+ if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) {
+ attrs->backgroundColor =
+ stack->getRef (stack->size () - 2)->style->backgroundColor;
+
+ attrs->valign = stack->getRef (stack->size () - 2)->style->valign;
+ }
+ /* initial value of border-width is 'medium' */
+ attrs->borderWidth.top = 2;
+ attrs->borderWidth.bottom = 2;
+ attrs->borderWidth.left = 2;
+ attrs->borderWidth.right = 2;
+}
+
+void StyleEngine::postprocessAttrs (dw::core::style::StyleAttrs *attrs) {
+ /* if border-color is not specified use color as computed value */
+ if (attrs->borderColor.top == NULL)
+ attrs->borderColor.top = attrs->color;
+ if (attrs->borderColor.bottom == NULL)
+ attrs->borderColor.bottom = attrs->color;
+ if (attrs->borderColor.left == NULL)
+ attrs->borderColor.left = attrs->color;
+ if (attrs->borderColor.right == NULL)
+ attrs->borderColor.right = attrs->color;
+ /* computed value of border-width is 0 if border-style is 'none' */
+ if (attrs->borderStyle.top == BORDER_NONE)
+ attrs->borderWidth.top = 0;
+ if (attrs->borderStyle.bottom == BORDER_NONE)
+ attrs->borderWidth.bottom = 0;
+ if (attrs->borderStyle.left == BORDER_NONE)
+ attrs->borderWidth.left = 0;
+ if (attrs->borderStyle.right == BORDER_NONE)
+ attrs->borderWidth.right = 0;
+}
+
/**
* \brief Make changes to StyleAttrs attrs according to CssPropertyList props.
*/
@@ -191,7 +257,7 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) {
char *c, *fontName;
int lineHeight;
- /* Determine font first so it can be used to resolve relative lenths. */
+ /* Determine font first so it can be used to resolve relative lengths. */
for (int i = 0; i < props->size (); i++) {
CssProperty *p = props->getRef (i);
@@ -327,6 +393,9 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) {
else if (fontAttrs.letterSpacing < -1000)
fontAttrs.letterSpacing = -1000;
break;
+ case CSS_PROPERTY_FONT_VARIANT:
+ fontAttrs.fontVariant = (FontVariant) p->value.intVal;
+ break;
default:
break;
}
@@ -498,16 +567,6 @@ void StyleEngine::apply (StyleAttrs *attrs, CssPropertyList *props) {
}
}
- /* make sure border colors are set */
- if (attrs->borderColor.top == NULL)
- attrs->borderColor.top = attrs->color;
- if (attrs->borderColor.bottom == NULL)
- attrs->borderColor.bottom = attrs->color;
- if (attrs->borderColor.left == NULL)
- attrs->borderColor.left = attrs->color;
- if (attrs->borderColor.right == NULL)
- attrs->borderColor.right = attrs->color;
-
}
/**
@@ -607,56 +666,44 @@ Style * StyleEngine::backgroundStyle () {
* HTML elements and the nonCssProperties that have been set.
* This method is private. Call style() to get a current style object.
*/
-Style * StyleEngine::style0 (CssPropertyList *nonCssProperties) {
- CssPropertyList props, *styleAttributeProps = NULL;
- const char *styleAttribute =
- stack->getRef (stack->size () - 1)->styleAttribute;
+Style * StyleEngine::style0 (int i) {
+ CssPropertyList props, *styleAttrProperties, *nonCssProperties;
// get previous style from the stack
- StyleAttrs attrs = *stack->getRef (stack->size () - 2)->style;
+ StyleAttrs attrs = *stack->getRef (i - 1)->style;
// Ensure that StyleEngine::style0() has not been called before for
// this element.
// Style computation is expensive so limit it as much as possible.
// If this assertion is hit, you need to rearrange the code that is
- // doing styleEngine calls to call setNonCssHints() before calling
+ // doing styleEngine calls to call setNonCssHint() before calling
// style() or wordStyle() for each new element.
- assert (stack->getRef (stack->size () - 1)->style == NULL);
+ assert (stack->getRef (i)->style == NULL);
// reset values that are not inherited according to CSS
attrs.resetValues ();
+ preprocessAttrs (&attrs);
- if (stack->getRef (stack->size () - 2)->inheritBackgroundColor) {
- attrs.backgroundColor =
- stack->getRef (stack->size () - 2)->style->backgroundColor;
-
- attrs.valign = stack->getRef (stack->size () - 2)->style->valign;
- }
-
- // parse style information from style="" attribute, if it exists
- if (styleAttribute && prefs.parse_embedded_css)
- styleAttributeProps =
- CssParser::parseDeclarationBlock (styleAttribute,
- strlen (styleAttribute));
+ styleAttrProperties = stack->getRef (i)->styleAttrProperties;
+ nonCssProperties = stack->getRef (i)->nonCssProperties;
// merge style information
- cssContext->apply (&props, doctree, styleAttributeProps, nonCssProperties);
+ cssContext->apply (&props, doctree, styleAttrProperties, nonCssProperties);
// apply style
apply (&attrs, &props);
- stack->getRef (stack->size () - 1)->style = Style::create (layout, &attrs);
+ postprocessAttrs (&attrs);
- if (styleAttributeProps)
- delete styleAttributeProps;
+ stack->getRef (i)->style = Style::create (layout, &attrs);
- return stack->getRef (stack->size () - 1)->style;
+ return stack->getRef (i)->style;
}
-Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) {
+Style * StyleEngine::wordStyle0 () {
StyleAttrs attrs = *style ();
attrs.resetValues ();
- if (stack->getRef (stack->size () - 1)->inheritBackgroundColor)
+ if (stack->getRef (stack->size() - 1)->inheritBackgroundColor)
attrs.backgroundColor = style ()->backgroundColor;
attrs.valign = style ()->valign;
@@ -665,6 +712,17 @@ Style * StyleEngine::wordStyle0 (CssPropertyList *nonCssProperties) {
return stack->getRef (stack->size () - 1)->wordStyle;
}
+void StyleEngine::restyle () {
+ for (int i = 0; i < stack->size (); i++) {
+ Node *n = stack->getRef (i);
+ if (n->style) {
+ n->style->unref ();
+ n->style = NULL;
+ }
+ style0 (i);
+ }
+}
+
void StyleEngine::parse (DilloHtml *html, DilloUrl *url, const char *buf,
int buflen, CssOrigin origin) {
if (importDepth > 10) { // avoid looping with recursive @import directives