diff options
Diffstat (limited to 'khtml/css/css_valueimpl.cpp')
-rw-r--r-- | khtml/css/css_valueimpl.cpp | 1071 |
1 files changed, 1071 insertions, 0 deletions
diff --git a/khtml/css/css_valueimpl.cpp b/khtml/css/css_valueimpl.cpp new file mode 100644 index 000000000..531cb88bf --- /dev/null +++ b/khtml/css/css_valueimpl.cpp @@ -0,0 +1,1071 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2004, 2005, 2006 Apple Computer, Inc. + * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "dom/css_value.h" +#include "dom/dom_exception.h" +#include "dom/dom_string.h" + +#include "css/css_valueimpl.h" +#include "css/css_ruleimpl.h" +#include "css/css_stylesheetimpl.h" +#include "css/cssparser.h" +#include "css/cssproperties.h" +#include "css/cssvalues.h" + +#include "xml/dom_stringimpl.h" +#include "xml/dom_docimpl.h" + +#include "misc/loader.h" + +#include "rendering/font.h" +#include "rendering/render_style.h" + +#include <kdebug.h> +#include <qregexp.h> +#include <qpaintdevice.h> +#include <qpaintdevicemetrics.h> + +// Hack for debugging purposes +extern DOM::DOMString getPropertyName(unsigned short id); + +using khtml::FontDef; + +using namespace DOM; + +// Quotes the string if it needs quoting. +static DOMString quoteStringIfNeeded(const DOMString &string) +{ + // FIXME: Also need to transform control characters into \ sequences. + QString s = string.string(); + s.replace('\\', "\\\\"); + s.replace('\'', "\\'"); + return '\'' + s + '\''; +} + + +CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent) + : StyleBaseImpl(parent) +{ + m_lstValues = 0; + m_node = 0; +} + +CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent, QPtrList<CSSProperty> *lstValues) + : StyleBaseImpl(parent) +{ + m_lstValues = lstValues; + m_node = 0; +} + +CSSStyleDeclarationImpl& CSSStyleDeclarationImpl::operator= (const CSSStyleDeclarationImpl& o) +{ + // don't attach it to the same node, just leave the current m_node value + delete m_lstValues; + m_lstValues = 0; + if (o.m_lstValues) { + m_lstValues = new QPtrList<CSSProperty>; + m_lstValues->setAutoDelete( true ); + + QPtrListIterator<CSSProperty> lstValuesIt(*o.m_lstValues); + for (lstValuesIt.toFirst(); lstValuesIt.current(); ++lstValuesIt) + m_lstValues->append(new CSSProperty(*lstValuesIt.current())); + } + + return *this; +} + +CSSStyleDeclarationImpl::~CSSStyleDeclarationImpl() +{ + delete m_lstValues; + // we don't use refcounting for m_node, to avoid cyclic references (see ElementImpl) +} + +DOMString CSSStyleDeclarationImpl::getPropertyValue( int propertyID ) const +{ + if(!m_lstValues) return DOMString(); + CSSValueImpl* value = getPropertyCSSValue( propertyID ); + if ( value ) + return value->cssText(); + + // Shorthand and 4-values properties + switch ( propertyID ) { + case CSS_PROP_BACKGROUND_POSITION: + { + // ## Is this correct? The code in cssparser.cpp is confusing + const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X, + CSS_PROP_BACKGROUND_POSITION_Y }; + return getShortHandValue( properties, 2 ); + } + case CSS_PROP_BACKGROUND: + { + const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, + CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, + CSS_PROP_BACKGROUND_COLOR }; + return getShortHandValue( properties, 5 ); + } + case CSS_PROP_BORDER: + { + const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE, + CSS_PROP_BORDER_COLOR }; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_BORDER_TOP: + { + const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE, + CSS_PROP_BORDER_TOP_COLOR}; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_BORDER_RIGHT: + { + const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE, + CSS_PROP_BORDER_RIGHT_COLOR}; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_BORDER_BOTTOM: + { + const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, + CSS_PROP_BORDER_BOTTOM_COLOR}; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_BORDER_LEFT: + { + const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, + CSS_PROP_BORDER_LEFT_COLOR}; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_OUTLINE: + { + const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE, + CSS_PROP_OUTLINE_COLOR }; + return getShortHandValue( properties, 3 ); + } + case CSS_PROP_BORDER_COLOR: + { + const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR, + CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR }; + return get4Values( properties ); + } + case CSS_PROP_BORDER_WIDTH: + { + const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH, + CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH }; + return get4Values( properties ); + } + case CSS_PROP_BORDER_STYLE: + { + const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE, + CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE }; + return get4Values( properties ); + } + case CSS_PROP_MARGIN: + { + const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, + CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; + return get4Values( properties ); + } + case CSS_PROP_PADDING: + { + const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, + CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; + return get4Values( properties ); + } + case CSS_PROP_LIST_STYLE: + { + const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION, + CSS_PROP_LIST_STYLE_IMAGE }; + return getShortHandValue( properties, 3 ); + } + } + //kdDebug() << k_funcinfo << "property not found:" << propertyID << endl; + return DOMString(); +} + +DOMString CSSStyleDeclarationImpl::get4Values( const int* properties ) const +{ + DOMString res; + for ( int i = 0 ; i < 4 ; ++i ) { + CSSValueImpl* value = getPropertyCSSValue( properties[i] ); + if ( !value ) { // apparently all 4 properties must be specified. + return DOMString(); + } + if ( i > 0 ) + res += " "; + res += value->cssText(); + } + return res; +} + +DOMString CSSStyleDeclarationImpl::getShortHandValue( const int* properties, int number ) const +{ + DOMString res; + for ( int i = 0 ; i < number ; ++i ) { + CSSValueImpl* value = getPropertyCSSValue( properties[i] ); + if ( value ) { // TODO provide default value if !value + if ( !res.isNull() ) + res += " "; + res += value->cssText(); + } + } + return res; +} + + CSSValueImpl *CSSStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const +{ + if(!m_lstValues) return 0; + + QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); + CSSProperty *current; + for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt ) + if (current->m_id == propertyID && !current->nonCSSHint) + return current->value(); + return 0; +} + +DOMString CSSStyleDeclarationImpl::removeProperty( int propertyID, bool NonCSSHint ) +{ + if(!m_lstValues) return DOMString(); + DOMString value; + + QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); + CSSProperty *current; + for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt ) { + if (current->m_id == propertyID && NonCSSHint == current->nonCSSHint) { + value = current->value()->cssText(); + m_lstValues->removeRef(current); + setChanged(); + break; + } + } + + return value; +} + +void CSSStyleDeclarationImpl::setChanged() +{ + if (m_node) { + m_node->setChanged(); + return; + } + + // ### quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk) + for (StyleBaseImpl* stylesheet = this; stylesheet; stylesheet = stylesheet->parent()) + if (stylesheet->isCSSStyleSheet()) { + static_cast<CSSStyleSheetImpl*>(stylesheet)->doc()->updateStyleSelector(); + break; + } +} + +void CSSStyleDeclarationImpl::removeCSSHints() +{ + if (!m_lstValues) + return; + + for (int i = (int)m_lstValues->count()-1; i >= 0; i--) { + if (!m_lstValues->at(i)->nonCSSHint) + m_lstValues->remove(i); + } +} + +bool CSSStyleDeclarationImpl::getPropertyPriority( int propertyID ) const +{ + if ( m_lstValues) { + QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); + CSSProperty *current; + for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) { + if( propertyID == current->m_id ) + return current->m_important; + } + } + return false; +} + +bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool nonCSSHint) +{ + if(!m_lstValues) { + m_lstValues = new QPtrList<CSSProperty>; + m_lstValues->setAutoDelete(true); + } + + CSSParser parser( strictParsing ); + bool success = parser.parseValue( this, id, value, important, nonCSSHint ); + if(!success) + kdDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string() + << "] value: [" << value.string() << "]"<< endl; + else + setChanged(); + return success; +} + +void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool nonCSSHint) +{ + if(!m_lstValues) { + m_lstValues = new QPtrList<CSSProperty>; + m_lstValues->setAutoDelete(true); + } + removeProperty(id, nonCSSHint ); + + CSSValueImpl * cssValue = new CSSPrimitiveValueImpl(value); + setParsedValue(id, cssValue, important, nonCSSHint, m_lstValues); + setChanged(); +} + +void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint, bool _multiLength ) +{ + bool parseMode = strictParsing; + strictParsing = false; + multiLength = _multiLength; + setProperty( id, value, important, nonCSSHint); + strictParsing = parseMode; + multiLength = false; +} + +void CSSStyleDeclarationImpl::setProperty ( const DOMString &propertyString) +{ + if(!m_lstValues) { + m_lstValues = new QPtrList<CSSProperty>; + m_lstValues->setAutoDelete( true ); + } + + CSSParser parser( strictParsing ); + parser.parseDeclaration( this, propertyString, false ); + setChanged(); +} + +unsigned long CSSStyleDeclarationImpl::length() const +{ + return m_lstValues ? m_lstValues->count() : 0; +} + +DOMString CSSStyleDeclarationImpl::item( unsigned long index ) const +{ + if(m_lstValues && index < m_lstValues->count() && m_lstValues->at(index)) + return getPropertyName(m_lstValues->at(index)->m_id); + return DOMString(); +} + +CSSRuleImpl *CSSStyleDeclarationImpl::parentRule() const +{ + return (m_parent && m_parent->isRule() ) ? + static_cast<CSSRuleImpl *>(m_parent) : 0; +} + +DOM::DOMString CSSStyleDeclarationImpl::cssText() const +{ + DOMString result; + + if ( m_lstValues) { + QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues); + CSSProperty *current; + for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) { + result += current->cssText(); + } + } + + return result; +} + +void CSSStyleDeclarationImpl::setCssText(DOM::DOMString text) +{ + if (m_lstValues) { + m_lstValues->clear(); + } else { + m_lstValues = new QPtrList<CSSProperty>; + m_lstValues->setAutoDelete( true ); + } + + CSSParser parser( strictParsing ); + parser.parseDeclaration( this, text, false ); + setChanged(); +} + +bool CSSStyleDeclarationImpl::parseString( const DOMString &/*string*/, bool ) +{ + kdDebug() << "WARNING: CSSStyleDeclarationImpl::parseString, unimplemented, was called" << endl; + return false; + // ### +} + + +// -------------------------------------------------------------------------------------- + +unsigned short CSSInheritedValueImpl::cssValueType() const +{ + return CSSValue::CSS_INHERIT; +} + +DOM::DOMString CSSInheritedValueImpl::cssText() const +{ + return DOMString("inherit"); +} + +unsigned short CSSInitialValueImpl::cssValueType() const +{ + return CSSValue::CSS_INITIAL; +} + +DOM::DOMString CSSInitialValueImpl::cssText() const +{ + return DOMString("initial"); +} + +// ---------------------------------------------------------------------------------------- + +CSSValueListImpl::~CSSValueListImpl() +{ + CSSValueImpl *val = m_values.first(); + while( val ) { + val->deref(); + val = m_values.next(); + } +} + +unsigned short CSSValueListImpl::cssValueType() const +{ + return CSSValue::CSS_VALUE_LIST; +} + +void CSSValueListImpl::append(CSSValueImpl *val) +{ + m_values.append(val); + val->ref(); +} + +DOM::DOMString CSSValueListImpl::cssText() const +{ + DOMString result = ""; + + for (QPtrListIterator<CSSValueImpl> iterator(m_values); iterator.current(); ++iterator) { + result += iterator.current()->cssText(); + } + + return result; +} + +// ------------------------------------------------------------------------------------- + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl() + : CSSValueImpl() +{ + m_type = 0; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(int ident) + : CSSValueImpl() +{ + m_value.ident = ident; + m_type = CSSPrimitiveValue::CSS_IDENT; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type) +{ + m_value.num = num; + m_type = type; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type) +{ + m_value.string = str.implementation(); + if(m_value.string) m_value.string->ref(); + m_type = type; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(CounterImpl *c) +{ + m_value.counter = c; + if (m_value.counter) + m_value.counter->ref(); + m_type = CSSPrimitiveValue::CSS_COUNTER; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl( RectImpl *r) +{ + m_value.rect = r; + if (m_value.rect) + m_value.rect->ref(); + m_type = CSSPrimitiveValue::CSS_RECT; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color) +{ + m_value.rgbcolor = color; + m_type = CSSPrimitiveValue::CSS_RGBCOLOR; +} + +CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(PairImpl *p) +{ + m_value.pair = p; + if (m_value.pair) + m_value.pair->ref(); + m_type = CSSPrimitiveValue::CSS_PAIR; +} + + +CSSPrimitiveValueImpl::~CSSPrimitiveValueImpl() +{ + cleanup(); +} + +void CSSPrimitiveValueImpl::cleanup() +{ + switch(m_type) { + case CSSPrimitiveValue::CSS_STRING: + case CSSPrimitiveValue::CSS_URI: + case CSSPrimitiveValue::CSS_ATTR: + if(m_value.string) m_value.string->deref(); + break; + case CSSPrimitiveValue::CSS_COUNTER: + m_value.counter->deref(); + break; + case CSSPrimitiveValue::CSS_RECT: + m_value.rect->deref(); + break; + case CSSPrimitiveValue::CSS_PAIR: + m_value.pair->deref(); + break; + default: + break; + } + + m_type = 0; +} + +int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics ) +{ + double result = computeLengthFloat( style, devMetrics ); + // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We + // need to go ahead and round if we're really close to the next integer value. + int intResult = (int)(result + (result < 0 ? -0.01 : +0.01)); + return intResult; +} + +double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics ) +{ + unsigned short type = primitiveType(); + + double dpiY = 72.; // fallback + if ( devMetrics ) + dpiY = devMetrics->logicalDpiY(); + if ( !khtml::printpainter && dpiY < 96 ) + dpiY = 96.; + + double factor = 1.; + switch(type) + { + case CSSPrimitiveValue::CSS_EMS: + factor = style->font().pixelSize(); + break; + case CSSPrimitiveValue::CSS_EXS: + { + QFontMetrics fm = style->fontMetrics(); +#ifdef APPLE_CHANGES + factor = fm.xHeight(); +#else + QRect b = fm.boundingRect('x'); + factor = b.height(); +#endif + break; + } + case CSSPrimitiveValue::CSS_PX: + break; + case CSSPrimitiveValue::CSS_CM: + factor = dpiY/2.54; //72dpi/(2.54 cm/in) + break; + case CSSPrimitiveValue::CSS_MM: + factor = dpiY/25.4; + break; + case CSSPrimitiveValue::CSS_IN: + factor = dpiY; + break; + case CSSPrimitiveValue::CSS_PT: + factor = dpiY/72.; + break; + case CSSPrimitiveValue::CSS_PC: + // 1 pc == 12 pt + factor = dpiY*12./72.; + break; + default: + return -1; + } + + return floatValue(type)*factor; +} + +void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode ) +{ + exceptioncode = 0; + cleanup(); + // ### check if property supports this type + if(m_type > CSSPrimitiveValue::CSS_DIMENSION) { + exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET; + return; + } + //if(m_type > CSSPrimitiveValue::CSS_DIMENSION) throw DOMException(DOMException::INVALID_ACCESS_ERR); + m_value.num = floatValue; + m_type = unitType; +} + +void CSSPrimitiveValueImpl::setStringValue( unsigned short stringType, const DOMString &stringValue, int &exceptioncode ) +{ + exceptioncode = 0; + cleanup(); + //if(m_type < CSSPrimitiveValue::CSS_STRING) throw DOMException(DOMException::INVALID_ACCESS_ERR); + //if(m_type > CSSPrimitiveValue::CSS_ATTR) throw DOMException(DOMException::INVALID_ACCESS_ERR); + if(m_type < CSSPrimitiveValue::CSS_STRING || m_type > CSSPrimitiveValue::CSS_ATTR) { + exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET; + return; + } + if(stringType != CSSPrimitiveValue::CSS_IDENT) + { + m_value.string = stringValue.implementation(); + m_value.string->ref(); + m_type = stringType; + } + // ### parse ident +} + +unsigned short CSSPrimitiveValueImpl::cssValueType() const +{ + return CSSValue::CSS_PRIMITIVE_VALUE; +} + +bool CSSPrimitiveValueImpl::parseString( const DOMString &/*string*/, bool ) +{ + // ### + kdDebug() << "WARNING: CSSPrimitiveValueImpl::parseString, unimplemented, was called" << endl; + return false; +} + +int CSSPrimitiveValueImpl::getIdent() +{ + if(m_type != CSSPrimitiveValue::CSS_IDENT) return 0; + return m_value.ident; +} + +DOM::DOMString CSSPrimitiveValueImpl::cssText() const +{ + // ### return the original value instead of a generated one (e.g. color + // name if it was specified) - check what spec says about this + DOMString text; + switch ( m_type ) { + case CSSPrimitiveValue::CSS_UNKNOWN: + // ### + break; + case CSSPrimitiveValue::CSS_NUMBER: + text = DOMString(QString::number( (int)m_value.num )); + break; + case CSSPrimitiveValue::CSS_PERCENTAGE: + text = DOMString(QString::number( m_value.num ) + "%"); + break; + case CSSPrimitiveValue::CSS_EMS: + text = DOMString(QString::number( m_value.num ) + "em"); + break; + case CSSPrimitiveValue::CSS_EXS: + text = DOMString(QString::number( m_value.num ) + "ex"); + break; + case CSSPrimitiveValue::CSS_PX: + text = DOMString(QString::number( m_value.num ) + "px"); + break; + case CSSPrimitiveValue::CSS_CM: + text = DOMString(QString::number( m_value.num ) + "cm"); + break; + case CSSPrimitiveValue::CSS_MM: + text = DOMString(QString::number( m_value.num ) + "mm"); + break; + case CSSPrimitiveValue::CSS_IN: + text = DOMString(QString::number( m_value.num ) + "in"); + break; + case CSSPrimitiveValue::CSS_PT: + text = DOMString(QString::number( m_value.num ) + "pt"); + break; + case CSSPrimitiveValue::CSS_PC: + text = DOMString(QString::number( m_value.num ) + "pc"); + break; + case CSSPrimitiveValue::CSS_DEG: + text = DOMString(QString::number( m_value.num ) + "deg"); + break; + case CSSPrimitiveValue::CSS_RAD: + text = DOMString(QString::number( m_value.num ) + "rad"); + break; + case CSSPrimitiveValue::CSS_GRAD: + text = DOMString(QString::number( m_value.num ) + "grad"); + break; + case CSSPrimitiveValue::CSS_MS: + text = DOMString(QString::number( m_value.num ) + "ms"); + break; + case CSSPrimitiveValue::CSS_S: + text = DOMString(QString::number( m_value.num ) + "s"); + break; + case CSSPrimitiveValue::CSS_HZ: + text = DOMString(QString::number( m_value.num ) + "hz"); + break; + case CSSPrimitiveValue::CSS_KHZ: + text = DOMString(QString::number( m_value.num ) + "khz"); + break; + case CSSPrimitiveValue::CSS_DIMENSION: + // ### + break; + case CSSPrimitiveValue::CSS_STRING: + text = quoteStringIfNeeded(m_value.string); + break; + case CSSPrimitiveValue::CSS_URI: + text = "url("; + text += DOMString( m_value.string ); + text += ")"; + break; + case CSSPrimitiveValue::CSS_IDENT: + text = getValueName(m_value.ident); + break; + case CSSPrimitiveValue::CSS_ATTR: + // ### + break; + case CSSPrimitiveValue::CSS_COUNTER: + text = "counter("; + text += m_value.counter->m_identifier; + text += ")"; + // ### add list-style and separator + break; + case CSSPrimitiveValue::CSS_RECT: + { + RectImpl* rectVal = getRectValue(); + text = "rect("; + text += rectVal->top()->cssText() + " "; + text += rectVal->right()->cssText() + " "; + text += rectVal->bottom()->cssText() + " "; + text += rectVal->left()->cssText() + ")"; + break; + } + case CSSPrimitiveValue::CSS_RGBCOLOR: + if (qAlpha(m_value.rgbcolor) != 0xFF) { + if (m_value.rgbcolor == khtml::transparentColor) + text = "transparent"; + else + text = "rgba(" + QString::number(qRed (m_value.rgbcolor)) + "," + + QString::number(qBlue (m_value.rgbcolor)) + "," + + QString::number(qGreen(m_value.rgbcolor)) + "," + + QString::number(qAlpha(m_value.rgbcolor)/255.0) + ")"; + } else { + text = QColor(m_value.rgbcolor).name(); + } + break; + case CSSPrimitiveValue::CSS_PAIR: + text = m_value.pair->first()->cssText(); + text += " "; + text += m_value.pair->second()->cssText(); + break; + default: + break; + } + return text; +} + +// ----------------------------------------------------------------- + +RectImpl::RectImpl() +{ + m_top = 0; + m_right = 0; + m_bottom = 0; + m_left = 0; +} + +RectImpl::~RectImpl() +{ + if (m_top) m_top->deref(); + if (m_right) m_right->deref(); + if (m_bottom) m_bottom->deref(); + if (m_left) m_left->deref(); +} + +void RectImpl::setTop( CSSPrimitiveValueImpl *top ) +{ + if( top ) top->ref(); + if ( m_top ) m_top->deref(); + m_top = top; +} + +void RectImpl::setRight( CSSPrimitiveValueImpl *right ) +{ + if( right ) right->ref(); + if ( m_right ) m_right->deref(); + m_right = right; +} + +void RectImpl::setBottom( CSSPrimitiveValueImpl *bottom ) +{ + if( bottom ) bottom->ref(); + if ( m_bottom ) m_bottom->deref(); + m_bottom = bottom; +} + +void RectImpl::setLeft( CSSPrimitiveValueImpl *left ) +{ + if( left ) left->ref(); + if ( m_left ) m_left->deref(); + m_left = left; +} + +// ----------------------------------------------------------------- + +PairImpl::~PairImpl() +{ + if (m_first) m_first->deref(); if (m_second) m_second->deref(); +} + +void PairImpl::setFirst(CSSPrimitiveValueImpl* first) +{ + if (first == m_first) return; + if (m_first) m_first->deref(); + m_first = first; + if (m_first) m_first->ref(); +} + +void PairImpl::setSecond(CSSPrimitiveValueImpl* second) +{ + if (second == m_second) return; + if (m_second) m_second->deref(); + m_second = second; + if (m_second) m_second->ref(); +} + +// ----------------------------------------------------------------- + +CSSImageValueImpl::CSSImageValueImpl(const DOMString &url, const StyleBaseImpl* style) + : CSSPrimitiveValueImpl(url, CSSPrimitiveValue::CSS_URI) +{ + khtml::DocLoader *docLoader = 0; + const StyleBaseImpl *root = style; + while (root->parent()) + root = root->parent(); + if (root->isCSSStyleSheet()) + docLoader = static_cast<const CSSStyleSheetImpl*>(root)->docLoader(); + + m_image = docLoader->requestImage(url); + if(m_image) m_image->ref(this); +} + +CSSImageValueImpl::CSSImageValueImpl() + : CSSPrimitiveValueImpl(CSS_VAL_NONE) +{ + m_image = 0; +} + +CSSImageValueImpl::~CSSImageValueImpl() +{ + if(m_image) m_image->deref(this); +} + +// ------------------------------------------------------------------------ + +FontFamilyValueImpl::FontFamilyValueImpl( const QString &string) +: CSSPrimitiveValueImpl( DOMString(string), CSSPrimitiveValue::CSS_STRING) +{ + static const QRegExp parenReg(" \\(.*\\)$"); + static const QRegExp braceReg(" \\[.*\\]$"); + + parsedFontName = string; + // a language tag is often added in braces at the end. Remove it. + parsedFontName.replace(parenReg, QString::null); + // remove [Xft] qualifiers + parsedFontName.replace(braceReg, QString::null); + +#ifndef APPLE_CHANGES + const QString &available = KHTMLSettings::availableFamilies(); + + parsedFontName = parsedFontName.lower(); + // kdDebug(0) << "searching for face '" << parsedFontName << "'" << endl; + + int pos = available.find( ',' + parsedFontName + ',', 0, false ); + if ( pos == -1 ) { + // many pages add extra MSs to make sure it's windows only ;( + if ( parsedFontName.startsWith( "ms " ) ) + parsedFontName = parsedFontName.mid( 3 ); + if ( parsedFontName.endsWith( " ms" ) ) + parsedFontName.truncate( parsedFontName.length() - 3 ); + pos = available.find( ",ms " + parsedFontName + ',', 0, false ); + if ( pos == -1 ) + pos = available.find( ',' + parsedFontName + " ms,", 0, false ); + } + + if ( pos != -1 ) { + ++pos; + int p = available.find(',', pos); + assert( p != -1 ); // available is supposed to start and end with , + parsedFontName = available.mid( pos, p - pos); + // kdDebug(0) << "going for '" << parsedFontName << "'" << endl; + } else + parsedFontName = QString::null; + +#endif // !APPLE_CHANGES +} + +FontValueImpl::FontValueImpl() + : style(0), variant(0), weight(0), size(0), lineHeight(0), family(0) +{ +} + +FontValueImpl::~FontValueImpl() +{ + delete style; + delete variant; + delete weight; + delete size; + delete lineHeight; + delete family; +} + +DOMString FontValueImpl::cssText() const +{ + // font variant weight size / line-height family + + DOMString result(""); + + if (style) { + result += style->cssText(); + } + if (variant) { + if (result.length() > 0) { + result += " "; + } + result += variant->cssText(); + } + if (weight) { + if (result.length() > 0) { + result += " "; + } + result += weight->cssText(); + } + if (size) { + if (result.length() > 0) { + result += " "; + } + result += size->cssText(); + } + if (lineHeight) { + if (!size) { + result += " "; + } + result += "/"; + result += lineHeight->cssText(); + } + if (family) { + if (result.length() > 0) { + result += " "; + } + result += family->cssText(); + } + + return result; +} + +QuotesValueImpl::QuotesValueImpl() + : levels(0) +{ +} + +DOMString QuotesValueImpl::cssText() const +{ + return "\"" + data.join("\" \"") + "\""; +} + +void QuotesValueImpl::addLevel(const QString& open, const QString& close) +{ + data.append(open); + data.append(close); + levels++; +} + +QString QuotesValueImpl::openQuote(int level) const +{ + if (levels == 0) return ""; + level--; // increments are calculated before openQuote is called +// kdDebug( 6080 ) << "Open quote level:" << level << endl; + if (level < 0) level = 0; + else + if (level >= (int) levels) level = (int) (levels-1); + return data[level*2]; +} + +QString QuotesValueImpl::closeQuote(int level) const +{ + if (levels == 0) return ""; +// kdDebug( 6080 ) << "Close quote level:" << level << endl; + if (level < 0) level = 0; + else + if (level >= (int) levels) level = (int) (levels-1); + return data[level*2+1]; +} + +// Used for text-shadow and box-shadow +ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y, + CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color) + :x(_x), y(_y), blur(_blur), color(_color) +{} + +ShadowValueImpl::~ShadowValueImpl() +{ + delete x; + delete y; + delete blur; + delete color; +} + +DOMString ShadowValueImpl::cssText() const +{ + DOMString text(""); + if (color) { + text += color->cssText(); + } + if (x) { + if (text.length() > 0) { + text += " "; + } + text += x->cssText(); + } + if (y) { + if (text.length() > 0) { + text += " "; + } + text += y->cssText(); + } + if (blur) { + if (text.length() > 0) { + text += " "; + } + text += blur->cssText(); + } + + return text; +} + +DOMString CounterActImpl::cssText() const +{ + DOMString text(m_counter); + text += DOMString(QString::number(m_value)); + + return text; +} + +DOMString CSSProperty::cssText() const +{ + return getPropertyName(m_id) + DOMString(": ") + m_value->cssText() + (m_important ? DOMString(" !important") : DOMString()) + DOMString("; "); +} |