diff options
Diffstat (limited to 'src/styleengine.cc')
-rw-r--r-- | src/styleengine.cc | 156 |
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 |