#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 "css/cssstyleselector.h"
#include "xml/dom_stringimpl.h"
#include "xml/dom_docimpl.h"
#include "html/html_elementimpl.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>
extern DOM::DOMString getPropertyName(unsigned short id);
using khtml::FontDef;
using khtml::CSSStyleSelector;
namespace DOM {
#if 0
static bool isLegalIdentifier(const DOMString &string)
{
int len = string.length();
if (len == 0) {
return false;
}
QChar *p = string.unicode();
int i = 0;
if (p[0] == '-') {
++i;
}
if (i == len) {
return false;
}
ushort code = p[i].unicode();
if (!(code >= 0x80 || code == '_' || isalpha(code))) {
return false;
}
++i;
while (i != len) {
code = p[i].unicode();
if (!(code >= 0x80 || code == '-' || code == '_' || isalnum(code))) {
return false;
}
++i;
}
return true;
}
#endif
static DOMString quoteStringIfNeeded(const DOMString &string)
{
if (string[0] != '#') {
return string;
}
QString s = string.string();
s.replace('\\', "\\\\");
s.replace('\'', "\\'");
return '\'' + s + '\'';
}
CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent)
: StyleBaseImpl(parent)
{
}
bool CSSStyleDeclarationImpl::isStyleDeclaration()
{
return true;
}
CSSMutableStyleDeclarationImpl::CSSMutableStyleDeclarationImpl()
: m_node(0)
{
}
CSSMutableStyleDeclarationImpl::CSSMutableStyleDeclarationImpl(CSSRuleImpl *parent)
: CSSStyleDeclarationImpl(parent), m_node(0)
{
}
CSSMutableStyleDeclarationImpl::CSSMutableStyleDeclarationImpl(CSSRuleImpl *parent, const QValueList<CSSProperty> &values)
: CSSStyleDeclarationImpl(parent), m_values(values), m_node(0)
{
}
CSSMutableStyleDeclarationImpl::CSSMutableStyleDeclarationImpl(CSSRuleImpl *parent, const CSSProperty * const *properties, int numProperties)
: CSSStyleDeclarationImpl(parent), m_node(0)
{
for (int i = 0; i < numProperties; ++i)
m_values.append(*properties[i]);
}
CSSMutableStyleDeclarationImpl& CSSMutableStyleDeclarationImpl::operator=(const CSSMutableStyleDeclarationImpl& o)
{
m_values = o.m_values;
return *this;
}
CSSMutableStyleDeclarationImpl::~CSSMutableStyleDeclarationImpl()
{
}
DOMString CSSMutableStyleDeclarationImpl::getPropertyValue( int propertyID ) const
{
CSSValueImpl* value = getPropertyCSSValue( propertyID );
if (value)
return CSSValue(value).cssText();
switch ( propertyID ) {
case CSS_PROP_BACKGROUND_POSITION:
{
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 );
}
}
return DOMString();
}
DOMString CSSMutableStyleDeclarationImpl::get4Values( const int* properties ) const
{
DOMString res;
for ( int i = 0 ; i < 4 ; ++i ) {
CSSValueImpl* value = getPropertyCSSValue( properties[i] );
if ( !value ) { return DOMString();
}
value->ref();
if ( i > 0 )
res += " ";
res += value->cssText();
value->deref();
}
return res;
}
DOMString CSSMutableStyleDeclarationImpl::getShortHandValue( const int* properties, int number ) const
{
DOMString res;
for ( int i = 0 ; i < number ; ++i ) {
CSSValueImpl* value = getPropertyCSSValue( properties[i] );
if ( value ) { value->ref();
if ( !res.isNull() )
res += " ";
res += value->cssText();
value->deref();
}
}
return res;
}
CSSValueImpl *CSSMutableStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const
{
QValueListConstIterator<CSSProperty> end;
for (QValueListConstIterator<CSSProperty> it = m_values.fromLast(); it != end; --it)
if (propertyID == (*it).m_id)
return (*it).value();
return 0;
}
DOMString CSSMutableStyleDeclarationImpl::removeProperty(int propertyID, bool notifyChanged, int &exceptionCode)
{
if (m_node && !m_node->getDocument())
return "";
exceptionCode = 0;
DOMString value;
QValueListIterator<CSSProperty> end;
for (QValueListIterator<CSSProperty> it = m_values.fromLast(); it != end; --it)
if (propertyID == (*it).m_id) {
value = (*it).value()->cssText();
m_values.remove(it);
if (notifyChanged)
setChanged();
break;
}
return value;
}
void CSSMutableStyleDeclarationImpl::clear()
{
m_values.clear();
setChanged();
}
void CSSMutableStyleDeclarationImpl::setChanged()
{
if (m_node) {
m_node->setChanged();
if (m_node->isHTMLElement() && this == static_cast<HTMLElementImpl *>(m_node)->inlineStyleDecl())
static_cast<HTMLElementImpl *>(m_node)->invalidateStyleAttribute();
return;
}
StyleBaseImpl *root = this;
StyleBaseImpl *parent;
while ( ( parent = root->parent()) )
root = parent;
if (root->isCSSStyleSheet())
static_cast<CSSStyleSheetImpl*>(root)->doc()->updateStyleSelector();
}
bool CSSMutableStyleDeclarationImpl::getPropertyPriority(int propertyID) const
{
QValueListConstIterator<CSSProperty> end;
for (QValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it)
if (propertyID == (*it).m_id)
return (*it).m_bImportant;
return false;
}
void CSSMutableStyleDeclarationImpl::setProperty(int propertyID, const DOMString &value, bool important, int &exceptionCode)
{
setProperty(propertyID, value, important, true, exceptionCode);
}
DOMString CSSMutableStyleDeclarationImpl::removeProperty(int propertyID, int &exceptionCode)
{
return removeProperty(propertyID, true, exceptionCode);
}
bool CSSMutableStyleDeclarationImpl::setProperty(int propertyID, const DOMString &value, bool important, bool notifyChanged, int &exceptionCode)
{
if (m_node && !m_node->getDocument())
return false; exceptionCode = 0;
removeProperty(propertyID);
CSSParser parser(strictParsing);
bool success = parser.parseValue(this, propertyID, value, important);
if (!success) {
#if !APPLE_CHANGES
kdDebug( 6080 ) << "CSSMutableStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string()
<< "] value: [" << value.string() << "]"<< endl;
#endif
exceptionCode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
} else if (notifyChanged)
setChanged();
return success;
}
bool CSSMutableStyleDeclarationImpl::setProperty(int propertyID, int value, bool important, bool notifyChanged)
{
removeProperty(propertyID);
m_values.append(CSSProperty(propertyID, new CSSPrimitiveValueImpl(value), important));
if (notifyChanged)
setChanged();
return true;
}
void CSSMutableStyleDeclarationImpl::setStringProperty(int propertyId, const DOMString &value, CSSPrimitiveValue::UnitTypes type, bool important)
{
removeProperty(propertyId);
m_values.append(CSSProperty(propertyId, new CSSPrimitiveValueImpl(value, type), important));
setChanged();
}
void CSSMutableStyleDeclarationImpl::setImageProperty(int propertyId, const DOMString &URL, bool important)
{
removeProperty(propertyId);
m_values.append(CSSProperty(propertyId, new CSSImageValueImpl(URL, this), important));
setChanged();
}
void CSSMutableStyleDeclarationImpl::parseDeclaration(const DOMString &styleDeclaration)
{
m_values.clear();
CSSParser parser(strictParsing);
parser.parseDeclaration(this, styleDeclaration);
setChanged();
}
void CSSMutableStyleDeclarationImpl::addParsedProperties(const CSSProperty * const *properties, int numProperties)
{
for (int i = 0; i < numProperties; ++i) {
removeProperty(properties[i]->id(), false);
m_values.append(*properties[i]);
}
}
void CSSMutableStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool _multiLength )
{
bool parseMode = strictParsing;
strictParsing = false;
multiLength = _multiLength;
setProperty( id, value, important);
strictParsing = parseMode;
multiLength = false;
}
unsigned long CSSMutableStyleDeclarationImpl::length() const
{
return m_values.count();
}
DOMString CSSMutableStyleDeclarationImpl::item( unsigned long ) const
{
return DOMString();
}
CSSRuleImpl *CSSStyleDeclarationImpl::parentRule() const
{
return (m_parent && m_parent->isRule() ) ?
static_cast<CSSRuleImpl *>(m_parent) : 0;
}
DOM::DOMString CSSMutableStyleDeclarationImpl::cssText() const
{
DOMString result = "";
QValueListConstIterator<CSSProperty> end;
for (QValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it)
result += (*it).cssText();
return result;
}
void CSSMutableStyleDeclarationImpl::setCssText(const DOM::DOMString& text, int &exceptionCode)
{
exceptionCode = 0;
m_values.clear();
CSSParser parser(strictParsing);
parser.parseDeclaration(this, text);
setChanged();
}
void CSSMutableStyleDeclarationImpl::merge(CSSMutableStyleDeclarationImpl *other, bool argOverridesOnConflict)
{
QValueListConstIterator<CSSProperty> end;
for (QValueListConstIterator<CSSProperty> it = other->valuesIterator(); it != end; ++it) {
const CSSProperty &property = *it;
CSSValueImpl *value = getPropertyCSSValue(property.id());
if (value) {
value->ref();
value->deref();
if (!argOverridesOnConflict)
continue;
removeProperty(property.id());
}
m_values.append(property);
}
}
void CSSStyleDeclarationImpl::diff(CSSMutableStyleDeclarationImpl *style) const
{
if (!style)
return;
QValueList<int> properties;
QValueListConstIterator<CSSProperty> end;
for (QValueListConstIterator<CSSProperty> it(style->valuesIterator()); it != end; ++it) {
const CSSProperty &property = *it;
CSSValueImpl *value = getPropertyCSSValue(property.id());
if (value) {
value->ref();
if (value->cssText() == property.value()->cssText()) {
properties.append(property.id());
}
value->deref();
}
}
for (QValueListIterator<int> it(properties.begin()); it != properties.end(); ++it)
style->removeProperty(*it);
}
const int inheritableProperties[] = {
CSS_PROP_BORDER_COLLAPSE,
CSS_PROP_BORDER_SPACING,
CSS_PROP_COLOR,
CSS_PROP_FONT_FAMILY,
CSS_PROP_FONT_SIZE,
CSS_PROP_FONT_STYLE,
CSS_PROP_FONT_VARIANT,
CSS_PROP_FONT_WEIGHT,
CSS_PROP_LETTER_SPACING,
CSS_PROP_LINE_HEIGHT,
CSS_PROP_TEXT_ALIGN,
CSS_PROP__KHTML_TEXT_DECORATIONS_IN_EFFECT,
CSS_PROP_TEXT_INDENT,
CSS_PROP__APPLE_TEXT_SIZE_ADJUST,
CSS_PROP_TEXT_TRANSFORM,
CSS_PROP_ORPHANS,
CSS_PROP_WHITE_SPACE,
CSS_PROP_WIDOWS,
CSS_PROP_WORD_SPACING,
};
const unsigned numInheritableProperties = sizeof(inheritableProperties) / sizeof(inheritableProperties[0]);
static const int blockProperties[] = {
CSS_PROP_ORPHANS,
CSS_PROP_OVERFLOW, CSS_PROP_PAGE_BREAK_AFTER,
CSS_PROP_PAGE_BREAK_BEFORE,
CSS_PROP_PAGE_BREAK_INSIDE,
CSS_PROP_TEXT_ALIGN,
CSS_PROP_TEXT_INDENT,
CSS_PROP_WIDOWS
};
const unsigned numBlockProperties = sizeof(blockProperties) / sizeof(blockProperties[0]);
CSSMutableStyleDeclarationImpl *CSSMutableStyleDeclarationImpl::copyBlockProperties() const
{
return copyPropertiesInSet(blockProperties, numBlockProperties);
}
void CSSMutableStyleDeclarationImpl::removeBlockProperties()
{
removePropertiesInSet(blockProperties, numBlockProperties);
}
void CSSMutableStyleDeclarationImpl::removeInheritableProperties()
{
removePropertiesInSet(inheritableProperties, numInheritableProperties);
}
CSSMutableStyleDeclarationImpl *CSSStyleDeclarationImpl::copyPropertiesInSet(const int *set, unsigned length) const
{
QValueList<CSSProperty> list;
for (unsigned i = 0; i < length; i++) {
CSSValueImpl *value = getPropertyCSSValue(set[i]);
if (value)
list.append(CSSProperty(set[i], value, false));
}
return new CSSMutableStyleDeclarationImpl(0, list);
}
void CSSMutableStyleDeclarationImpl::removePropertiesInSet(const int *set, unsigned length)
{
bool changed = false;
for (unsigned i = 0; i < length; i++) {
CSSValueImpl *value = getPropertyCSSValue(set[i]);
if (value) {
m_values.remove(CSSProperty(set[i], value, false));
changed = true;
}
}
if (changed)
setChanged();
}
CSSMutableStyleDeclarationImpl *CSSMutableStyleDeclarationImpl::makeMutable()
{
return this;
}
CSSMutableStyleDeclarationImpl *CSSMutableStyleDeclarationImpl::copy() const
{
return new CSSMutableStyleDeclarationImpl(0, m_values);
}
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()
{
}
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) {
if (result.length() != 0) {
result += ", ";
}
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(const Counter &c)
{
m_value.counter = c.handle();
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( DashboardRegionImpl *r)
{
m_value.region = r;
if (m_value.region)
m_value.region->ref();
m_type = CSSPrimitiveValue::CSS_DASHBOARD_REGION;
}
CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color)
{
m_value.rgbcolor = color;
m_type = CSSPrimitiveValue::CSS_RGBCOLOR;
}
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_DASHBOARD_REGION:
if (m_value.region)
m_value.region->deref();
break;
default:
break;
}
m_type = 0;
}
int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics )
{
double result = computeLengthFloat( style, devMetrics );
#if APPLE_CHANGES
int intResult = (int)(result + (result < 0 ? -0.01 : +0.01));
#else
int intResult = (int)result;
#endif
return intResult;
}
int CSSPrimitiveValueImpl::computeLength( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics,
double multiplier )
{
double result = multiplier * computeLengthFloat( style, devMetrics );
#if APPLE_CHANGES
int intResult = (int)(result + (result < 0 ? -0.01 : +0.01));
#else
int intResult = (int)result;
#endif
return intResult;
}
double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPaintDeviceMetrics *devMetrics,
bool applyZoomFactor )
{
unsigned short type = primitiveType();
double dpiY = 72.; if ( devMetrics )
dpiY = devMetrics->logicalDpiY();
if ( !khtml::printpainter && dpiY < 96 )
dpiY = 96.;
double factor = 1.;
switch(type)
{
case CSSPrimitiveValue::CSS_EMS:
factor = applyZoomFactor ?
style->htmlFont().getFontDef().computedSize :
style->htmlFont().getFontDef().specifiedSize;
break;
case CSSPrimitiveValue::CSS_EXS:
{
QFontMetrics fm = style->fontMetrics();
#if 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; 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:
factor = dpiY*12./72.;
break;
default:
return -1;
}
return getFloatValue(type)*factor;
}
void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode )
{
exceptioncode = 0;
cleanup();
if(m_type > CSSPrimitiveValue::CSS_DIMENSION) {
exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
return;
}
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 || 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;
}
}
DOMString CSSPrimitiveValueImpl::getStringValue() const
{
switch (m_type) {
case CSSPrimitiveValue::CSS_STRING:
case CSSPrimitiveValue::CSS_ATTR:
case CSSPrimitiveValue::CSS_URI:
return m_value.string;
case CSSPrimitiveValue::CSS_IDENT:
return getValueName(m_value.ident);
default:
break;
}
return DOMString();
}
unsigned short CSSPrimitiveValueImpl::cssValueType() const
{
return CSSValue::CSS_PRIMITIVE_VALUE;
}
bool CSSPrimitiveValueImpl::parseString( const DOMString &, bool )
{
return false;
}
int CSSPrimitiveValueImpl::getIdent()
{
if(m_type != CSSPrimitiveValue::CSS_IDENT) return 0;
return m_value.ident;
}
DOM::DOMString CSSPrimitiveValueImpl::cssText() const
{
DOMString text;
switch ( m_type ) {
case CSSPrimitiveValue::CSS_UNKNOWN:
break;
case CSSPrimitiveValue::CSS_NUMBER:
text = DOMString(QString::number( 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:
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: {
QColor color(m_value.rgbcolor);
if (qAlpha(m_value.rgbcolor) < 0xFF)
text = "rgba(";
else
text = "rgb(";
text += QString::number(color.red()) + ", ";
text += QString::number(color.green()) + ", ";
text += QString::number(color.blue());
if (qAlpha(m_value.rgbcolor) < 0xFF)
text += ", " + QString::number((float)qAlpha(m_value.rgbcolor) / 0xFF);
text += ")";
break;
}
#if APPLE_CHANGES
case CSSPrimitiveValue::CSS_DASHBOARD_REGION: {
DashboardRegionImpl *region = getDashboardRegionValue();
while (region) {
text = "dashboard-region(";
text += region->m_label;
if (region->m_isCircle){
text += " circle ";
}
else if (region->m_isRectangle){
text += " rectangle ";
}
else
break;
text += region->top()->cssText() + " ";
text += region->right()->cssText() + " ";
text += region->bottom()->cssText() + " ";
text += region->left()->cssText();
text += ")";
region = region->m_next;
}
break;
}
#endif
}
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;
}
CSSImageValueImpl::CSSImageValueImpl(const DOMString &url, StyleBaseImpl *style)
: CSSPrimitiveValueImpl(url, CSSPrimitiveValue::CSS_URI), m_image(0), m_accessedImage(false)
{
}
CSSImageValueImpl::CSSImageValueImpl()
: CSSPrimitiveValueImpl(CSS_VAL_NONE), m_image(0), m_accessedImage(true)
{
}
CSSImageValueImpl::~CSSImageValueImpl()
{
if(m_image) m_image->deref(this);
}
khtml::CachedImage* CSSImageValueImpl::image(khtml::DocLoader* loader)
{
if (!m_accessedImage) {
m_accessedImage = true;
if (loader)
m_image = loader->requestImage(getStringValue());
else
m_image = khtml::Cache::requestImage(0, getStringValue());
if(m_image) m_image->ref(this);
}
return m_image;
}
FontFamilyValueImpl::FontFamilyValueImpl( const QString &string)
: CSSPrimitiveValueImpl( DOMString(), CSSPrimitiveValue::CSS_STRING)
{
static const QRegExp parenReg(" \\(.*\\)$");
static const QRegExp braceReg(" \\[.*\\]$");
#if APPLE_CHANGES
parsedFontName = string;
parsedFontName.replace(parenReg, "");
parsedFontName.replace(braceReg, "");
#else
const QString &available = KHTMLSettings::availableFamilies();
QString face = string.lower();
face = face.replace(parenReg, "");
face = face.replace(braceReg, "");
int pos = available.find( face, 0, false );
if( pos == -1 ) {
QString str = face;
int p = face.find(' ');
if ( p != -1 ) {
if(p > 0 && (int)str.length() - p > p + 1)
str = str.mid( p+1 );
else
str.truncate( p );
pos = available.find( str, 0, false);
}
}
if ( pos != -1 ) {
int pos1 = available.findRev( ',', pos ) + 1;
pos = available.find( ',', pos );
if ( pos == -1 )
pos = available.length();
parsedFontName = available.mid( pos1, pos - pos1 );
}
#endif // !APPLE_CHANGES
}
DOM::DOMString FontFamilyValueImpl::cssText() const
{
return quoteStringIfNeeded(parsedFontName);
}
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
{
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;
}
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;
}
FlexGroupTransitionValueImpl::FlexGroupTransitionValueImpl()
:autoValue(true), group1(0), group2(0), length(0)
{}
FlexGroupTransitionValueImpl::FlexGroupTransitionValueImpl(unsigned int _group1,
unsigned int _group2,
CSSPrimitiveValueImpl* _length)
:autoValue(false), group1(_group1), group2(_group2), length(_length)
{}
FlexGroupTransitionValueImpl::~FlexGroupTransitionValueImpl()
{
delete length;
}
DOMString FlexGroupTransitionValueImpl::cssText() const
{
DOMString text(QString::number(group1));
if (group2) {
text += "/";
text += QString::number(group2);
}
if (length) {
text += " ";
text += length->cssText();
}
return text;
}
DOMString CSSProperty::cssText() const
{
return getPropertyName(m_id) + DOMString(": ") + m_value->cssText() + (m_bImportant ? DOMString(" !important") : DOMString()) + DOMString("; ");
}
bool operator==(const CSSProperty &a, const CSSProperty &b)
{
return a.m_id == b.m_id && a.m_bImportant == b.m_bImportant && a.m_value == b.m_value;
}
}