diff options
Diffstat (limited to 'WebCore/css')
135 files changed, 28161 insertions, 0 deletions
diff --git a/WebCore/css/CSSBorderImageValue.cpp b/WebCore/css/CSSBorderImageValue.cpp new file mode 100644 index 0000000..1f38997 --- /dev/null +++ b/WebCore/css/CSSBorderImageValue.cpp @@ -0,0 +1,64 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSBorderImageValue.h" + +#include "CSSImageValue.h" +#include "PlatformString.h" +#include "Rect.h" + +namespace WebCore { + +CSSBorderImageValue::CSSBorderImageValue(PassRefPtr<CSSImageValue> image, PassRefPtr<Rect> imageRect, int horizontalRule, int verticalRule) + : m_image(image) + , m_imageSliceRect(imageRect) + , m_horizontalSizeRule(horizontalRule) + , m_verticalSizeRule(verticalRule) +{ +} + +String CSSBorderImageValue::cssText() const +{ + // Image first. + String text(m_image->cssText()); + text += " "; + + // Now the rect, but it isn't really a rect, so we dump manually + text += m_imageSliceRect->top()->cssText(); + text += " "; + text += m_imageSliceRect->right()->cssText(); + text += " "; + text += m_imageSliceRect->bottom()->cssText(); + text += " "; + text += m_imageSliceRect->left()->cssText(); + + // Now the keywords. + text += " "; + text += CSSPrimitiveValue(m_horizontalSizeRule).cssText(); + text += " "; + text += CSSPrimitiveValue(m_verticalSizeRule).cssText(); + + return text; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSBorderImageValue.h b/WebCore/css/CSSBorderImageValue.h new file mode 100644 index 0000000..42372ff --- /dev/null +++ b/WebCore/css/CSSBorderImageValue.h @@ -0,0 +1,57 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSBorderImageValue_h +#define CSSBorderImageValue_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSImageValue; +class Rect; + +class CSSBorderImageValue : public CSSValue { +public: + CSSBorderImageValue(); + CSSBorderImageValue(PassRefPtr<CSSImageValue>, PassRefPtr<Rect>, int horizontalRule, int verticalRule); + + virtual String cssText() const; + +public: + // The border image. + RefPtr<CSSImageValue> m_image; + + // These four values are used to make "cuts" in the image. They can be numbers + // or percentages. + RefPtr<Rect> m_imageSliceRect; + + // Values for how to handle the scaling/stretching/tiling of the image slices. + int m_horizontalSizeRule; // Rule for how to adjust the widths of the top/middle/bottom + int m_verticalSizeRule; // Rule for how to adjust the heights of the left/middle/right +}; + +} // namespace WebCore + +#endif // CSSBorderImageValue_h diff --git a/WebCore/css/CSSCharsetRule.cpp b/WebCore/css/CSSCharsetRule.cpp new file mode 100644 index 0000000..ac04108 --- /dev/null +++ b/WebCore/css/CSSCharsetRule.cpp @@ -0,0 +1,43 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Alexey Proskuryakov (ap@macrules.ru) + * + * 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 "config.h" +#include "CSSCharsetRule.h" + +namespace WebCore { + +CSSCharsetRule::CSSCharsetRule(StyleBase* parent, const String& encoding) + : CSSRule(parent) + , m_encoding(encoding) +{ +} + +CSSCharsetRule::~CSSCharsetRule() +{ +} + +String CSSCharsetRule::cssText() const +{ + return "@charset \"" + m_encoding + "\";"; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSCharsetRule.h b/WebCore/css/CSSCharsetRule.h new file mode 100644 index 0000000..d860ed3 --- /dev/null +++ b/WebCore/css/CSSCharsetRule.h @@ -0,0 +1,55 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSCharsetRule_h +#define CSSCharsetRule_h + +#include "CSSRule.h" +#include "PlatformString.h" + +namespace WebCore { + +typedef int ExceptionCode; + +class CSSCharsetRule : public CSSRule { +public: + CSSCharsetRule(StyleBase* parent, const String& encoding); + virtual ~CSSCharsetRule(); + + virtual bool isCharsetRule() { return true; } + + String encoding() const { return m_encoding; } + void setEncoding(const String& encoding, ExceptionCode&) { m_encoding = encoding; } + + // Inherited from CSSRule + virtual unsigned short type() const { return CHARSET_RULE; } + + virtual String cssText() const; + +protected: + String m_encoding; +}; + +} // namespace WebCore + +#endif // CSSCharsetRule_h diff --git a/WebCore/css/CSSCharsetRule.idl b/WebCore/css/CSSCharsetRule.idl new file mode 100644 index 0000000..ebe659c --- /dev/null +++ b/WebCore/css/CSSCharsetRule.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=94180bad-a74e-4df9-adbc-6ce4e5b96155, + ImplementationUUID=354aa39e-ad53-4e9a-a927-80c3966c47f2 + ] CSSCharsetRule : CSSRule { +#if defined(LANGUAGE_OBJECTIVE_C) + readonly attribute [ConvertNullStringTo=Null] DOMString encoding; +#else + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString encoding + setter raises(DOMException); +#endif + }; + +} diff --git a/WebCore/css/CSSComputedStyleDeclaration.cpp b/WebCore/css/CSSComputedStyleDeclaration.cpp new file mode 100644 index 0000000..d848c1b --- /dev/null +++ b/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -0,0 +1,1042 @@ +/** + * + * Copyright (C) 2004 Zack Rusin <zack@kde.org> + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "config.h" +#include "CSSComputedStyleDeclaration.h" + +#include "CSSMutableStyleDeclaration.h" +#include "CSSPrimitiveValue.h" +#include "CSSPrimitiveValueMappings.h" +#include "CSSPropertyNames.h" +#include "CSSValueList.h" +#include "CachedImage.h" +#include "DashboardRegion.h" +#include "Document.h" +#include "ExceptionCode.h" +#include "Pair.h" +#include "RenderObject.h" +#include "ShadowValue.h" + +namespace WebCore { + +// List of all properties we know how to compute, omitting shorthands. +static const int computedProperties[] = { + CSS_PROP_BACKGROUND_ATTACHMENT, + CSS_PROP_BACKGROUND_COLOR, + CSS_PROP_BACKGROUND_IMAGE, + // more specific background-position-x/y are non-standard + CSS_PROP_BACKGROUND_POSITION, + CSS_PROP_BACKGROUND_REPEAT, + CSS_PROP_BORDER_BOTTOM_COLOR, + CSS_PROP_BORDER_BOTTOM_STYLE, + CSS_PROP_BORDER_BOTTOM_WIDTH, + CSS_PROP_BORDER_COLLAPSE, + CSS_PROP_BORDER_LEFT_COLOR, + CSS_PROP_BORDER_LEFT_STYLE, + CSS_PROP_BORDER_LEFT_WIDTH, + CSS_PROP_BORDER_RIGHT_COLOR, + CSS_PROP_BORDER_RIGHT_STYLE, + CSS_PROP_BORDER_RIGHT_WIDTH, + CSS_PROP_BORDER_TOP_COLOR, + CSS_PROP_BORDER_TOP_STYLE, + CSS_PROP_BORDER_TOP_WIDTH, + CSS_PROP_BOTTOM, + CSS_PROP_CAPTION_SIDE, + CSS_PROP_CLEAR, + CSS_PROP_COLOR, + CSS_PROP_CURSOR, + CSS_PROP_DIRECTION, + CSS_PROP_DISPLAY, + CSS_PROP_EMPTY_CELLS, + CSS_PROP_FLOAT, + CSS_PROP_FONT_FAMILY, + CSS_PROP_FONT_SIZE, + CSS_PROP_FONT_STYLE, + CSS_PROP_FONT_VARIANT, + CSS_PROP_FONT_WEIGHT, + CSS_PROP_HEIGHT, + CSS_PROP_LEFT, + CSS_PROP_LETTER_SPACING, + CSS_PROP_LINE_HEIGHT, + CSS_PROP_LIST_STYLE_IMAGE, + CSS_PROP_LIST_STYLE_POSITION, + CSS_PROP_LIST_STYLE_TYPE, + CSS_PROP_MARGIN_BOTTOM, + CSS_PROP_MARGIN_LEFT, + CSS_PROP_MARGIN_RIGHT, + CSS_PROP_MARGIN_TOP, + CSS_PROP_MAX_HEIGHT, + CSS_PROP_MAX_WIDTH, + CSS_PROP_MIN_HEIGHT, + CSS_PROP_MIN_WIDTH, + CSS_PROP_OPACITY, + CSS_PROP_ORPHANS, + CSS_PROP_OUTLINE_COLOR, + CSS_PROP_OUTLINE_STYLE, + CSS_PROP_OUTLINE_WIDTH, + CSS_PROP_OVERFLOW_X, + CSS_PROP_OVERFLOW_Y, + CSS_PROP_PADDING_BOTTOM, + CSS_PROP_PADDING_LEFT, + CSS_PROP_PADDING_RIGHT, + CSS_PROP_PADDING_TOP, + CSS_PROP_PAGE_BREAK_AFTER, + CSS_PROP_PAGE_BREAK_BEFORE, + CSS_PROP_PAGE_BREAK_INSIDE, + CSS_PROP_POSITION, + CSS_PROP_RESIZE, + CSS_PROP_RIGHT, + CSS_PROP_TABLE_LAYOUT, + CSS_PROP_TEXT_ALIGN, + CSS_PROP_TEXT_DECORATION, + CSS_PROP_TEXT_INDENT, + CSS_PROP_TEXT_SHADOW, + CSS_PROP_TEXT_TRANSFORM, + CSS_PROP_TOP, + CSS_PROP_UNICODE_BIDI, + CSS_PROP_VERTICAL_ALIGN, + CSS_PROP_VISIBILITY, + CSS_PROP_WHITE_SPACE, + CSS_PROP_WIDOWS, + CSS_PROP_WIDTH, + CSS_PROP_WORD_SPACING, + CSS_PROP_WORD_WRAP, + CSS_PROP_Z_INDEX, + + CSS_PROP__WEBKIT_APPEARANCE, + CSS_PROP__WEBKIT_BACKGROUND_CLIP, + CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE, + CSS_PROP__WEBKIT_BACKGROUND_ORIGIN, + CSS_PROP__WEBKIT_BACKGROUND_SIZE, + CSS_PROP__WEBKIT_BORDER_FIT, + CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING, + CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING, + CSS_PROP__WEBKIT_BOX_ALIGN, + CSS_PROP__WEBKIT_BOX_DIRECTION, + CSS_PROP__WEBKIT_BOX_FLEX, + CSS_PROP__WEBKIT_BOX_FLEX_GROUP, + CSS_PROP__WEBKIT_BOX_LINES, + CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP, + CSS_PROP__WEBKIT_BOX_ORIENT, + CSS_PROP__WEBKIT_BOX_PACK, + CSS_PROP__WEBKIT_BOX_SHADOW, + CSS_PROP__WEBKIT_BOX_SIZING, + CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER, + CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE, + CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE, + CSS_PROP__WEBKIT_COLUMN_COUNT, + CSS_PROP__WEBKIT_COLUMN_GAP, + CSS_PROP__WEBKIT_COLUMN_RULE_COLOR, + CSS_PROP__WEBKIT_COLUMN_RULE_STYLE, + CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, + CSS_PROP__WEBKIT_COLUMN_WIDTH, + CSS_PROP__WEBKIT_HIGHLIGHT, + CSS_PROP__WEBKIT_LINE_BREAK, + CSS_PROP__WEBKIT_LINE_CLAMP, + CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE, + CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE, + CSS_PROP__WEBKIT_MARQUEE_DIRECTION, + CSS_PROP__WEBKIT_MARQUEE_INCREMENT, + CSS_PROP__WEBKIT_MARQUEE_REPETITION, + CSS_PROP__WEBKIT_MARQUEE_STYLE, + CSS_PROP__WEBKIT_NBSP_MODE, + CSS_PROP__WEBKIT_RTL_ORDERING, + CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT, + CSS_PROP__WEBKIT_TEXT_FILL_COLOR, + CSS_PROP__WEBKIT_TEXT_SECURITY, + CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, + CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH, + CSS_PROP__WEBKIT_USER_DRAG, + CSS_PROP__WEBKIT_USER_MODIFY, + CSS_PROP__WEBKIT_USER_SELECT, + CSS_PROP__WEBKIT_DASHBOARD_REGION, + CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, + CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS + +#if ENABLE(SVG) + , + CSS_PROP_CLIP_PATH, + CSS_PROP_CLIP_RULE, + CSS_PROP_MASK, + CSS_PROP_FILTER, + CSS_PROP_FLOOD_COLOR, + CSS_PROP_FLOOD_OPACITY, + CSS_PROP_LIGHTING_COLOR, + CSS_PROP_STOP_COLOR, + CSS_PROP_STOP_OPACITY, + CSS_PROP_POINTER_EVENTS, + CSS_PROP_COLOR_INTERPOLATION, + CSS_PROP_COLOR_INTERPOLATION_FILTERS, + CSS_PROP_COLOR_RENDERING, + CSS_PROP_FILL, + CSS_PROP_FILL_OPACITY, + CSS_PROP_FILL_RULE, + CSS_PROP_IMAGE_RENDERING, + CSS_PROP_MARKER_END, + CSS_PROP_MARKER_MID, + CSS_PROP_MARKER_START, + CSS_PROP_SHAPE_RENDERING, + CSS_PROP_STROKE, + CSS_PROP_STROKE_DASHARRAY, + CSS_PROP_STROKE_DASHOFFSET, + CSS_PROP_STROKE_LINECAP, + CSS_PROP_STROKE_LINEJOIN, + CSS_PROP_STROKE_MITERLIMIT, + CSS_PROP_STROKE_OPACITY, + CSS_PROP_STROKE_WIDTH, + CSS_PROP_TEXT_RENDERING, + CSS_PROP_ALIGNMENT_BASELINE, + CSS_PROP_BASELINE_SHIFT, + CSS_PROP_DOMINANT_BASELINE, + CSS_PROP_KERNING, + CSS_PROP_TEXT_ANCHOR, + CSS_PROP_WRITING_MODE, + CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL, + CSS_PROP_GLYPH_ORIENTATION_VERTICAL +#endif +}; + +const unsigned numComputedProperties = sizeof(computedProperties) / sizeof(computedProperties[0]); + +static PassRefPtr<CSSValue> valueForShadow(const ShadowData* shadow) +{ + if (!shadow) + return new CSSPrimitiveValue(CSS_VAL_NONE); + + RefPtr<CSSValueList> list = new CSSValueList; + for (const ShadowData* s = shadow; s; s = s->next) { + RefPtr<CSSPrimitiveValue> x = new CSSPrimitiveValue(s->x, CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> y = new CSSPrimitiveValue(s->y, CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> blur = new CSSPrimitiveValue(s->blur, CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> color = new CSSPrimitiveValue(s->color.rgb()); + list->append(new ShadowValue(x.release(), y.release(), blur.release(), color.release())); + } + return list.release(); +} + +static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int propertyID) +{ + if (!style) + return 0; + + Length l; + switch (propertyID) { + case CSS_PROP_LEFT: + l = style->left(); + break; + case CSS_PROP_RIGHT: + l = style->right(); + break; + case CSS_PROP_TOP: + l = style->top(); + break; + case CSS_PROP_BOTTOM: + l = style->bottom(); + break; + default: + return 0; + } + + if (style->position() == AbsolutePosition || style->position() == FixedPosition) + return new CSSPrimitiveValue(l); + + if (style->position() == RelativePosition) + // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined. + // In other words if left is auto and right is not auto, then left's computed value is negative right. + // So we should get the opposite length unit and see if it is auto. + return new CSSPrimitiveValue(l); + + return new CSSPrimitiveValue(CSS_VAL_AUTO); +} + +static PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle* style, const Color& color) +{ + if (!color.isValid()) + return new CSSPrimitiveValue(style->color().rgb()); + return new CSSPrimitiveValue(color.rgb()); +} + +static PassRefPtr<CSSValue> getBorderRadiusCornerValue(IntSize radius) +{ + if (radius.width() == radius.height()) + return new CSSPrimitiveValue(radius.width(), CSSPrimitiveValue::CSS_PX); + + RefPtr<CSSValueList> list = new CSSValueList(true); + list->append(new CSSPrimitiveValue(radius.width(), CSSPrimitiveValue::CSS_PX)); + list->append(new CSSPrimitiveValue(radius.height(), CSSPrimitiveValue::CSS_PX)); + return list.release(); +} + +static IntRect sizingBox(RenderObject* renderer) +{ + return renderer->style()->boxSizing() == CONTENT_BOX ? renderer->contentBox() : renderer->borderBox(); +} + +CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n) + : m_node(n) +{ +} + +CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() +{ +} + +String CSSComputedStyleDeclaration::cssText() const +{ + String result(""); + + for (unsigned i = 0; i < numComputedProperties; i++) { + if (i) + result += " "; + result += getPropertyName(static_cast<CSSPropertyID>(computedProperties[i])); + result += ": "; + result += getPropertyValue(computedProperties[i]); + result += ";"; + } + + return result; +} + +void CSSComputedStyleDeclaration::setCssText(const String&, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int propertyID) const +{ + return getPropertyCSSValue(propertyID, UpdateLayout); +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const +{ + Node* node = m_node.get(); + if (!node) + return 0; + + // Make sure our layout is up to date before we allow a query on these attributes. + if (updateLayout) + node->document()->updateLayoutIgnorePendingStylesheets(); + + RenderObject* renderer = node->renderer(); + + RenderStyle* style = node->computedStyle(); + if (!style) + return 0; + + switch (static_cast<CSSPropertyID>(propertyID)) { + case CSS_PROP_INVALID: + break; + + case CSS_PROP_BACKGROUND_COLOR: + return new CSSPrimitiveValue(style->backgroundColor().rgb()); + case CSS_PROP_BACKGROUND_IMAGE: + if (style->backgroundImage()) + return new CSSPrimitiveValue(style->backgroundImage()->url(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP__WEBKIT_BACKGROUND_SIZE: { + RefPtr<CSSValueList> list = new CSSValueList(true); + list->append(new CSSPrimitiveValue(style->backgroundSize().width)); + list->append(new CSSPrimitiveValue(style->backgroundSize().height)); + return list.release(); + } + case CSS_PROP_BACKGROUND_REPEAT: + return new CSSPrimitiveValue(style->backgroundRepeat()); + case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: + return new CSSPrimitiveValue(style->backgroundComposite()); + case CSS_PROP_BACKGROUND_ATTACHMENT: + if (style->backgroundAttachment()) + return new CSSPrimitiveValue(CSS_VAL_SCROLL); + return new CSSPrimitiveValue(CSS_VAL_FIXED); + case CSS_PROP__WEBKIT_BACKGROUND_CLIP: + case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN: { + EBackgroundBox box = (propertyID == CSS_PROP__WEBKIT_BACKGROUND_CLIP ? style->backgroundClip() : style->backgroundOrigin()); + return new CSSPrimitiveValue(box); + } + case CSS_PROP_BACKGROUND_POSITION: { + RefPtr<CSSValueList> list = new CSSValueList(true); + + list->append(new CSSPrimitiveValue(style->backgroundXPosition())); + list->append(new CSSPrimitiveValue(style->backgroundYPosition())); + + return list.release(); + } + case CSS_PROP_BACKGROUND_POSITION_X: + return new CSSPrimitiveValue(style->backgroundXPosition()); + case CSS_PROP_BACKGROUND_POSITION_Y: + return new CSSPrimitiveValue(style->backgroundYPosition()); + case CSS_PROP_BORDER_COLLAPSE: + if (style->borderCollapse()) + return new CSSPrimitiveValue(CSS_VAL_COLLAPSE); + return new CSSPrimitiveValue(CSS_VAL_SEPARATE); + case CSS_PROP_BORDER_SPACING: { + RefPtr<CSSValueList> list = new CSSValueList(true); + list->append(new CSSPrimitiveValue(style->horizontalBorderSpacing(), CSSPrimitiveValue::CSS_PX)); + list->append(new CSSPrimitiveValue(style->verticalBorderSpacing(), CSSPrimitiveValue::CSS_PX)); + return list.release(); + } + case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: + return new CSSPrimitiveValue(style->horizontalBorderSpacing(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: + return new CSSPrimitiveValue(style->verticalBorderSpacing(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_BORDER_TOP_COLOR: + return currentColorOrValidColor(style, style->borderTopColor()); + case CSS_PROP_BORDER_RIGHT_COLOR: + return currentColorOrValidColor(style, style->borderRightColor()); + case CSS_PROP_BORDER_BOTTOM_COLOR: + return currentColorOrValidColor(style, style->borderBottomColor()); + case CSS_PROP_BORDER_LEFT_COLOR: + return currentColorOrValidColor(style, style->borderLeftColor()); + case CSS_PROP_BORDER_TOP_STYLE: + return new CSSPrimitiveValue(style->borderTopStyle()); + case CSS_PROP_BORDER_RIGHT_STYLE: + return new CSSPrimitiveValue(style->borderRightStyle()); + case CSS_PROP_BORDER_BOTTOM_STYLE: + return new CSSPrimitiveValue(style->borderBottomStyle()); + case CSS_PROP_BORDER_LEFT_STYLE: + return new CSSPrimitiveValue(style->borderLeftStyle()); + case CSS_PROP_BORDER_TOP_WIDTH: + return new CSSPrimitiveValue(style->borderTopWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_BORDER_RIGHT_WIDTH: + return new CSSPrimitiveValue(style->borderRightWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_BORDER_BOTTOM_WIDTH: + return new CSSPrimitiveValue(style->borderBottomWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_BORDER_LEFT_WIDTH: + return new CSSPrimitiveValue(style->borderLeftWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_BOTTOM: + return getPositionOffsetValue(style, CSS_PROP_BOTTOM); + case CSS_PROP__WEBKIT_BOX_ALIGN: + return new CSSPrimitiveValue(style->boxAlign()); + case CSS_PROP__WEBKIT_BOX_DIRECTION: + return new CSSPrimitiveValue(style->boxDirection()); + case CSS_PROP__WEBKIT_BOX_FLEX: + return new CSSPrimitiveValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_BOX_FLEX_GROUP: + return new CSSPrimitiveValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_BOX_LINES: + return new CSSPrimitiveValue(style->boxLines()); + case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP: + return new CSSPrimitiveValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_BOX_ORIENT: + return new CSSPrimitiveValue(style->boxOrient()); + case CSS_PROP__WEBKIT_BOX_PACK: { + EBoxAlignment boxPack = style->boxPack(); + ASSERT(boxPack != BSTRETCH); + ASSERT(boxPack != BBASELINE); + if (boxPack == BJUSTIFY || boxPack== BBASELINE) + return 0; + return new CSSPrimitiveValue(boxPack); + } + case CSS_PROP__WEBKIT_BOX_SHADOW: + return valueForShadow(style->boxShadow()); + case CSS_PROP_CAPTION_SIDE: + return new CSSPrimitiveValue(style->captionSide()); + case CSS_PROP_CLEAR: + return new CSSPrimitiveValue(style->clear()); + case CSS_PROP_COLOR: + return new CSSPrimitiveValue(style->color().rgb()); + case CSS_PROP__WEBKIT_COLUMN_COUNT: + if (style->hasAutoColumnCount()) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + return new CSSPrimitiveValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_COLUMN_GAP: + if (style->hasNormalColumnGap()) + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + return new CSSPrimitiveValue(style->columnGap(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: + return currentColorOrValidColor(style, style->columnRuleColor()); + case CSS_PROP__WEBKIT_COLUMN_RULE_STYLE: + return new CSSPrimitiveValue(style->columnRuleStyle()); + case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: + return new CSSPrimitiveValue(style->columnRuleWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER: + return new CSSPrimitiveValue(style->columnBreakAfter()); + case CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE: + return new CSSPrimitiveValue(style->columnBreakBefore()); + case CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE: + return new CSSPrimitiveValue(style->columnBreakInside()); + case CSS_PROP__WEBKIT_COLUMN_WIDTH: + if (style->hasAutoColumnWidth()) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + return new CSSPrimitiveValue(style->columnWidth(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_CURSOR: { + RefPtr<CSSValueList> list; + CursorList* cursors = style->cursors(); + if (cursors && cursors->size() > 0) { + list = new CSSValueList; + for (unsigned i = 0; i < cursors->size(); ++i) + list->append(new CSSPrimitiveValue((*cursors)[i].cursorImage->url(), CSSPrimitiveValue::CSS_URI)); + } + RefPtr<CSSValue> value = new CSSPrimitiveValue(style->cursor()); + if (list) { + list->append(value); + return list.release(); + } + return value.release(); + } + case CSS_PROP_DIRECTION: + return new CSSPrimitiveValue(style->direction()); + case CSS_PROP_DISPLAY: + return new CSSPrimitiveValue(style->display()); + case CSS_PROP_EMPTY_CELLS: + return new CSSPrimitiveValue(style->emptyCells()); + case CSS_PROP_FLOAT: + return new CSSPrimitiveValue(style->floating()); + case CSS_PROP_FONT_FAMILY: + // FIXME: This only returns the first family. + return new CSSPrimitiveValue(style->fontDescription().family().family().string(), CSSPrimitiveValue::CSS_STRING); + case CSS_PROP_FONT_SIZE: + return new CSSPrimitiveValue(style->fontDescription().computedPixelSize(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP__WEBKIT_BINDING: + break; + case CSS_PROP_FONT_STYLE: + if (style->fontDescription().italic()) + return new CSSPrimitiveValue(CSS_VAL_ITALIC); + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + case CSS_PROP_FONT_VARIANT: + if (style->fontDescription().smallCaps()) + return new CSSPrimitiveValue(CSS_VAL_SMALL_CAPS); + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + case CSS_PROP_FONT_WEIGHT: + // FIXME: this does not reflect the full range of weights + // that can be expressed with CSS + if (style->fontDescription().weight() == cBoldWeight) + return new CSSPrimitiveValue(CSS_VAL_BOLD); + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + case CSS_PROP_HEIGHT: + if (renderer) + return new CSSPrimitiveValue(sizingBox(renderer).height(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->height()); + case CSS_PROP__WEBKIT_HIGHLIGHT: + if (style->highlight() == nullAtom) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(style->highlight(), CSSPrimitiveValue::CSS_STRING); + case CSS_PROP__WEBKIT_BORDER_FIT: + if (style->borderFit() == BorderFitBorder) + return new CSSPrimitiveValue(CSS_VAL_BORDER); + return new CSSPrimitiveValue(CSS_VAL_LINES); + case CSS_PROP_LEFT: + return getPositionOffsetValue(style, CSS_PROP_LEFT); + case CSS_PROP_LETTER_SPACING: + if (!style->letterSpacing()) + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + return new CSSPrimitiveValue(style->letterSpacing(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP__WEBKIT_LINE_CLAMP: + if (style->lineClamp() == -1) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(style->lineClamp(), CSSPrimitiveValue::CSS_PERCENTAGE); + case CSS_PROP_LINE_HEIGHT: { + Length length = style->lineHeight(); + if (length.isNegative()) + return new CSSPrimitiveValue(CSS_VAL_NORMAL); + if (length.isPercent()) + // This is imperfect, because it doesn't include the zoom factor and the real computation + // for how high to be in pixels does include things like minimum font size and the zoom factor. + // On the other hand, since font-size doesn't include the zoom factor, we really can't do + // that here either. + return new CSSPrimitiveValue(static_cast<int>(length.percent() * style->fontDescription().specifiedSize()) / 100, CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(length.value(), CSSPrimitiveValue::CSS_PX); + } + case CSS_PROP_LIST_STYLE_IMAGE: + if (style->listStyleImage()) + return new CSSPrimitiveValue(style->listStyleImage()->url(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_LIST_STYLE_POSITION: + return new CSSPrimitiveValue(style->listStylePosition()); + case CSS_PROP_LIST_STYLE_TYPE: + return new CSSPrimitiveValue(style->listStyleType()); + case CSS_PROP_MARGIN_TOP: + if (renderer) + // FIXME: Supposed to return the percentage if percentage was specified. + return new CSSPrimitiveValue(renderer->marginTop(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->marginTop()); + case CSS_PROP_MARGIN_RIGHT: + if (renderer) + // FIXME: Supposed to return the percentage if percentage was specified. + return new CSSPrimitiveValue(renderer->marginRight(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->marginRight()); + case CSS_PROP_MARGIN_BOTTOM: + if (renderer) + // FIXME: Supposed to return the percentage if percentage was specified. + return new CSSPrimitiveValue(renderer->marginBottom(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->marginBottom()); + case CSS_PROP_MARGIN_LEFT: + if (renderer) + // FIXME: Supposed to return the percentage if percentage was specified. + return new CSSPrimitiveValue(renderer->marginLeft(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->marginLeft()); + case CSS_PROP__WEBKIT_MARQUEE_DIRECTION: + return new CSSPrimitiveValue(style->marqueeDirection()); + case CSS_PROP__WEBKIT_MARQUEE_INCREMENT: + return new CSSPrimitiveValue(style->marqueeIncrement()); + case CSS_PROP__WEBKIT_MARQUEE_REPETITION: + if (style->marqueeLoopCount() < 0) + return new CSSPrimitiveValue(CSS_VAL_INFINITE); + return new CSSPrimitiveValue(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_MARQUEE_STYLE: + return new CSSPrimitiveValue(style->marqueeBehavior()); + case CSS_PROP__WEBKIT_USER_MODIFY: + return new CSSPrimitiveValue(style->userModify()); + case CSS_PROP_MAX_HEIGHT: { + const Length& maxHeight = style->maxHeight(); + if (maxHeight.isFixed() && maxHeight.value() == undefinedLength) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(maxHeight); + } + case CSS_PROP_MAX_WIDTH: { + const Length& maxWidth = style->maxHeight(); + if (maxWidth.isFixed() && maxWidth.value() == undefinedLength) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(maxWidth); + } + case CSS_PROP_MIN_HEIGHT: + return new CSSPrimitiveValue(style->minHeight()); + case CSS_PROP_MIN_WIDTH: + return new CSSPrimitiveValue(style->minWidth()); + case CSS_PROP_OPACITY: + return new CSSPrimitiveValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_ORPHANS: + return new CSSPrimitiveValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_OUTLINE_COLOR: + return currentColorOrValidColor(style, style->outlineColor()); + case CSS_PROP_OUTLINE_STYLE: + if (style->outlineStyleIsAuto()) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + return new CSSPrimitiveValue(style->outlineStyle()); + case CSS_PROP_OUTLINE_WIDTH: + return new CSSPrimitiveValue(style->outlineWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_OVERFLOW: + return new CSSPrimitiveValue(max(style->overflowX(), style->overflowY())); + case CSS_PROP_OVERFLOW_X: + return new CSSPrimitiveValue(style->overflowX()); + case CSS_PROP_OVERFLOW_Y: + return new CSSPrimitiveValue(style->overflowY()); + case CSS_PROP_PADDING_TOP: + if (renderer) + return new CSSPrimitiveValue(renderer->paddingTop(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->paddingTop()); + case CSS_PROP_PADDING_RIGHT: + if (renderer) + return new CSSPrimitiveValue(renderer->paddingRight(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->paddingRight()); + case CSS_PROP_PADDING_BOTTOM: + if (renderer) + return new CSSPrimitiveValue(renderer->paddingBottom(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->paddingBottom()); + case CSS_PROP_PADDING_LEFT: + if (renderer) + return new CSSPrimitiveValue(renderer->paddingLeft(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->paddingLeft()); + case CSS_PROP_PAGE_BREAK_AFTER: + return new CSSPrimitiveValue(style->pageBreakAfter()); + case CSS_PROP_PAGE_BREAK_BEFORE: + return new CSSPrimitiveValue(style->pageBreakBefore()); + case CSS_PROP_PAGE_BREAK_INSIDE: { + EPageBreak pageBreak = style->pageBreakInside(); + ASSERT(pageBreak != PBALWAYS); + if (pageBreak == PBALWAYS) + return 0; + return new CSSPrimitiveValue(style->pageBreakInside()); + } + case CSS_PROP_POSITION: + return new CSSPrimitiveValue(style->position()); + case CSS_PROP_RIGHT: + return getPositionOffsetValue(style, CSS_PROP_RIGHT); + case CSS_PROP_TABLE_LAYOUT: + return new CSSPrimitiveValue(style->tableLayout()); + case CSS_PROP_TEXT_ALIGN: + return new CSSPrimitiveValue(style->textAlign()); + case CSS_PROP_TEXT_DECORATION: { + String string; + if (style->textDecoration() & UNDERLINE) + string += "underline"; + if (style->textDecoration() & OVERLINE) { + if (string.length()) + string += " "; + string += "overline"; + } + if (style->textDecoration() & LINE_THROUGH) { + if (string.length()) + string += " "; + string += "line-through"; + } + if (style->textDecoration() & BLINK) { + if (string.length()) + string += " "; + string += "blink"; + } + if (!string.length()) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(string, CSSPrimitiveValue::CSS_STRING); + } + case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT: { + String string; + if (style->textDecorationsInEffect() & UNDERLINE) + string += "underline"; + if (style->textDecorationsInEffect() & OVERLINE) { + if (string.length()) + string += " "; + string += "overline"; + } + if (style->textDecorationsInEffect() & LINE_THROUGH) { + if (string.length()) + string += " "; + string += "line-through"; + } + if (style->textDecorationsInEffect() & BLINK) { + if (string.length()) + string += " "; + string += "blink"; + } + if (!string.length()) + return new CSSPrimitiveValue(CSS_VAL_NONE); + return new CSSPrimitiveValue(string, CSSPrimitiveValue::CSS_STRING); + } + case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: + return currentColorOrValidColor(style, style->textFillColor()); + case CSS_PROP_TEXT_INDENT: + return new CSSPrimitiveValue(style->textIndent()); + case CSS_PROP_TEXT_SHADOW: + return valueForShadow(style->textShadow()); + case CSS_PROP__WEBKIT_TEXT_SECURITY: + return new CSSPrimitiveValue(style->textSecurity()); + case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: + if (style->textSizeAdjust()) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: + return currentColorOrValidColor(style, style->textStrokeColor()); + case CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH: + return new CSSPrimitiveValue(style->textStrokeWidth(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_TEXT_TRANSFORM: + return new CSSPrimitiveValue(style->textTransform()); + case CSS_PROP_TOP: + return getPositionOffsetValue(style, CSS_PROP_TOP); + case CSS_PROP_UNICODE_BIDI: + return new CSSPrimitiveValue(style->unicodeBidi()); + case CSS_PROP_VERTICAL_ALIGN: + switch (style->verticalAlign()) { + case BASELINE: + return new CSSPrimitiveValue(CSS_VAL_BASELINE); + case MIDDLE: + return new CSSPrimitiveValue(CSS_VAL_MIDDLE); + case SUB: + return new CSSPrimitiveValue(CSS_VAL_SUB); + case SUPER: + return new CSSPrimitiveValue(CSS_VAL_SUPER); + case TEXT_TOP: + return new CSSPrimitiveValue(CSS_VAL_TEXT_TOP); + case TEXT_BOTTOM: + return new CSSPrimitiveValue(CSS_VAL_TEXT_BOTTOM); + case TOP: + return new CSSPrimitiveValue(CSS_VAL_TOP); + case BOTTOM: + return new CSSPrimitiveValue(CSS_VAL_BOTTOM); + case BASELINE_MIDDLE: + return new CSSPrimitiveValue(CSS_VAL__WEBKIT_BASELINE_MIDDLE); + case LENGTH: + return new CSSPrimitiveValue(style->verticalAlignLength()); + } + ASSERT_NOT_REACHED(); + return 0; + case CSS_PROP_VISIBILITY: + return new CSSPrimitiveValue(style->visibility()); + case CSS_PROP_WHITE_SPACE: + return new CSSPrimitiveValue(style->whiteSpace()); + case CSS_PROP_WIDOWS: + return new CSSPrimitiveValue(style->widows(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_WIDTH: + if (renderer) + return new CSSPrimitiveValue(sizingBox(renderer).width(), CSSPrimitiveValue::CSS_PX); + return new CSSPrimitiveValue(style->width()); + case CSS_PROP_WORD_BREAK: + return new CSSPrimitiveValue(style->wordBreak()); + case CSS_PROP_WORD_SPACING: + return new CSSPrimitiveValue(style->wordSpacing(), CSSPrimitiveValue::CSS_PX); + case CSS_PROP_WORD_WRAP: + return new CSSPrimitiveValue(style->wordWrap()); + case CSS_PROP__WEBKIT_LINE_BREAK: + return new CSSPrimitiveValue(style->khtmlLineBreak()); + case CSS_PROP__WEBKIT_NBSP_MODE: + return new CSSPrimitiveValue(style->nbspMode()); + case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: + return new CSSPrimitiveValue(style->matchNearestMailBlockquoteColor()); + case CSS_PROP_RESIZE: + return new CSSPrimitiveValue(style->resize()); + case CSS_PROP_Z_INDEX: + if (style->hasAutoZIndex()) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + return new CSSPrimitiveValue(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP__WEBKIT_BOX_SIZING: + if (style->boxSizing() == CONTENT_BOX) + return new CSSPrimitiveValue(CSS_VAL_CONTENT_BOX); + return new CSSPrimitiveValue(CSS_VAL_BORDER_BOX); + case CSS_PROP__WEBKIT_DASHBOARD_REGION: + { + const Vector<StyleDashboardRegion>& regions = style->dashboardRegions(); + unsigned count = regions.size(); + if (count == 1 && regions[0].type == StyleDashboardRegion::None) + return new CSSPrimitiveValue(CSS_VAL_NONE); + + RefPtr<DashboardRegion> firstRegion; + DashboardRegion* previousRegion = 0; + for (unsigned i = 0; i < count; i++) { + RefPtr<DashboardRegion> region = new DashboardRegion; + StyleDashboardRegion styleRegion = regions[i]; + + region->m_label = styleRegion.label; + LengthBox offset = styleRegion.offset; + region->setTop(new CSSPrimitiveValue(offset.top.value(), CSSPrimitiveValue::CSS_PX)); + region->setRight(new CSSPrimitiveValue(offset.right.value(), CSSPrimitiveValue::CSS_PX)); + region->setBottom(new CSSPrimitiveValue(offset.bottom.value(), CSSPrimitiveValue::CSS_PX)); + region->setLeft(new CSSPrimitiveValue(offset.left.value(), CSSPrimitiveValue::CSS_PX)); + region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle); + region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle); + + if (previousRegion) + previousRegion->m_next = region; + else + firstRegion = region; + previousRegion = region.get(); + } + return new CSSPrimitiveValue(firstRegion.release()); + } + case CSS_PROP__WEBKIT_APPEARANCE: + return new CSSPrimitiveValue(style->appearance()); + case CSS_PROP__WEBKIT_FONT_SIZE_DELTA: + // Not a real style property -- used by the editing engine -- so has no computed value. + break; + case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE: + return new CSSPrimitiveValue(style->marginBottomCollapse()); + case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE: + return new CSSPrimitiveValue(style->marginTopCollapse()); + case CSS_PROP__WEBKIT_RTL_ORDERING: + if (style->visuallyOrdered()) + return new CSSPrimitiveValue(CSS_VAL_VISUAL); + return new CSSPrimitiveValue(CSS_VAL_LOGICAL); + case CSS_PROP__WEBKIT_USER_DRAG: + return new CSSPrimitiveValue(style->userDrag()); + case CSS_PROP__WEBKIT_USER_SELECT: + return new CSSPrimitiveValue(style->userSelect()); + case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: + return getBorderRadiusCornerValue(style->borderBottomLeftRadius()); + case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: + return getBorderRadiusCornerValue(style->borderBottomRightRadius()); + case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: + return getBorderRadiusCornerValue(style->borderTopLeftRadius()); + case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: + return getBorderRadiusCornerValue(style->borderTopRightRadius()); + case CSS_PROP_BACKGROUND: + case CSS_PROP_BORDER: + case CSS_PROP_BORDER_BOTTOM: + case CSS_PROP_BORDER_COLOR: + case CSS_PROP_BORDER_LEFT: + case CSS_PROP_BORDER_RIGHT: + case CSS_PROP_BORDER_STYLE: + case CSS_PROP_BORDER_TOP: + case CSS_PROP_BORDER_WIDTH: + case CSS_PROP_CLIP: + case CSS_PROP_CONTENT: + case CSS_PROP_COUNTER_INCREMENT: + case CSS_PROP_COUNTER_RESET: + case CSS_PROP_FONT: + case CSS_PROP_FONT_STRETCH: + case CSS_PROP_LIST_STYLE: + case CSS_PROP_MARGIN: + case CSS_PROP_OUTLINE: + case CSS_PROP_OUTLINE_OFFSET: + case CSS_PROP_PADDING: + case CSS_PROP_PAGE: + case CSS_PROP_QUOTES: + case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: + case CSS_PROP_SCROLLBAR_ARROW_COLOR: + case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: + case CSS_PROP_SCROLLBAR_FACE_COLOR: + case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: + case CSS_PROP_SCROLLBAR_SHADOW_COLOR: + case CSS_PROP_SCROLLBAR_TRACK_COLOR: + case CSS_PROP_SRC: // Only used in @font-face rules. + case CSS_PROP_SIZE: + case CSS_PROP_TEXT_LINE_THROUGH: + case CSS_PROP_TEXT_LINE_THROUGH_COLOR: + case CSS_PROP_TEXT_LINE_THROUGH_MODE: + case CSS_PROP_TEXT_LINE_THROUGH_STYLE: + case CSS_PROP_TEXT_LINE_THROUGH_WIDTH: + case CSS_PROP_TEXT_OVERFLOW: + case CSS_PROP_TEXT_OVERLINE: + case CSS_PROP_TEXT_OVERLINE_COLOR: + case CSS_PROP_TEXT_OVERLINE_MODE: + case CSS_PROP_TEXT_OVERLINE_STYLE: + case CSS_PROP_TEXT_OVERLINE_WIDTH: + case CSS_PROP_TEXT_UNDERLINE: + case CSS_PROP_TEXT_UNDERLINE_COLOR: + case CSS_PROP_TEXT_UNDERLINE_MODE: + case CSS_PROP_TEXT_UNDERLINE_STYLE: + case CSS_PROP_TEXT_UNDERLINE_WIDTH: + case CSS_PROP_UNICODE_RANGE: // Only used in @font-face rules. + case CSS_PROP__WEBKIT_BORDER_IMAGE: + case CSS_PROP__WEBKIT_BORDER_RADIUS: + case CSS_PROP__WEBKIT_COLUMNS: + case CSS_PROP__WEBKIT_COLUMN_RULE: + case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: + case CSS_PROP__WEBKIT_MARGIN_START: + case CSS_PROP__WEBKIT_MARQUEE: + case CSS_PROP__WEBKIT_MARQUEE_SPEED: + case CSS_PROP__WEBKIT_PADDING_START: + case CSS_PROP__WEBKIT_TEXT_STROKE: + case CSS_PROP__WEBKIT_TRANSFORM: + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN: + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_X: + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_Y: + case CSS_PROP__WEBKIT_TRANSITION: + case CSS_PROP__WEBKIT_TRANSITION_DURATION: + case CSS_PROP__WEBKIT_TRANSITION_PROPERTY: + case CSS_PROP__WEBKIT_TRANSITION_REPEAT_COUNT: + case CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION: + // FIXME: The above are unimplemented. + break; +#if ENABLE(SVG) + default: + return getSVGPropertyCSSValue(propertyID, DoNotUpdateLayout); +#endif + } + + LOG_ERROR("unimplemented propertyID: %d", propertyID); + return 0; +} + +String CSSComputedStyleDeclaration::getPropertyValue(int propertyID) const +{ + RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); + if (value) + return value->cssText(); + return ""; +} + +bool CSSComputedStyleDeclaration::getPropertyPriority(int /*propertyID*/) const +{ + // All computed styles have a priority of false (not "important"). + return false; +} + +String CSSComputedStyleDeclaration::removeProperty(int /*propertyID*/, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; + return String(); +} + +void CSSComputedStyleDeclaration::setProperty(int /*propertyID*/, const String& /*value*/, bool /*important*/, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; +} + +unsigned CSSComputedStyleDeclaration::length() const +{ + Node* node = m_node.get(); + if (!node) + return 0; + + RenderStyle* style = node->computedStyle(); + if (!style) + return 0; + + return numComputedProperties; +} + +String CSSComputedStyleDeclaration::item(unsigned i) const +{ + if (i >= length()) + return String(); + + return getPropertyName(static_cast<CSSPropertyID>(computedProperties[i])); +} + +// This is the list of properties we want to copy in the copyInheritableProperties() function. +// It is the intersection of the list of inherited CSS properties and the +// properties for which we have a computed implementation in this file. +const int inheritableProperties[] = { + CSS_PROP_BORDER_COLLAPSE, + 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_ORPHANS, + CSS_PROP_TEXT_ALIGN, + CSS_PROP_TEXT_INDENT, + CSS_PROP_TEXT_TRANSFORM, + CSS_PROP_WHITE_SPACE, + CSS_PROP_WIDOWS, + CSS_PROP_WORD_SPACING, + CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING, + CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING, + CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT, + CSS_PROP__WEBKIT_TEXT_FILL_COLOR, + CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST, + CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, + CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH, +}; + +const unsigned numInheritableProperties = sizeof(inheritableProperties) / sizeof(inheritableProperties[0]); + +void CSSComputedStyleDeclaration::removeComputedInheritablePropertiesFrom(CSSMutableStyleDeclaration* declaration) +{ + declaration->removePropertiesInSet(inheritableProperties, numInheritableProperties); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copyInheritableProperties() const +{ + RefPtr<CSSMutableStyleDeclaration> style = copyPropertiesInSet(inheritableProperties, numInheritableProperties); + if (style && m_node && m_node->computedStyle()) { + // If a node's text fill color is invalid, then its children use + // their font-color as their text fill color (they don't + // inherit it). Likewise for stroke color. + ExceptionCode ec = 0; + if (!m_node->computedStyle()->textFillColor().isValid()) + style->removeProperty(CSS_PROP__WEBKIT_TEXT_FILL_COLOR, ec); + if (!m_node->computedStyle()->textStrokeColor().isValid()) + style->removeProperty(CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, ec); + ASSERT(ec == 0); + } + return style.release(); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copy() const +{ + return copyPropertiesInSet(computedProperties, numComputedProperties); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::makeMutable() +{ + return copy(); +} + +PassRefPtr<CSSComputedStyleDeclaration> computedStyle(Node* node) +{ + return new CSSComputedStyleDeclaration(node); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSComputedStyleDeclaration.h b/WebCore/css/CSSComputedStyleDeclaration.h new file mode 100644 index 0000000..b19455c --- /dev/null +++ b/WebCore/css/CSSComputedStyleDeclaration.h @@ -0,0 +1,78 @@ +/** + * + * Copyright (C) 2004 Zack Rusin <zack@kde.org> + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef CSSComputedStyleDeclaration_h +#define CSSComputedStyleDeclaration_h + +#include "CSSStyleDeclaration.h" +#include "Node.h" + +namespace WebCore { + +class CSSMutableStyleDeclaration; +class CSSProperty; +class RenderObject; +class RenderStyle; + +enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; + +class CSSComputedStyleDeclaration : public CSSStyleDeclaration { +public: + CSSComputedStyleDeclaration(PassRefPtr<Node>); + virtual ~CSSComputedStyleDeclaration(); + + virtual String cssText() const; + + virtual unsigned length() const; + virtual String item(unsigned index) const; + + virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; + virtual String getPropertyValue(int propertyID) const; + virtual bool getPropertyPriority(int propertyID) const; + virtual int getPropertyShorthand(int propertyID) const { return -1; } + virtual bool isPropertyImplicit(int propertyID) const { return false; } + + virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const; + virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable(); + + PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID, EUpdateLayout) const; +#if ENABLE(SVG) + PassRefPtr<CSSValue> getSVGPropertyCSSValue(int propertyID, EUpdateLayout) const; +#endif + + PassRefPtr<CSSMutableStyleDeclaration> copyInheritableProperties() const; + + static void removeComputedInheritablePropertiesFrom(CSSMutableStyleDeclaration*); + +private: + virtual void setCssText(const String&, ExceptionCode&); + + virtual String removeProperty(int propertyID, ExceptionCode&); + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); + + RefPtr<Node> m_node; +}; + +PassRefPtr<CSSComputedStyleDeclaration> computedStyle(Node*); + +} // namespace WebCore + +#endif // CSSComputedStyleDeclaration_h diff --git a/WebCore/css/CSSCursorImageValue.cpp b/WebCore/css/CSSCursorImageValue.cpp new file mode 100644 index 0000000..5c0752a --- /dev/null +++ b/WebCore/css/CSSCursorImageValue.cpp @@ -0,0 +1,130 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2006 Rob Buis <buis@kde.org> + * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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 "config.h" +#include "CSSCursorImageValue.h" + +#include "CachedImage.h" +#include "DocLoader.h" +#include "PlatformString.h" + +#if ENABLE(SVG) +#include "SVGCursorElement.h" +#include "SVGURIReference.h" +#endif + +#include <wtf/MathExtras.h> + +namespace WebCore { + +#if ENABLE(SVG) +inline bool isSVGCursorIdentifier(const String& url) +{ + KURL kurl(url); + return kurl.hasRef(); +} + +inline SVGCursorElement* resourceReferencedByCursorElement(const String& fragmentId, Document* document) +{ + Element* element = document->getElementById(SVGURIReference::getTarget(fragmentId)); + if (element && element->hasTagName(SVGNames::cursorTag)) + return static_cast<SVGCursorElement*>(element); + + return 0; +} +#endif + +CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& hotspot, StyleBase* style) + : CSSImageValue(url, style) + , m_hotspot(hotspot) +{ +} + +CSSCursorImageValue::~CSSCursorImageValue() +{ +#if ENABLE(SVG) + const String& url = getStringValue(); + if (!isSVGCursorIdentifier(url)) + return; + + HashSet<SVGElement*>::const_iterator it = m_referencedElements.begin(); + HashSet<SVGElement*>::const_iterator end = m_referencedElements.end(); + + for (; it != end; ++it) { + SVGElement* referencedElement = *it; + if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document())) + cursorElement->removeClient(referencedElement); + } +#endif +} + +bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) +{ +#if ENABLE(SVG) + if (!element || !element->isSVGElement()) + return false; + + const String& url = getStringValue(); + if (!isSVGCursorIdentifier(url)) + return false; + + if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->document())) { + int x = roundf(cursorElement->x().value()); + if (x != m_hotspot.x()) + m_hotspot.setX(x); + + int y = roundf(cursorElement->y().value()); + if (y != m_hotspot.y()) + m_hotspot.setY(y); + + if (m_image && m_image->url() != element->document()->completeURL(cursorElement->href())) { + m_image->deref(this); + m_image = 0; + + m_accessedImage = false; + } + + SVGElement* svgElement = static_cast<SVGElement*>(element); + m_referencedElements.add(svgElement); + cursorElement->addClient(svgElement); + return true; + } +#endif + + return false; +} + +CachedImage* CSSCursorImageValue::image(DocLoader* loader) +{ + String url = getStringValue(); + +#if ENABLE(SVG) + if (isSVGCursorIdentifier(url) && loader && loader->doc()) { + if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, loader->doc())) + url = cursorElement->href(); + } +#endif + + return CSSImageValue::image(loader, url); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSCursorImageValue.h b/WebCore/css/CSSCursorImageValue.h new file mode 100644 index 0000000..69d4668 --- /dev/null +++ b/WebCore/css/CSSCursorImageValue.h @@ -0,0 +1,55 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2006 Rob Buis <buis@kde.org> + * + * 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. + */ + +#ifndef CSSCursorImageValue_h +#define CSSCursorImageValue_h + +#include "CSSImageValue.h" +#include "IntPoint.h" + +#include <wtf/HashSet.h> + +namespace WebCore { + +class Element; +class SVGElement; + +class CSSCursorImageValue : public CSSImageValue { +public: + CSSCursorImageValue(const String& url, const IntPoint& hotspot, StyleBase*); + virtual ~CSSCursorImageValue(); + + IntPoint hotspot() const { return m_hotspot; } + + bool updateIfSVGCursorIsUsed(Element*); + virtual CachedImage* image(DocLoader*); + +private: + IntPoint m_hotspot; + +#if ENABLE(SVG) + HashSet<SVGElement*> m_referencedElements; +#endif +}; + +} // namespace WebCore + +#endif // CSSCursorImageValue_h diff --git a/WebCore/css/CSSFontFace.cpp b/WebCore/css/CSSFontFace.cpp new file mode 100644 index 0000000..b98e1db --- /dev/null +++ b/WebCore/css/CSSFontFace.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSFontFace.h" + +#include "CSSFontFaceSource.h" +#include "CSSSegmentedFontFace.h" +#include "FontDescription.h" +#include "SimpleFontData.h" + +namespace WebCore { + +CSSFontFace::~CSSFontFace() +{ + deleteAllValues(m_sources); +} + +bool CSSFontFace::isLoaded() const +{ + unsigned size = m_sources.size(); + for (unsigned i = 0; i < size; i++) { + if (!m_sources[i]->isLoaded()) + return false; + } + return true; +} + +bool CSSFontFace::isValid() const +{ + unsigned size = m_sources.size(); + if (!size) + return false; + for (unsigned i = 0; i < size; i++) { + if (m_sources[i]->isValid()) + return true; + } + return false; +} + +void CSSFontFace::addSource(CSSFontFaceSource* source) +{ + m_sources.append(source); + source->setFontFace(this); +} + +void CSSFontFace::fontLoaded(CSSFontFaceSource*) +{ + m_segmentedFontFace->fontLoaded(this); +} + +SimpleFontData* CSSFontFace::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic) +{ + if (!isValid()) + return 0; + + // If we hit a local font, we know it is valid, and can just return it. + SimpleFontData* result = 0; + unsigned size = m_sources.size(); + for (unsigned i = 0; i < size && !result; i++) + result = m_sources[i]->getFontData(fontDescription, syntheticBold, syntheticItalic, m_segmentedFontFace->fontSelector()); + return result; +} + +} + diff --git a/WebCore/css/CSSFontFace.h b/WebCore/css/CSSFontFace.h new file mode 100644 index 0000000..8c26b9f --- /dev/null +++ b/WebCore/css/CSSFontFace.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSFontFace_h +#define CSSFontFace_h + +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class CSSFontFaceSource; +class CSSSegmentedFontFace; +class FontDescription; +class SimpleFontData; + +class CSSFontFace : public RefCounted<CSSFontFace> { +public: + CSSFontFace() + : RefCounted<CSSFontFace>(0) + , m_segmentedFontFace(0) + { + } + + virtual ~CSSFontFace(); + + void setSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace) { m_segmentedFontFace = segmentedFontFace; } + + bool isLoaded() const; + virtual bool isValid() const; + + virtual void addSource(CSSFontFaceSource*); + + void fontLoaded(CSSFontFaceSource*); + + virtual SimpleFontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic); + +private: + CSSSegmentedFontFace* m_segmentedFontFace; + Vector<CSSFontFaceSource*> m_sources; +}; + +} + +#endif diff --git a/WebCore/css/CSSFontFaceRule.cpp b/WebCore/css/CSSFontFaceRule.cpp new file mode 100644 index 0000000..b1ffc05 --- /dev/null +++ b/WebCore/css/CSSFontFaceRule.cpp @@ -0,0 +1,54 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSFontFaceRule.h" + +#include "CSSMutableStyleDeclaration.h" + +namespace WebCore { + +CSSFontFaceRule::CSSFontFaceRule(StyleBase* parent) + : CSSRule(parent) +{ +} + +CSSFontFaceRule::~CSSFontFaceRule() +{ +} + +void CSSFontFaceRule::setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) +{ + m_style = style; +} + +String CSSFontFaceRule::cssText() const +{ + String result("@font-face"); + result += " { "; + result += m_style->cssText(); + result += "}"; + return result; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSFontFaceRule.h b/WebCore/css/CSSFontFaceRule.h new file mode 100644 index 0000000..bc551a6 --- /dev/null +++ b/WebCore/css/CSSFontFaceRule.h @@ -0,0 +1,57 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSFontFaceRule_h +#define CSSFontFaceRule_h + +#include "CSSRule.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSMutableStyleDeclaration; + +class CSSFontFaceRule : public CSSRule { +public: + CSSFontFaceRule(StyleBase* parent); + virtual ~CSSFontFaceRule(); + + virtual bool isFontFaceRule() { return true; } + + CSSMutableStyleDeclaration* style() const { return m_style.get(); } + + // Inherited from CSSRule + virtual unsigned short type() const { return FONT_FACE_RULE; } + + virtual String cssText() const; + + void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration>); + +protected: + RefPtr<CSSMutableStyleDeclaration> m_style; +}; + +} // namespace WebCore + +#endif // CSSFontFaceRule_h diff --git a/WebCore/css/CSSFontFaceRule.idl b/WebCore/css/CSSFontFaceRule.idl new file mode 100644 index 0000000..514c7dd --- /dev/null +++ b/WebCore/css/CSSFontFaceRule.idl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=8afa4b1a-39fe-49fb-be6d-4d56e81d9b4a, + ImplementationUUID=5a7971d9-5aad-4ed7-be67-3a1644560256 + ] CSSFontFaceRule : CSSRule { + readonly attribute CSSStyleDeclaration style; + }; + +} diff --git a/WebCore/css/CSSFontFaceSource.cpp b/WebCore/css/CSSFontFaceSource.cpp new file mode 100644 index 0000000..7202787 --- /dev/null +++ b/WebCore/css/CSSFontFaceSource.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSFontFaceSource.h" + +#include "CachedFont.h" +#include "CSSFontFace.h" +#include "CSSFontSelector.h" +#include "DocLoader.h" +#include "FontCache.h" +#include "FontDescription.h" +#include "GlyphPageTreeNode.h" +#include "SimpleFontData.h" + +#if ENABLE(SVG_FONTS) +#include "FontCustomPlatformData.h" +#include "HTMLNames.h" +#include "SVGFontData.h" +#include "SVGFontElement.h" +#include "SVGURIReference.h" +#endif + +namespace WebCore { + +CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font) +: m_string(str) +, m_font(font) +, m_face(0) +{ + if (m_font) + m_font->ref(this); +} + +CSSFontFaceSource::~CSSFontFaceSource() +{ + if (m_font) + m_font->deref(this); + pruneTable(); +} + +void CSSFontFaceSource::pruneTable() +{ + if (m_fontDataTable.isEmpty()) + return; + HashMap<int, SimpleFontData*>::iterator end = m_fontDataTable.end(); + for (HashMap<int, SimpleFontData*>::iterator it = m_fontDataTable.begin(); it != end; ++it) + GlyphPageTreeNode::pruneTreeCustomFontData(it->second); + deleteAllValues(m_fontDataTable); + m_fontDataTable.clear(); +} + +bool CSSFontFaceSource::isLoaded() const +{ + if (m_font) + return m_font->isLoaded(); + return true; +} + +bool CSSFontFaceSource::isValid() const +{ + if (m_font) + return !m_font->errorOccurred(); + return true; +} + +void CSSFontFaceSource::fontLoaded(CachedFont*) +{ + pruneTable(); + if (m_face) + m_face->fontLoaded(this); +} + +SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector) +{ + // If the font hasn't loaded or an error occurred, then we've got nothing. + if (!isValid()) + return 0; + +#if ENABLE(SVG_FONTS) + if (!m_font && !m_svgFontFaceElement) { +#else + if (!m_font) { +#endif + FontPlatformData* data = FontCache::getCachedFontPlatformData(fontDescription, m_string); + SimpleFontData* fontData = FontCache::getCachedFontData(data); + + // We're local. Just return a SimpleFontData from the normal cache. + return fontData; + } + + // See if we have a mapping in our FontData cache. + if (SimpleFontData* cachedData = m_fontDataTable.get(fontDescription.computedPixelSize())) + return cachedData; + + OwnPtr<SimpleFontData> fontData; + + // If we are still loading, then we let the system pick a font. + if (isLoaded()) { + if (m_font) { +#if ENABLE(SVG_FONTS) + if (m_font->isSVGFont()) { + // For SVG fonts parse the external SVG document, and extract the <font> element. + if (!m_font->ensureSVGFontData()) + return 0; + + if (!m_externalSVGFontElement) + m_externalSVGFontElement = m_font->getSVGFontById(SVGURIReference::getTarget(m_string)); + + if (!m_externalSVGFontElement) + return 0; + + SVGFontFaceElement* fontFaceElement = 0; + + // Select first <font-face> child + for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) { + if (fontChild->hasTagName(SVGNames::font_faceTag)) { + fontFaceElement = static_cast<SVGFontFaceElement*>(fontChild); + break; + } + } + + if (fontFaceElement) { + if (!m_svgFontFaceElement) { + // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement. + // Use the imported <font-face> tag as referencing font-face element for these cases. + m_svgFontFaceElement = fontFaceElement; + } + + SVGFontData* svgFontData = new SVGFontData(fontFaceElement); + fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic), true, false, svgFontData)); + } + } else +#endif + { + // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. + if (!m_font->ensureCustomFontData()) + return 0; + + fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic), true, false)); + } + } else { +#if ENABLE(SVG_FONTS) + // In-Document SVG Fonts + if (m_svgFontFaceElement) { + SVGFontData* svgFontData = new SVGFontData(m_svgFontFaceElement.get()); + fontData.set(new SimpleFontData(FontPlatformData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic), true, false, svgFontData)); + } +#endif + } + } else { + // Kick off the load now. + m_font->beginLoadIfNeeded(fontSelector->docLoader()); + FontPlatformData* tempData = FontCache::getCachedFontPlatformData(fontDescription, m_string); + if (!tempData) + tempData = FontCache::getLastResortFallbackFont(fontDescription); + fontData.set(new SimpleFontData(*tempData, true, true)); + } + + m_fontDataTable.set(fontDescription.computedPixelSize(), fontData.get()); + return fontData.release(); +} + +} + diff --git a/WebCore/css/CSSFontFaceSource.h b/WebCore/css/CSSFontFaceSource.h new file mode 100644 index 0000000..76d6288 --- /dev/null +++ b/WebCore/css/CSSFontFaceSource.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSFontFaceSource_h +#define CSSFontFaceSource_h + +#include "AtomicString.h" +#include "CachedResourceClient.h" +#include <wtf/HashMap.h> + +#if ENABLE(SVG_FONTS) +#include "SVGFontFaceElement.h" +#endif + +namespace WebCore { + +class CachedFont; +class CSSFontFace; +class CSSFontSelector; +class FontDescription; +class SimpleFontData; + +class CSSFontFaceSource : public CachedResourceClient { +public: + CSSFontFaceSource(const String&, CachedFont* = 0); + virtual ~CSSFontFaceSource(); + + bool isLoaded() const; + bool isValid() const; + + const AtomicString& string() const { return m_string; } + + void setFontFace(CSSFontFace* face) { m_face = face; } + + virtual void fontLoaded(CachedFont*); + + SimpleFontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic, CSSFontSelector*); + + void pruneTable(); + +#if ENABLE(SVG_FONTS) + SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement.get(); } + void setSVGFontFaceElement(SVGFontFaceElement* element) { m_svgFontFaceElement = element; } +#endif + +private: + AtomicString m_string; // URI for remote, built-in font name for local. + CachedFont* m_font; // For remote fonts, a pointer to our cached resource. + CSSFontFace* m_face; // Our owning font face. + HashMap<int, SimpleFontData*> m_fontDataTable; // A cache of FontDatas for various pixel sizes. + +#if ENABLE(SVG_FONTS) + RefPtr<SVGFontFaceElement> m_svgFontFaceElement; + RefPtr<SVGFontElement> m_externalSVGFontElement; +#endif +}; + +} + +#endif diff --git a/WebCore/css/CSSFontFaceSrcValue.cpp b/WebCore/css/CSSFontFaceSrcValue.cpp new file mode 100644 index 0000000..3456532 --- /dev/null +++ b/WebCore/css/CSSFontFaceSrcValue.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSFontFaceSrcValue.h" + +namespace WebCore { + +#if ENABLE(SVG_FONTS) +bool CSSFontFaceSrcValue::isSVGFontFaceSrc() const +{ + return equalIgnoringCase(m_format, "svg"); +} +#endif + +bool CSSFontFaceSrcValue::isSupportedFormat() const +{ + // Normally we would just check the format, but in order to avoid conflicts with the old WinIE style of font-face, + // we will also check to see if the URL ends with .eot. If so, we'll go ahead and assume that we shouldn't load it. + if (m_format.isEmpty()) { + // Check for .eot. + if (m_resource.endsWith("eot", false)) + return false; + return true; + } + + return equalIgnoringCase(m_format, "truetype") || equalIgnoringCase(m_format, "opentype") +#if ENABLE(SVG_FONTS) + || isSVGFontFaceSrc() +#endif + ; +} + +String CSSFontFaceSrcValue::cssText() const +{ + String result; + if (isLocal()) + result += "local("; + else + result += "url("; + result += m_resource; + result += ")"; + if (!m_format.isEmpty()) + result += " format(" + m_format + ")"; + return result; +} + +} + diff --git a/WebCore/css/CSSFontFaceSrcValue.h b/WebCore/css/CSSFontFaceSrcValue.h new file mode 100644 index 0000000..328f505 --- /dev/null +++ b/WebCore/css/CSSFontFaceSrcValue.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSFontFaceSrcValue_h +#define CSSFontFaceSrcValue_h + +#include "CSSValue.h" +#include "PlatformString.h" + +#if ENABLE(SVG_FONTS) +#include "SVGFontFaceElement.h" +#endif + +namespace WebCore { + +class CSSFontFaceSrcValue : public CSSValue { +public: + CSSFontFaceSrcValue(const String& resource, bool local) + :m_resource(resource), m_isLocal(local) + {} + virtual ~CSSFontFaceSrcValue() {} + + const String& resource() const { return m_resource; } + const String& format() const { return m_format; } + bool isLocal() const { return m_isLocal; } + + void setFormat(const String& format) { m_format = format; } + + bool isSupportedFormat() const; + +#if ENABLE(SVG_FONTS) + bool isSVGFontFaceSrc() const; + + SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement.get(); } + void setSVGFontFaceElement(SVGFontFaceElement* element) { m_svgFontFaceElement = element; } +#endif + + virtual String cssText() const; + +private: + String m_resource; + String m_format; + bool m_isLocal; + +#if ENABLE(SVG_FONTS) + RefPtr<SVGFontFaceElement> m_svgFontFaceElement; +#endif +}; + +} + +#endif diff --git a/WebCore/css/CSSFontSelector.cpp b/WebCore/css/CSSFontSelector.cpp new file mode 100644 index 0000000..14002dd --- /dev/null +++ b/WebCore/css/CSSFontSelector.cpp @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "CSSFontSelector.h" +#include "AtomicString.h" +#include "CachedFont.h" +#include "CSSFontFace.h" +#include "CSSFontFaceRule.h" +#include "CSSFontFaceSource.h" +#include "CSSFontFaceSrcValue.h" +#include "CSSMutableStyleDeclaration.h" +#include "CSSPrimitiveValue.h" +#include "CSSPropertyNames.h" +#include "CSSSegmentedFontFace.h" +#include "CSSUnicodeRangeValue.h" +#include "CSSValueKeywords.h" +#include "CSSValueList.h" +#include "DocLoader.h" +#include "Document.h" +#include "FontCache.h" +#include "FontFamilyValue.h" +#include "Frame.h" +#include "NodeList.h" +#include "RenderObject.h" +#include "Settings.h" +#include "SimpleFontData.h" + +#if ENABLE(SVG) +#include "SVGFontFaceElement.h" +#include "SVGNames.h" +#endif + +namespace WebCore { + +CSSFontSelector::CSSFontSelector(Document* document) +: m_document(document) +{ + ASSERT(m_document); +} + +CSSFontSelector::~CSSFontSelector() +{} + +bool CSSFontSelector::isEmpty() const +{ + return m_fonts.isEmpty(); +} + +DocLoader* CSSFontSelector::docLoader() const +{ + return m_document->docLoader(); +} + +static String hashForFont(const String& familyName, bool bold, bool italic) +{ + String familyHash(familyName); + if (bold) + familyHash += "-webkit-bold"; + if (italic) + familyHash += "-webkit-italic"; + return AtomicString(familyHash); +} + +void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) +{ + // Obtain the font-family property and the src property. Both must be defined. + const CSSMutableStyleDeclaration* style = fontFaceRule->style(); + RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSS_PROP_FONT_FAMILY); + RefPtr<CSSValue> src = style->getPropertyCSSValue(CSS_PROP_SRC); + RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSS_PROP_UNICODE_RANGE); + if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || unicodeRange && !unicodeRange->isValueList()) + return; + + CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get()); + if (!familyList->length()) + return; + + CSSValueList* srcList = static_cast<CSSValueList*>(src.get()); + if (!srcList->length()) + return; + + CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get()); + + // Create a FontDescription for this font and set up bold/italic info properly. + FontDescription fontDescription; + + if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSS_PROP_FONT_STYLE)) + fontDescription.setItalic(static_cast<CSSPrimitiveValue*>(fontStyle.get())->getIdent() != CSS_VAL_NORMAL); + + if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSS_PROP_FONT_WEIGHT)) { + // FIXME: Need to support weights for real, since we're effectively limiting the number of supported weights to two. + // This behavior could also result in the "last kinda bold variant" described winning even if it isn't the best match for bold. + switch (static_cast<CSSPrimitiveValue*>(fontWeight.get())->getIdent()) { + case CSS_VAL_BOLD: + case CSS_VAL_BOLDER: + case CSS_VAL_600: + case CSS_VAL_700: + case CSS_VAL_800: + case CSS_VAL_900: + fontDescription.setWeight(cBoldWeight); + default: + break; + } + } + + if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSS_PROP_FONT_VARIANT)) + fontDescription.setSmallCaps(static_cast<CSSPrimitiveValue*>(fontVariant.get())->getIdent() == CSS_VAL_SMALL_CAPS); + + // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. + CSSFontFace* fontFace = 0; + + int i; + int srcLength = srcList->length(); + + bool foundLocal = false; + +#if ENABLE(SVG_FONTS) + bool foundSVGFont = false; +#endif + + for (i = 0; i < srcLength; i++) { + // An item in the list either specifies a string (local font name) or a URL (remote font to download). + CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->item(i)); + CSSFontFaceSource* source = 0; + +#if ENABLE(SVG_FONTS) + foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); +#endif + + if (!item->isLocal()) { + if (item->isSupportedFormat()) { + CachedFont* cachedFont = m_document->docLoader()->requestFont(item->resource()); + if (cachedFont) { +#if ENABLE(SVG_FONTS) + if (foundSVGFont) + cachedFont->setSVGFont(true); +#endif + source = new CSSFontFaceSource(item->resource(), cachedFont); + } + } + } else { + String family = item->resource(); + + // Test the validity of the local font now. We don't want to include this font if it does not exist + // on the system. If it *does* exist on the system, then we don't need to look any further. + if (FontCache::fontExists(fontDescription, family) +#if ENABLE(SVG_FONTS) + || foundSVGFont +#endif + ) { + source = new CSSFontFaceSource(family); + foundLocal = true; + } + } + + if (!fontFace) + fontFace = new CSSFontFace(); + + if (source) { +#if ENABLE(SVG_FONTS) + source->setSVGFontFaceElement(item->svgFontFaceElement()); +#endif + fontFace->addSource(source); + } + + // We can just break if we see a local font that is valid. + if (foundLocal) + break; + } + + ASSERT(fontFace); + + if (fontFace && !fontFace->isValid()) { + delete fontFace; + return; + } + + // Hash under every single family name. + int familyLength = familyList->length(); + for (i = 0; i < familyLength; i++) { + CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->item(i)); + String familyName; + if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING) + familyName = static_cast<FontFamilyValue*>(item)->familyName(); + else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { + // We need to use the raw text for all the generic family types, since @font-face is a way of actually + // defining what font to use for those types. + String familyName; + switch (item->getIdent()) { + case CSS_VAL_SERIF: + familyName = "-webkit-serif"; + break; + case CSS_VAL_SANS_SERIF: + familyName = "-webkit-sans-serif"; + break; + case CSS_VAL_CURSIVE: + familyName = "-webkit-cursive"; + break; + case CSS_VAL_FANTASY: + familyName = "-webkit-fantasy"; + break; + case CSS_VAL_MONOSPACE: + familyName = "-webkit-monospace"; + break; + default: + break; + } + } + + if (familyName.isEmpty()) + continue; + +#if ENABLE(SVG_FONTS) + // SVG allows several <font> elements with the same font-family, differing only + // in ie. font-variant. Be sure to pick up the right one - in getFontData below. + if (foundSVGFont && fontDescription.smallCaps()) + familyName += "-webkit-svg-small-caps"; +#endif + + String hash = hashForFont(familyName.lower(), fontDescription.bold(), fontDescription.italic()); + CSSSegmentedFontFace* segmentedFontFace = m_fonts.get(hash).get(); + if (!segmentedFontFace) { + segmentedFontFace = new CSSSegmentedFontFace(this); + m_fonts.set(hash, segmentedFontFace); + } + if (rangeList) { + // A local font matching the font description should come first, so that it gets used for + // any character not overlaid by explicit @font-face rules for the family. + if (!segmentedFontFace->numRanges() && FontCache::fontExists(fontDescription, familyName)) { + CSSFontFace* implicitFontFace = new CSSFontFace(); + implicitFontFace->addSource(new CSSFontFaceSource(familyName)); + ASSERT(implicitFontFace->isValid()); + segmentedFontFace->overlayRange(0, 0x7FFFFFFF, implicitFontFace); + } + + unsigned numRanges = rangeList->length(); + for (unsigned i = 0; i < numRanges; i++) { + CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->item(i)); + segmentedFontFace->overlayRange(range->from(), range->to(), fontFace); + } + } else + segmentedFontFace->overlayRange(0, 0x7FFFFFFF, fontFace); + } +} + +void CSSFontSelector::fontLoaded(CSSSegmentedFontFace*) +{ + if (m_document->inPageCache()) + return; + m_document->recalcStyle(Document::Force); + m_document->renderer()->setNeedsLayoutAndPrefWidthsRecalc(); +} + +FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName) +{ + if (m_fonts.isEmpty() && !familyName.startsWith("-webkit-")) + return 0; + + bool bold = fontDescription.bold(); + bool italic = fontDescription.italic(); + + bool syntheticBold = false; + bool syntheticItalic = false; + + String family = familyName.string().lower(); + +#if ENABLE(SVG_FONTS) + RefPtr<CSSSegmentedFontFace> face; + + if (fontDescription.smallCaps()) { + String testFamily = family + "-webkit-svg-small-caps"; + face = m_fonts.get(hashForFont(testFamily, bold, italic)); + } else + face = m_fonts.get(hashForFont(family, bold, italic)); +#else + RefPtr<CSSSegmentedFontFace> face = m_fonts.get(hashForFont(family, bold, italic)); +#endif + + // If we don't find a face, and if bold/italic are set, we should try other variants. + // Bold/italic should try bold first, then italic, then normal (on the assumption that we are better at synthesizing italic than we are + // at synthesizing bold). + if (!face) { + if (bold && italic) { + syntheticItalic = true; + face = m_fonts.get(hashForFont(family, bold, false)); + if (!face) { + syntheticBold = true; + face = m_fonts.get(hashForFont(family, false, italic)); + } + } + + // Bold should try normal. + // Italic should try normal. + if (!face && (bold || italic)) { + syntheticBold = bold; + syntheticItalic = italic; + face = m_fonts.get(hashForFont(family, false, false)); + } + } + +#if ENABLE(SVG_FONTS) + // If no face was found, and if we're a SVG Font we may have hit following case: + // <font-face> specified font-weight and/or font-style to be ie. bold and italic. + // And the font-family requested is non-bold & non-italic. For SVG Fonts we still + // have to return the defined font, and not fallback to the system default. + if (!face && !bold) + face = m_fonts.get(hashForFont(family, true, italic)); + + if (!face && !italic) + face = m_fonts.get(hashForFont(family, bold, true)); + + if (!face && !bold && !italic) + face = m_fonts.get(hashForFont(family, true, true)); +#endif + + // If no face was found, then return 0 and let the OS come up with its best match for the name. + if (!face) { + // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our + // settings. + const Settings* settings = m_document->frame()->settings(); + AtomicString genericFamily; + if (familyName == "-webkit-serif") + genericFamily = settings->serifFontFamily(); + else if (familyName == "-webkit-sans-serif") + genericFamily = settings->sansSerifFontFamily(); + else if (familyName == "-webkit-cursive") + genericFamily = settings->cursiveFontFamily(); + else if (familyName == "-webkit-fantasy") + genericFamily = settings->fantasyFontFamily(); + else if (familyName == "-webkit-monospace") + genericFamily = settings->fixedFontFamily(); + else if (familyName == "-webkit-standard") + genericFamily = settings->standardFontFamily(); + + if (!genericFamily.isEmpty()) + return FontCache::getCachedFontData(FontCache::getCachedFontPlatformData(fontDescription, genericFamily)); + return 0; + } + + // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over. + return face->getFontData(fontDescription, syntheticBold, syntheticItalic); +} + +} diff --git a/WebCore/css/CSSFontSelector.h b/WebCore/css/CSSFontSelector.h new file mode 100644 index 0000000..51de2f2 --- /dev/null +++ b/WebCore/css/CSSFontSelector.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSFontSelector_h +#define CSSFontSelector_h + +#include "FontSelector.h" + +#include "StringHash.h" +#include <wtf/HashMap.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class AtomicString; +class CSSFontFaceRule; +class CSSSegmentedFontFace; +class Document; +class DocLoader; +class FontDescription; +class String; + +class CSSFontSelector : public FontSelector { +public: + CSSFontSelector(Document* doc); + virtual ~CSSFontSelector(); + + virtual FontData* getFontData(const FontDescription& fontDescription, const AtomicString& familyName); + + void addFontFaceRule(const CSSFontFaceRule*); + + void fontLoaded(CSSSegmentedFontFace*); + + bool isEmpty() const; + + DocLoader* docLoader() const; + +protected: + Document* m_document; // No need to ref, since we will always get destroyed before the document does. + HashMap<String, RefPtr<CSSSegmentedFontFace> > m_fonts; +}; + +} // namespace WebCore + +#endif // CSSFontSelector_h diff --git a/WebCore/css/CSSGrammar.y b/WebCore/css/CSSGrammar.y new file mode 100644 index 0000000..c91ca32 --- /dev/null +++ b/WebCore/css/CSSGrammar.y @@ -0,0 +1,1164 @@ +%{ + +/* + * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" + +#include "CSSMediaRule.h" +#include "CSSParser.h" +#include "CSSRuleList.h" +#include "CSSSelector.h" +#include "CSSStyleSheet.h" +#include "Document.h" +#include "HTMLNames.h" +#include "MediaList.h" +#include <stdlib.h> +#include <string.h> + +using namespace WebCore; +using namespace HTMLNames; + +#define YYENABLE_NLS 0 +#define YYLTYPE_IS_TRIVIAL 1 +#define YYMAXDEPTH 10000 +#define YYDEBUG 0 + +// FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x +#define YYPARSE_PARAM parser + +%} + +%pure_parser + +%union { + bool boolean; + char character; + int integer; + double number; + ParseString string; + + CSSRule* rule; + CSSRuleList* ruleList; + CSSSelector* selector; + CSSSelector::Relation relation; + MediaList* mediaList; + MediaQuery* mediaQuery; + MediaQuery::Restrictor mediaQueryRestrictor; + MediaQueryExp* mediaQueryExp; + Value value; + ValueList* valueList; + Vector<MediaQueryExp*>* mediaQueryExpList; +} + +%{ + +static inline int cssyyerror(const char*) { return 1; } +static int cssyylex(YYSTYPE* yylval) { return CSSParser::current()->lex(yylval); } + +%} + +%expect 41 + +%left UNIMPORTANT_TOK + +%token WHITESPACE SGML_CD + +%token INCLUDES +%token DASHMATCH +%token BEGINSWITH +%token ENDSWITH +%token CONTAINS + +%token <string> STRING +%right <string> IDENT +%token <string> NTH + +%nonassoc <string> HEX +%nonassoc <string> IDSEL +%nonassoc ':' +%nonassoc '.' +%nonassoc '[' +%nonassoc <string> '*' +%nonassoc error +%left '|' + +%token IMPORT_SYM +%token PAGE_SYM +%token MEDIA_SYM +%token FONT_FACE_SYM +%token CHARSET_SYM +%token NAMESPACE_SYM +%token WEBKIT_RULE_SYM +%token WEBKIT_DECLS_SYM +%token WEBKIT_VALUE_SYM +%token WEBKIT_MEDIAQUERY_SYM + +%token IMPORTANT_SYM +%token MEDIA_ONLY +%token MEDIA_NOT +%token MEDIA_AND + +%token <number> QEMS +%token <number> EMS +%token <number> EXS +%token <number> PXS +%token <number> CMS +%token <number> MMS +%token <number> INS +%token <number> PTS +%token <number> PCS +%token <number> DEGS +%token <number> RADS +%token <number> GRADS +%token <number> MSECS +%token <number> SECS +%token <number> HERZ +%token <number> KHERZ +%token <string> DIMEN +%token <number> PERCENTAGE +%token <number> FLOATTOKEN +%token <number> INTEGER + +%token <string> URI +%token <string> FUNCTION +%token <string> NOTFUNCTION + +%token <string> UNICODERANGE + +%type <relation> combinator + +%type <rule> charset +%type <rule> ruleset +%type <rule> ruleset_or_import +%type <rule> media +%type <rule> import +%type <rule> page +%type <rule> font_face +%type <rule> invalid_rule +%type <rule> invalid_at +%type <rule> invalid_import +%type <rule> rule + +%type <string> maybe_ns_prefix + +%type <string> namespace_selector + +%type <string> string_or_uri +%type <string> ident_or_string +%type <string> medium +%type <string> hexcolor + +%type <string> media_feature +%type <mediaList> media_list +%type <mediaList> maybe_media_list +%type <mediaQuery> media_query +%type <mediaQueryRestrictor> maybe_media_restrictor +%type <valueList> maybe_media_value +%type <mediaQueryExp> media_query_exp +%type <mediaQueryExpList> media_query_exp_list +%type <mediaQueryExpList> maybe_media_query_exp_list + +%type <ruleList> ruleset_list + +%type <integer> property + +%type <selector> specifier +%type <selector> specifier_list +%type <selector> simple_selector +%type <selector> selector +%type <selector> selector_list +%type <selector> selector_with_trailing_whitespace +%type <selector> class +%type <selector> attrib +%type <selector> pseudo + +%type <boolean> declaration_list +%type <boolean> decl_list +%type <boolean> declaration + +%type <boolean> prio + +%type <integer> match +%type <integer> unary_operator +%type <character> operator + +%type <valueList> expr +%type <value> term +%type <value> unary_term +%type <value> function + +%type <string> element_name +%type <string> attr_name + +%% + +stylesheet: + maybe_charset maybe_sgml import_list namespace_list rule_list + | webkit_rule maybe_space + | webkit_decls maybe_space + | webkit_value maybe_space + | webkit_mediaquery maybe_space + ; + +ruleset_or_import: + ruleset | + import +; + +webkit_rule: + WEBKIT_RULE_SYM '{' maybe_space ruleset_or_import maybe_space '}' { + static_cast<CSSParser*>(parser)->rule = $4; + } +; + +webkit_decls: + WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' { + /* can be empty */ + } +; + +webkit_value: + WEBKIT_VALUE_SYM '{' maybe_space expr '}' { + CSSParser* p = static_cast<CSSParser*>(parser); + if ($4) { + p->valueList = p->sinkFloatingValueList($4); + int oldParsedProperties = p->numParsedProperties; + if (!p->parseValue(p->id, p->important)) + p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties); + delete p->valueList; + p->valueList = 0; + } + } +; + +webkit_mediaquery: + WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' { + CSSParser* p = static_cast<CSSParser*>(parser); + p->mediaQuery = p->sinkFloatingMediaQuery($4); + } +; + +maybe_space: + /* empty */ %prec UNIMPORTANT_TOK + | maybe_space WHITESPACE + ; + +maybe_sgml: + /* empty */ + | maybe_sgml SGML_CD + | maybe_sgml WHITESPACE + ; + +maybe_charset: + /* empty */ + | charset { + } +; + +charset: + CHARSET_SYM maybe_space STRING maybe_space ';' { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3); + if ($$ && p->styleElement && p->styleElement->isCSSStyleSheet()) + p->styleElement->append($$); + } + | CHARSET_SYM error invalid_block { + } + | CHARSET_SYM error ';' { + } +; + +import_list: + /* empty */ + | import_list import maybe_sgml { + CSSParser* p = static_cast<CSSParser*>(parser); + if ($2 && p->styleElement && p->styleElement->isCSSStyleSheet()) + p->styleElement->append($2); + } + ; + +namespace_list: +/* empty */ +| namespace_list namespace maybe_sgml +; + +rule_list: + /* empty */ + | rule_list rule maybe_sgml { + CSSParser* p = static_cast<CSSParser*>(parser); + if ($2 && p->styleElement && p->styleElement->isCSSStyleSheet()) + p->styleElement->append($2); + } + ; + +rule: + ruleset + | media + | page + | font_face + | invalid_rule + | invalid_at + | invalid_import + ; + +import: + IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' { + $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5); + } + | IMPORT_SYM error invalid_block { + $$ = 0; + } + | IMPORT_SYM error ';' { + $$ = 0; + } + ; + +namespace: +NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' { + CSSParser* p = static_cast<CSSParser*>(parser); + if (p->styleElement && p->styleElement->isCSSStyleSheet()) + static_cast<CSSStyleSheet*>(p->styleElement)->addNamespace(p, $3, $4); +} +| NAMESPACE_SYM error invalid_block +| NAMESPACE_SYM error ';' +; + +maybe_ns_prefix: +/* empty */ { $$.characters = 0; } +| IDENT WHITESPACE { $$ = $1; } +; + +string_or_uri: +STRING +| URI +; + +media_feature: + IDENT maybe_space { + $$ = $1; + } + ; + +maybe_media_value: + /*empty*/ { + $$ = 0; + } + | ':' maybe_space expr maybe_space { + $$ = $3; + } + ; + +media_query_exp: + MEDIA_AND maybe_space '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space { + $5.lower(); + $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($5, $7); + } + ; + +media_query_exp_list: + media_query_exp { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingMediaQueryExpList(); + $$->append(p->sinkFloatingMediaQueryExp($1)); + } + | media_query_exp_list media_query_exp { + $$ = $1; + $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($2)); + } + ; + +maybe_media_query_exp_list: + /*empty*/ { + $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList(); + } + | media_query_exp_list + ; + +maybe_media_restrictor: + /*empty*/ { + $$ = MediaQuery::None; + } + | MEDIA_ONLY { + $$ = MediaQuery::Only; + } + | MEDIA_NOT { + $$ = MediaQuery::Not; + } + ; + +media_query: + maybe_media_restrictor maybe_space medium maybe_media_query_exp_list { + CSSParser* p = static_cast<CSSParser*>(parser); + $3.lower(); + $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4)); + } + ; + +maybe_media_list: + /* empty */ { + $$ = static_cast<CSSParser*>(parser)->createMediaList(); + } + | media_list + ; + +media_list: + media_query { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createMediaList(); + $$->appendMediaQuery(p->sinkFloatingMediaQuery($1)); + } + | media_list ',' maybe_space media_query { + $$ = $1; + if ($$) + $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4)); + } + | media_list error { + $$ = 0; + } + ; + +media: + MEDIA_SYM maybe_space media_list '{' maybe_space ruleset_list '}' { + $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6); + } + | MEDIA_SYM maybe_space '{' maybe_space ruleset_list '}' { + $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5); + } + ; + +ruleset_list: + /* empty */ { $$ = 0; } + | ruleset_list ruleset maybe_space { + $$ = $1; + if ($2) { + if (!$$) + $$ = static_cast<CSSParser*>(parser)->createRuleList(); + $$->append($2); + } + } + ; + +medium: + IDENT maybe_space { + $$ = $1; + } + ; + +/* +page: + PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space + '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space + ; + +pseudo_page + : ':' IDENT + ; +*/ + +page: + PAGE_SYM error invalid_block { + $$ = 0; + } + | PAGE_SYM error ';' { + $$ = 0; + } + ; + +font_face: + FONT_FACE_SYM maybe_space + '{' maybe_space declaration_list '}' maybe_space { + $$ = static_cast<CSSParser*>(parser)->createFontFaceRule(); + } + | FONT_FACE_SYM error invalid_block { + $$ = 0; + } + | FONT_FACE_SYM error ';' { + $$ = 0; + } +; + +combinator: + '+' maybe_space { $$ = CSSSelector::DirectAdjacent; } + | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; } + | '>' maybe_space { $$ = CSSSelector::Child; } + ; + +unary_operator: + '-' { $$ = -1; } + | '+' { $$ = 1; } + ; + +ruleset: + selector_list '{' maybe_space declaration_list '}' { + $$ = static_cast<CSSParser*>(parser)->createStyleRule($1); + } + ; + +selector_list: + selector %prec UNIMPORTANT_TOK { + $$ = $1; + } + | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK { + if ($1 && $4) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = $1; + $$->append(p->sinkFloatingSelector($4)); + } else + $$ = 0; + } + | selector_list error { + $$ = 0; + } + ; + +selector_with_trailing_whitespace: + selector WHITESPACE { + $$ = $1; + } + ; + +selector: + simple_selector { + $$ = $1; + } + | selector_with_trailing_whitespace + { + $$ = $1; + } + | selector_with_trailing_whitespace simple_selector + { + $$ = $2; + if (!$1) + $$ = 0; + else if ($$) { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSSelector* end = $$; + while (end->m_tagHistory) + end = end->m_tagHistory; + end->m_relation = CSSSelector::Descendant; + end->m_tagHistory = p->sinkFloatingSelector($1); + if (Document* doc = p->document()) + doc->setUsesDescendantRules(true); + } + } + | selector combinator simple_selector { + $$ = $3; + if (!$1) + $$ = 0; + else if ($$) { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSSelector* end = $$; + while (end->m_tagHistory) + end = end->m_tagHistory; + end->m_relation = $2; + end->m_tagHistory = p->sinkFloatingSelector($1); + if ($2 == CSSSelector::Child) { + if (Document* doc = p->document()) + doc->setUsesDescendantRules(true); + } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) { + if (Document* doc = p->document()) + doc->setUsesSiblingRules(true); + } + } + } + | selector error { + $$ = 0; + } + ; + +namespace_selector: + /* empty */ '|' { $$.characters = 0; $$.length = 0; } + | '*' '|' { static UChar star = '*'; $$.characters = ☆ $$.length = 1; } + | IDENT '|' { $$ = $1; } +; + +simple_selector: + element_name { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_tag = QualifiedName(nullAtom, $1, p->defaultNamespace); + } + | element_name specifier_list { + $$ = $2; + if ($$) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$->m_tag = QualifiedName(nullAtom, $1, p->defaultNamespace); + } + } + | specifier_list { + $$ = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + if ($$ && p->defaultNamespace != starAtom) + $$->m_tag = QualifiedName(nullAtom, starAtom, p->defaultNamespace); + } + | namespace_selector element_name { + AtomicString namespacePrefix = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + if (p->styleElement && p->styleElement->isCSSStyleSheet()) { + $$->m_tag = QualifiedName(namespacePrefix, $2, + static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix)); + } else // FIXME: Shouldn't this case be an error? + $$->m_tag = QualifiedName(nullAtom, $2, p->defaultNamespace); + } + | namespace_selector element_name specifier_list { + $$ = $3; + if ($$) { + AtomicString namespacePrefix = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + if (p->styleElement && p->styleElement->isCSSStyleSheet()) { + $$->m_tag = QualifiedName(namespacePrefix, $2, + static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix)); + } else // FIXME: Shouldn't this case be an error? + $$->m_tag = QualifiedName(nullAtom, $2, p->defaultNamespace); + } + } + | namespace_selector specifier_list { + $$ = $2; + if ($$) { + AtomicString namespacePrefix = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + if (p->styleElement && p->styleElement->isCSSStyleSheet()) + $$->m_tag = QualifiedName(namespacePrefix, + starAtom, + static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix)); + } + } + ; + +element_name: + IDENT { + ParseString& str = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + Document* doc = p->document(); + if (doc && doc->isHTMLDocument()) + str.lower(); + $$ = str; + } + | '*' { + static UChar star = '*'; + $$.characters = ☆ + $$.length = 1; + } + ; + +specifier_list: + specifier { + $$ = $1; + } + | specifier_list specifier { + if (!$2) + $$ = 0; + else if ($1) { + $$ = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + CSSSelector* end = $1; + while (end->m_tagHistory) + end = end->m_tagHistory; + end->m_relation = CSSSelector::SubSelector; + end->m_tagHistory = p->sinkFloatingSelector($2); + } + } + | specifier_list error { + $$ = 0; + } +; + +specifier: + IDSEL { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::Id; + if (!p->strict) + $1.lower(); + $$->m_attr = idAttr; + $$->m_value = $1; + } + | HEX { + if ($1.characters[0] >= '0' && $1.characters[0] <= '9') { + $$ = 0; + } else { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::Id; + if (!p->strict) + $1.lower(); + $$->m_attr = idAttr; + $$->m_value = $1; + } + } + | class + | attrib + | pseudo + ; + +class: + '.' IDENT { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::Class; + if (!p->strict) + $2.lower(); + $$->m_attr = classAttr; + $$->m_value = $2; + } + ; + +attr_name: + IDENT maybe_space { + ParseString& str = $1; + CSSParser* p = static_cast<CSSParser*>(parser); + Document* doc = p->document(); + if (doc && doc->isHTMLDocument()) + str.lower(); + $$ = str; + } + ; + +attrib: + '[' maybe_space attr_name ']' { + $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); + $$->m_attr = QualifiedName(nullAtom, $3, nullAtom); + $$->m_match = CSSSelector::Set; + } + | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' { + $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); + $$->m_attr = QualifiedName(nullAtom, $3, nullAtom); + $$->m_match = (CSSSelector::Match)$4; + $$->m_value = $6; + } + | '[' maybe_space namespace_selector attr_name ']' { + AtomicString namespacePrefix = $3; + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_attr = QualifiedName(namespacePrefix, $4, + static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix)); + $$->m_match = CSSSelector::Set; + } + | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' { + AtomicString namespacePrefix = $3; + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_attr = QualifiedName(namespacePrefix, $4, + static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix)); + $$->m_match = (CSSSelector::Match)$5; + $$->m_value = $7; + } + ; + +match: + '=' { + $$ = CSSSelector::Exact; + } + | INCLUDES { + $$ = CSSSelector::List; + } + | DASHMATCH { + $$ = CSSSelector::Hyphen; + } + | BEGINSWITH { + $$ = CSSSelector::Begin; + } + | ENDSWITH { + $$ = CSSSelector::End; + } + | CONTAINS { + $$ = CSSSelector::Contain; + } + ; + +ident_or_string: + IDENT + | STRING + ; + +pseudo: + ':' IDENT { + $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoClass; + $2.lower(); + $$->m_value = $2; + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; + else if (type == CSSSelector::PseudoEmpty || + type == CSSSelector::PseudoFirstChild || + type == CSSSelector::PseudoFirstOfType || + type == CSSSelector::PseudoLastChild || + type == CSSSelector::PseudoLastOfType || + type == CSSSelector::PseudoOnlyChild || + type == CSSSelector::PseudoOnlyOfType) { + CSSParser* p = static_cast<CSSParser*>(parser); + Document* doc = p->document(); + if (doc) + doc->setUsesSiblingRules(true); + } else if (type == CSSSelector::PseudoFirstLine) { + CSSParser* p = static_cast<CSSParser*>(parser); + if (Document* doc = p->document()) + doc->setUsesFirstLineRules(true); + } + } + | ':' ':' IDENT { + $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoElement; + $3.lower(); + $$->m_value = $3; + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; + else if (type == CSSSelector::PseudoFirstLine) { + CSSParser* p = static_cast<CSSParser*>(parser); + if (Document* doc = p->document()) + doc->setUsesFirstLineRules(true); + } + } + // used by :nth-*(ax+b) + | ':' FUNCTION NTH ')' { + CSSParser *p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoClass; + $$->m_argument = $3; + $$->m_value = $2; + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; + else if (type == CSSSelector::PseudoNthChild || + type == CSSSelector::PseudoNthOfType || + type == CSSSelector::PseudoNthLastChild || + type == CSSSelector::PseudoNthLastOfType) { + if (p->document()) + p->document()->setUsesSiblingRules(true); + } + } + // used by :nth-* + | ':' FUNCTION INTEGER ')' { + CSSParser *p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoClass; + $$->m_argument = String::number($3); + $$->m_value = $2; + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; + else if (type == CSSSelector::PseudoNthChild || + type == CSSSelector::PseudoNthOfType || + type == CSSSelector::PseudoNthLastChild || + type == CSSSelector::PseudoNthLastOfType) { + if (p->document()) + p->document()->setUsesSiblingRules(true); + } + } + // used by :nth-*(odd/even) and :lang + | ':' FUNCTION IDENT ')' { + CSSParser *p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoClass; + $$->m_argument = $3; + $2.lower(); + $$->m_value = $2; + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; + else if (type == CSSSelector::PseudoNthChild || + type == CSSSelector::PseudoNthOfType || + type == CSSSelector::PseudoNthLastChild || + type == CSSSelector::PseudoNthLastOfType) { + if (p->document()) + p->document()->setUsesSiblingRules(true); + } + } + // used by :not + | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' { + if (!$4) + $$ = 0; + else { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->m_match = CSSSelector::PseudoClass; + $$->m_simpleSelector = p->sinkFloatingSelector($4); + $2.lower(); + $$->m_value = $2; + } + } + ; + +declaration_list: + declaration { + $$ = $1; + } + | decl_list declaration { + $$ = $1; + if ( $2 ) + $$ = $2; + } + | decl_list { + $$ = $1; + } + | error invalid_block_list error { + $$ = false; + } + | error { + $$ = false; + } + | decl_list error { + $$ = $1; + } + ; + +decl_list: + declaration ';' maybe_space { + $$ = $1; + } + | declaration invalid_block_list ';' maybe_space { + $$ = false; + } + | error ';' maybe_space { + $$ = false; + } + | error invalid_block_list error ';' maybe_space { + $$ = false; + } + | decl_list declaration ';' maybe_space { + $$ = $1; + if ($2) + $$ = $2; + } + | decl_list error ';' maybe_space { + $$ = $1; + } + | decl_list error invalid_block_list error ';' maybe_space { + $$ = $1; + } + ; + +declaration: + property ':' maybe_space expr prio { + $$ = false; + CSSParser* p = static_cast<CSSParser*>(parser); + if ($1 && $4) { + p->valueList = p->sinkFloatingValueList($4); + int oldParsedProperties = p->numParsedProperties; + $$ = p->parseValue($1, $5); + if (!$$) + p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties); + delete p->valueList; + p->valueList = 0; + } + } + | + property error { + $$ = false; + } + | + property ':' maybe_space error expr prio { + /* The default movable type template has letter-spacing: .none; Handle this by looking for + error tokens at the start of an expr, recover the expr and then treat as an error, cleaning + up and deleting the shifted expr. */ + $$ = false; + } + | + IMPORTANT_SYM maybe_space { + /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */ + $$ = false; + } + | + property ':' maybe_space { + /* div { font-family: } Just reduce away this property with no value. */ + $$ = false; + } + | + property ':' maybe_space error { + /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */ + $$ = false; + } + ; + +property: + IDENT maybe_space { + $$ = cssPropertyID($1); + } + ; + +prio: + IMPORTANT_SYM maybe_space { $$ = true; } + | /* empty */ { $$ = false; } + ; + +expr: + term { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingValueList(); + $$->addValue(p->sinkFloatingValue($1)); + } + | expr operator term { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = $1; + if ($$) { + if ($2) { + Value v; + v.id = 0; + v.unit = Value::Operator; + v.iValue = $2; + $$->addValue(v); + } + $$->addValue(p->sinkFloatingValue($3)); + } + } + | expr error { + $$ = 0; + } + ; + +operator: + '/' maybe_space { + $$ = '/'; + } + | ',' maybe_space { + $$ = ','; + } + | /* empty */ { + $$ = 0; + } + ; + +term: + unary_term { $$ = $1; } + | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } + | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } + | IDENT maybe_space { + $$.id = cssValueKeywordID($1); + $$.unit = CSSPrimitiveValue::CSS_IDENT; + $$.string = $1; + } + /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */ + | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION } + | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION } + | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; } + | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE } + | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; } + | '#' maybe_space { $$.id = 0; $$.string = ParseString(); $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; } /* Handle error case: "color: #;" */ + /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ + | function { + $$ = $1; + } + | '%' maybe_space {} /* Handle width: %; */ + ; + +unary_term: + INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; } + | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; } + | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; } + | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; } + | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; } + | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; } + | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; } + | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; } + | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; } + | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; } + | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; } + | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; } + | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; } + | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; } + | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; } + | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; } + | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; } + | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS; } + | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; } + ; + + +function: + FUNCTION maybe_space expr ')' maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + Function* f = p->createFloatingFunction(); + f->name = $1; + f->args = p->sinkFloatingValueList($3); + $$.id = 0; + $$.unit = Value::Function; + $$.function = f; + } | + FUNCTION maybe_space error { + CSSParser* p = static_cast<CSSParser*>(parser); + Function* f = p->createFloatingFunction(); + f->name = $1; + f->args = 0; + $$.id = 0; + $$.unit = Value::Function; + $$.function = f; + } + ; +/* + * There is a constraint on the color that it must + * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) + * after the "#"; e.g., "#000" is OK, but "#abcd" is not. + */ +hexcolor: + HEX maybe_space { $$ = $1; } + | IDSEL maybe_space { $$ = $1; } + ; + + +/* error handling rules */ + +invalid_at: + '@' error invalid_block { + $$ = 0; + } + | '@' error ';' { + $$ = 0; + } + ; + +invalid_import: + import { + $$ = 0; + } + ; + +invalid_rule: + error invalid_block { + $$ = 0; + } +/* + Seems like the two rules below are trying too much and violating + http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html + + | error ';' { + $$ = 0; + } + | error '}' { + $$ = 0; + } +*/ + ; + +invalid_block: + '{' error invalid_block_list error '}' + | '{' error '}' + ; + +invalid_block_list: + invalid_block + | invalid_block_list error invalid_block +; + +%% diff --git a/WebCore/css/CSSHelper.cpp b/WebCore/css/CSSHelper.cpp new file mode 100644 index 0000000..aa1186c --- /dev/null +++ b/WebCore/css/CSSHelper.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSHelper.h" + +#include "PlatformString.h" +#include <wtf/Vector.h> + +namespace WebCore { + +String parseURL(const String& url) +{ + StringImpl* i = url.impl(); + if (!i) + return String(); + + int o = 0; + int l = i->length(); + + while (o < l && (*i)[o] <= ' ') { + ++o; + --l; + } + while (l > 0 && (*i)[o + l - 1] <= ' ') + --l; + + if (l >= 5 + && ((*i)[o] == 'u' || (*i)[o] == 'U') + && ((*i)[o + 1] == 'r' || (*i)[o + 1] == 'R') + && ((*i)[o + 2] == 'l' || (*i)[o + 2] == 'L') + && (*i)[o + 3] == '(' + && (*i)[o + l - 1] == ')') { + o += 4; + l -= 5; + } + + while (o < l && (*i)[o] <= ' ') { + ++o; + --l; + } + while (l > 0 && (*i)[o + l - 1] <= ' ') + --l; + + if (l >= 2 && (*i)[o] == (*i)[o + l - 1] && ((*i)[o] == '\'' || (*i)[o] == '\"')) { + o++; + l -= 2; + } + + while (o < l && (*i)[o] <= ' ') { + ++o; + --l; + } + while (l > 0 && (*i)[o + l - 1] <= ' ') + --l; + + Vector<UChar, 2048> buffer(l); + + int nl = 0; + for (int k = o; k < o + l; k++) { + UChar c = (*i)[k]; + if (c > '\r') + buffer[nl++] = c; + } + + return String(buffer.data(), nl); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSHelper.h b/WebCore/css/CSSHelper.h new file mode 100644 index 0000000..2a882e4 --- /dev/null +++ b/WebCore/css/CSSHelper.h @@ -0,0 +1,46 @@ +/* + * This file is part of the CSS implementation for KDE. + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * + * 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. + * + */ + +#ifndef CSSHelper_h +#define CSSHelper_h + +namespace WebCore { + + class String; + + /* + * mostly just removes the url("...") brace + */ + String parseURL(const String& url); + + // We always assume 96 CSS pixels in a CSS inch. This is the cold hard truth of the Web. + // At high DPI, we may scale a CSS pixel, but the ratio of the CSS pixel to the so-called + // "absolute" CSS length units like inch and pt is always fixed and never changes. + const float cssPixelsPerInch = 96.0f; + + // Used by animation. + const int cAnimateNone = 0; + const int cAnimateAll = -2; + +} // namespace WebCore + +#endif // CSSHelper_h diff --git a/WebCore/css/CSSImageValue.cpp b/WebCore/css/CSSImageValue.cpp new file mode 100644 index 0000000..7d917b2 --- /dev/null +++ b/WebCore/css/CSSImageValue.cpp @@ -0,0 +1,75 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSImageValue.h" + +#include "CSSValueKeywords.h" +#include "Cache.h" +#include "CachedImage.h" +#include "DocLoader.h" + +namespace WebCore { + +CSSImageValue::CSSImageValue(const String& url, StyleBase* style) + : CSSPrimitiveValue(url, CSS_URI) + , m_image(0) + , m_accessedImage(false) +{ +} + +CSSImageValue::CSSImageValue() + : CSSPrimitiveValue(CSS_VAL_NONE) + , m_image(0) + , m_accessedImage(true) +{ +} + +CSSImageValue::~CSSImageValue() +{ + if (m_image) + m_image->deref(this); +} + +CachedImage* CSSImageValue::image(DocLoader* loader) +{ + return image(loader, getStringValue()); +} + +CachedImage* CSSImageValue::image(DocLoader* loader, const String& url) +{ + if (!m_accessedImage) { + m_accessedImage = true; + + if (loader) + m_image = loader->requestImage(url); + else { + // FIXME: Should find a way to make these images sit in their own memory partition, since they are user agent images. + m_image = static_cast<CachedImage*>(cache()->requestResource(0, CachedResource::ImageResource, KURL(url), 0, 0)); + } + + if (m_image) + m_image->ref(this); + } + + return m_image; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSImageValue.h b/WebCore/css/CSSImageValue.h new file mode 100644 index 0000000..f2b2025 --- /dev/null +++ b/WebCore/css/CSSImageValue.h @@ -0,0 +1,51 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSImageValue_h +#define CSSImageValue_h + +#include "CSSPrimitiveValue.h" +#include "CachedResourceClient.h" + +namespace WebCore { + +class DocLoader; + +class CSSImageValue : public CSSPrimitiveValue, + public CachedResourceClient { +public: + CSSImageValue(); + CSSImageValue(const String& url, StyleBase*); + virtual ~CSSImageValue(); + + virtual CachedImage* image(DocLoader*); + +protected: + CachedImage* image(DocLoader*, const String& url); + + CachedImage* m_image; + bool m_accessedImage; +}; + +} // namespace WebCore + +#endif // CSSImageValue_h diff --git a/WebCore/css/CSSImportRule.cpp b/WebCore/css/CSSImportRule.cpp new file mode 100644 index 0000000..0672826 --- /dev/null +++ b/WebCore/css/CSSImportRule.cpp @@ -0,0 +1,129 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSImportRule.h" + +#include "CachedCSSStyleSheet.h" +#include "CSSStyleSheet.h" +#include "DocLoader.h" +#include "Document.h" +#include "MediaList.h" + +namespace WebCore { + +CSSImportRule::CSSImportRule(StyleBase* parent, const String& href, MediaList* media) + : CSSRule(parent) + , m_strHref(href) + , m_lstMedia(media) + , m_cachedSheet(0) + , m_loading(false) +{ + if (m_lstMedia) + m_lstMedia->setParent(this); + else + m_lstMedia = new MediaList(this, String()); +} + +CSSImportRule::~CSSImportRule() +{ + if (m_lstMedia) + m_lstMedia->setParent(0); + if (m_styleSheet) + m_styleSheet->setParent(0); + if (m_cachedSheet) + m_cachedSheet->deref(this); +} + +void CSSImportRule::setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet* sheet) +{ + if (m_styleSheet) + m_styleSheet->setParent(0); + m_styleSheet = new CSSStyleSheet(this, url, charset); + + CSSStyleSheet* parent = parentStyleSheet(); + bool strict = !parent || parent->useStrictParsing(); + m_styleSheet->parseString(sheet->sheetText(strict), strict); + m_loading = false; + + checkLoaded(); +} + +bool CSSImportRule::isLoading() const +{ + return m_loading || (m_styleSheet && m_styleSheet->isLoading()); +} + +void CSSImportRule::insertedIntoParent() +{ + StyleBase* root = this; + StyleBase* parent; + while ((parent = root->parent())) + root = parent; + if (!root->isCSSStyleSheet()) + return; + DocLoader* docLoader = static_cast<CSSStyleSheet*>(root)->docLoader(); + if (!docLoader) + return; + + String absHref = m_strHref; + CSSStyleSheet* parentSheet = parentStyleSheet(); + if (!parentSheet->href().isNull()) + // use parent styleheet's URL as the base URL + absHref = KURL(KURL(parentSheet->href()), m_strHref).string(); + + // Check for a cycle in our import chain. If we encounter a stylesheet + // in our parent chain with the same URL, then just bail. + for (parent = static_cast<StyleBase*>(this)->parent(); parent; parent = parent->parent()) { + if (absHref == parent->baseURL()) + return; + } + + m_cachedSheet = docLoader->requestCSSStyleSheet(absHref, parentSheet->charset()); + if (m_cachedSheet) { + // if the import rule is issued dynamically, the sheet may be + // removed from the pending sheet count, so let the doc know + // the sheet being imported is pending. + if (parentSheet && parentSheet->loadCompleted() && parentSheet->doc()) + parentSheet->doc()->addPendingSheet(); + m_loading = true; + m_cachedSheet->ref(this); + } +} + +String CSSImportRule::cssText() const +{ + String result = "@import url(\""; + result += m_strHref; + result += "\")"; + + if (m_lstMedia) { + result += " "; + result += m_lstMedia->mediaText(); + } + result += ";"; + + return result; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSImportRule.h b/WebCore/css/CSSImportRule.h new file mode 100644 index 0000000..ea40584 --- /dev/null +++ b/WebCore/css/CSSImportRule.h @@ -0,0 +1,70 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSImportRule_h +#define CSSImportRule_h + +#include "CSSRule.h" +#include "CachedResourceClient.h" +#include "PlatformString.h" + +namespace WebCore { + +class CachedCSSStyleSheet; +class MediaList; + +class CSSImportRule : public CSSRule, public CachedResourceClient { +public: + CSSImportRule(StyleBase* parent, const String& href, MediaList*); + virtual ~CSSImportRule(); + + virtual bool isImportRule() { return true; } + + String href() const { return m_strHref; } + MediaList* media() const { return m_lstMedia.get(); } + CSSStyleSheet* styleSheet() const { return m_styleSheet.get(); } + + // Inherited from CSSRule + virtual unsigned short type() const { return IMPORT_RULE; } + + virtual String cssText() const; + + // Not part of the CSSOM + bool isLoading() const; + + // from CachedResourceClient + virtual void setCSSStyleSheet(const String& url, const String& charset, const CachedCSSStyleSheet*); + + virtual void insertedIntoParent(); + +protected: + String m_strHref; + RefPtr<MediaList> m_lstMedia; + RefPtr<CSSStyleSheet> m_styleSheet; + CachedCSSStyleSheet* m_cachedSheet; + bool m_loading; +}; + +} // namespace WebCore + +#endif // CSSImportRule_h diff --git a/WebCore/css/CSSImportRule.idl b/WebCore/css/CSSImportRule.idl new file mode 100644 index 0000000..454553e --- /dev/null +++ b/WebCore/css/CSSImportRule.idl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=8f60b3a2-ebf0-484d-a714-47a9974a6a9e, + ImplementationUUID=437ea93c-68e5-4897-85fe-e161653801eb + ] CSSImportRule : CSSRule { + readonly attribute [ConvertNullStringTo=Null] DOMString href; + readonly attribute stylesheets::MediaList media; + readonly attribute CSSStyleSheet styleSheet; + }; + +} diff --git a/WebCore/css/CSSInheritedValue.cpp b/WebCore/css/CSSInheritedValue.cpp new file mode 100644 index 0000000..08d3db3 --- /dev/null +++ b/WebCore/css/CSSInheritedValue.cpp @@ -0,0 +1,40 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSInheritedValue.h" + +#include "PlatformString.h" + +namespace WebCore { + +unsigned short CSSInheritedValue::cssValueType() const +{ + return CSS_INHERIT; +} + +String CSSInheritedValue::cssText() const +{ + return "inherit"; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSInheritedValue.h b/WebCore/css/CSSInheritedValue.h new file mode 100644 index 0000000..a2332d2 --- /dev/null +++ b/WebCore/css/CSSInheritedValue.h @@ -0,0 +1,38 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSInheritedValue_h +#define CSSInheritedValue_h + +#include "CSSValue.h" + +namespace WebCore { + +class CSSInheritedValue : public CSSValue { +public: + virtual unsigned short cssValueType() const; + virtual String cssText() const; +}; + +} // namespace WebCore + +#endif // CSSInheritedValue_h diff --git a/WebCore/css/CSSInitialValue.cpp b/WebCore/css/CSSInitialValue.cpp new file mode 100644 index 0000000..9c2bb23 --- /dev/null +++ b/WebCore/css/CSSInitialValue.cpp @@ -0,0 +1,40 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSInitialValue.h" + +#include "PlatformString.h" + +namespace WebCore { + +unsigned short CSSInitialValue::cssValueType() const +{ + return CSS_INITIAL; +} + +String CSSInitialValue::cssText() const +{ + return "initial"; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSInitialValue.h b/WebCore/css/CSSInitialValue.h new file mode 100644 index 0000000..1e04015 --- /dev/null +++ b/WebCore/css/CSSInitialValue.h @@ -0,0 +1,47 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSInitialValue_h +#define CSSInitialValue_h + +#include "CSSValue.h" + +namespace WebCore { + +class CSSInitialValue : public CSSValue { +public: + CSSInitialValue(bool implicit) + :m_implicit(implicit) + {} + + virtual unsigned short cssValueType() const; + virtual String cssText() const; + + virtual bool isImplicitInitialValue() const { return m_implicit; } + +private: + bool m_implicit; +}; + +} // namespace WebCore + +#endif // CSSInitialValue_h diff --git a/WebCore/css/CSSMediaRule.cpp b/WebCore/css/CSSMediaRule.cpp new file mode 100644 index 0000000..c46d9b7 --- /dev/null +++ b/WebCore/css/CSSMediaRule.cpp @@ -0,0 +1,151 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) + * + * 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 "config.h" +#include "CSSMediaRule.h" + +#include "CSSParser.h" +#include "CSSRuleList.h" +#include "ExceptionCode.h" +#include "MediaList.h" +#include "StyleSheet.h" + +namespace WebCore { + +CSSMediaRule::CSSMediaRule(StyleBase* parent, MediaList* mediaList, CSSRuleList* ruleList) + : CSSRule(parent) + , m_lstMedia(mediaList) + , m_lstCSSRules(ruleList) +{ +} + +CSSMediaRule::CSSMediaRule(StyleBase* parent) + : CSSRule(parent) + , m_lstMedia(0) + , m_lstCSSRules(new CSSRuleList()) + +{ +} + +CSSMediaRule::CSSMediaRule(StyleBase* parent, const String &media) + : CSSRule(parent) + , m_lstMedia(new MediaList(this, media)) + , m_lstCSSRules(new CSSRuleList()) +{ +} + +CSSMediaRule::~CSSMediaRule() +{ + if (m_lstMedia) + m_lstMedia->setParent(0); + + int length = m_lstCSSRules->length(); + for (int i = 0; i < length; i++) + m_lstCSSRules->item(i)->setParent(0); +} + +unsigned CSSMediaRule::append(CSSRule* rule) +{ + if (!rule) + return 0; + + rule->setParent(this); + return m_lstCSSRules->insertRule(rule, m_lstCSSRules->length()); +} + +unsigned CSSMediaRule::insertRule(const String& rule, unsigned index, ExceptionCode& ec) +{ + if (index > m_lstCSSRules->length()) { + // INDEX_SIZE_ERR: Raised if the specified index is not a valid insertion point. + ec = INDEX_SIZE_ERR; + return 0; + } + + CSSParser p(useStrictParsing()); + RefPtr<CSSRule> newRule = p.parseRule(parentStyleSheet(), rule); + if (!newRule) { + // SYNTAX_ERR: Raised if the specified rule has a syntax error and is unparsable. + ec = SYNTAX_ERR; + return 0; + } + + if (newRule->isImportRule()) { + // FIXME: an HIERARCHY_REQUEST_ERR should also be thrown for a @charset or a nested + // @media rule. They are currently not getting parsed, resulting in a SYNTAX_ERR + // to get raised above. + + // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified + // index, e.g., if an @import rule is inserted after a standard rule set or other + // at-rule. + ec = HIERARCHY_REQUEST_ERR; + return 0; + } + + newRule->setParent(this); + unsigned returnedIndex = m_lstCSSRules->insertRule(newRule.get(), index); + + // stylesheet() can only return 0 for computed style declarations. + stylesheet()->styleSheetChanged(); + + return returnedIndex; +} + +void CSSMediaRule::deleteRule(unsigned index, ExceptionCode& ec) +{ + if (index >= m_lstCSSRules->length()) { + // INDEX_SIZE_ERR: Raised if the specified index does not correspond to a + // rule in the media rule list. + ec = INDEX_SIZE_ERR; + return; + } + + m_lstCSSRules->deleteRule(index); + + // stylesheet() can only return 0 for computed style declarations. + stylesheet()->styleSheetChanged(); +} + +String CSSMediaRule::cssText() const +{ + String result = "@media "; + if (m_lstMedia) { + result += m_lstMedia->mediaText(); + result += " "; + } + result += "{ \n"; + + if (m_lstCSSRules) { + unsigned len = m_lstCSSRules->length(); + for (unsigned i = 0; i < len; i++) { + result += " "; + result += m_lstCSSRules->item(i)->cssText(); + result += "\n"; + } + } + + result += "}"; + return result; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSMediaRule.h b/WebCore/css/CSSMediaRule.h new file mode 100644 index 0000000..f6a7e48 --- /dev/null +++ b/WebCore/css/CSSMediaRule.h @@ -0,0 +1,68 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) + * + * 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. + */ + +#ifndef CSSMediaRule_h +#define CSSMediaRule_h + +#include "CSSRule.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSRuleList; +class MediaList; + +typedef int ExceptionCode; + +class CSSMediaRule : public CSSRule { +public: + CSSMediaRule(StyleBase* parent); + CSSMediaRule(StyleBase* parent, const String& media); + CSSMediaRule(StyleBase* parent, MediaList* mediaList, CSSRuleList* ruleList); + virtual ~CSSMediaRule(); + + virtual bool isMediaRule() { return true; } + + MediaList* media() const { return m_lstMedia.get(); } + CSSRuleList* cssRules() { return m_lstCSSRules.get(); } + + unsigned insertRule(const String& rule, unsigned index, ExceptionCode&); + void deleteRule(unsigned index, ExceptionCode&); + + // Inherited from CSSRule + virtual unsigned short type() const { return MEDIA_RULE; } + + virtual String cssText() const; + + // Not part of the CSSOM + unsigned append(CSSRule*); + +protected: + RefPtr<MediaList> m_lstMedia; + RefPtr<CSSRuleList> m_lstCSSRules; +}; + +} // namespace WebCore + +#endif // CSSMediaRule_h diff --git a/WebCore/css/CSSMediaRule.idl b/WebCore/css/CSSMediaRule.idl new file mode 100644 index 0000000..1347171 --- /dev/null +++ b/WebCore/css/CSSMediaRule.idl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=9c623c09-2677-4d28-ba90-826da0ae316a, + ImplementationUUID=30493ec9-e139-4e9e-ae24-cc8f532006d9 + ] CSSMediaRule : CSSRule { + readonly attribute stylesheets::MediaList media; + readonly attribute CSSRuleList cssRules; + + [OldStyleObjC] unsigned long insertRule(in DOMString rule, + in unsigned long index) + raises(DOMException); + void deleteRule(in unsigned long index) + raises(DOMException); + }; + +} diff --git a/WebCore/css/CSSMutableStyleDeclaration.cpp b/WebCore/css/CSSMutableStyleDeclaration.cpp new file mode 100644 index 0000000..bc354ff --- /dev/null +++ b/WebCore/css/CSSMutableStyleDeclaration.cpp @@ -0,0 +1,729 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSMutableStyleDeclaration.h" + +#include "CSSImageValue.h" +#include "CSSParser.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSStyleSheet.h" +#include "CSSValueList.h" +#include "Document.h" +#include "ExceptionCode.h" +#include "StyledElement.h" + +using namespace std; + +namespace WebCore { + +CSSMutableStyleDeclaration::CSSMutableStyleDeclaration() + : m_node(0) +{ +} + +CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent) + : CSSStyleDeclaration(parent) + , m_node(0) +{ +} + +CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const DeprecatedValueList<CSSProperty>& values) + : CSSStyleDeclaration(parent) + , m_values(values) + , m_node(0) +{ + // FIXME: This allows duplicate properties. +} + +CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CSSProperty* const * properties, int numProperties) + : CSSStyleDeclaration(parent) + , m_node(0) +{ + for (int i = 0; i < numProperties; ++i) { + ASSERT(properties[i]); + m_values.append(*properties[i]); + } + // FIXME: This allows duplicate properties. +} + +CSSMutableStyleDeclaration& CSSMutableStyleDeclaration::operator=(const CSSMutableStyleDeclaration& other) +{ + // don't attach it to the same node, just leave the current m_node value + m_values = other.m_values; + return *this; +} + +String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const +{ + RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); + if (value) + return value->cssText(); + + // Shorthand and 4-values properties + switch (propertyID) { + case CSS_PROP_BACKGROUND_POSITION: { + // FIXME: 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 getLayeredShorthandValue(properties, 2); + } + case CSS_PROP_BACKGROUND: { + const int properties[6] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, + CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION_X, + CSS_PROP_BACKGROUND_POSITION_Y, CSS_PROP_BACKGROUND_COLOR }; + return getLayeredShorthandValue(properties, 6); + } + 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 String(); +} + +String CSSMutableStyleDeclaration::get4Values( const int* properties ) const +{ + String res; + for (int i = 0; i < 4; ++i) { + if (!isPropertyImplicit(properties[i])) { + RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); + + // apparently all 4 properties must be specified. + if (!value) + return String(); + + if (!res.isNull()) + res += " "; + res += value->cssText(); + } + } + return res; +} + +String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, unsigned number) const +{ + String res; + unsigned i; + unsigned j; + + // Begin by collecting the properties into an array. + Vector< RefPtr<CSSValue> > values(number); + unsigned numLayers = 0; + + for (i = 0; i < number; ++i) { + values[i] = getPropertyCSSValue(properties[i]); + if (values[i]) { + if (values[i]->isValueList()) { + CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get()); + numLayers = max(valueList->length(), numLayers); + } else + numLayers = max(1U, numLayers); + } + } + + // Now stitch the properties together. Implicit initial values are flagged as such and + // can safely be omitted. + for (i = 0; i < numLayers; i++) { + String layerRes; + for (j = 0; j < number; j++) { + RefPtr<CSSValue> value; + if (values[j]) { + if (values[j]->isValueList()) + value = static_cast<CSSValueList*>(values[j].get())->item(i); + else { + value = values[j]; + + // Color only belongs in the last layer. + if (properties[j] == CSS_PROP_BACKGROUND_COLOR) { + if (i != numLayers - 1) + value = 0; + } else if (i != 0) // Other singletons only belong in the first layer. + value = 0; + } + } + + if (value && !value->isImplicitInitialValue()) { + if (!layerRes.isNull()) + layerRes += " "; + layerRes += value->cssText(); + } + } + + if (!layerRes.isNull()) { + if (!res.isNull()) + res += ", "; + res += layerRes; + } + } + + return res; +} + +String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, int number) const +{ + String res; + for (int i = 0; i < number; ++i) { + if (!isPropertyImplicit(properties[i])) { + RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); + // FIXME: provide default value if !value + if (value) { + if (!res.isNull()) + res += " "; + res += value->cssText(); + } + } + } + return res; +} + +PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propertyID) const +{ + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.fromLast(); it != end; --it) { + if (propertyID == (*it).m_id) + return (*it).value(); + } + return 0; +} + +struct PropertyLonghand { + PropertyLonghand() + : m_properties(0) + , m_length(0) + { + } + + PropertyLonghand(const int* firstProperty, unsigned numProperties) + : m_properties(firstProperty) + , m_length(numProperties) + { + } + + const int* properties() const { return m_properties; } + unsigned length() const { return m_length; } + +private: + const int* m_properties; + unsigned m_length; +}; + +static void initShorthandMap(HashMap<int, PropertyLonghand>& shorthandMap) +{ + #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \ + map.set(propID, PropertyLonghand(array, sizeof(array) / sizeof(array[0]))) + + // FIXME: The 'font' property has "shorthand nature" but is not parsed as a shorthand. + + // Do not change the order of the following four shorthands, and keep them together. + static const int borderProperties[4][3] = { + { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_TOP_WIDTH }, + { CSS_PROP_BORDER_RIGHT_COLOR, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_RIGHT_WIDTH }, + { CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_BOTTOM_WIDTH }, + { CSS_PROP_BORDER_LEFT_COLOR, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_LEFT_WIDTH } + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_TOP, borderProperties[0]); + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_RIGHT, borderProperties[1]); + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_BOTTOM, borderProperties[2]); + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_LEFT, borderProperties[3]); + + shorthandMap.set(CSS_PROP_BORDER, PropertyLonghand(borderProperties[0], sizeof(borderProperties) / sizeof(borderProperties[0][0]))); + + static const int borderColorProperties[] = { + CSS_PROP_BORDER_TOP_COLOR, + CSS_PROP_BORDER_RIGHT_COLOR, + CSS_PROP_BORDER_BOTTOM_COLOR, + CSS_PROP_BORDER_LEFT_COLOR + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_COLOR, borderColorProperties); + + static const int borderStyleProperties[] = { + CSS_PROP_BORDER_TOP_STYLE, + CSS_PROP_BORDER_RIGHT_STYLE, + CSS_PROP_BORDER_BOTTOM_STYLE, + CSS_PROP_BORDER_LEFT_STYLE + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_STYLE, borderStyleProperties); + + static const int borderWidthProperties[] = { + CSS_PROP_BORDER_TOP_WIDTH, + CSS_PROP_BORDER_RIGHT_WIDTH, + CSS_PROP_BORDER_BOTTOM_WIDTH, + CSS_PROP_BORDER_LEFT_WIDTH + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_WIDTH, borderWidthProperties); + + static const int backgroundPositionProperties[] = { CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BACKGROUND_POSITION, backgroundPositionProperties); + + static const int borderSpacingProperties[] = { CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING, CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_SPACING, borderSpacingProperties); + + static const int listStyleProperties[] = { + CSS_PROP_LIST_STYLE_IMAGE, + CSS_PROP_LIST_STYLE_POSITION, + CSS_PROP_LIST_STYLE_TYPE + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_LIST_STYLE, listStyleProperties); + + static const int marginProperties[] = { + CSS_PROP_MARGIN_TOP, + CSS_PROP_MARGIN_RIGHT, + CSS_PROP_MARGIN_BOTTOM, + CSS_PROP_MARGIN_LEFT + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_MARGIN, marginProperties); + + static const int marginCollapseProperties[] = { CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE, CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_MARGIN_COLLAPSE, marginCollapseProperties); + + static const int marqueeProperties[] = { + CSS_PROP__WEBKIT_MARQUEE_DIRECTION, + CSS_PROP__WEBKIT_MARQUEE_INCREMENT, + CSS_PROP__WEBKIT_MARQUEE_REPETITION, + CSS_PROP__WEBKIT_MARQUEE_STYLE, + CSS_PROP__WEBKIT_MARQUEE_SPEED + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_MARQUEE, marqueeProperties); + + static const int outlineProperties[] = { + CSS_PROP_OUTLINE_COLOR, + CSS_PROP_OUTLINE_OFFSET, + CSS_PROP_OUTLINE_STYLE, + CSS_PROP_OUTLINE_WIDTH + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_OUTLINE, outlineProperties); + + static const int paddingProperties[] = { + CSS_PROP_PADDING_TOP, + CSS_PROP_PADDING_RIGHT, + CSS_PROP_PADDING_BOTTOM, + CSS_PROP_PADDING_LEFT + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_PADDING, paddingProperties); + + static const int textStrokeProperties[] = { CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_TEXT_STROKE, textStrokeProperties); + + static const int backgroundProperties[] = { + CSS_PROP_BACKGROUND_ATTACHMENT, + CSS_PROP_BACKGROUND_COLOR, + CSS_PROP_BACKGROUND_IMAGE, + CSS_PROP_BACKGROUND_POSITION_X, + CSS_PROP_BACKGROUND_POSITION_Y, + CSS_PROP_BACKGROUND_REPEAT, + CSS_PROP__WEBKIT_BACKGROUND_SIZE + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BACKGROUND, backgroundProperties); + + static const int columnsProperties[] = { CSS_PROP__WEBKIT_COLUMN_WIDTH, CSS_PROP__WEBKIT_COLUMN_COUNT }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_COLUMNS, columnsProperties); + + static const int columnRuleProperties[] = { + CSS_PROP__WEBKIT_COLUMN_RULE_COLOR, + CSS_PROP__WEBKIT_COLUMN_RULE_STYLE, + CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_COLUMN_RULE, columnRuleProperties); + + static const int overflowProperties[] = { CSS_PROP_OVERFLOW_X, CSS_PROP_OVERFLOW_Y }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_OVERFLOW, overflowProperties); + + static const int borderRadiusProperties[] = { + CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, + CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_BORDER_RADIUS, borderRadiusProperties); + + #undef SET_SHORTHAND_MAP_ENTRY +} + +String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText, ExceptionCode& ec) +{ + ec = 0; + + static HashMap<int, PropertyLonghand> shorthandMap; + if (shorthandMap.isEmpty()) + initShorthandMap(shorthandMap); + + PropertyLonghand longhand = shorthandMap.get(propertyID); + if (longhand.length()) { + removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged); + // FIXME: Return an equivalent shorthand when possible. + return String(); + } + + String value; + + DeprecatedValueListIterator<CSSProperty> end; + for (DeprecatedValueListIterator<CSSProperty> it = m_values.fromLast(); it != end; --it) { + if (propertyID == (*it).m_id) { + if (returnText) + value = (*it).value()->cssText(); + m_values.remove(it); + if (notifyChanged) + setChanged(); + break; + } + } + + return value; +} + +void CSSMutableStyleDeclaration::clear() +{ + m_values.clear(); + setChanged(); +} + +void CSSMutableStyleDeclaration::setChanged(StyleChangeType changeType) +{ + if (m_node) { + m_node->setChanged(changeType); + // FIXME: Ideally, this should be factored better and there + // should be a subclass of CSSMutableStyleDeclaration just + // for inline style declarations that handles this + if (m_node->isStyledElement() && this == static_cast<StyledElement*>(m_node)->inlineStyleDecl()) + static_cast<StyledElement*>(m_node)->invalidateStyleAttribute(); + return; + } + + // FIXME: quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk) + StyleBase* root = this; + while (StyleBase* parent = root->parent()) + root = parent; + if (root->isCSSStyleSheet()) + static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector(); +} + +bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const +{ + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) { + if (propertyID == (*it).id()) + return (*it).isImportant(); + } + return false; +} + +int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const +{ + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) { + if (propertyID == (*it).id()) + return (*it).shorthandID(); + } + return false; +} + +bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const +{ + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) { + if (propertyID == (*it).id()) + return (*it).isImplicit(); + } + return false; +} + +void CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, ExceptionCode& ec) +{ + setProperty(propertyID, value, important, true, ec); +} + +String CSSMutableStyleDeclaration::removeProperty(int propertyID, ExceptionCode& ec) +{ + return removeProperty(propertyID, true, true, ec); +} + +bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, bool notifyChanged, ExceptionCode& ec) +{ + ec = 0; + + // Setting the value to an empty string just removes the property in both IE and Gecko. + // Setting it to null seems to produce less consistent results, but we treat it just the same. + if (value.isEmpty()) { + removeProperty(propertyID, notifyChanged, false, ec); + return ec == 0; + } + + // When replacing an existing property value, this moves the property to the end of the list. + // Firefox preserves the position, and MSIE moves the property to the beginning. + CSSParser parser(useStrictParsing()); + bool success = parser.parseValue(this, propertyID, value, important); + if (!success) { + // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility, + // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. + } else if (notifyChanged) + setChanged(InlineStyleChange); + ASSERT(!ec); + return success; +} + +bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged) +{ + removeProperty(propertyID); + m_values.append(CSSProperty(propertyID, new CSSPrimitiveValue(value), important)); + if (notifyChanged) + setChanged(); + return true; +} + +void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important) +{ + removeProperty(propertyId); + m_values.append(CSSProperty(propertyId, new CSSPrimitiveValue(value, type), important)); + setChanged(); +} + +void CSSMutableStyleDeclaration::setImageProperty(int propertyId, const String& url, bool important) +{ + removeProperty(propertyId); + m_values.append(CSSProperty(propertyId, new CSSImageValue(url, this), important)); + setChanged(); +} + +void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration) +{ + m_values.clear(); + CSSParser parser(useStrictParsing()); + parser.parseDeclaration(this, styleDeclaration); + setChanged(); +} + +void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty * const * properties, int numProperties) +{ + for (int i = 0; i < numProperties; ++i) { + // Only add properties that have no !important counterpart present + if (!getPropertyPriority(properties[i]->id()) || properties[i]->isImportant()) { + removeProperty(properties[i]->id(), false); + ASSERT(properties[i]); + m_values.append(*properties[i]); + } + } + // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add + // a notifyChanged argument to this function to follow the model of other functions in this class. +} + +void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool /*multiLength*/) +{ + bool parseMode = useStrictParsing(); + setStrictParsing(false); + setProperty(propertyId, value, important); + setStrictParsing(parseMode); +} + +unsigned CSSMutableStyleDeclaration::length() const +{ + return m_values.count(); +} + +String CSSMutableStyleDeclaration::item(unsigned i) const +{ + if (i >= m_values.count()) + return String(); + return getPropertyName(static_cast<CSSPropertyID>(m_values[i].id())); +} + +String CSSMutableStyleDeclaration::cssText() const +{ + String result = ""; + + const CSSProperty* positionXProp = 0; + const CSSProperty* positionYProp = 0; + + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) { + const CSSProperty& prop = *it; + if (prop.id() == CSS_PROP_BACKGROUND_POSITION_X) + positionXProp = ∝ + else if (prop.id() == CSS_PROP_BACKGROUND_POSITION_Y) + positionYProp = ∝ + else + result += prop.cssText(); + } + + // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. + // It is required because background-position-x/y are non-standard properties and WebKit generated output + // would not work in Firefox (<rdar://problem/5143183>) + // It would be a better solution if background-position was CSS_PAIR. + if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) { + String positionValue; + const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y }; + if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList()) + positionValue = getLayeredShorthandValue(properties, 2); + else + positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText(); + result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; "; + } else { + if (positionXProp) + result += positionXProp->cssText(); + if (positionYProp) + result += positionYProp->cssText(); + } + + return result; +} + +void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec) +{ + ec = 0; + m_values.clear(); + CSSParser parser(useStrictParsing()); + parser.parseDeclaration(this, text); + // FIXME: Detect syntax errors and set ec. + setChanged(); +} + +void CSSMutableStyleDeclaration::merge(CSSMutableStyleDeclaration* other, bool argOverridesOnConflict) +{ + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = other->valuesIterator(); it != end; ++it) { + const CSSProperty& property = *it; + RefPtr<CSSValue> value = getPropertyCSSValue(property.id()); + if (value) { + if (!argOverridesOnConflict) + continue; + removeProperty(property.id()); + } + m_values.append(property); + } + // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add + // a notifyChanged argument to this function to follow the model of other functions in this class. +} + +// This is the list of properties we want to copy in the copyBlockProperties() function. +// It is the list of CSS properties that apply specially to block-level elements. +static const int blockProperties[] = { + CSS_PROP_ORPHANS, + CSS_PROP_OVERFLOW, // This can be also be applied to replaced elements + CSS_PROP__WEBKIT_COLUMN_COUNT, + CSS_PROP__WEBKIT_COLUMN_GAP, + CSS_PROP__WEBKIT_COLUMN_RULE_COLOR, + CSS_PROP__WEBKIT_COLUMN_RULE_STYLE, + CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, + CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE, + CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER, + CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE, + CSS_PROP__WEBKIT_COLUMN_WIDTH, + 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]); + +PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const +{ + return copyPropertiesInSet(blockProperties, numBlockProperties); +} + +void CSSMutableStyleDeclaration::removeBlockProperties() +{ + removePropertiesInSet(blockProperties, numBlockProperties); +} + +void CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged) +{ + bool changed = false; + for (unsigned i = 0; i < length; i++) { + RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); + if (value) { + m_values.remove(CSSProperty(set[i], value.release(), false)); + changed = true; + } + } + if (changed && notifyChanged) + setChanged(); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable() +{ + return this; +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const +{ + return new CSSMutableStyleDeclaration(0, m_values); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSMutableStyleDeclaration.h b/WebCore/css/CSSMutableStyleDeclaration.h new file mode 100644 index 0000000..b193d8d --- /dev/null +++ b/WebCore/css/CSSMutableStyleDeclaration.h @@ -0,0 +1,116 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSMutableStyleDeclaration_h +#define CSSMutableStyleDeclaration_h + +#include "CSSStyleDeclaration.h" +#include "CSSPrimitiveValue.h" +#include "DeprecatedValueList.h" +#include "Node.h" +#include "PlatformString.h" + +namespace WebCore { + +class CSSProperty; +class Node; + +class CSSMutableStyleDeclaration : public CSSStyleDeclaration { +public: + CSSMutableStyleDeclaration(); + CSSMutableStyleDeclaration(CSSRule* parentRule); + CSSMutableStyleDeclaration(CSSRule* parentRule, const DeprecatedValueList<CSSProperty>&); + CSSMutableStyleDeclaration(CSSRule* parentRule, const CSSProperty* const *, int numProperties); + + CSSMutableStyleDeclaration& operator=(const CSSMutableStyleDeclaration&); + + void setNode(Node* node) { m_node = node; } + + virtual String cssText() const; + virtual void setCssText(const String&, ExceptionCode&); + + virtual unsigned length() const; + virtual String item(unsigned index) const; + + virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; + virtual String getPropertyValue(int propertyID) const; + virtual bool getPropertyPriority(int propertyID) const; + virtual int getPropertyShorthand(int propertyID) const; + virtual bool isPropertyImplicit(int propertyID) const; + + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); + virtual String removeProperty(int propertyID, ExceptionCode&); + + virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const; + virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable(); + + DeprecatedValueListConstIterator<CSSProperty> valuesIterator() const { return m_values.begin(); } + + bool setProperty(int propertyID, int value, bool important = false, bool notifyChanged = true); + bool setProperty(int propertyID, const String& value, bool important, bool notifyChanged, ExceptionCode&); + bool setProperty(int propertyId, const String& value, bool important = false, bool notifyChanged = true) + { + ExceptionCode ec; + return setProperty(propertyId, value, important, notifyChanged, ec); + } + + String removeProperty(int propertyID, bool notifyChanged, bool returnText, ExceptionCode&); + void removeProperty(int propertyID, bool notifyChanged = true) + { + ExceptionCode ec; + removeProperty(propertyID, notifyChanged, false, ec); + } + + void clear(); + + void setChanged(StyleChangeType changeType = FullStyleChange); + + // setLengthProperty treats integers as pixels! (Needed for conversion of HTML attributes.) + void setLengthProperty(int propertyId, const String& value, bool important, bool multiLength = false); + void setStringProperty(int propertyId, const String& value, CSSPrimitiveValue::UnitTypes, bool important = false); // parsed string value + void setImageProperty(int propertyId, const String& url, bool important = false); + + // The following parses an entire new style declaration. + void parseDeclaration(const String& styleDeclaration); + + // Besides adding the properties, this also removes any existing properties with these IDs. + // It does no notification since it's called by the parser. + void addParsedProperties(const CSSProperty* const *, int numProperties); + + PassRefPtr<CSSMutableStyleDeclaration> copyBlockProperties() const; + void removeBlockProperties(); + void removePropertiesInSet(const int* set, unsigned length, bool notifyChanged = true); + + void merge(CSSMutableStyleDeclaration*, bool argOverridesOnConflict = true); + +private: + String getShorthandValue(const int* properties, int number) const; + String getLayeredShorthandValue(const int* properties, unsigned number) const; + String get4Values(const int* properties) const; + + DeprecatedValueList<CSSProperty> m_values; + Node* m_node; +}; + +} // namespace WebCore + +#endif // CSSMutableStyleDeclaration_h diff --git a/WebCore/css/CSSNamespace.h b/WebCore/css/CSSNamespace.h new file mode 100644 index 0000000..9194be8 --- /dev/null +++ b/WebCore/css/CSSNamespace.h @@ -0,0 +1,59 @@ +/* + * This file is part of the CSS implementation for KDE. + * + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSNamespace_h +#define CSSNamespace_h + +#include "AtomicString.h" + +namespace WebCore { + + struct CSSNamespace { + AtomicString m_prefix; + AtomicString m_uri; + CSSNamespace* m_parent; + + CSSNamespace(const AtomicString& prefix, const AtomicString& uri, CSSNamespace* parent) + : m_prefix(prefix) + , m_uri(uri) + , m_parent(parent) + { + } + ~CSSNamespace() { delete m_parent; } + + const AtomicString& uri() { return m_uri; } + const AtomicString& prefix() { return m_prefix; } + + CSSNamespace* namespaceForPrefix(const AtomicString& prefix) + { + if (prefix == m_prefix) + return this; + if (m_parent) + return m_parent->namespaceForPrefix(prefix); + return 0; + } + }; + +} // namespace WebCore + +#endif // CSSNamespace_h diff --git a/WebCore/css/CSSPageRule.cpp b/WebCore/css/CSSPageRule.cpp new file mode 100644 index 0000000..4e95473 --- /dev/null +++ b/WebCore/css/CSSPageRule.cpp @@ -0,0 +1,57 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSPageRule.h" + +#include "CSSMutableStyleDeclaration.h" + +namespace WebCore { + +CSSPageRule::CSSPageRule(StyleBase* parent) + : CSSRule(parent) +{ +} + +CSSPageRule::~CSSPageRule() +{ +} + +String CSSPageRule::selectorText() const +{ + // FIXME: Implement! + return String(); +} + +void CSSPageRule::setSelectorText(const String& /*selectorText*/, ExceptionCode& /*ec*/) +{ + // FIXME: Implement! +} + +String CSSPageRule::cssText() const +{ + // FIXME: Implement! + return String(); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSPageRule.h b/WebCore/css/CSSPageRule.h new file mode 100644 index 0000000..afa78c1 --- /dev/null +++ b/WebCore/css/CSSPageRule.h @@ -0,0 +1,59 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSPageRule_h +#define CSSPageRule_h + +#include "CSSRule.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSMutableStyleDeclaration; + +typedef int ExceptionCode; + +class CSSPageRule : public CSSRule { +public: + CSSPageRule(StyleBase* parent); + virtual ~CSSPageRule(); + + virtual bool isPageRule() { return true; } + + String selectorText() const; + void setSelectorText(const String&, ExceptionCode&); + + CSSMutableStyleDeclaration* style() const { return m_style.get(); } + + // Inherited from CSSRule + virtual unsigned short type() const { return PAGE_RULE; } + + virtual String cssText() const; + +protected: + RefPtr<CSSMutableStyleDeclaration> m_style; +}; + +} // namespace WebCore + +#endif // CSSPageRule_h diff --git a/WebCore/css/CSSPageRule.idl b/WebCore/css/CSSPageRule.idl new file mode 100644 index 0000000..3ad570e --- /dev/null +++ b/WebCore/css/CSSPageRule.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=4e8d9d26-65ca-483f-a6d4-be1a25905056, + ImplementationUUID=d8e40379-8b0e-4dce-b1f8-636dcf055a5f + ] CSSPageRule : CSSRule { + + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText + setter raises(DOMException); + + readonly attribute CSSStyleDeclaration style; + + }; + +} diff --git a/WebCore/css/CSSParser.cpp b/WebCore/css/CSSParser.cpp new file mode 100644 index 0000000..91c4c50 --- /dev/null +++ b/WebCore/css/CSSParser.cpp @@ -0,0 +1,4035 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSParser.h" + +#include "CString.h" +#include "CSSTimingFunctionValue.h" +#include "CSSBorderImageValue.h" +#include "CSSCharsetRule.h" +#include "CSSCursorImageValue.h" +#include "CSSHelper.h" +#include "CSSImageValue.h" +#include "CSSFontFaceRule.h" +#include "CSSFontFaceSrcValue.h" +#include "CSSImportRule.h" +#include "CSSInheritedValue.h" +#include "CSSInitialValue.h" +#include "CSSMediaRule.h" +#include "CSSMutableStyleDeclaration.h" +#include "CSSPrimitiveValue.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSQuirkPrimitiveValue.h" +#include "CSSRuleList.h" +#include "CSSSelector.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "CSSTransformValue.h" +#include "CSSUnicodeRangeValue.h" +#include "CSSValueKeywords.h" +#include "CSSValueList.h" +#include "Counter.h" +#include "DashboardRegion.h" +#include "Document.h" +#include "FloatConversion.h" +#include "FontFamilyValue.h" +#include "FontValue.h" +#include "MediaList.h" +#include "MediaQueryExp.h" +#include "Pair.h" +#include "ShadowValue.h" +#include <kjs/dtoa.h> + +#define YYDEBUG 0 + +#if YYDEBUG > 0 +extern int cssyydebug; +#endif + +extern int cssyyparse(void* parser); + +using namespace std; +using namespace WTF; + +#include "CSSPropertyNames.c" +#include "CSSValueKeywords.c" + +namespace WebCore { + +static bool equal(const ParseString& a, const char* b) +{ + for (int i = 0; i < a.length; ++i) { + if (!b[i]) + return false; + if (a.characters[i] != b[i]) + return false; + } + return !b[a.length]; +} + +static bool equalIgnoringCase(const ParseString& a, const char* b) +{ + for (int i = 0; i < a.length; ++i) { + if (!b[i]) + return false; + ASSERT(!isASCIIUpper(b[i])); + if (toASCIILower(a.characters[i]) != b[i]) + return false; + } + return !b[a.length]; +} + +static bool hasPrefix(const char* string, unsigned length, const char* prefix) +{ + for (unsigned i = 0; i < length; ++i) { + if (!prefix[i]) + return true; + if (string[i] != prefix[i]) + return false; + } + return false; +} + +ValueList::~ValueList() +{ + size_t numValues = m_values.size(); + for (size_t i = 0; i < numValues; i++) + if (m_values[i].unit == Value::Function) + delete m_values[i].function; +} + +namespace { + class ShorthandScope { + public: + ShorthandScope(CSSParser* parser, int propId) : m_parser(parser) + { + if (!(m_parser->m_inParseShorthand++)) + m_parser->m_currentShorthand = propId; + } + ~ShorthandScope() + { + if (!(--m_parser->m_inParseShorthand)) + m_parser->m_currentShorthand = 0; + } + + private: + CSSParser* m_parser; + }; +} + +CSSParser* CSSParser::currentParser = 0; + +CSSParser::CSSParser(bool strictParsing) + : m_floatingMediaQuery(0) + , m_floatingMediaQueryExp(0) + , m_floatingMediaQueryExpList(0) +{ +#ifdef CSS_DEBUG + kdDebug(6080) << "CSSParser::CSSParser this=" << this << endl; +#endif + strict = strictParsing; + + parsedProperties = (CSSProperty **)fastMalloc(32 * sizeof(CSSProperty *)); + numParsedProperties = 0; + maxParsedProperties = 32; + + data = 0; + valueList = 0; + id = 0; + important = false; + m_inParseShorthand = 0; + m_currentShorthand = 0; + m_implicitShorthand = false; + + defaultNamespace = starAtom; + + yy_start = 1; + +#if YYDEBUG > 0 + cssyydebug = 1; +#endif +} + +CSSParser::~CSSParser() +{ + clearProperties(); + fastFree(parsedProperties); + + delete valueList; + + fastFree(data); + + if (m_floatingMediaQueryExpList) { + deleteAllValues(*m_floatingMediaQueryExpList); + delete m_floatingMediaQueryExpList; + } + delete m_floatingMediaQueryExp; + delete m_floatingMediaQuery; + deleteAllValues(m_floatingSelectors); + deleteAllValues(m_floatingValueLists); + deleteAllValues(m_floatingFunctions); +} + +void ParseString::lower() +{ + // FIXME: If we need Unicode lowercasing here, then we probably want the real kind + // that can potentially change the length of the string rather than the character + // by character kind. If we don't need Unicode lowercasing, it would be good to + // simplify this function. + + if (charactersAreAllASCII(characters, length)) { + // Fast case for all-ASCII. + for (int i = 0; i < length; i++) + characters[i] = toASCIILower(characters[i]); + } else { + for (int i = 0; i < length; i++) + characters[i] = Unicode::toLower(characters[i]); + } +} + +void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix) +{ + int length = string.length() + strlen(prefix) + strlen(suffix) + 2; + + if (data) + fastFree(data); + + data = static_cast<UChar*>(fastMalloc(length * sizeof(UChar))); + for (unsigned i = 0; i < strlen(prefix); i++) + data[i] = prefix[i]; + + memcpy(data + strlen(prefix), string.characters(), string.length() * sizeof(UChar)); + + unsigned start = strlen(prefix) + string.length(); + unsigned end = start + strlen(suffix); + for (unsigned i = start; i < end; i++) + data[i] = suffix[i - start]; + + data[length - 1] = 0; + data[length - 2] = 0; + + yy_hold_char = 0; + yyleng = 0; + yytext = yy_c_buf_p = data; + yy_hold_char = *yy_c_buf_p; +} + +void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string) +{ + styleElement = sheet; + defaultNamespace = starAtom; // Reset the default namespace. + + setupParser("", string, ""); + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + rule = 0; +} + +PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet *sheet, const String &string) +{ + styleElement = sheet; + + setupParser("@-webkit-rule{", string, "} "); + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + return rule.release(); +} + +bool CSSParser::parseValue(CSSMutableStyleDeclaration *declaration, int _id, const String &string, bool _important) +{ + styleElement = declaration->stylesheet(); + + setupParser("@-webkit-value{", string, "} "); + + id = _id; + important = _important; + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + rule = 0; + + bool ok = false; + if (numParsedProperties) { + ok = true; + declaration->addParsedProperties(parsedProperties, numParsedProperties); + clearProperties(); + } + + return ok; +} + +// color will only be changed when string contains a valid css color, making it +// possible to set up a default color. +bool CSSParser::parseColor(RGBA32& color, const String &string, bool strict) +{ + color = 0; + CSSParser parser(true); + + // First try creating a color specified by name or the "#" syntax. + if (!parser.parseColor(string, color, strict)) { + RefPtr<CSSMutableStyleDeclaration> dummyStyleDeclaration(new CSSMutableStyleDeclaration); + + // Now try to create a color from the rgb() or rgba() syntax. + if (parser.parseColor(dummyStyleDeclaration.get(), string)) { + CSSValue* value = parser.parsedProperties[0]->value(); + if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) { + CSSPrimitiveValue *primitiveValue = static_cast<CSSPrimitiveValue *>(value); + color = primitiveValue->getRGBColorValue(); + } + } else + return false; + } + + return true; +} + +bool CSSParser::parseColor(CSSMutableStyleDeclaration *declaration, const String &string) +{ + styleElement = declaration->stylesheet(); + + setupParser("@-webkit-decls{color:", string, "} "); + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + rule = 0; + + bool ok = false; + if (numParsedProperties && parsedProperties[0]->m_id == CSS_PROP_COLOR) + ok = true; + + return ok; +} + +bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration *declaration, const String &string) +{ + styleElement = declaration->stylesheet(); + + setupParser("@-webkit-decls{", string, "} "); + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + rule = 0; + + bool ok = false; + if (numParsedProperties) { + ok = true; + declaration->addParsedProperties(parsedProperties, numParsedProperties); + clearProperties(); + } + + return ok; +} + +bool CSSParser::parseMediaQuery(MediaList* queries, const String& string) +{ + if (string.isEmpty() || string.isNull()) { + return true; + } + + mediaQuery = 0; + // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token. + // instead insert one " " (which is WHITESPACE in CSSGrammar.y) + setupParser ("@-webkit-mediaquery ", string, "} "); + + CSSParser* old = currentParser; + currentParser = this; + cssyyparse(this); + currentParser = old; + + bool ok = false; + if (mediaQuery) { + ok = true; + queries->appendMediaQuery(mediaQuery); + mediaQuery = 0; + } + + return ok; +} + + +void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important) +{ + CSSProperty *prop = new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand); + if (numParsedProperties >= maxParsedProperties) { + maxParsedProperties += 32; + parsedProperties = (CSSProperty **)fastRealloc(parsedProperties, + maxParsedProperties*sizeof(CSSProperty *)); + } + parsedProperties[numParsedProperties++] = prop; +} + +void CSSParser::rollbackLastProperties(int num) +{ + ASSERT(num >= 0); + ASSERT(numParsedProperties >= num); + + for (int i = 0; i < num; ++i) + delete parsedProperties[--numParsedProperties]; +} + +void CSSParser::clearProperties() +{ + for (int i = 0; i < numParsedProperties; i++) + delete parsedProperties[i]; + numParsedProperties = 0; +} + +Document *CSSParser::document() const +{ + StyleBase *root = styleElement; + Document *doc = 0; + while (root->parent()) + root = root->parent(); + if (root->isCSSStyleSheet()) + doc = static_cast<CSSStyleSheet*>(root)->doc(); + return doc; +} + +bool CSSParser::validUnit(Value* value, Units unitflags, bool strict) +{ + if (unitflags & FNonNeg && value->fValue < 0) + return false; + + bool b = false; + switch(value->unit) { + case CSSPrimitiveValue::CSS_NUMBER: + b = (unitflags & FNumber); + if (!b && ((unitflags & (FLength | FAngle)) && (value->fValue == 0 || !strict))) { + value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX : CSSPrimitiveValue::CSS_DEG; + b = true; + } + if (!b && (unitflags & FInteger) && value->isInt) + b = true; + break; + case CSSPrimitiveValue::CSS_PERCENTAGE: + b = (unitflags & FPercent); + break; + case Value::Q_EMS: + case CSSPrimitiveValue::CSS_EMS: + case CSSPrimitiveValue::CSS_EXS: + case CSSPrimitiveValue::CSS_PX: + case CSSPrimitiveValue::CSS_CM: + case CSSPrimitiveValue::CSS_MM: + case CSSPrimitiveValue::CSS_IN: + case CSSPrimitiveValue::CSS_PT: + case CSSPrimitiveValue::CSS_PC: + b = (unitflags & FLength); + break; + case CSSPrimitiveValue::CSS_MS: + case CSSPrimitiveValue::CSS_S: + b = (unitflags & FTime); + break; + case CSSPrimitiveValue::CSS_DEG: + case CSSPrimitiveValue::CSS_RAD: + case CSSPrimitiveValue::CSS_GRAD: + b = (unitflags & FAngle); + break; + case CSSPrimitiveValue::CSS_HZ: + case CSSPrimitiveValue::CSS_KHZ: + case CSSPrimitiveValue::CSS_DIMENSION: + default: + break; + } + return b; +} + +static int unitFromString(Value* value) +{ + if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id) + return 0; + + if (equal(value->string, "em")) + return CSSPrimitiveValue::CSS_EMS; + if (equal(value->string, "ex")) + return CSSPrimitiveValue::CSS_EXS; + if (equal(value->string, "px")) + return CSSPrimitiveValue::CSS_PX; + if (equal(value->string, "cm")) + return CSSPrimitiveValue::CSS_CM; + if (equal(value->string, "mm")) + return CSSPrimitiveValue::CSS_MM; + if (equal(value->string, "in")) + return CSSPrimitiveValue::CSS_IN; + if (equal(value->string, "pt")) + return CSSPrimitiveValue::CSS_PT; + if (equal(value->string, "pc")) + return CSSPrimitiveValue::CSS_PC; + if (equal(value->string, "deg")) + return CSSPrimitiveValue::CSS_DEG; + if (equal(value->string, "rad")) + return CSSPrimitiveValue::CSS_RAD; + if (equal(value->string, "grad")) + return CSSPrimitiveValue::CSS_GRAD; + if (equal(value->string, "ms")) + return CSSPrimitiveValue::CSS_MS; + if (equal(value->string, "s")) + return CSSPrimitiveValue::CSS_S; + if (equal(value->string, "Hz")) + return CSSPrimitiveValue::CSS_HZ; + if (equal(value->string, "kHz")) + return CSSPrimitiveValue::CSS_KHZ; + + return 0; +} + +void CSSParser::checkForOrphanedUnits() +{ + if (strict || inShorthand()) + return; + + // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values + // by whitespace, so e.g., width: 20 px instead of width:20px. This is invalid CSS, so we don't do this in strict mode. + Value* numericVal = 0; + unsigned size = valueList->size(); + for (unsigned i = 0; i < size; i++) { + Value* value = valueList->valueAt(i); + if (numericVal) { + // Change the unit type of the numeric val to match. + int unit = unitFromString(value); + if (unit) { + numericVal->unit = unit; + numericVal = 0; + + // Now delete the bogus unit value. + valueList->deleteValueAt(i); + i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here). + size--; + continue; + } + } + + numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0; + } +} + +bool CSSParser::parseValue(int propId, bool important) +{ + if (!valueList) + return false; + + Value *value = valueList->current(); + + if (!value) + return false; + + int id = value->id; + + int num = inShorthand() ? 1 : valueList->size(); + + if (id == CSS_VAL_INHERIT) { + if (num != 1) + return false; + addProperty(propId, new CSSInheritedValue(), important); + return true; + } + else if (id == CSS_VAL_INITIAL) { + if (num != 1) + return false; + addProperty(propId, new CSSInitialValue(false), important); + return true; + } + + bool valid_primitive = false; + RefPtr<CSSValue> parsedValue; + + // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to + // by a space. We go ahead and associate the unit with the number even though it is invalid CSS. + checkForOrphanedUnits(); + + switch (static_cast<CSSPropertyID>(propId)) { + /* The comment to the left defines all valid value of this properties as defined + * in CSS 2, Appendix F. Property index + */ + + /* All the CSS properties are not supported by the renderer at the moment. + * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined + * (see parseAuralValues). As we don't support them at all this seems reasonable. + */ + + case CSS_PROP_SIZE: // <length>{1,2} | auto | portrait | landscape | inherit + case CSS_PROP_QUOTES: // [<string> <string>]+ | none | inherit + if (id) + valid_primitive = true; + break; + case CSS_PROP_UNICODE_BIDI: // normal | embed | bidi-override | inherit + if (id == CSS_VAL_NORMAL || + id == CSS_VAL_EMBED || + id == CSS_VAL_BIDI_OVERRIDE) + valid_primitive = true; + break; + + case CSS_PROP_POSITION: // static | relative | absolute | fixed | inherit + if (id == CSS_VAL_STATIC || + id == CSS_VAL_RELATIVE || + id == CSS_VAL_ABSOLUTE || + id == CSS_VAL_FIXED) + valid_primitive = true; + break; + + case CSS_PROP_PAGE_BREAK_AFTER: // auto | always | avoid | left | right | inherit + case CSS_PROP_PAGE_BREAK_BEFORE: + case CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER: + case CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE: + if (id == CSS_VAL_AUTO || + id == CSS_VAL_ALWAYS || + id == CSS_VAL_AVOID || + id == CSS_VAL_LEFT || + id == CSS_VAL_RIGHT) + valid_primitive = true; + break; + + case CSS_PROP_PAGE_BREAK_INSIDE: // avoid | auto | inherit + case CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE: + if (id == CSS_VAL_AUTO || id == CSS_VAL_AVOID) + valid_primitive = true; + break; + + case CSS_PROP_EMPTY_CELLS: // show | hide | inherit + if (id == CSS_VAL_SHOW || + id == CSS_VAL_HIDE) + valid_primitive = true; + break; + + case CSS_PROP_CONTENT: // [ <string> | <uri> | <counter> | attr(X) | open-quote | + // close-quote | no-open-quote | no-close-quote ]+ | inherit + return parseContent(propId, important); + break; + + case CSS_PROP_WHITE_SPACE: // normal | pre | nowrap | inherit + if (id == CSS_VAL_NORMAL || + id == CSS_VAL_PRE || + id == CSS_VAL_PRE_WRAP || + id == CSS_VAL_PRE_LINE || + id == CSS_VAL_NOWRAP) + valid_primitive = true; + break; + + case CSS_PROP_CLIP: // <shape> | auto | inherit + if (id == CSS_VAL_AUTO) + valid_primitive = true; + else if (value->unit == Value::Function) + return parseShape(propId, important); + break; + + /* Start of supported CSS properties with validation. This is needed for parseShorthand to work + * correctly and allows optimization in WebCore::applyRule(..) + */ + case CSS_PROP_CAPTION_SIDE: // top | bottom | left | right | inherit + if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || + id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) + valid_primitive = true; + break; + + case CSS_PROP_BORDER_COLLAPSE: // collapse | separate | inherit + if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE) + valid_primitive = true; + break; + + case CSS_PROP_VISIBILITY: // visible | hidden | collapse | inherit + if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_COLLAPSE) + valid_primitive = true; + break; + + case CSS_PROP_OVERFLOW: { + ShorthandScope scope(this, propId); + if (num != 1 || !parseValue(CSS_PROP_OVERFLOW_X, important)) + return false; + CSSValue* value = parsedProperties[numParsedProperties - 1]->value(); + addProperty(CSS_PROP_OVERFLOW_Y, value, important); + return true; + } + case CSS_PROP_OVERFLOW_X: + case CSS_PROP_OVERFLOW_Y: // visible | hidden | scroll | auto | marquee | overlay | inherit + if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_SCROLL || id == CSS_VAL_AUTO || + id == CSS_VAL_OVERLAY || id == CSS_VAL__WEBKIT_MARQUEE) + valid_primitive = true; + break; + + case CSS_PROP_LIST_STYLE_POSITION: // inside | outside | inherit + if (id == CSS_VAL_INSIDE || id == CSS_VAL_OUTSIDE) + valid_primitive = true; + break; + + case CSS_PROP_LIST_STYLE_TYPE: + // disc | circle | square | decimal | decimal-leading-zero | lower-roman | + // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha | + // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana | + // katakana | hiragana-iroha | katakana-iroha | none | inherit + if ((id >= CSS_VAL_DISC && id <= CSS_VAL_KATAKANA_IROHA) || id == CSS_VAL_NONE) + valid_primitive = true; + break; + + case CSS_PROP_DISPLAY: + // inline | block | list-item | run-in | inline-block | table | + // inline-table | table-row-group | table-header-group | table-footer-group | table-row | + // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit + if ((id >= CSS_VAL_INLINE && id <= CSS_VAL__WEBKIT_INLINE_BOX) || id == CSS_VAL_NONE) + valid_primitive = true; + break; + + case CSS_PROP_DIRECTION: // ltr | rtl | inherit + if (id == CSS_VAL_LTR || id == CSS_VAL_RTL) + valid_primitive = true; + break; + + case CSS_PROP_TEXT_TRANSFORM: // capitalize | uppercase | lowercase | none | inherit + if ((id >= CSS_VAL_CAPITALIZE && id <= CSS_VAL_LOWERCASE) || id == CSS_VAL_NONE) + valid_primitive = true; + break; + + case CSS_PROP_FLOAT: // left | right | none | inherit + center for buggy CSS + if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || + id == CSS_VAL_NONE || id == CSS_VAL_CENTER) + valid_primitive = true; + break; + + case CSS_PROP_CLEAR: // none | left | right | both | inherit + if (id == CSS_VAL_NONE || id == CSS_VAL_LEFT || + id == CSS_VAL_RIGHT|| id == CSS_VAL_BOTH) + valid_primitive = true; + break; + + case CSS_PROP_TEXT_ALIGN: + // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit + if ((id >= CSS_VAL__WEBKIT_AUTO && id <= CSS_VAL__WEBKIT_CENTER) || id == CSS_VAL_START || id == CSS_VAL_END || + value->unit == CSSPrimitiveValue::CSS_STRING) + valid_primitive = true; + break; + + case CSS_PROP_OUTLINE_STYLE: // <border-style> | auto | inherit + if (id == CSS_VAL_AUTO) { + valid_primitive = true; + break; + } // Fall through! + case CSS_PROP_BORDER_TOP_STYLE: //// <border-style> | inherit + case CSS_PROP_BORDER_RIGHT_STYLE: // Defined as: none | hidden | dotted | dashed | + case CSS_PROP_BORDER_BOTTOM_STYLE: // solid | double | groove | ridge | inset | outset + case CSS_PROP_BORDER_LEFT_STYLE: + case CSS_PROP__WEBKIT_COLUMN_RULE_STYLE: + if (id >= CSS_VAL_NONE && id <= CSS_VAL_DOUBLE) + valid_primitive = true; + break; + + case CSS_PROP_FONT_WEIGHT: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | + // 500 | 600 | 700 | 800 | 900 | inherit + if (id >= CSS_VAL_NORMAL && id <= CSS_VAL_900) { + // Allready correct id + valid_primitive = true; + } else if (validUnit(value, FInteger|FNonNeg, false)) { + int weight = (int)value->fValue; + if ((weight % 100)) + break; + weight /= 100; + if (weight >= 1 && weight <= 9) { + id = CSS_VAL_100 + weight - 1; + valid_primitive = true; + } + } + break; + + case CSS_PROP_BORDER_SPACING: { + const int properties[2] = { CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING, + CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING }; + if (num == 1) { + ShorthandScope scope(this, CSS_PROP_BORDER_SPACING); + if (!parseValue(properties[0], important)) + return false; + CSSValue* value = parsedProperties[numParsedProperties-1]->value(); + addProperty(properties[1], value, important); + return true; + } + else if (num == 2) { + ShorthandScope scope(this, CSS_PROP_BORDER_SPACING); + if (!parseValue(properties[0], important) || !parseValue(properties[1], important)) + return false; + return true; + } + return false; + } + case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: + case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: + valid_primitive = validUnit(value, FLength|FNonNeg, strict); + break; + case CSS_PROP_SCROLLBAR_FACE_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_SHADOW_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_TRACK_COLOR: // IE5.5 + case CSS_PROP_SCROLLBAR_ARROW_COLOR: // IE5.5 + if (strict) + break; + /* nobreak */ + case CSS_PROP_OUTLINE_COLOR: // <color> | invert | inherit + // Outline color has "invert" as additional keyword. + // Also, we want to allow the special focus color even in strict parsing mode. + if (propId == CSS_PROP_OUTLINE_COLOR && (id == CSS_VAL_INVERT || id == CSS_VAL__WEBKIT_FOCUS_RING_COLOR)) { + valid_primitive = true; + break; + } + /* nobreak */ + case CSS_PROP_BACKGROUND_COLOR: // <color> | inherit + case CSS_PROP_BORDER_TOP_COLOR: // <color> | inherit + case CSS_PROP_BORDER_RIGHT_COLOR: // <color> | inherit + case CSS_PROP_BORDER_BOTTOM_COLOR: // <color> | inherit + case CSS_PROP_BORDER_LEFT_COLOR: // <color> | inherit + case CSS_PROP_COLOR: // <color> | inherit + case CSS_PROP_TEXT_LINE_THROUGH_COLOR: // CSS3 text decoration colors + case CSS_PROP_TEXT_UNDERLINE_COLOR: + case CSS_PROP_TEXT_OVERLINE_COLOR: + case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: + case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: + case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: + if (id == CSS_VAL__WEBKIT_TEXT) + valid_primitive = true; // Always allow this, even when strict parsing is on, + // since we use this in our UA sheets. + else if (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT || id == CSS_VAL_MENU || + (id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && id < CSS_VAL__WEBKIT_TEXT && !strict)) { + valid_primitive = true; + } else { + parsedValue = parseColor(); + if (parsedValue) + valueList->next(); + } + break; + + case CSS_PROP_CURSOR: { + // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize | + // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | + // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help ] ] | inherit + RefPtr<CSSValueList> list; + while (value && value->unit == CSSPrimitiveValue::CSS_URI) { + if (!list) + list = new CSSValueList; + String uri = parseURL(value->string); + Vector<int> coords; + value = valueList->next(); + while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) { + coords.append(int(value->fValue)); + value = valueList->next(); + } + IntPoint hotspot; + int nrcoords = coords.size(); + if (nrcoords > 0 && nrcoords != 2) { + if (strict) // only support hotspot pairs in strict mode + return false; + } else if(strict && nrcoords == 2) + hotspot = IntPoint(coords[0], coords[1]); + if (strict || coords.size() == 0) { + if (!uri.isEmpty()) { + list->append(new CSSCursorImageValue(KURL(styleElement->baseURL(), uri).string(), + hotspot, styleElement)); + } + } + if ((strict && !value) || (value && !(value->unit == Value::Operator && value->iValue == ','))) + return false; + value = valueList->next(); // comma + } + if (list) { + if (!value) { // no value after url list (MSIE 5 compatibility) + if (list->length() != 1) + return false; + } else if (!strict && value->id == CSS_VAL_HAND) // MSIE 5 compatibility :/ + list->append(new CSSPrimitiveValue(CSS_VAL_POINTER)); + else if (value && ((value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_ALL_SCROLL) || value->id == CSS_VAL_COPY || value->id == CSS_VAL_NONE)) + list->append(new CSSPrimitiveValue(value->id)); + valueList->next(); + parsedValue = list.release(); + break; + } + id = value->id; + if (!strict && value->id == CSS_VAL_HAND) { // MSIE 5 compatibility :/ + id = CSS_VAL_POINTER; + valid_primitive = true; + } else if ((value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_ALL_SCROLL) || value->id == CSS_VAL_COPY || value->id == CSS_VAL_NONE) + valid_primitive = true; + break; + } + + case CSS_PROP_BACKGROUND_ATTACHMENT: + case CSS_PROP__WEBKIT_BACKGROUND_CLIP: + case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: + case CSS_PROP_BACKGROUND_IMAGE: + case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN: + case CSS_PROP_BACKGROUND_POSITION: + case CSS_PROP_BACKGROUND_POSITION_X: + case CSS_PROP_BACKGROUND_POSITION_Y: + case CSS_PROP__WEBKIT_BACKGROUND_SIZE: + case CSS_PROP_BACKGROUND_REPEAT: { + RefPtr<CSSValue> val1; + RefPtr<CSSValue> val2; + int propId1, propId2; + if (parseBackgroundProperty(propId, propId1, propId2, val1, val2)) { + addProperty(propId1, val1.release(), important); + if (val2) + addProperty(propId2, val2.release(), important); + return true; + } + return false; + } + case CSS_PROP_LIST_STYLE_IMAGE: // <uri> | none | inherit + if (id == CSS_VAL_NONE) { + parsedValue = new CSSImageValue(); + valueList->next(); + } + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + // ### allow string in non strict mode? + String uri = parseURL(value->string); + if (!uri.isEmpty()) { + parsedValue = new CSSImageValue(KURL(styleElement->baseURL(), uri).string(), styleElement); + valueList->next(); + } + } + break; + + case CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH: + case CSS_PROP_OUTLINE_WIDTH: // <border-width> | inherit + case CSS_PROP_BORDER_TOP_WIDTH: //// <border-width> | inherit + case CSS_PROP_BORDER_RIGHT_WIDTH: // Which is defined as + case CSS_PROP_BORDER_BOTTOM_WIDTH: // thin | medium | thick | <length> + case CSS_PROP_BORDER_LEFT_WIDTH: + case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: + if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength, strict); + break; + + case CSS_PROP_LETTER_SPACING: // normal | <length> | inherit + case CSS_PROP_WORD_SPACING: // normal | <length> | inherit + if (id == CSS_VAL_NORMAL) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength, strict); + break; + + case CSS_PROP_WORD_BREAK: // normal | break-all | break-word (this is a custom extension) + if (id == CSS_VAL_NORMAL || id == CSS_VAL_BREAK_ALL || id == CSS_VAL_BREAK_WORD) + valid_primitive = true; + break; + + case CSS_PROP_WORD_WRAP: // normal | break-word + if (id == CSS_VAL_NORMAL || id == CSS_VAL_BREAK_WORD) + valid_primitive = true; + break; + + case CSS_PROP_TEXT_INDENT: // <length> | <percentage> | inherit + case CSS_PROP_PADDING_TOP: //// <padding-width> | inherit + case CSS_PROP_PADDING_RIGHT: // Which is defined as + case CSS_PROP_PADDING_BOTTOM: // <length> | <percentage> + case CSS_PROP_PADDING_LEFT: //// + case CSS_PROP__WEBKIT_PADDING_START: + valid_primitive = (!id && validUnit(value, FLength|FPercent, strict)); + break; + + case CSS_PROP_MAX_HEIGHT: // <length> | <percentage> | none | inherit + case CSS_PROP_MAX_WIDTH: // <length> | <percentage> | none | inherit + if (id == CSS_VAL_NONE || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC) { + valid_primitive = true; + break; + } + /* nobreak */ + case CSS_PROP_MIN_HEIGHT: // <length> | <percentage> | inherit + case CSS_PROP_MIN_WIDTH: // <length> | <percentage> | inherit + if (id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC) + valid_primitive = true; + else + valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict)); + break; + + case CSS_PROP_FONT_SIZE: + // <absolute-size> | <relative-size> | <length> | <percentage> | inherit + if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER) + valid_primitive = true; + else + valid_primitive = (validUnit(value, FLength|FPercent, strict)); + break; + + case CSS_PROP_FONT_STYLE: // normal | italic | oblique | inherit + if (id == CSS_VAL_NORMAL || id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE) + valid_primitive = true; + break; + + case CSS_PROP_FONT_VARIANT: // normal | small-caps | inherit + if (id == CSS_VAL_NORMAL || id == CSS_VAL_SMALL_CAPS) + valid_primitive = true; + break; + + case CSS_PROP_VERTICAL_ALIGN: + // baseline | sub | super | top | text-top | middle | bottom | text-bottom | + // <percentage> | <length> | inherit + + if (id >= CSS_VAL_BASELINE && id <= CSS_VAL__WEBKIT_BASELINE_MIDDLE) + valid_primitive = true; + else + valid_primitive = (!id && validUnit(value, FLength|FPercent, strict)); + break; + + case CSS_PROP_HEIGHT: // <length> | <percentage> | auto | inherit + case CSS_PROP_WIDTH: // <length> | <percentage> | auto | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_INTRINSIC || id == CSS_VAL_MIN_INTRINSIC) + valid_primitive = true; + else + // ### handle multilength case where we allow relative units + valid_primitive = (!id && validUnit(value, FLength|FPercent|FNonNeg, strict)); + break; + + case CSS_PROP_BOTTOM: // <length> | <percentage> | auto | inherit + case CSS_PROP_LEFT: // <length> | <percentage> | auto | inherit + case CSS_PROP_RIGHT: // <length> | <percentage> | auto | inherit + case CSS_PROP_TOP: // <length> | <percentage> | auto | inherit + case CSS_PROP_MARGIN_TOP: //// <margin-width> | inherit + case CSS_PROP_MARGIN_RIGHT: // Which is defined as + case CSS_PROP_MARGIN_BOTTOM: // <length> | <percentage> | auto | inherit + case CSS_PROP_MARGIN_LEFT: //// + case CSS_PROP__WEBKIT_MARGIN_START: + if (id == CSS_VAL_AUTO) + valid_primitive = true; + else + valid_primitive = (!id && validUnit(value, FLength|FPercent, strict)); + break; + + case CSS_PROP_Z_INDEX: // auto | <integer> | inherit + if (id == CSS_VAL_AUTO) { + valid_primitive = true; + break; + } + /* nobreak */ + case CSS_PROP_ORPHANS: // <integer> | inherit + case CSS_PROP_WIDOWS: // <integer> | inherit + // ### not supported later on + valid_primitive = (!id && validUnit(value, FInteger, false)); + break; + + case CSS_PROP_LINE_HEIGHT: // normal | <number> | <length> | <percentage> | inherit + if (id == CSS_VAL_NORMAL) + valid_primitive = true; + else + valid_primitive = (!id && validUnit(value, FNumber|FLength|FPercent, strict)); + break; + case CSS_PROP_COUNTER_INCREMENT: // [ <identifier> <integer>? ]+ | none | inherit + if (id != CSS_VAL_NONE) + return parseCounter(propId, 1, important); + valid_primitive = true; + break; + case CSS_PROP_COUNTER_RESET: // [ <identifier> <integer>? ]+ | none | inherit + if (id != CSS_VAL_NONE) + return parseCounter(propId, 0, important); + valid_primitive = true; + break; + case CSS_PROP_FONT_FAMILY: + // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit + { + parsedValue = parseFontFamily(); + break; + } + + case CSS_PROP_TEXT_DECORATION: + case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT: + // none | [ underline || overline || line-through || blink ] | inherit + if (id == CSS_VAL_NONE) { + valid_primitive = true; + } else { + RefPtr<CSSValueList> list(new CSSValueList); + bool is_valid = true; + while(is_valid && value) { + switch (value->id) { + case CSS_VAL_BLINK: + break; + case CSS_VAL_UNDERLINE: + case CSS_VAL_OVERLINE: + case CSS_VAL_LINE_THROUGH: + list->append(new CSSPrimitiveValue(value->id)); + break; + default: + is_valid = false; + } + value = valueList->next(); + } + if (list->length() && is_valid) { + parsedValue = list.release(); + valueList->next(); + } + } + break; + + case CSS_PROP_TABLE_LAYOUT: // auto | fixed | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_FIXED) + valid_primitive = true; + break; + + case CSS_PROP_SRC: // Only used within @font-face, so cannot use inherit | initial or be !important. This is a list of urls or local references. + return parseFontFaceSrc(); + + case CSS_PROP_UNICODE_RANGE: + return parseFontFaceUnicodeRange(); + + /* CSS3 properties */ + case CSS_PROP__WEBKIT_APPEARANCE: + if ((id >= CSS_VAL_CHECKBOX && id <= CSS_VAL_TEXTAREA) || id == CSS_VAL_NONE) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_BINDING: +#if ENABLE(XBL) + if (id == CSS_VAL_NONE) + valid_primitive = true; + else { + RefPtr<CSSValueList> values(new CSSValueList()); + Value* val; + RefPtr<CSSValue> parsedValue; + while ((val = valueList->current())) { + if (val->unit == CSSPrimitiveValue::CSS_URI) { + String value = parseURL(val->string); + parsedValue = new CSSPrimitiveValue(KURL(styleElement->baseURL(), value).string(), + CSSPrimitiveValue::CSS_URI); + } + if (!parsedValue) + break; + + // FIXME: We can't use release() here since we might hit this path twice + // but that logic seems wrong to me to begin with, we convert all non-uri values + // into the last seen URI value!? + // -webkit-binding: url(foo.xml), 1, 2; (if that were valid) is treated as: + // -webkit-binding: url(foo.xml), url(foo.xml), url(foo.xml); !? + values->append(parsedValue.get()); + valueList->next(); + } + if (!values->length()) + return false; + + addProperty(propId, values.release(), important); + valueList->next(); + return true; + } +#endif + break; + case CSS_PROP__WEBKIT_BORDER_IMAGE: + if (id == CSS_VAL_NONE) + valid_primitive = true; + else + return parseBorderImage(propId, important); + break; + case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_RADIUS: { + if (num != 1 && num != 2) + return false; + valid_primitive = validUnit(value, FLength, strict); + if (!valid_primitive) + return false; + RefPtr<CSSPrimitiveValue> parsedValue1 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + RefPtr<CSSPrimitiveValue> parsedValue2; + if (num == 2) { + value = valueList->next(); + valid_primitive = validUnit(value, FLength, strict); + if (!valid_primitive) + return false; + parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + } else + parsedValue2 = parsedValue1; + + RefPtr<Pair> pair = new Pair(parsedValue1.release(), parsedValue2.release()); + RefPtr<CSSPrimitiveValue> val = new CSSPrimitiveValue(pair.release()); + if (propId == CSS_PROP__WEBKIT_BORDER_RADIUS) { + const int properties[4] = { CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, + CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, + CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS }; + for (int i = 0; i < 4; i++) + addProperty(properties[i], val.get(), important); + } else + addProperty(propId, val.release(), important); + return true; + } + case CSS_PROP_OUTLINE_OFFSET: + valid_primitive = validUnit(value, FLength, strict); + break; + case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3 + case CSS_PROP__WEBKIT_BOX_SHADOW: + if (id == CSS_VAL_NONE) + valid_primitive = true; + else + return parseShadow(propId, important); + break; + case CSS_PROP_OPACITY: + valid_primitive = validUnit(value, FNumber, strict); + break; + case CSS_PROP__WEBKIT_BOX_ALIGN: + if (id == CSS_VAL_STRETCH || id == CSS_VAL_START || id == CSS_VAL_END || + id == CSS_VAL_CENTER || id == CSS_VAL_BASELINE) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_BOX_DIRECTION: + if (id == CSS_VAL_NORMAL || id == CSS_VAL_REVERSE) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_BOX_LINES: + if (id == CSS_VAL_SINGLE || id == CSS_VAL_MULTIPLE) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_BOX_ORIENT: + if (id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL || + id == CSS_VAL_INLINE_AXIS || id == CSS_VAL_BLOCK_AXIS) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_BOX_PACK: + if (id == CSS_VAL_START || id == CSS_VAL_END || + id == CSS_VAL_CENTER || id == CSS_VAL_JUSTIFY) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_BOX_FLEX: + valid_primitive = validUnit(value, FNumber, strict); + break; + case CSS_PROP__WEBKIT_BOX_FLEX_GROUP: + case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP: + valid_primitive = validUnit(value, FInteger|FNonNeg, true); + break; + case CSS_PROP__WEBKIT_BOX_SIZING: + valid_primitive = id == CSS_VAL_BORDER_BOX || id == CSS_VAL_CONTENT_BOX; + break; + case CSS_PROP__WEBKIT_MARQUEE: { + const int properties[5] = { CSS_PROP__WEBKIT_MARQUEE_DIRECTION, CSS_PROP__WEBKIT_MARQUEE_INCREMENT, + CSS_PROP__WEBKIT_MARQUEE_REPETITION, + CSS_PROP__WEBKIT_MARQUEE_STYLE, CSS_PROP__WEBKIT_MARQUEE_SPEED }; + return parseShorthand(propId, properties, 5, important); + } + case CSS_PROP__WEBKIT_MARQUEE_DIRECTION: + if (id == CSS_VAL_FORWARDS || id == CSS_VAL_BACKWARDS || id == CSS_VAL_AHEAD || + id == CSS_VAL_REVERSE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL_DOWN || + id == CSS_VAL_UP || id == CSS_VAL_AUTO) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_MARQUEE_INCREMENT: + if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength|FPercent, strict); + break; + case CSS_PROP__WEBKIT_MARQUEE_STYLE: + if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_MARQUEE_REPETITION: + if (id == CSS_VAL_INFINITE) + valid_primitive = true; + else + valid_primitive = validUnit(value, FInteger|FNonNeg, strict); + break; + case CSS_PROP__WEBKIT_MARQUEE_SPEED: + if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST) + valid_primitive = true; + else + valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict); + break; + case CSS_PROP__WEBKIT_USER_DRAG: // auto | none | element + if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_ELEMENT) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_USER_MODIFY: // read-only | read-write + if (id == CSS_VAL_READ_ONLY || id == CSS_VAL_READ_WRITE || id == CSS_VAL_READ_WRITE_PLAINTEXT_ONLY) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_USER_SELECT: // auto | none | text + if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE || id == CSS_VAL_TEXT) + valid_primitive = true; + break; + case CSS_PROP_TEXT_OVERFLOW: // clip | ellipsis + if (id == CSS_VAL_CLIP || id == CSS_VAL_ELLIPSIS) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_TRANSFORM: + if (id == CSS_VAL_NONE) + valid_primitive = true; + else { + PassRefPtr<CSSValue> val = parseTransform(); + if (val) { + addProperty(propId, val, important); + return true; + } + return false; + } + break; + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN: + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_X: + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_Y: { + RefPtr<CSSValue> val1; + RefPtr<CSSValue> val2; + int propId1, propId2; + if (parseTransformOrigin(propId, propId1, propId2, val1, val2)) { + addProperty(propId1, val1.release(), important); + if (val2) + addProperty(propId2, val2.release(), important); + return true; + } + return false; + } + case CSS_PROP__WEBKIT_TRANSITION_DURATION: + case CSS_PROP__WEBKIT_TRANSITION_REPEAT_COUNT: + case CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION: + case CSS_PROP__WEBKIT_TRANSITION_PROPERTY: { + RefPtr<CSSValue> val; + if (parseTransitionProperty(propId, val)) { + addProperty(propId, val.release(), important); + return true; + } + return false; + } + case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: { + const int properties[2] = { CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE, + CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE }; + if (num == 1) { + ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE); + if (!parseValue(properties[0], important)) + return false; + CSSValue* value = parsedProperties[numParsedProperties-1]->value(); + addProperty(properties[1], value, important); + return true; + } + else if (num == 2) { + ShorthandScope scope(this, CSS_PROP__WEBKIT_MARGIN_COLLAPSE); + if (!parseValue(properties[0], important) || !parseValue(properties[1], important)) + return false; + return true; + } + return false; + } + case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE: + case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE: + if (id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE || id == CSS_VAL_DISCARD) + valid_primitive = true; + break; + case CSS_PROP_TEXT_LINE_THROUGH_MODE: + case CSS_PROP_TEXT_OVERLINE_MODE: + case CSS_PROP_TEXT_UNDERLINE_MODE: + if (id == CSS_VAL_CONTINUOUS || id == CSS_VAL_SKIP_WHITE_SPACE) + valid_primitive = true; + break; + case CSS_PROP_TEXT_LINE_THROUGH_STYLE: + case CSS_PROP_TEXT_OVERLINE_STYLE: + case CSS_PROP_TEXT_UNDERLINE_STYLE: + if (id == CSS_VAL_NONE || id == CSS_VAL_SOLID || id == CSS_VAL_DOUBLE || + id == CSS_VAL_DASHED || id == CSS_VAL_DOT_DASH || id == CSS_VAL_DOT_DOT_DASH || + id == CSS_VAL_WAVE) + valid_primitive = true; + break; + case CSS_PROP_TEXT_LINE_THROUGH_WIDTH: + case CSS_PROP_TEXT_OVERLINE_WIDTH: + case CSS_PROP_TEXT_UNDERLINE_WIDTH: + if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL || id == CSS_VAL_THIN || + id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK) + valid_primitive = true; + else + valid_primitive = !id && validUnit(value, FNumber|FLength|FPercent, strict); + break; + case CSS_PROP_RESIZE: // none | both | horizontal | vertical | auto + if (id == CSS_VAL_NONE || id == CSS_VAL_BOTH || id == CSS_VAL_HORIZONTAL || id == CSS_VAL_VERTICAL || id == CSS_VAL_AUTO) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_COLUMN_COUNT: + if (id == CSS_VAL_AUTO) + valid_primitive = true; + else + valid_primitive = !id && validUnit(value, FInteger | FNonNeg, false); + break; + case CSS_PROP__WEBKIT_COLUMN_GAP: // normal | <length> + if (id == CSS_VAL_NORMAL) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength, strict); + break; + case CSS_PROP__WEBKIT_COLUMN_WIDTH: // auto | <length> + if (id == CSS_VAL_AUTO) + valid_primitive = true; + else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property. + valid_primitive = validUnit(value, FLength, true); + break; + // End of CSS3 properties + + // Apple specific properties. These will never be standardized and are purely to + // support custom WebKit-based Apple applications. + case CSS_PROP__WEBKIT_LINE_CLAMP: + valid_primitive = (!id && validUnit(value, FPercent, false)); + break; + case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: + if (id == CSS_VAL_AUTO || id == CSS_VAL_NONE) + valid_primitive = true; + break; + case CSS_PROP__WEBKIT_RTL_ORDERING: + if (id == CSS_VAL_LOGICAL || id == CSS_VAL_VISUAL) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_FONT_SIZE_DELTA: // <length> + valid_primitive = validUnit(value, FLength, strict); + break; + + case CSS_PROP__WEBKIT_NBSP_MODE: // normal | space + if (id == CSS_VAL_NORMAL || id == CSS_VAL_SPACE) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_LINE_BREAK: // normal | after-white-space + if (id == CSS_VAL_NORMAL || id == CSS_VAL_AFTER_WHITE_SPACE) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: // normal | match + if (id == CSS_VAL_NORMAL || id == CSS_VAL_MATCH) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_HIGHLIGHT: + if (id == CSS_VAL_NONE || value->unit == CSSPrimitiveValue::CSS_STRING) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_BORDER_FIT: + if (id == CSS_VAL_BORDER || id == CSS_VAL_LINES) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_TEXT_SECURITY: + // disc | circle | square | none | inherit + if (id == CSS_VAL_DISC || id == CSS_VAL_CIRCLE || id == CSS_VAL_SQUARE|| id == CSS_VAL_NONE) + valid_primitive = true; + break; + + case CSS_PROP__WEBKIT_DASHBOARD_REGION: // <dashboard-region> | <dashboard-region> + if (value->unit == Value::Function || id == CSS_VAL_NONE) + return parseDashboardRegions(propId, important); + break; + // End Apple-specific properties + + /* shorthand properties */ + case CSS_PROP_BACKGROUND: + // ['background-color' || 'background-image' || 'background-size' || 'background-repeat' || + // 'background-attachment' || 'background-position'] | inherit + return parseBackgroundShorthand(important); + case CSS_PROP_BORDER: + // [ 'border-width' || 'border-style' || <color> ] | inherit + { + const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE, + CSS_PROP_BORDER_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_BORDER_TOP: + // [ 'border-top-width' || 'border-style' || <color> ] | inherit + { + const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE, + CSS_PROP_BORDER_TOP_COLOR}; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_BORDER_RIGHT: + // [ 'border-right-width' || 'border-style' || <color> ] | inherit + { + const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE, + CSS_PROP_BORDER_RIGHT_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_BORDER_BOTTOM: + // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit + { + const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, + CSS_PROP_BORDER_BOTTOM_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_BORDER_LEFT: + // [ 'border-left-width' || 'border-style' || <color> ] | inherit + { + const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, + CSS_PROP_BORDER_LEFT_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_OUTLINE: + // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit + { + const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE, + CSS_PROP_OUTLINE_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP_BORDER_COLOR: + // <color>{1,4} | inherit + { + 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 parse4Values(propId, properties, important); + } + case CSS_PROP_BORDER_WIDTH: + // <border-width>{1,4} | inherit + { + 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 parse4Values(propId, properties, important); + } + case CSS_PROP_BORDER_STYLE: + // <border-style>{1,4} | inherit + { + 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 parse4Values(propId, properties, important); + } + case CSS_PROP_MARGIN: + // <margin-width>{1,4} | inherit + { + const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, + CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; + return parse4Values(propId, properties, important); + } + case CSS_PROP_PADDING: + // <padding-width>{1,4} | inherit + { + const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, + CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; + return parse4Values(propId, properties, important); + } + case CSS_PROP_FONT: + // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? + // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit + if (id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR) + valid_primitive = true; + else + return parseFont(important); + break; + 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 parseShorthand(propId, properties, 3, important); + } + case CSS_PROP__WEBKIT_COLUMNS: { + const int properties[2] = { CSS_PROP__WEBKIT_COLUMN_WIDTH, CSS_PROP__WEBKIT_COLUMN_COUNT }; + return parseShorthand(propId, properties, 2, important); + } + case CSS_PROP__WEBKIT_COLUMN_RULE: { + const int properties[3] = { CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, CSS_PROP__WEBKIT_COLUMN_RULE_STYLE, + CSS_PROP__WEBKIT_COLUMN_RULE_COLOR }; + return parseShorthand(propId, properties, 3, important); + } + case CSS_PROP__WEBKIT_TEXT_STROKE: { + const int properties[2] = { CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH, CSS_PROP__WEBKIT_TEXT_STROKE_COLOR }; + return parseShorthand(propId, properties, 2, important); + } + case CSS_PROP__WEBKIT_TRANSITION: + return parseTransitionShorthand(important); + case CSS_PROP_INVALID: + return false; + case CSS_PROP_FONT_STRETCH: + case CSS_PROP_PAGE: + case CSS_PROP_TEXT_LINE_THROUGH: + case CSS_PROP_TEXT_OVERLINE: + case CSS_PROP_TEXT_UNDERLINE: + return false; +#if ENABLE(SVG) + default: + return parseSVGValue(propId, important); +#endif + } + + if (valid_primitive) { + if (id != 0) + parsedValue = new CSSPrimitiveValue(id); + else if (value->unit == CSSPrimitiveValue::CSS_STRING) + parsedValue = new CSSPrimitiveValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + parsedValue = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + else if (value->unit >= Value::Q_EMS) + parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS); + valueList->next(); + } + if (parsedValue) { + if (!valueList->current() || inShorthand()) { + addProperty(propId, parsedValue.release(), important); + return true; + } + } + return false; +} + +void CSSParser::addBackgroundValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) +{ + if (lval) { + if (lval->isValueList()) + static_cast<CSSValueList*>(lval.get())->append(rval); + else { + PassRefPtr<CSSValue> oldlVal(lval.release()); + PassRefPtr<CSSValueList> list(new CSSValueList()); + list->append(oldlVal); + list->append(rval); + lval = list; + } + } + else + lval = rval; +} + +bool CSSParser::parseBackgroundShorthand(bool important) +{ + // Position must come before color in this array because a plain old "0" is a legal color + // in quirks mode but it's usually the X coordinate of a position. + // FIXME: Add CSS_PROP__KHTML_BACKGROUND_SIZE to the shorthand. + const int properties[] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, + CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP__WEBKIT_BACKGROUND_CLIP, + CSS_PROP__WEBKIT_BACKGROUND_ORIGIN, CSS_PROP_BACKGROUND_COLOR }; + const int numProperties = sizeof(properties) / sizeof(properties[0]); + + ShorthandScope scope(this, CSS_PROP_BACKGROUND); + + bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary + RefPtr<CSSValue> values[numProperties]; + RefPtr<CSSValue> positionYValue; + int i; + + while (valueList->current()) { + Value* val = valueList->current(); + if (val->unit == Value::Operator && val->iValue == ',') { + // We hit the end. Fill in all remaining values with the initial value. + valueList->next(); + for (i = 0; i < numProperties; ++i) { + if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i]) + // Color is not allowed except as the last item in a list. Reject the entire + // property. + return false; + + if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) { + addBackgroundValue(values[i], new CSSInitialValue(true)); + if (properties[i] == CSS_PROP_BACKGROUND_POSITION) + addBackgroundValue(positionYValue, new CSSInitialValue(true)); + } + parsedProperty[i] = false; + } + if (!valueList->current()) + break; + } + + bool found = false; + for (i = 0; !found && i < numProperties; ++i) { + if (!parsedProperty[i]) { + RefPtr<CSSValue> val1; + RefPtr<CSSValue> val2; + int propId1, propId2; + if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) { + parsedProperty[i] = found = true; + addBackgroundValue(values[i], val1.release()); + if (properties[i] == CSS_PROP_BACKGROUND_POSITION) + addBackgroundValue(positionYValue, val2.release()); + } + } + } + + // if we didn't find at least one match, this is an + // invalid shorthand and we have to ignore it + if (!found) + return false; + } + + // Fill in any remaining properties with the initial value. + for (i = 0; i < numProperties; ++i) { + if (!parsedProperty[i]) { + addBackgroundValue(values[i], new CSSInitialValue(true)); + if (properties[i] == CSS_PROP_BACKGROUND_POSITION) + addBackgroundValue(positionYValue, new CSSInitialValue(true)); + } + } + + // Now add all of the properties we found. + for (i = 0; i < numProperties; i++) { + if (properties[i] == CSS_PROP_BACKGROUND_POSITION) { + addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i].release(), important); + // it's OK to call positionYValue.release() since we only see CSS_PROP_BACKGROUND_POSITION once + addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue.release(), important); + } else + addProperty(properties[i], values[i].release(), important); + } + + return true; +} + +void CSSParser::addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) +{ + if (lval) { + if (lval->isValueList()) + static_cast<CSSValueList*>(lval.get())->append(rval); + else { + PassRefPtr<CSSValue> oldVal(lval.release()); + PassRefPtr<CSSValueList> list(new CSSValueList()); + list->append(oldVal); + list->append(rval); + lval = list; + } + } + else + lval = rval; +} + +bool CSSParser::parseTransitionShorthand(bool important) +{ + const int properties[] = { CSS_PROP__WEBKIT_TRANSITION_PROPERTY, CSS_PROP__WEBKIT_TRANSITION_DURATION, + CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION, CSS_PROP__WEBKIT_TRANSITION_REPEAT_COUNT }; + const int numProperties = sizeof(properties) / sizeof(properties[0]); + + ShorthandScope scope(this, CSS_PROP__WEBKIT_TRANSITION); + + bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary + RefPtr<CSSValue> values[numProperties]; + + int i; + while (valueList->current()) { + Value* val = valueList->current(); + if (val->unit == Value::Operator && val->iValue == ',') { + // We hit the end. Fill in all remaining values with the initial value. + valueList->next(); + for (i = 0; i < numProperties; ++i) { + if (!parsedProperty[i]) + addTransitionValue(values[i], new CSSInitialValue(true)); + parsedProperty[i] = false; + } + if (!valueList->current()) + break; + } + + bool found = false; + for (i = 0; !found && i < numProperties; ++i) { + if (!parsedProperty[i]) { + RefPtr<CSSValue> val; + if (parseTransitionProperty(properties[i], val)) { + parsedProperty[i] = found = true; + addTransitionValue(values[i], val.release()); + } + } + } + + // if we didn't find at least one match, this is an + // invalid shorthand and we have to ignore it + if (!found) + return false; + } + + // Fill in any remaining properties with the initial value. + for (i = 0; i < numProperties; ++i) { + if (!parsedProperty[i]) + addTransitionValue(values[i], new CSSInitialValue(true)); + } + + // Now add all of the properties we found. + for (i = 0; i < numProperties; i++) + addProperty(properties[i], values[i].release(), important); + + return true; +} + +bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important) +{ + // We try to match as many properties as possible + // We set up an array of booleans to mark which property has been found, + // and we try to search for properties until it makes no longer any sense. + ShorthandScope scope(this, propId); + + bool found = false; + bool fnd[6]; // Trust me ;) + for (int i = 0; i < numProperties; i++) + fnd[i] = false; + + while (valueList->current()) { + found = false; + for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) { + if (!fnd[propIndex]) { + if (parseValue(properties[propIndex], important)) + fnd[propIndex] = found = true; + } + } + + // if we didn't find at least one match, this is an + // invalid shorthand and we have to ignore it + if (!found) + return false; + } + + // Fill in any remaining properties with the initial value. + m_implicitShorthand = true; + for (int i = 0; i < numProperties; ++i) { + if (!fnd[i]) + addProperty(properties[i], new CSSInitialValue(true), important); + } + m_implicitShorthand = false; + + return true; +} + +bool CSSParser::parse4Values(int propId, const int *properties, bool important) +{ + /* From the CSS 2 specs, 8.3 + * If there is only one value, it applies to all sides. If there are two values, the top and + * bottom margins are set to the first value and the right and left margins are set to the second. + * If there are three values, the top is set to the first value, the left and right are set to the + * second, and the bottom is set to the third. If there are four values, they apply to the top, + * right, bottom, and left, respectively. + */ + + int num = inShorthand() ? 1 : valueList->size(); + + ShorthandScope scope(this, propId); + + // the order is top, right, bottom, left + switch (num) { + case 1: { + if (!parseValue(properties[0], important)) + return false; + CSSValue *value = parsedProperties[numParsedProperties-1]->value(); + m_implicitShorthand = true; + addProperty(properties[1], value, important); + addProperty(properties[2], value, important); + addProperty(properties[3], value, important); + m_implicitShorthand = false; + break; + } + case 2: { + if (!parseValue(properties[0], important) || !parseValue(properties[1], important)) + return false; + CSSValue *value = parsedProperties[numParsedProperties-2]->value(); + m_implicitShorthand = true; + addProperty(properties[2], value, important); + value = parsedProperties[numParsedProperties-2]->value(); + addProperty(properties[3], value, important); + m_implicitShorthand = false; + break; + } + case 3: { + if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important)) + return false; + CSSValue *value = parsedProperties[numParsedProperties-2]->value(); + m_implicitShorthand = true; + addProperty(properties[3], value, important); + m_implicitShorthand = false; + break; + } + case 4: { + if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || + !parseValue(properties[2], important) || !parseValue(properties[3], important)) + return false; + break; + } + default: { + return false; + } + } + + return true; +} + +// [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit +// in CSS 2.1 this got somewhat reduced: +// [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit +bool CSSParser::parseContent(int propId, bool important) +{ + RefPtr<CSSValueList> values = new CSSValueList; + + while (Value* val = valueList->current()) { + RefPtr<CSSValue> parsedValue; + if (val->unit == CSSPrimitiveValue::CSS_URI) { + // url + String value = parseURL(val->string); + parsedValue = new CSSImageValue(KURL(styleElement->baseURL(), value).string(), styleElement); + } else if (val->unit == Value::Function) { + // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) + ValueList* args = val->function->args; + if (!args) + return false; + if (equalIgnoringCase(val->function->name, "attr(")) { + if (args->size() != 1) + return false; + Value* a = args->current(); + String attrName = a->string; + if (document()->isHTMLDocument()) + attrName = attrName.lower(); + parsedValue = new CSSPrimitiveValue(attrName, CSSPrimitiveValue::CSS_ATTR); + } else if (equalIgnoringCase(val->function->name, "counter(")) { + parsedValue = parseCounterContent(args, false); + if (!parsedValue) return false; + } else if (equalIgnoringCase(val->function->name, "counters(")) { + parsedValue = parseCounterContent(args, true); + if (!parsedValue) + return false; + } else + return false; + } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) { + // open-quote + // close-quote + // no-open-quote + // no-close-quote + // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503). + } else if (val->unit == CSSPrimitiveValue::CSS_STRING) { + parsedValue = new CSSPrimitiveValue(val->string, CSSPrimitiveValue::CSS_STRING); + } + if (!parsedValue) + break; + values->append(parsedValue.release()); + valueList->next(); + } + + if (values->length()) { + addProperty(propId, values.release(), important); + valueList->next(); + return true; + } + + return false; +} + +PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() +{ + int id = valueList->current()->id; + if (id == CSS_VAL__WEBKIT_TEXT || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU || + (id >= CSS_VAL_GREY && id < CSS_VAL__WEBKIT_TEXT && !strict)) + return new CSSPrimitiveValue(id); + return parseColor(); +} + +bool CSSParser::parseBackgroundImage(RefPtr<CSSValue>& value) +{ + if (valueList->current()->id == CSS_VAL_NONE) { + value = new CSSImageValue(); + return true; + } + if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) { + String uri = parseURL(valueList->current()->string); + if (!uri.isEmpty()) + value = new CSSImageValue(KURL(styleElement->baseURL(), uri).string(), styleElement); + return true; + } + return false; +} + +PassRefPtr<CSSValue> CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound) +{ + int id = valueList->current()->id; + if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) { + int percent = 0; + if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) { + if (xFound) + return 0; + xFound = true; + if (id == CSS_VAL_RIGHT) + percent = 100; + } + else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) { + if (yFound) + return 0; + yFound = true; + if (id == CSS_VAL_BOTTOM) + percent = 100; + } + else if (id == CSS_VAL_CENTER) + // Center is ambiguous, so we're not sure which position we've found yet, an x or a y. + percent = 50; + return new CSSPrimitiveValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent|FLength, strict)) + return new CSSPrimitiveValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); + + return 0; +} + +void CSSParser::parseBackgroundPosition(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2) +{ + Value* value = valueList->current(); + + // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length. + bool value1IsX = false, value1IsY = false; + value1 = parseBackgroundPositionXY(value1IsX, value1IsY); + if (!value1) + return; + + // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we + // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the + // value was explicitly specified for our property. + value = valueList->next(); + + // First check for the comma. If so, we are finished parsing this value or value pair. + if (value && value->unit == Value::Operator && value->iValue == ',') + value = 0; + + bool value2IsX = false, value2IsY = false; + if (value) { + value2 = parseBackgroundPositionXY(value2IsX, value2IsY); + if (value2) + valueList->next(); + else { + if (!inShorthand()) { + value1.clear(); + return; + } + } + } + + if (!value2) + // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position + // is simply 50%. This is our default. + // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center). + // For left/right/center, the default of 50% in the y is still correct. + value2 = new CSSPrimitiveValue(50, CSSPrimitiveValue::CSS_PERCENTAGE); + + if (value1IsY || value2IsX) + value1.swap(value2); +} + +PassRefPtr<CSSValue> CSSParser::parseBackgroundSize() +{ + Value* value = valueList->current(); + CSSPrimitiveValue* parsedValue1; + + if (value->id == CSS_VAL_AUTO) + parsedValue1 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN); + else { + if (!validUnit(value, FLength|FPercent, strict)) + return 0; + parsedValue1 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + } + + CSSPrimitiveValue* parsedValue2 = parsedValue1; + if ((value = valueList->next())) { + if (value->id == CSS_VAL_AUTO) + parsedValue2 = new CSSPrimitiveValue(0, CSSPrimitiveValue::CSS_UNKNOWN); + else { + if (!validUnit(value, FLength|FPercent, strict)) { + delete parsedValue1; + return 0; + } + parsedValue2 = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + } + } + + Pair* pair = new Pair(parsedValue1, parsedValue2); + return new CSSPrimitiveValue(pair); +} + +bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2, + RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2) +{ + RefPtr<CSSValueList> values; + RefPtr<CSSValueList> values2; + Value* val; + RefPtr<CSSValue> value; + RefPtr<CSSValue> value2; + + bool allowComma = false; + + retValue1 = retValue2 = 0; + propId1 = propId; + propId2 = propId; + if (propId == CSS_PROP_BACKGROUND_POSITION) { + propId1 = CSS_PROP_BACKGROUND_POSITION_X; + propId2 = CSS_PROP_BACKGROUND_POSITION_Y; + } + + while ((val = valueList->current())) { + RefPtr<CSSValue> currValue; + RefPtr<CSSValue> currValue2; + + if (allowComma) { + if (val->unit != Value::Operator || val->iValue != ',') + return false; + valueList->next(); + allowComma = false; + } else { + switch (propId) { + case CSS_PROP_BACKGROUND_ATTACHMENT: + if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) { + currValue = new CSSPrimitiveValue(val->id); + valueList->next(); + } + break; + case CSS_PROP_BACKGROUND_COLOR: + currValue = parseBackgroundColor(); + if (currValue) + valueList->next(); + break; + case CSS_PROP_BACKGROUND_IMAGE: + if (parseBackgroundImage(currValue)) + valueList->next(); + break; + case CSS_PROP__WEBKIT_BACKGROUND_CLIP: + case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN: + if (val->id == CSS_VAL_BORDER || val->id == CSS_VAL_PADDING || val->id == CSS_VAL_CONTENT) { + currValue = new CSSPrimitiveValue(val->id); + valueList->next(); + } + break; + case CSS_PROP_BACKGROUND_POSITION: + parseBackgroundPosition(currValue, currValue2); + // unlike the other functions, parseBackgroundPosition advances the valueList pointer + break; + case CSS_PROP_BACKGROUND_POSITION_X: { + bool xFound = false, yFound = true; + currValue = parseBackgroundPositionXY(xFound, yFound); + if (currValue) + valueList->next(); + break; + } + case CSS_PROP_BACKGROUND_POSITION_Y: { + bool xFound = true, yFound = false; + currValue = parseBackgroundPositionXY(xFound, yFound); + if (currValue) + valueList->next(); + break; + } + case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: + if ((val->id >= CSS_VAL_CLEAR && val->id <= CSS_VAL_PLUS_LIGHTER) || val->id == CSS_VAL_HIGHLIGHT) { + currValue = new CSSPrimitiveValue(val->id); + valueList->next(); + } + break; + case CSS_PROP_BACKGROUND_REPEAT: + if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) { + currValue = new CSSPrimitiveValue(val->id); + valueList->next(); + } + break; + case CSS_PROP__WEBKIT_BACKGROUND_SIZE: + currValue = parseBackgroundSize(); + if (currValue) + valueList->next(); + break; + } + if (!currValue) + return false; + + if (value && !values) { + values = new CSSValueList(); + values->append(value.release()); + } + + if (value2 && !values2) { + values2 = new CSSValueList(); + values2->append(value2.release()); + } + + if (values) + values->append(currValue.release()); + else + value = currValue.release(); + if (currValue2) { + if (values2) + values2->append(currValue2.release()); + else + value2 = currValue2.release(); + } + allowComma = true; + } + + // When parsing the 'background' shorthand property, we let it handle building up the lists for all + // properties. + if (inShorthand()) + break; + } + + if (values && values->length()) { + retValue1 = values.release(); + if (values2 && values2->length()) + retValue2 = values2.release(); + return true; + } + if (value) { + retValue1 = value.release(); + retValue2 = value2.release(); + return true; + } + return false; +} + +PassRefPtr<CSSValue> CSSParser::parseTransitionDuration() +{ + Value* value = valueList->current(); + if (validUnit(value, FTime, strict)) + return new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return 0; +} + +PassRefPtr<CSSValue> CSSParser::parseTransitionRepeatCount() +{ + Value* value = valueList->current(); + if (value->id == CSS_VAL_INFINITE) + return new CSSPrimitiveValue(value->id); + if (validUnit(value, FInteger|FNonNeg, strict)) + return new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return 0; +} + +bool CSSParser::parseTimingFunctionValue(ValueList*& args, double& result) +{ + Value* v = args->current(); + if (!validUnit(v, FNumber, strict)) + return false; + result = v->fValue; + if (result < 0 || result > 1.0) + return false; + v = args->next(); + if (!v) + // The last number in the function has no comma after it, so we're done. + return true; + if (v->unit != Value::Operator && v->iValue != ',') + return false; + v = args->next(); + return true; +} + +PassRefPtr<CSSValue> CSSParser::parseTransitionTimingFunction() +{ + Value* value = valueList->current(); + if (value->id == CSS_VAL_AUTO || value->id == CSS_VAL_LINEAR || value->id == CSS_VAL_EASE_IN || value->id == CSS_VAL_EASE_OUT || value->id == CSS_VAL_EASE_IN_OUT) + return new CSSPrimitiveValue(value->id); + + // We must be a function. + if (value->unit != Value::Function) + return 0; + + // The only timing function we accept for now is a cubic bezier function. 4 points must be specified. + ValueList* args = value->function->args; + if (!equalIgnoringCase(value->function->name, "cubic-bezier(") || !args || args->size() != 7) + return 0; + + // There are two points specified. The values must be between 0 and 1. + double x1, y1, x2, y2; + + if (!parseTimingFunctionValue(args, x1)) + return 0; + if (!parseTimingFunctionValue(args, y1)) + return 0; + if (!parseTimingFunctionValue(args, x2)) + return 0; + if (!parseTimingFunctionValue(args, y2)) + return 0; + + return new CSSTimingFunctionValue(x1, y1, x2, y2); +} + +PassRefPtr<CSSValue> CSSParser::parseTransitionProperty() +{ + Value* value = valueList->current(); + if (value->unit != CSSPrimitiveValue::CSS_IDENT) + return 0; + int result = cssPropertyID(value->string); + if (result) + return new CSSPrimitiveValue(result); + if (equalIgnoringCase(value->string, "all")) + return new CSSPrimitiveValue(cAnimateAll); + if (equalIgnoringCase(value->string, "none")) + return new CSSPrimitiveValue(cAnimateNone); + return 0; +} + +bool CSSParser::parseTransitionProperty(int propId, RefPtr<CSSValue>& result) +{ + RefPtr<CSSValueList> values; + Value* val; + RefPtr<CSSValue> value; + bool allowComma = false; + + result = 0; + + while ((val = valueList->current())) { + RefPtr<CSSValue> currValue; + if (allowComma) { + if (val->unit != Value::Operator || val->iValue != ',') + return false; + valueList->next(); + allowComma = false; + } + else { + switch (propId) { + case CSS_PROP__WEBKIT_TRANSITION_DURATION: + currValue = parseTransitionDuration(); + if (currValue) + valueList->next(); + break; + case CSS_PROP__WEBKIT_TRANSITION_REPEAT_COUNT: + currValue = parseTransitionRepeatCount(); + if (currValue) + valueList->next(); + break; + case CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION: + currValue = parseTransitionTimingFunction(); + if (currValue) + valueList->next(); + break; + case CSS_PROP__WEBKIT_TRANSITION_PROPERTY: + currValue = parseTransitionProperty(); + if (currValue) + valueList->next(); + break; + } + + if (!currValue) + return false; + + if (value && !values) { + values = new CSSValueList(); + values->append(value.release()); + } + + if (values) + values->append(currValue.release()); + else + value = currValue.release(); + + allowComma = true; + } + + // When parsing the 'transition' shorthand property, we let it handle building up the lists for all + // properties. + if (inShorthand()) + break; + } + + if (values && values->length()) { + result = values.release(); + return true; + } + if (value) { + result = value.release(); + return true; + } + return false; +} + +#define DASHBOARD_REGION_NUM_PARAMETERS 6 +#define DASHBOARD_REGION_SHORT_NUM_PARAMETERS 2 + +static Value *skipCommaInDashboardRegion (ValueList *args) +{ + if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) || + args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) { + Value *current = args->current(); + if (current->unit == Value::Operator && current->iValue == ',') + return args->next(); + } + return args->current(); +} + +bool CSSParser::parseDashboardRegions(int propId, bool important) +{ + bool valid = true; + + Value *value = valueList->current(); + + if (value->id == CSS_VAL_NONE) { + if (valueList->next()) + return false; + addProperty(propId, new CSSPrimitiveValue(value->id), important); + return valid; + } + + RefPtr<DashboardRegion> firstRegion = new DashboardRegion; + DashboardRegion* region = 0; + + while (value) { + if (region == 0) { + region = firstRegion.get(); + } else { + RefPtr<DashboardRegion> nextRegion = new DashboardRegion(); + region->m_next = nextRegion; + region = nextRegion.get(); + } + + if (value->unit != Value::Function) { + valid = false; + break; + } + + // Commas count as values, so allow: + // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l) + // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l) + // also allow + // dashboard-region(label, type) or dashboard-region(label type) + // dashboard-region(label, type) or dashboard-region(label type) + ValueList* args = value->function->args; + if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) { + valid = false; + break; + } + + int numArgs = args->size(); + if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) && + (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))){ + valid = false; + break; + } + + // First arg is a label. + Value* arg = args->current(); + if (arg->unit != CSSPrimitiveValue::CSS_IDENT) { + valid = false; + break; + } + + region->m_label = arg->string; + + // Second arg is a type. + arg = args->next(); + arg = skipCommaInDashboardRegion (args); + if (arg->unit != CSSPrimitiveValue::CSS_IDENT) { + valid = false; + break; + } + + if (equalIgnoringCase(arg->string, "circle")) + region->m_isCircle = true; + else if (equalIgnoringCase(arg->string, "rectangle")) + region->m_isRectangle = true; + else { + valid = false; + break; + } + + region->m_geometryType = arg->string; + + if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) { + // This originally used CSS_VAL_INVALID by accident. It might be more logical to use something else. + CSSPrimitiveValue *amount = new CSSPrimitiveValue(CSS_VAL_INVALID); + + region->setTop(amount); + region->setRight(amount); + region->setBottom(amount); + region->setLeft(amount); + } + else { + // Next four arguments must be offset numbers + int i; + for (i = 0; i < 4; i++) { + arg = args->next(); + arg = skipCommaInDashboardRegion (args); + + valid = arg->id == CSS_VAL_AUTO || validUnit(arg, FLength, strict); + if (!valid) + break; + + CSSPrimitiveValue *amount = arg->id == CSS_VAL_AUTO ? + new CSSPrimitiveValue(CSS_VAL_AUTO) : + new CSSPrimitiveValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit); + + if (i == 0) + region->setTop(amount); + else if (i == 1) + region->setRight(amount); + else if (i == 2) + region->setBottom(amount); + else + region->setLeft(amount); + } + } + + if (args->next()) + return false; + + value = valueList->next(); + } + + if (valid) + addProperty(propId, new CSSPrimitiveValue(firstRegion.release()), important); + + return valid; +} + +PassRefPtr<CSSValue> CSSParser::parseCounterContent(ValueList* args, bool counters) +{ + unsigned numArgs = args->size(); + if (counters && numArgs != 3 && numArgs != 5) + return 0; + if (!counters && numArgs != 1 && numArgs != 3) + return 0; + + Value* i = args->current(); + RefPtr<CSSPrimitiveValue> identifier = new CSSPrimitiveValue(i->string, CSSPrimitiveValue::CSS_STRING); + + RefPtr<CSSPrimitiveValue> separator; + if (!counters) + separator = new CSSPrimitiveValue(String(), CSSPrimitiveValue::CSS_STRING); + else { + i = args->next(); + if (i->unit != Value::Operator || i->iValue != ',') + return 0; + + i = args->next(); + if (i->unit != CSSPrimitiveValue::CSS_STRING) + return 0; + + separator = new CSSPrimitiveValue(i->string, (CSSPrimitiveValue::UnitTypes) i->unit); + } + + RefPtr<CSSPrimitiveValue> listStyle; + i = args->next(); + if (!i) // Make the list style default decimal + listStyle = new CSSPrimitiveValue(CSS_VAL_DECIMAL - CSS_VAL_DISC, CSSPrimitiveValue::CSS_NUMBER); + else { + if (i->unit != Value::Operator || i->iValue != ',') + return 0; + + i = args->next(); + if (i->unit != CSSPrimitiveValue::CSS_IDENT) + return 0; + + short ls = 0; + if (i->id == CSS_VAL_NONE) + ls = CSS_VAL_KATAKANA_IROHA - CSS_VAL_DISC + 1; + else if (i->id >= CSS_VAL_DISC && i->id <= CSS_VAL_KATAKANA_IROHA) + ls = i->id - CSS_VAL_DISC; + else + return 0; + + listStyle = new CSSPrimitiveValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit); + } + + return new CSSPrimitiveValue(new Counter(identifier.release(), listStyle.release(), separator.release())); +} + +bool CSSParser::parseShape(int propId, bool important) +{ + Value* value = valueList->current(); + ValueList* args = value->function->args; + if (!equalIgnoringCase(value->function->name, "rect(") || !args) + return false; + + // rect(t, r, b, l) || rect(t r b l) + if (args->size() != 4 && args->size() != 7) + return false; + Rect *rect = new Rect(); + bool valid = true; + int i = 0; + Value *a = args->current(); + while (a) { + valid = a->id == CSS_VAL_AUTO || validUnit(a, FLength, strict); + if (!valid) + break; + CSSPrimitiveValue *length = a->id == CSS_VAL_AUTO ? + new CSSPrimitiveValue(CSS_VAL_AUTO) : + new CSSPrimitiveValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + if (i == 0) + rect->setTop(length); + else if (i == 1) + rect->setRight(length); + else if (i == 2) + rect->setBottom(length); + else + rect->setLeft(length); + a = args->next(); + if (a && args->size() == 7) { + if (a->unit == Value::Operator && a->iValue == ',') { + a = args->next(); + } else { + valid = false; + break; + } + } + i++; + } + if (valid) { + addProperty(propId, new CSSPrimitiveValue(rect), important); + valueList->next(); + return true; + } + delete rect; + return false; +} + +// [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family' +bool CSSParser::parseFont(bool important) +{ + bool valid = true; + Value *value = valueList->current(); + RefPtr<FontValue> font = new FontValue; + // optional font-style, font-variant and font-weight + while (value) { + int id = value->id; + if (id) { + if (id == CSS_VAL_NORMAL) { + // do nothing, it's the inital value for all three + } else if (id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE) { + if (font->style) + return false; + font->style = new CSSPrimitiveValue(id); + } else if (id == CSS_VAL_SMALL_CAPS) { + if (font->variant) + return false; + font->variant = new CSSPrimitiveValue(id); + } else if (id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER) { + if (font->weight) + return false; + font->weight = new CSSPrimitiveValue(id); + } else { + valid = false; + } + } else if (!font->weight && validUnit(value, FInteger|FNonNeg, true)) { + int weight = (int)value->fValue; + int val = 0; + if (weight == 100) + val = CSS_VAL_100; + else if (weight == 200) + val = CSS_VAL_200; + else if (weight == 300) + val = CSS_VAL_300; + else if (weight == 400) + val = CSS_VAL_400; + else if (weight == 500) + val = CSS_VAL_500; + else if (weight == 600) + val = CSS_VAL_600; + else if (weight == 700) + val = CSS_VAL_700; + else if (weight == 800) + val = CSS_VAL_800; + else if (weight == 900) + val = CSS_VAL_900; + + if (val) + font->weight = new CSSPrimitiveValue(val); + else + valid = false; + } else { + valid = false; + } + if (!valid) + break; + value = valueList->next(); + } + if (!value) + return false; + + // set undefined values to default + if (!font->style) + font->style = new CSSPrimitiveValue(CSS_VAL_NORMAL); + if (!font->variant) + font->variant = new CSSPrimitiveValue(CSS_VAL_NORMAL); + if (!font->weight) + font->weight = new CSSPrimitiveValue(CSS_VAL_NORMAL); + + // now a font size _must_ come + // <absolute-size> | <relative-size> | <length> | <percentage> | inherit + if (value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER) + font->size = new CSSPrimitiveValue(value->id); + else if (validUnit(value, FLength|FPercent, strict)) + font->size = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + value = valueList->next(); + if (!font->size || !value) + return false; + + if (value->unit == Value::Operator && value->iValue == '/') { + // line-height + value = valueList->next(); + if (!value) + return false; + if (value->id == CSS_VAL_NORMAL) { + // default value, nothing to do + } else if (validUnit(value, FNumber|FLength|FPercent, strict)) + font->lineHeight = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + else + return false; + value = valueList->next(); + if (!value) + return false; + } + + if (!font->lineHeight) + font->lineHeight = new CSSPrimitiveValue(CSS_VAL_NORMAL); + + // font family must come now + font->family = parseFontFamily(); + + if (valueList->current() || !font->family) + return false; + + addProperty(CSS_PROP_FONT, font.release(), important); + return true; +} + +PassRefPtr<CSSValueList> CSSParser::parseFontFamily() +{ + CSSValueList* list = new CSSValueList; + Value* value = valueList->current(); + FontFamilyValue* currFamily = 0; + while (value) { + Value* nextValue = valueList->next(); + bool nextValBreaksFont = !nextValue || + (nextValue->unit == Value::Operator && nextValue->iValue == ','); + bool nextValIsFontName = nextValue && + ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL__WEBKIT_BODY) || + (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT)); + + if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL__WEBKIT_BODY) { + if (currFamily) + currFamily->appendSpaceSeparated(value->string.characters, value->string.length); + else if (nextValBreaksFont || !nextValIsFontName) + list->append(new CSSPrimitiveValue(value->id)); + else + list->append(currFamily = new FontFamilyValue(value->string)); + } + else if (value->unit == CSSPrimitiveValue::CSS_STRING) { + // Strings never share in a family name. + currFamily = 0; + list->append(new FontFamilyValue(value->string)); + } + else if (value->unit == CSSPrimitiveValue::CSS_IDENT) { + if (currFamily) + currFamily->appendSpaceSeparated(value->string.characters, value->string.length); + else if (nextValBreaksFont || !nextValIsFontName) + list->append(new FontFamilyValue(value->string)); + else + list->append(currFamily = new FontFamilyValue(value->string)); + } + else { + break; + } + + if (!nextValue) + break; + + if (nextValBreaksFont) { + value = valueList->next(); + currFamily = 0; + } + else if (nextValIsFontName) + value = nextValue; + else + break; + } + if (!list->length()) { + delete list; + list = 0; + } + return list; +} + +bool CSSParser::parseFontFaceSrc() +{ + RefPtr<CSSValueList> values(new CSSValueList()); + Value* val; + bool expectComma = false; + bool allowFormat = false; + bool failed = false; + RefPtr<CSSFontFaceSrcValue> uriValue; + while ((val = valueList->current())) { + RefPtr<CSSFontFaceSrcValue> parsedValue; + if (val->unit == CSSPrimitiveValue::CSS_URI && !expectComma) { + String value = parseURL(val->string); + parsedValue = new CSSFontFaceSrcValue(KURL(styleElement->baseURL(), value).string(), false); + uriValue = parsedValue; + allowFormat = true; + expectComma = true; + } else if (val->unit == Value::Function) { + // There are two allowed functions: local() and format(). + ValueList* args = val->function->args; + if (args && args->size() == 1) { + if (equalIgnoringCase(val->function->name, "local(") && !expectComma) { + expectComma = true; + allowFormat = false; + Value* a = args->current(); + uriValue.clear(); + parsedValue = new CSSFontFaceSrcValue(a->string, true); + } else if (equalIgnoringCase(val->function->name, "format(") && allowFormat && uriValue) { + expectComma = true; + allowFormat = false; + uriValue->setFormat(args->current()->string); + uriValue.clear(); + valueList->next(); + continue; + } + } + } else if (val->unit == Value::Operator && val->iValue == ',' && expectComma) { + expectComma = false; + allowFormat = false; + uriValue.clear(); + valueList->next(); + continue; + } + + if (parsedValue) + values->append(parsedValue.release()); + else { + failed = true; + break; + } + valueList->next(); + } + + if (values->length() && !failed) { + addProperty(CSS_PROP_SRC, values.release(), important); + valueList->next(); + return true; + } + + return false; +} + +bool CSSParser::parseFontFaceUnicodeRange() +{ + CSSValueList* values = new CSSValueList(); + Value* currentValue; + bool failed = false; + while ((currentValue = valueList->current())) { + if (valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) { + failed = true; + break; + } + + String rangeString = valueList->current()->string; + UChar32 from = 0; + UChar32 to = 0; + unsigned length = rangeString.length(); + + if (length < 3) { + failed = true; + break; + } + + unsigned i = 2; + while (i < length) { + UChar c = rangeString[i]; + if (c == '-' || c == '?') + break; + from *= 16; + if (c >= '0' && c <= '9') + from += c - '0'; + else if (c >= 'A' && c <= 'F') + from += 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + from += 10 + c - 'a'; + else { + failed = true; + break; + } + i++; + } + if (failed) + break; + + if (i == length) + to = from; + else if (rangeString[i] == '?') { + unsigned span = 1; + while (i < length && rangeString[i] == '?') { + span *= 16; + from *= 16; + i++; + } + if (i < length) + failed = true; + to = from + span - 1; + } else { + if (length < i + 2) { + failed = true; + break; + } + i++; + while (i < length) { + UChar c = rangeString[i]; + to *= 16; + if (c >= '0' && c <= '9') + to += c - '0'; + else if (c >= 'A' && c <= 'F') + to += 10 + c - 'A'; + else if (c >= 'a' && c <= 'f') + to += 10 + c - 'a'; + else { + failed = true; + break; + } + i++; + } + if (failed) + break; + } + values->append(new CSSUnicodeRangeValue(from, to)); + valueList->next(); + } + if (failed || !values->length()) { + delete values; + return false; + } + addProperty(CSS_PROP_UNICODE_RANGE, values, important); + return true; +} + +bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) +{ + if (!strict && Color::parseHexColor(name, rgb)) + return true; + + // try a little harder + Color tc; + tc.setNamedColor(name); + if (tc.isValid()) { + rgb = tc.rgb(); + return true; + } + + return false; +} + +bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha) +{ + ValueList* args = value->function->args; + Value* v = args->current(); + // Get the first value + if (!validUnit(v, FInteger | FPercent, true)) + return false; + colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0)); + for (int i = 1; i < 3; i++) { + v = args->next(); + if (v->unit != Value::Operator && v->iValue != ',') + return false; + v = args->next(); + if (!validUnit(v, FInteger | FPercent, true)) + return false; + colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0)); + } + if (parseAlpha) { + v = args->next(); + if (v->unit != Value::Operator && v->iValue != ',') + return false; + v = args->next(); + if (!validUnit(v, FNumber, true)) + return false; + colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * 255); + } + return true; +} + +// CSS3 sepcification defines the format of a HSL color as +// hsl(<number>, <percent>, <percent>) +// and with alpha, the format is +// hsla(<number>, <percent>, <percent>, <number>) +// The first value, HUE, is in an angle with a value between 0 and 360 +bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha) +{ + ValueList* args = value->function->args; + Value* v = args->current(); + // Get the first value + if (!validUnit(v, FNumber, true)) + return false; + // normalize the Hue value and change it to be between 0 and 1.0 + colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0; + for (int i = 1; i < 3; i++) { + v = args->next(); + if (v->unit != Value::Operator && v->iValue != ',') + return false; + v = args->next(); + if (!validUnit(v, FPercent, true)) + return false; + colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0 + } + if (parseAlpha) { + v = args->next(); + if (v->unit != Value::Operator && v->iValue != ',') + return false; + v = args->next(); + if (!validUnit(v, FNumber, true)) + return false; + colorArray[3] = max(0.0, min(1.0, v->fValue)); + } + return true; +} + +PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(Value* value) +{ + RGBA32 c = Color::transparent; + if (!parseColorFromValue(value ? value : valueList->current(), c)) + return 0; + return new CSSPrimitiveValue(c); +} + +bool CSSParser::parseColorFromValue(Value* value, RGBA32& c, bool svg) +{ + if (!strict && value->unit == CSSPrimitiveValue::CSS_NUMBER && + value->fValue >= 0. && value->fValue < 1000000.) { + String str = String::format("%06d", (int)(value->fValue+.5)); + if (!CSSParser::parseColor(str, c, strict)) + return false; + } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR || + value->unit == CSSPrimitiveValue::CSS_IDENT || + (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) { + if (!CSSParser::parseColor(value->string, c, strict && value->unit == CSSPrimitiveValue::CSS_IDENT)) + return false; + } else if (value->unit == Value::Function && + value->function->args != 0 && + value->function->args->size() == 5 /* rgb + two commas */ && + equalIgnoringCase(value->function->name, "rgb(")) { + int colorValues[3]; + if (!parseColorParameters(value, colorValues, false)) + return false; + c = makeRGB(colorValues[0], colorValues[1], colorValues[2]); + } else if (!svg) { + if (value->unit == Value::Function && + value->function->args != 0 && + value->function->args->size() == 7 /* rgba + three commas */ && + equalIgnoringCase(value->function->name, "rgba(")) { + int colorValues[4]; + if (!parseColorParameters(value, colorValues, true)) + return false; + c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]); + } else if (value->unit == Value::Function && + value->function->args != 0 && + value->function->args->size() == 5 /* hsl + two commas */ && + equalIgnoringCase(value->function->name, "hsl(")) { + double colorValues[3]; + if (!parseHSLParameters(value, colorValues, false)) + return false; + c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0); + } else if (value->unit == Value::Function && + value->function->args != 0 && + value->function->args->size() == 7 /* hsla + three commas */ && + equalIgnoringCase(value->function->name, "hsla(")) { + double colorValues[4]; + if (!parseHSLParameters(value, colorValues, true)) + return false; + c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]); + } else + return false; + } else + return false; + + return true; +} + +// This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) +// without the allowBreak bit being set, then it will clean up all of the objects and destroy them. +struct ShadowParseContext { + ShadowParseContext() + : allowX(true) + , allowY(false) + , allowBlur(false) + , allowColor(true) + , allowBreak(true) + {} + + bool allowLength() { return allowX || allowY || allowBlur; } + + void commitValue() { + // Handle the ,, case gracefully by doing nothing. + if (x || y || blur || color) { + if (!values) + values = new CSSValueList(); + + // Construct the current shadow value and add it to the list. + values->append(new ShadowValue(x.release(), y.release(), blur.release(), color.release())); + } + + // Now reset for the next shadow value. + x = y = blur = color = 0; + allowX = allowColor = allowBreak = true; + allowY = allowBlur = false; + } + + void commitLength(Value* v) { + RefPtr<CSSPrimitiveValue> val = new CSSPrimitiveValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + + if (allowX) { + x = val.release(); + allowX = false; allowY = true; allowColor = false; allowBreak = false; + } + else if (allowY) { + y = val.release(); + allowY = false; allowBlur = true; allowColor = true; allowBreak = true; + } + else if (allowBlur) { + blur = val.release(); + allowBlur = false; + } + } + + void commitColor(PassRefPtr<CSSPrimitiveValue> val) { + color = val; + allowColor = false; + if (allowX) + allowBreak = false; + else + allowBlur = false; + } + + RefPtr<CSSValueList> values; + RefPtr<CSSPrimitiveValue> x; + RefPtr<CSSPrimitiveValue> y; + RefPtr<CSSPrimitiveValue> blur; + RefPtr<CSSPrimitiveValue> color; + + bool allowX; + bool allowY; + bool allowBlur; + bool allowColor; + bool allowBreak; +}; + +bool CSSParser::parseShadow(int propId, bool important) +{ + ShadowParseContext context; + Value* val; + while ((val = valueList->current())) { + // Check for a comma break first. + if (val->unit == Value::Operator) { + if (val->iValue != ',' || !context.allowBreak) + // Other operators aren't legal or we aren't done with the current shadow + // value. Treat as invalid. + return false; + + // The value is good. Commit it. + context.commitValue(); + } + // Check to see if we're a length. + else if (validUnit(val, FLength, true)) { + // We required a length and didn't get one. Invalid. + if (!context.allowLength()) + return false; + + // A length is allowed here. Construct the value and add it. + context.commitLength(val); + } + else { + // The only other type of value that's ok is a color value. + RefPtr<CSSPrimitiveValue> parsedColor; + bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU || + (val->id >= CSS_VAL__WEBKIT_FOCUS_RING_COLOR && val->id <= CSS_VAL__WEBKIT_TEXT && !strict)); + if (isColor) { + if (!context.allowColor) + return false; + parsedColor = new CSSPrimitiveValue(val->id); + } + + if (!parsedColor) + // It's not built-in. Try to parse it as a color. + parsedColor = parseColor(val); + + if (!parsedColor || !context.allowColor) + return false; // This value is not a color or length and is invalid or + // it is a color, but a color isn't allowed at this point. + + context.commitColor(parsedColor.release()); + } + + valueList->next(); + } + + if (context.allowBreak) { + context.commitValue(); + if (context.values->length()) { + addProperty(propId, context.values.release(), important); + valueList->next(); + return true; + } + } + + return false; +} + +struct BorderImageParseContext +{ + BorderImageParseContext() + : m_allowBreak(false) + , m_allowNumber(false) + , m_allowSlash(false) + , m_allowWidth(false) + , m_allowRule(false) + , m_borderTop(0) + , m_borderRight(0) + , m_borderBottom(0) + , m_borderLeft(0) + , m_horizontalRule(0) + , m_verticalRule(0) + {} + + bool allowBreak() const { return m_allowBreak; } + bool allowNumber() const { return m_allowNumber; } + bool allowSlash() const { return m_allowSlash; } + bool allowWidth() const { return m_allowWidth; } + bool allowRule() const { return m_allowRule; } + + void commitImage(CSSImageValue* image) { m_image = image; m_allowNumber = true; } + void commitNumber(Value* v) { + PassRefPtr<CSSPrimitiveValue> val = new CSSPrimitiveValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + if (!m_top) + m_top = val; + else if (!m_right) + m_right = val; + else if (!m_bottom) + m_bottom = val; + else { + ASSERT(!m_left); + m_left = val; + } + + m_allowBreak = m_allowSlash = m_allowRule = true; + m_allowNumber = !m_left; + } + void commitSlash() { m_allowBreak = m_allowSlash = m_allowNumber = false; m_allowWidth = true; } + void commitWidth(Value* val) { + if (!m_borderTop) + m_borderTop = val; + else if (!m_borderRight) + m_borderRight = val; + else if (!m_borderBottom) + m_borderBottom = val; + else { + ASSERT(!m_borderLeft); + m_borderLeft = val; + } + + m_allowBreak = m_allowRule = true; + m_allowWidth = !m_borderLeft; + } + void commitRule(int keyword) { + if (!m_horizontalRule) + m_horizontalRule = keyword; + else if (!m_verticalRule) + m_verticalRule = keyword; + m_allowRule = !m_verticalRule; + } + void commitBorderImage(CSSParser* p, int propId, bool important) { + // We need to clone and repeat values for any omissions. + if (!m_right) { + m_right = new CSSPrimitiveValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_bottom = new CSSPrimitiveValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = new CSSPrimitiveValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + } + if (!m_bottom) { + m_bottom = new CSSPrimitiveValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = new CSSPrimitiveValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + } + if (!m_left) + m_left = new CSSPrimitiveValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + + // Now build a rect value to hold all four of our primitive values. + RefPtr<Rect> rect = new Rect; + rect->setTop(m_top); + rect->setRight(m_right); + rect->setBottom(m_bottom); + rect->setLeft(m_left); + + // Fill in STRETCH as the default if it wasn't specified. + if (!m_horizontalRule) + m_horizontalRule = CSS_VAL_STRETCH; + + // The vertical rule should match the horizontal rule if unspecified. + if (!m_verticalRule) + m_verticalRule = m_horizontalRule; + + // Make our new border image value now and add it as the result. + CSSBorderImageValue* borderImage = new CSSBorderImageValue(m_image, rect.release(), m_horizontalRule, m_verticalRule); + p->addProperty(propId, borderImage, important); + + // Now we have to deal with the border widths. The best way to deal with these is to actually put these values into a value + // list and then make our parsing machinery do the parsing. + if (m_borderTop) { + ValueList newList; + newList.addValue(*m_borderTop); + if (m_borderRight) + newList.addValue(*m_borderRight); + if (m_borderBottom) + newList.addValue(*m_borderBottom); + if (m_borderLeft) + newList.addValue(*m_borderLeft); + p->valueList = &newList; + p->parseValue(CSS_PROP_BORDER_WIDTH, important); + p->valueList = 0; + } + } + + bool m_allowBreak; + bool m_allowNumber; + bool m_allowSlash; + bool m_allowWidth; + bool m_allowRule; + + RefPtr<CSSImageValue> m_image; + + RefPtr<CSSPrimitiveValue> m_top; + RefPtr<CSSPrimitiveValue> m_right; + RefPtr<CSSPrimitiveValue> m_bottom; + RefPtr<CSSPrimitiveValue> m_left; + + Value* m_borderTop; + Value* m_borderRight; + Value* m_borderBottom; + Value* m_borderLeft; + + int m_horizontalRule; + int m_verticalRule; +}; + +bool CSSParser::parseBorderImage(int propId, bool important) +{ + // Look for an image initially. If the first value is not a URI, then we're done. + BorderImageParseContext context; + Value* val = valueList->current(); + if (val->unit != CSSPrimitiveValue::CSS_URI) + return false; + + String uri = parseURL(val->string); + if (uri.isEmpty()) + return false; + + context.commitImage(new CSSImageValue(KURL(styleElement->baseURL(), uri).string(), styleElement)); + while ((val = valueList->next())) { + if (context.allowNumber() && validUnit(val, FInteger|FNonNeg|FPercent, true)) { + context.commitNumber(val); + } else if (context.allowSlash() && val->unit == Value::Operator && val->iValue == '/') { + context.commitSlash(); + } else if (context.allowWidth() && + (val->id == CSS_VAL_THIN || val->id == CSS_VAL_MEDIUM || val->id == CSS_VAL_THICK || validUnit(val, FLength, strict))) { + context.commitWidth(val); + } else if (context.allowRule() && + (val->id == CSS_VAL_STRETCH || val->id == CSS_VAL_ROUND || val->id == CSS_VAL_REPEAT)) { + context.commitRule(val->id); + } else { + // Something invalid was encountered. + return false; + } + } + + if (context.allowBreak()) { + // Need to fully commit as a single value. + context.commitBorderImage(this, propId, important); + return true; + } + + return false; +} + +bool CSSParser::parseCounter(int propId, int defaultValue, bool important) +{ + enum { ID, VAL } state = ID; + + RefPtr<CSSValueList> list = new CSSValueList; + RefPtr<CSSPrimitiveValue> counterName; + + while (true) { + Value* val = valueList->current(); + switch (state) { + case ID: + if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) { + counterName = new CSSPrimitiveValue(val->string, CSSPrimitiveValue::CSS_STRING); + state = VAL; + valueList->next(); + continue; + } + break; + case VAL: { + int i = defaultValue; + if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) { + i = (int)val->fValue; + valueList->next(); + } + + list->append(new CSSPrimitiveValue(new Pair(counterName.release(), + new CSSPrimitiveValue(i, CSSPrimitiveValue::CSS_NUMBER)))); + state = ID; + continue; + } + } + break; + } + + if (list->length() > 0) { + addProperty(propId, list.release(), important); + return true; + } + + return false; +} + +class TransformOperationInfo { +public: + TransformOperationInfo(const ParseString& name) + : m_type(CSSTransformValue::UnknownTransformOperation) + , m_argCount(1) + , m_allowSingleArgument(false) + , m_unit(CSSParser::FUnknown) + { + if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scaleX(") || equalIgnoringCase(name, "scaleY(")) { + m_unit = CSSParser::FNumber; + if (equalIgnoringCase(name, "scale(")) + m_type = CSSTransformValue::ScaleTransformOperation; + else if (equalIgnoringCase(name, "scaleX(")) + m_type = CSSTransformValue::ScaleXTransformOperation; + else + m_type = CSSTransformValue::ScaleYTransformOperation; + } else if (equalIgnoringCase(name, "rotate(")) { + m_type = CSSTransformValue::RotateTransformOperation; + m_unit = CSSParser::FAngle; + } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewX(") || equalIgnoringCase(name, "skewY(")) { + m_unit = CSSParser::FAngle; + if (equalIgnoringCase(name, "skew(")) + m_type = CSSTransformValue::SkewTransformOperation; + else if (equalIgnoringCase(name, "skewX(")) + m_type = CSSTransformValue::SkewXTransformOperation; + else + m_type = CSSTransformValue::SkewYTransformOperation; + } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translateX(") || equalIgnoringCase(name, "translateY(")) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + if (equalIgnoringCase(name, "translate(")) + m_type = CSSTransformValue::TranslateTransformOperation; + else if (equalIgnoringCase(name, "translateX(")) + m_type = CSSTransformValue::TranslateXTransformOperation; + else + m_type = CSSTransformValue::TranslateYTransformOperation; + } else if (equalIgnoringCase(name, "matrix(")) { + m_type = CSSTransformValue::MatrixTransformOperation; + m_argCount = 11; + m_unit = CSSParser::FNumber; + } + + if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) { + m_allowSingleArgument = true; + m_argCount = 3; + } + } + + CSSTransformValue::TransformOperationType type() const { return m_type; } + unsigned argCount() const { return m_argCount; } + CSSParser::Units unit() const { return m_unit; } + + bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; } + bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); } + +private: + CSSTransformValue::TransformOperationType m_type; + unsigned m_argCount; + bool m_allowSingleArgument; + CSSParser::Units m_unit; +}; + +PassRefPtr<CSSValue> CSSParser::parseTransform() +{ + if (!valueList) + return 0; + + // The transform is a list of functional primitives that specify transform operations. We collect a list + // of CSSTransformValues, where each value specifies a single operation. + RefPtr<CSSValueList> list = new CSSValueList; + for (Value* value = valueList->current(); value; value = valueList->next()) { + if (value->unit != Value::Function || !value->function) + return 0; + + // Every primitive requires at least one argument. + ValueList* args = value->function->args; + if (!args) + return 0; + + // See if the specified primitive is one we understand. + TransformOperationInfo info(value->function->name); + if (info.unknown()) + return 0; + + if (!info.hasCorrectArgCount(args->size())) + return 0; + + // Create the new CSSTransformValue for this operation and add it to our list. + CSSTransformValue* transformValue = new CSSTransformValue(info.type()); + list->append(transformValue); + + // Snag our values. + Value* a = args->current(); + unsigned argNumber = 0; + while (a) { + CSSParser::Units unit = info.unit(); + + if (!validUnit(a, unit, true)) + return 0; + + // Add the value to the current transform operation. + transformValue->addValue(new CSSPrimitiveValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit)); + + a = args->next(); + if (!a) + break; + if (a->unit != Value::Operator || a->iValue != ',') + return 0; + a = args->next(); + + argNumber++; + } + } + + return list.release(); +} + +bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2) +{ + propId1 = propId; + propId2 = propId; + if (propId == CSS_PROP__WEBKIT_TRANSFORM_ORIGIN) { + propId1 = CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_X; + propId2 = CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_Y; + } + + switch (propId) { + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN: + parseBackgroundPosition(value, value2); + // Unlike the other functions, parseBackgroundPosition advances the valueList pointer + break; + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_X: { + bool xFound = false, yFound = true; + value = parseBackgroundPositionXY(xFound, yFound); + if (value) + valueList->next(); + break; + } + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_Y: { + bool xFound = true, yFound = false; + value = parseBackgroundPositionXY(xFound, yFound); + if (value) + valueList->next(); + break; + } + } + + return value; +} + +#ifdef CSS_DEBUG + +static inline int yyerror(const char *str) +{ + kdDebug(6080) << "CSS parse error " << str << endl; + return 1; +} + +#else + +static inline int yyerror(const char*) { return 1; } + +#endif + +#define END_TOKEN 0 + +#include "CSSGrammar.h" + +int CSSParser::lex(void* yylvalWithoutType) +{ + YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType); + int token = lex(); + int length; + UChar* t = text(&length); + + switch(token) { + case WHITESPACE: + case SGML_CD: + case INCLUDES: + case DASHMATCH: + break; + + case URI: + case STRING: + case IDENT: + case NTH: + case HEX: + case IDSEL: + case DIMEN: + case UNICODERANGE: + case FUNCTION: + case NOTFUNCTION: + yylval->string.characters = t; + yylval->string.length = length; + break; + + case IMPORT_SYM: + case PAGE_SYM: + case MEDIA_SYM: + case FONT_FACE_SYM: + case CHARSET_SYM: + case NAMESPACE_SYM: + + case IMPORTANT_SYM: + break; + + case QEMS: + length--; + case GRADS: + length--; + case DEGS: + case RADS: + case KHERZ: + length--; + case MSECS: + case HERZ: + case EMS: + case EXS: + case PXS: + case CMS: + case MMS: + case INS: + case PTS: + case PCS: + length--; + case SECS: + case PERCENTAGE: + length--; + case FLOATTOKEN: + case INTEGER: + yylval->number = charactersToDouble(t, length); + break; + + default: + break; + } + + return token; +} + +static inline int toHex(char c) +{ + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c<= 'F') + return c - 'A' + 10; + return 0; +} + +UChar* CSSParser::text(int *length) +{ + UChar* start = yytext; + int l = yyleng; + switch(yyTok) { + case STRING: + l--; + /* nobreak */ + case HEX: + case IDSEL: + start++; + l--; + break; + case URI: + // "url("{w}{string}{w}")" + // "url("{w}{url}{w}")" + + // strip "url(" and ")" + start += 4; + l -= 5; + // strip {w} + while (l && + (*start == ' ' || *start == '\t' || *start == '\r' || + *start == '\n' || *start == '\f')) { + start++; l--; + } + if (*start == '"' || *start == '\'') { + start++; l--; + } + while (l && + (start[l-1] == ' ' || start[l-1] == '\t' || start[l-1] == '\r' || + start[l-1] == '\n' || start[l-1] == '\f')) { + l--; + } + if (l && (start[l-1] == '\"' || start[l-1] == '\'')) + l--; + + default: + break; + } + + // process escapes + UChar* out = start; + UChar* escape = 0; + + for (int i = 0; i < l; i++) { + UChar* current = start + i; + if (escape == current - 1) { + if ((*current >= '0' && *current <= '9') || + (*current >= 'a' && *current <= 'f') || + (*current >= 'A' && *current <= 'F')) + continue; + if (yyTok == STRING && + (*current == '\n' || *current == '\r' || *current == '\f')) { + // ### handle \r\n case + if (*current != '\r') + escape = 0; + continue; + } + // in all other cases copy the char to output + // ### + *out++ = *current; + escape = 0; + continue; + } + if (escape == current - 2 && yyTok == STRING && + *(current-1) == '\r' && *current == '\n') { + escape = 0; + continue; + } + if (escape > current - 7 && + ((*current >= '0' && *current <= '9') || + (*current >= 'a' && *current <= 'f') || + (*current >= 'A' && *current <= 'F'))) + continue; + if (escape) { + // add escaped char + unsigned uc = 0; + escape++; + while (escape < current) { + uc *= 16; + uc += toHex(*escape); + escape++; + } + // can't handle chars outside ucs2 + if (uc > 0xffff) + uc = 0xfffd; + *out++ = uc; + escape = 0; + if (*current == ' ' || + *current == '\t' || + *current == '\r' || + *current == '\n' || + *current == '\f') + continue; + } + if (!escape && *current == '\\') { + escape = current; + continue; + } + *out++ = *current; + } + if (escape) { + // add escaped char + unsigned uc = 0; + escape++; + while (escape < start+l) { + uc *= 16; + uc += toHex(*escape); + escape++; + } + // can't handle chars outside ucs2 + if (uc > 0xffff) + uc = 0xfffd; + *out++ = uc; + } + + *length = out - start; + return start; +} + +CSSSelector* CSSParser::createFloatingSelector() +{ + CSSSelector* selector = new CSSSelector; + m_floatingSelectors.add(selector); + return selector; +} + +CSSSelector* CSSParser::sinkFloatingSelector(CSSSelector* selector) +{ + if (selector) { + ASSERT(m_floatingSelectors.contains(selector)); + m_floatingSelectors.remove(selector); + } + return selector; +} + +ValueList* CSSParser::createFloatingValueList() +{ + ValueList* list = new ValueList; + m_floatingValueLists.add(list); + return list; +} + +ValueList* CSSParser::sinkFloatingValueList(ValueList* list) +{ + if (list) { + ASSERT(m_floatingValueLists.contains(list)); + m_floatingValueLists.remove(list); + } + return list; +} + +Function* CSSParser::createFloatingFunction() +{ + Function* function = new Function; + m_floatingFunctions.add(function); + return function; +} + +Function* CSSParser::sinkFloatingFunction(Function* function) +{ + if (function) { + ASSERT(m_floatingFunctions.contains(function)); + m_floatingFunctions.remove(function); + } + return function; +} + +Value& CSSParser::sinkFloatingValue(Value& value) +{ + if (value.unit == Value::Function) { + ASSERT(m_floatingFunctions.contains(value.function)); + m_floatingFunctions.remove(value.function); + } + return value; +} + +MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, ValueList* values) +{ + delete m_floatingMediaQueryExp; + m_floatingMediaQueryExp = new MediaQueryExp(mediaFeature, values); + return m_floatingMediaQueryExp; +} + +MediaQueryExp* CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* e) +{ + ASSERT(e == m_floatingMediaQueryExp); + m_floatingMediaQueryExp = 0; + return e; +} + +Vector<MediaQueryExp*>* CSSParser::createFloatingMediaQueryExpList() +{ + if (m_floatingMediaQueryExpList) { + deleteAllValues(*m_floatingMediaQueryExpList); + delete m_floatingMediaQueryExpList; + } + m_floatingMediaQueryExpList = new Vector<MediaQueryExp*>; + return m_floatingMediaQueryExpList; +} + +Vector<MediaQueryExp*>* CSSParser::sinkFloatingMediaQueryExpList(Vector<MediaQueryExp*>* l) +{ + ASSERT(l == m_floatingMediaQueryExpList); + m_floatingMediaQueryExpList = 0; + return l; +} + +MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs) +{ + delete m_floatingMediaQuery; + m_floatingMediaQuery = new MediaQuery(r, mediaType, exprs); + return m_floatingMediaQuery; +} + +MediaQuery* CSSParser::sinkFloatingMediaQuery(MediaQuery* mq) +{ + ASSERT(mq == m_floatingMediaQuery); + m_floatingMediaQuery = 0; + return mq; +} + +MediaList* CSSParser::createMediaList() +{ + MediaList* list = new MediaList; + m_parsedStyleObjects.append(list); + return list; +} + +CSSRule* CSSParser::createCharsetRule(const ParseString& charset) +{ + if (!styleElement) + return 0; + if (!styleElement->isCSSStyleSheet()) + return 0; + CSSCharsetRule* rule = new CSSCharsetRule(styleElement, charset); + m_parsedStyleObjects.append(rule); + return rule; +} + +CSSRule* CSSParser::createImportRule(const ParseString& url, MediaList* media) +{ + if (!media) + return 0; + if (!styleElement) + return 0; + if (!styleElement->isCSSStyleSheet()) + return 0; + CSSImportRule* rule = new CSSImportRule(styleElement, url, media); + m_parsedStyleObjects.append(rule); + return rule; +} + +CSSRule* CSSParser::createMediaRule(MediaList* media, CSSRuleList* rules) +{ + if (!media) + return 0; + if (!rules) + return 0; + if (!styleElement) + return 0; + if (!styleElement->isCSSStyleSheet()) + return 0; + CSSMediaRule* rule = new CSSMediaRule(styleElement, media, rules); + m_parsedStyleObjects.append(rule); + return rule; +} + +CSSRuleList* CSSParser::createRuleList() +{ + CSSRuleList* list = new CSSRuleList; + m_parsedRuleLists.append(list); + return list; +} + +CSSRule* CSSParser::createStyleRule(CSSSelector* selector) +{ + CSSStyleRule* rule = 0; + if (selector) { + rule = new CSSStyleRule(styleElement); + m_parsedStyleObjects.append(rule); + rule->setSelector(sinkFloatingSelector(selector)); + rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties)); + } + clearProperties(); + return rule; +} + +CSSRule* CSSParser::createFontFaceRule() +{ + CSSFontFaceRule* rule = new CSSFontFaceRule(styleElement); + m_parsedStyleObjects.append(rule); + rule->setDeclaration(new CSSMutableStyleDeclaration(rule, parsedProperties, numParsedProperties)); + clearProperties(); + return rule; +} + +static int cssPropertyID(const UChar* propertyName, unsigned length) +{ + if (!length) + return 0; + if (length > maxCSSPropertyNameLength) + return 0; + + char buffer[maxCSSPropertyNameLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character + + for (unsigned i = 0; i != length; ++i) { + UChar c = propertyName[i]; + if (c == 0 || c >= 0x7F) + return 0; // illegal character + buffer[i] = toASCIILower(c); + } + buffer[length] = '\0'; + + const char* name = buffer; + if (buffer[0] == '-') { + // If the prefix is -apple- or -khtml-, change it to -webkit-. + // This makes the string one character longer. + if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) { + memmove(buffer + 7, buffer + 6, length + 1 - 6); + memcpy(buffer, "-webkit", 7); + ++length; + } + + // Honor -webkit-opacity as a synonym for opacity. + // This was the only syntax that worked in Safari 1.1, and may be in use on some websites and widgets. + if (strcmp(buffer, "-webkit-opacity") == 0) { + const char * const opacity = "opacity"; + name = opacity; + length = strlen(opacity); + } + } + + const props* hashTableEntry = findProp(name, length); + return hashTableEntry ? hashTableEntry->id : 0; +} + +int cssPropertyID(const String& string) +{ + return cssPropertyID(string.characters(), string.length()); +} + +int cssPropertyID(const ParseString& string) +{ + return cssPropertyID(string.characters, string.length); +} + +int cssValueKeywordID(const ParseString& string) +{ + unsigned length = string.length; + if (!length) + return 0; + if (length > maxCSSValueKeywordLength) + return 0; + + char buffer[maxCSSValueKeywordLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character + + for (unsigned i = 0; i != length; ++i) { + UChar c = string.characters[i]; + if (c == 0 || c >= 0x7F) + return 0; // illegal character + buffer[i] = WTF::toASCIILower(c); + } + buffer[length] = '\0'; + + if (buffer[0] == '-') { + // If the prefix is -apple- or -khtml-, change it to -webkit-. + // This makes the string one character longer. + if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) { + memmove(buffer + 7, buffer + 6, length + 1 - 6); + memcpy(buffer, "-webkit", 7); + ++length; + } + } + + const css_value* hashTableEntry = findValue(buffer, length); + return hashTableEntry ? hashTableEntry->id : 0; +} + +#define YY_DECL int CSSParser::lex() +#define yyconst const +typedef int yy_state_type; +typedef unsigned YY_CHAR; +// The following line makes sure we treat non-Latin-1 Unicode characters correctly. +#define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c) +#define YY_DO_BEFORE_ACTION \ + yytext = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = 0; \ + yy_c_buf_p = yy_cp; +#define YY_BREAK break; +#define ECHO +#define YY_RULE_SETUP +#define INITIAL 0 +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +#define yyterminate() yyTok = END_TOKEN; return yyTok +#define YY_FATAL_ERROR(a) +// The following line is needed to build the tokenizer with a condition stack. +// The macro is used in the tokenizer grammar with lines containing +// BEGIN(mediaqueries) and BEGIN(initial). yy_start acts as index to +// tokenizer transition table, and 'mediaqueries' and 'initial' are +// offset multipliers that specify which transitions are active +// in the tokenizer during in each condition (tokenizer state). +#define BEGIN yy_start = 1 + 2 * + +#include "tokenizer.cpp" + +} diff --git a/WebCore/css/CSSParser.h b/WebCore/css/CSSParser.h new file mode 100644 index 0000000..250961d --- /dev/null +++ b/WebCore/css/CSSParser.h @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSParser_h +#define CSSParser_h + +#include "AtomicString.h" +#include "Color.h" +#include "MediaQuery.h" +#include <wtf/HashSet.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class CSSMutableStyleDeclaration; + class CSSPrimitiveValue; + class CSSProperty; + class CSSRule; + class CSSRuleList; + class CSSSelector; + class CSSStyleSheet; + class CSSValue; + class CSSValueList; + class Document; + class MediaList; + class MediaList; + class MediaQueryExp; + class StyleBase; + class StyleList; + struct Function; + + struct ParseString { + UChar* characters; + int length; + + void lower(); + + operator String() const { return String(characters, length); } + operator AtomicString() const { return AtomicString(characters, length); } + }; + + struct Value { + int id; + bool isInt; + union { + double fValue; + int iValue; + ParseString string; + Function* function; + }; + enum { + Operator = 0x100000, + Function = 0x100001, + Q_EMS = 0x100002 + }; + int unit; + }; + + class ValueList { + public: + ValueList() : m_current(0) { } + ~ValueList(); + + void addValue(const Value& v) { m_values.append(v); } + unsigned size() const { return m_values.size(); } + Value* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; } + Value* next() { ++m_current; return current(); } + + Value* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; } + void deleteValueAt(unsigned i) { m_values.remove(i); } + + private: + Vector<Value, 16> m_values; + unsigned m_current; + }; + + struct Function { + ParseString name; + ValueList* args; + + ~Function() { delete args; } + }; + + class CSSParser { + public: + CSSParser(bool strictParsing = true); + ~CSSParser(); + + void parseSheet(CSSStyleSheet*, const String&); + PassRefPtr<CSSRule> parseRule(CSSStyleSheet*, const String&); + bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important); + static bool parseColor(RGBA32& color, const String&, bool strict = false); + bool parseColor(CSSMutableStyleDeclaration*, const String&); + bool parseDeclaration(CSSMutableStyleDeclaration*, const String&); + bool parseMediaQuery(MediaList*, const String&); + + static CSSParser* current() { return currentParser; } + + Document* document() const; + + void addProperty(int propId, PassRefPtr<CSSValue>, bool important); + void rollbackLastProperties(int num); + bool hasProperties() const { return numParsedProperties > 0; } + + bool parseValue(int propId, bool important); + bool parseShorthand(int propId, const int* properties, int numProperties, bool important); + bool parse4Values(int propId, const int* properties, bool important); + bool parseContent(int propId, bool important); + + PassRefPtr<CSSValue> parseBackgroundColor(); + bool parseBackgroundImage(RefPtr<CSSValue>&); + PassRefPtr<CSSValue> parseBackgroundPositionXY(bool& xFound, bool& yFound); + void parseBackgroundPosition(RefPtr<CSSValue>&, RefPtr<CSSValue>&); + PassRefPtr<CSSValue> parseBackgroundSize(); + + bool parseBackgroundProperty(int propId, int& propId1, int& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&); + bool parseBackgroundShorthand(bool important); + + void addBackgroundValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval); + + void addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval); + PassRefPtr<CSSValue> parseTransitionDuration(); + PassRefPtr<CSSValue> parseTransitionRepeatCount(); + PassRefPtr<CSSValue> parseTransitionTimingFunction(); + bool parseTimingFunctionValue(ValueList*& args, double& result); + PassRefPtr<CSSValue> parseTransitionProperty(); + bool parseTransitionProperty(int propId, RefPtr<CSSValue>&); + bool parseTransitionShorthand(bool important); + + bool parseDashboardRegions(int propId, bool important); + + bool parseShape(int propId, bool important); + + bool parseFont(bool important); + PassRefPtr<CSSValueList> parseFontFamily(); + + bool parseCounter(int propId, int defaultValue, bool important); + PassRefPtr<CSSValue> parseCounterContent(ValueList* args, bool counters); + + bool parseColorParameters(Value*, int* colorValues, bool parseAlpha); + bool parseHSLParameters(Value*, double* colorValues, bool parseAlpha); + PassRefPtr<CSSPrimitiveValue> parseColor(Value* = 0); + bool parseColorFromValue(Value*, RGBA32&, bool = false); + + static bool parseColor(const String&, RGBA32& rgb, bool strict); + + bool parseFontFaceSrc(); + bool parseFontFaceUnicodeRange(); + +#if ENABLE(SVG) + bool parseSVGValue(int propId, bool important); + PassRefPtr<CSSValue> parseSVGPaint(); + PassRefPtr<CSSValue> parseSVGColor(); + PassRefPtr<CSSValue> parseSVGStrokeDasharray(); +#endif + + // CSS3 Parsing Routines (for properties specific to CSS3) + bool parseShadow(int propId, bool important); + bool parseBorderImage(int propId, bool important); + + PassRefPtr<CSSValue> parseTransform(); + bool parseTransformOrigin(int propId, int& propId1, int& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&); + + int yyparse(); + + CSSSelector* createFloatingSelector(); + CSSSelector* sinkFloatingSelector(CSSSelector*); + + ValueList* createFloatingValueList(); + ValueList* sinkFloatingValueList(ValueList*); + + Function* createFloatingFunction(); + Function* sinkFloatingFunction(Function*); + + Value& sinkFloatingValue(Value&); + + MediaList* createMediaList(); + CSSRule* createCharsetRule(const ParseString&); + CSSRule* createImportRule(const ParseString&, MediaList*); + CSSRule* createMediaRule(MediaList*, CSSRuleList*); + CSSRuleList* createRuleList(); + CSSRule* createStyleRule(CSSSelector*); + CSSRule* createFontFaceRule(); + + MediaQueryExp* createFloatingMediaQueryExp(const AtomicString&, ValueList*); + MediaQueryExp* sinkFloatingMediaQueryExp(MediaQueryExp*); + Vector<MediaQueryExp*>* createFloatingMediaQueryExpList(); + Vector<MediaQueryExp*>* sinkFloatingMediaQueryExpList(Vector<MediaQueryExp*>*); + MediaQuery* createFloatingMediaQuery(MediaQuery::Restrictor, const String&, Vector<MediaQueryExp*>*); + MediaQuery* sinkFloatingMediaQuery(MediaQuery*); + + public: + bool strict; + bool important; + int id; + StyleList* styleElement; + RefPtr<CSSRule> rule; + MediaQuery* mediaQuery; + ValueList* valueList; + CSSProperty** parsedProperties; + int numParsedProperties; + int maxParsedProperties; + + int m_inParseShorthand; + int m_currentShorthand; + bool m_implicitShorthand; + + AtomicString defaultNamespace; + + static CSSParser* currentParser; + + // tokenizer methods and data + public: + int lex(void* yylval); + int token() { return yyTok; } + UChar* text(int* length); + int lex(); + + private: + void clearProperties(); + + void setupParser(const char* prefix, const String&, const char* suffix); + + bool inShorthand() const { return m_inParseShorthand; } + + void checkForOrphanedUnits(); + + UChar* data; + UChar* yytext; + UChar* yy_c_buf_p; + UChar yy_hold_char; + int yy_last_accepting_state; + UChar* yy_last_accepting_cpos; + int yyleng; + int yyTok; + int yy_start; + + Vector<RefPtr<StyleBase> > m_parsedStyleObjects; + Vector<RefPtr<CSSRuleList> > m_parsedRuleLists; + HashSet<CSSSelector*> m_floatingSelectors; + HashSet<ValueList*> m_floatingValueLists; + HashSet<Function*> m_floatingFunctions; + + MediaQuery* m_floatingMediaQuery; + MediaQueryExp* m_floatingMediaQueryExp; + Vector<MediaQueryExp*>* m_floatingMediaQueryExpList; + + // defines units allowed for a certain property, used in parseUnit + enum Units { + FUnknown = 0x0000, + FInteger = 0x0001, + FNumber = 0x0002, // Real Numbers + FPercent = 0x0004, + FLength = 0x0008, + FAngle = 0x0010, + FTime = 0x0020, + FFrequency = 0x0040, + FRelative = 0x0100, + FNonNeg = 0x0200 + }; + + friend inline Units operator|(Units a, Units b) + { + return static_cast<Units>(static_cast<unsigned>(a) | static_cast<unsigned>(b)); + } + + static bool validUnit(Value*, Units, bool strict); + + friend class TransformOperationInfo; + }; + + int cssPropertyID(const ParseString&); + int cssPropertyID(const String&); + int cssValueKeywordID(const ParseString&); + +} // namespace WebCore + +#endif // CSSParser_h diff --git a/WebCore/css/CSSPrimitiveValue.cpp b/WebCore/css/CSSPrimitiveValue.cpp new file mode 100644 index 0000000..b3d94ab --- /dev/null +++ b/WebCore/css/CSSPrimitiveValue.cpp @@ -0,0 +1,703 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSPrimitiveValue.h" + +#include "CSSHelper.h" +#include "CSSValueKeywords.h" +#include "Color.h" +#include "Counter.h" +#include "DashboardRegion.h" +#include "ExceptionCode.h" +#include "Pair.h" +#include "RenderStyle.h" +#include <wtf/ASCIICType.h> + +using namespace WTF; + +namespace WebCore { + +// "ident" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerIdentifier(const String& string) +{ + const UChar* p = string.characters(); + const UChar* end = p + string.length(); + + // -? + if (p != end && p[0] == '-') + ++p; + + // {nmstart} + if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0]))) + return false; + ++p; + + // {nmchar}* + for (; p != end; ++p) { + if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0]))) + return false; + } + + return true; +} + +// "url" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerURL(const String& string) +{ + const UChar* p = string.characters(); + const UChar* end = p + string.length(); + + for (; p != end; ++p) { + UChar c = p[0]; + switch (c) { + case '!': + case '#': + case '$': + case '%': + case '&': + break; + default: + if (c < '*') + return false; + if (c <= '~') + break; + if (c < 128) + return false; + } + } + + return true; +} + +// We use single quotes for now because markup.cpp uses double quotes. +static String quoteString(const String& string) +{ + // FIXME: Also need to escape characters like '\n'. + String s = string; + s.replace('\\', "\\\\"); + s.replace('\'', "\\'"); + return "'" + s + "'"; +} + +static String quoteStringIfNeeded(const String& string) +{ + return isCSSTokenizerIdentifier(string) ? string : quoteString(string); +} + +static String quoteURLIfNeeded(const String& string) +{ + return isCSSTokenizerURL(string) ? string : quoteString(string); +} + +CSSPrimitiveValue::CSSPrimitiveValue() + : m_type(0) +{ +} + +CSSPrimitiveValue::CSSPrimitiveValue(int ident) + : m_type(CSS_IDENT) +{ + m_value.ident = ident; +} + +CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) + : m_type(type) +{ + m_value.num = num; +} + +CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type) + : m_type(type) +{ + if ((m_value.string = str.impl())) + m_value.string->ref(); +} + +CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color) + : m_type(CSS_RGBCOLOR) +{ + m_value.rgbcolor = color; +} + +CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) +{ + switch (length.type()) { + case Auto: + m_type = CSS_IDENT; + m_value.ident = CSS_VAL_AUTO; + break; + case WebCore::Fixed: + m_type = CSS_PX; + m_value.num = length.value(); + break; + case Intrinsic: + m_type = CSS_IDENT; + m_value.ident = CSS_VAL_INTRINSIC; + break; + case MinIntrinsic: + m_type = CSS_IDENT; + m_value.ident = CSS_VAL_MIN_INTRINSIC; + break; + case Percent: + m_type = CSS_PERCENTAGE; + m_value.num = length.percent(); + break; + case Relative: + case Static: + ASSERT_NOT_REACHED(); + break; + } +} + +void CSSPrimitiveValue::init(PassRefPtr<Counter> c) +{ + m_type = CSS_COUNTER; + m_value.counter = c.releaseRef(); +} + +void CSSPrimitiveValue::init(PassRefPtr<Rect> r) +{ + m_type = CSS_RECT; + m_value.rect = r.releaseRef(); +} + +void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r) +{ + m_type = CSS_DASHBOARD_REGION; + m_value.region = r.releaseRef(); +} + +void CSSPrimitiveValue::init(PassRefPtr<Pair> p) +{ + m_type = CSS_PAIR; + m_value.pair = p.releaseRef(); +} + +CSSPrimitiveValue::~CSSPrimitiveValue() +{ + cleanup(); +} + +void CSSPrimitiveValue::cleanup() +{ + switch (m_type) { + case CSS_STRING: + case CSS_URI: + case CSS_ATTR: + if (m_value.string) + m_value.string->deref(); + break; + case CSS_COUNTER: + m_value.counter->deref(); + break; + case CSS_RECT: + m_value.rect->deref(); + break; + case CSS_PAIR: + m_value.pair->deref(); + break; + case CSS_DASHBOARD_REGION: + if (m_value.region) + m_value.region->deref(); + break; + default: + break; + } + + m_type = 0; +} + +int CSSPrimitiveValue::computeLengthInt(RenderStyle* style) +{ + double result = computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > INT_MAX || result < INT_MIN) + return 0; + return static_cast<int>(result); +} + +int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, double multiplier) +{ + double result = multiplier * computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > INT_MAX || result < INT_MIN) + return 0; + return static_cast<int>(result); +} + +const int intMaxForLength = 0x7ffffff; // max value for a 28-bit int +const int intMinForLength = (-0x7ffffff - 1); // min value for a 28-bit int + +// Lengths expect an int that is only 28-bits, so we have to check for a different overflow. +int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style) +{ + double result = computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > intMaxForLength || result < intMinForLength) + return 0; + return static_cast<int>(result); +} + +// Lengths expect an int that is only 28-bits, so we have to check for a different overflow. +int CSSPrimitiveValue::computeLengthIntForLength(RenderStyle* style, double multiplier) +{ + double result = multiplier * computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > intMaxForLength || result < intMinForLength) + return 0; + return static_cast<int>(result); +} + +short CSSPrimitiveValue::computeLengthShort(RenderStyle* style) +{ + double result = computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > SHRT_MAX || result < SHRT_MIN) + return 0; + return static_cast<short>(result); +} + +short CSSPrimitiveValue::computeLengthShort(RenderStyle* style, double multiplier) +{ + double result = multiplier * computeLengthDouble(style); + + // 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. + result += result < 0 ? -0.01 : +0.01; + + if (result > SHRT_MAX || result < SHRT_MIN) + return 0; + return static_cast<short>(result); +} + +float CSSPrimitiveValue::computeLengthFloat(RenderStyle* style, bool applyZoomFactor) +{ + return static_cast<float>(computeLengthDouble(style, applyZoomFactor)); +} + +double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, bool applyZoomFactor) +{ + unsigned short type = primitiveType(); + + double factor = 1.0; + switch (type) { + case CSS_EMS: + factor = applyZoomFactor ? style->fontDescription().computedSize() : style->fontDescription().specifiedSize(); + break; + case CSS_EXS: + // FIXME: We have a bug right now where the zoom will be applied multiple times to EX units. + // We really need to compute EX using fontMetrics for the original specifiedSize and not use + // our actual constructed rendering font. + factor = style->font().xHeight(); + break; + case CSS_PX: + break; + case CSS_CM: + factor = cssPixelsPerInch / 2.54; // (2.54 cm/in) + break; + case CSS_MM: + factor = cssPixelsPerInch / 25.4; + break; + case CSS_IN: + factor = cssPixelsPerInch; + break; + case CSS_PT: + factor = cssPixelsPerInch / 72.0; + break; + case CSS_PC: + // 1 pc == 12 pt + factor = cssPixelsPerInch * 12.0 / 72.0; + break; + default: + return -1.0; + } + + return getDoubleValue() * factor; +} + +void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue, ExceptionCode& ec) +{ + ec = 0; + + // FIXME: check if property supports this type + if (m_type > CSS_DIMENSION) { + ec = SYNTAX_ERR; + return; + } + + cleanup(); + + //if(m_type > CSS_DIMENSION) throw DOMException(INVALID_ACCESS_ERR); + m_value.num = floatValue; + m_type = unitType; +} + +double scaleFactorForConversion(unsigned short unitType) +{ + double factor = 1.0; + switch (unitType) { + case CSSPrimitiveValue::CSS_PX: + break; + case CSSPrimitiveValue::CSS_CM: + factor = cssPixelsPerInch / 2.54; // (2.54 cm/in) + break; + case CSSPrimitiveValue::CSS_MM: + factor = cssPixelsPerInch / 25.4; + break; + case CSSPrimitiveValue::CSS_IN: + factor = cssPixelsPerInch; + break; + case CSSPrimitiveValue::CSS_PT: + factor = cssPixelsPerInch / 72.0; + break; + case CSSPrimitiveValue::CSS_PC: + factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt + break; + default: + break; + } + + return factor; +} + +double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) +{ + ec = 0; + if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) { + ec = INVALID_ACCESS_ERR; + return 0.0; + } + + if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC) + return m_value.num; + + double convertedValue = m_value.num; + + // First convert the value from m_type into CSSPixels + double factor = scaleFactorForConversion(m_type); + convertedValue *= factor; + + // Now convert from CSSPixels to the specified unitType + factor = scaleFactorForConversion(unitType); + convertedValue /= factor; + + return convertedValue; +} + +double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) +{ + if (m_type < CSS_NUMBER || m_type > CSS_DIMENSION || unitType < CSS_NUMBER || unitType > CSS_DIMENSION) + return 0; + + if (unitType == m_type || unitType < CSS_PX || unitType > CSS_PC) + return m_value.num; + + double convertedValue = m_value.num; + + // First convert the value from m_type into CSSPixels + double factor = scaleFactorForConversion(m_type); + convertedValue *= factor; + + // Now convert from CSSPixels to the specified unitType + factor = scaleFactorForConversion(unitType); + convertedValue /= factor; + + return convertedValue; +} + + +void CSSPrimitiveValue::setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode& ec) +{ + ec = 0; + + //if(m_type < CSS_STRING) throw DOMException(INVALID_ACCESS_ERR); + //if(m_type > CSS_ATTR) throw DOMException(INVALID_ACCESS_ERR); + if (m_type < CSS_STRING || m_type > CSS_ATTR) { + ec = SYNTAX_ERR; + return; + } + + cleanup(); + + if (stringType != CSS_IDENT) { + m_value.string = stringValue.impl(); + m_value.string->ref(); + m_type = stringType; + } + // FIXME: parse ident +} + +String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const +{ + ec = 0; + switch (m_type) { + case CSS_STRING: + case CSS_ATTR: + case CSS_URI: + return m_value.string; + case CSS_IDENT: + return getValueName(m_value.ident); + default: + ec = INVALID_ACCESS_ERR; + break; + } + + return String(); +} + +String CSSPrimitiveValue::getStringValue() const +{ + switch (m_type) { + case CSS_STRING: + case CSS_ATTR: + case CSS_URI: + return m_value.string; + case CSS_IDENT: + return getValueName(m_value.ident); + default: + break; + } + + return String(); +} + +Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const +{ + ec = 0; + if (m_type != CSS_COUNTER) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + return m_value.counter; +} + +Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const +{ + ec = 0; + if (m_type != CSS_RECT) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + return m_value.rect; +} + +unsigned CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const +{ + ec = 0; + if (m_type != CSS_RGBCOLOR) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + return m_value.rgbcolor; +} + +Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const +{ + ec = 0; + if (m_type != CSS_PAIR) { + ec = INVALID_ACCESS_ERR; + return 0; + } + + return m_value.pair; +} + +unsigned short CSSPrimitiveValue::cssValueType() const +{ + return CSS_PRIMITIVE_VALUE; +} + +bool CSSPrimitiveValue::parseString(const String& /*string*/, bool /*strict*/) +{ + // FIXME + return false; +} + +int CSSPrimitiveValue::getIdent() +{ + if (m_type != CSS_IDENT) + return 0; + return m_value.ident; +} + +String CSSPrimitiveValue::cssText() const +{ + // FIXME: return the original value instead of a generated one (e.g. color + // name if it was specified) - check what spec says about this + String text; + switch (m_type) { + case CSS_UNKNOWN: + // FIXME + break; + case CSS_NUMBER: + text = String::number(m_value.num); + break; + case CSS_PERCENTAGE: + text = String::format("%.6lg%%", m_value.num); + break; + case CSS_EMS: + text = String::format("%.6lgem", m_value.num); + break; + case CSS_EXS: + text = String::format("%.6lgex", m_value.num); + break; + case CSS_PX: + text = String::format("%.6lgpx", m_value.num); + break; + case CSS_CM: + text = String::format("%.6lgcm", m_value.num); + break; + case CSS_MM: + text = String::format("%.6lgmm", m_value.num); + break; + case CSS_IN: + text = String::format("%.6lgin", m_value.num); + break; + case CSS_PT: + text = String::format("%.6lgpt", m_value.num); + break; + case CSS_PC: + text = String::format("%.6lgpc", m_value.num); + break; + case CSS_DEG: + text = String::format("%.6lgdeg", m_value.num); + break; + case CSS_RAD: + text = String::format("%.6lgrad", m_value.num); + break; + case CSS_GRAD: + text = String::format("%.6lggrad", m_value.num); + break; + case CSS_MS: + text = String::format("%.6lgms", m_value.num); + break; + case CSS_S: + text = String::format("%.6lgs", m_value.num); + break; + case CSS_HZ: + text = String::format("%.6lghz", m_value.num); + break; + case CSS_KHZ: + text = String::format("%.6lgkhz", m_value.num); + break; + case CSS_DIMENSION: + // FIXME + break; + case CSS_STRING: + text = quoteStringIfNeeded(m_value.string); + break; + case CSS_URI: + text = "url(" + quoteURLIfNeeded(m_value.string) + ")"; + break; + case CSS_IDENT: + text = getValueName(m_value.ident); + break; + case CSS_ATTR: + // FIXME + break; + case CSS_COUNTER: + text = "counter("; + text += String::number(m_value.num); + text += ")"; + // FIXME: Add list-style and separator + break; + case CSS_RECT: { + Rect* rectVal = getRectValue(); + text = "rect("; + text += rectVal->top()->cssText() + " "; + text += rectVal->right()->cssText() + " "; + text += rectVal->bottom()->cssText() + " "; + text += rectVal->left()->cssText() + ")"; + break; + } + case CSS_RGBCOLOR: { + Color color(m_value.rgbcolor); + text = (color.alpha() < 0xFF) ? "rgba(" : "rgb("; + text += String::number(color.red()) + ", "; + text += String::number(color.green()) + ", "; + text += String::number(color.blue()); + if (color.alpha() < 0xFF) + text += ", " + String::number(static_cast<float>(color.alpha()) / 0xFF); + text += ")"; + break; + } + case CSS_PAIR: + text = m_value.pair->first()->cssText(); + text += " "; + text += m_value.pair->second()->cssText(); + break; + case CSS_DASHBOARD_REGION: + for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { + if (!text.isEmpty()) + text.append(' '); + text += "dashboard-region("; + text += region->m_label; + if (region->m_isCircle) + text += " circle"; + else if (region->m_isRectangle) + text += " rectangle"; + else + break; + if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSS_VAL_INVALID) { + ASSERT(region->right()->m_type == CSS_IDENT); + ASSERT(region->bottom()->m_type == CSS_IDENT); + ASSERT(region->left()->m_type == CSS_IDENT); + ASSERT(region->right()->getIdent() == CSS_VAL_INVALID); + ASSERT(region->bottom()->getIdent() == CSS_VAL_INVALID); + ASSERT(region->left()->getIdent() == CSS_VAL_INVALID); + } else { + text.append(' '); + text += region->top()->cssText() + " "; + text += region->right()->cssText() + " "; + text += region->bottom()->cssText() + " "; + text += region->left()->cssText(); + } + text += ")"; + } + break; + } + return text; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSPrimitiveValue.h b/WebCore/css/CSSPrimitiveValue.h new file mode 100644 index 0000000..d81e7cf --- /dev/null +++ b/WebCore/css/CSSPrimitiveValue.h @@ -0,0 +1,180 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> + * + * 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. + */ + +#ifndef CSSPrimitiveValue_h +#define CSSPrimitiveValue_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class Counter; +class DashboardRegion; +struct Length; +class Pair; +class Rect; +class RenderStyle; +class StringImpl; + +typedef int ExceptionCode; + +class CSSPrimitiveValue : public CSSValue { +public: + enum UnitTypes { + CSS_UNKNOWN = 0, + CSS_NUMBER = 1, + CSS_PERCENTAGE = 2, + CSS_EMS = 3, + CSS_EXS = 4, + CSS_PX = 5, + CSS_CM = 6, + CSS_MM = 7, + CSS_IN = 8, + CSS_PT = 9, + CSS_PC = 10, + CSS_DEG = 11, + CSS_RAD = 12, + CSS_GRAD = 13, + CSS_MS = 14, + CSS_S = 15, + CSS_HZ = 16, + CSS_KHZ = 17, + CSS_DIMENSION = 18, + CSS_STRING = 19, + CSS_URI = 20, + CSS_IDENT = 21, + CSS_ATTR = 22, + CSS_COUNTER = 23, + CSS_RECT = 24, + CSS_RGBCOLOR = 25, + CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.) + CSS_DASHBOARD_REGION = 101, // FIXME: What on earth is this doing as a primitive value? It should not be! + CSS_UNICODE_RANGE = 102 + }; + + // FIXME: int vs. unsigned overloading is too tricky for color vs. ident + CSSPrimitiveValue(); + CSSPrimitiveValue(int ident); + CSSPrimitiveValue(double, UnitTypes); + CSSPrimitiveValue(const String&, UnitTypes); + CSSPrimitiveValue(unsigned color); // RGB value + CSSPrimitiveValue(const Length&); + template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h + template<typename T> CSSPrimitiveValue(T* val) { init(PassRefPtr<T>(val)); } + template<typename T> CSSPrimitiveValue(PassRefPtr<T> val) { init(val); } + + virtual ~CSSPrimitiveValue(); + + void cleanup(); + + unsigned short primitiveType() const { return m_type; } + + /* + * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get + * the fontinfo in case val is defined in em or ex. + * + * The metrics have to be a bit different for screen and printer output. + * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi + * + * this is screen/printer dependent, so we probably need a config option for this, + * and some tool to calibrate. + */ + int computeLengthInt(RenderStyle*); + int computeLengthInt(RenderStyle*, double multiplier); + int computeLengthIntForLength(RenderStyle*); + int computeLengthIntForLength(RenderStyle*, double multiplier); + short computeLengthShort(RenderStyle*); + short computeLengthShort(RenderStyle*, double multiplier); + float computeLengthFloat(RenderStyle*, bool applyZoomFactor = true); + double computeLengthDouble(RenderStyle*, bool applyZoomFactor = true); + + // use with care!!! + void setPrimitiveType(unsigned short type) { m_type = type; } + + double getDoubleValue(unsigned short unitType, ExceptionCode&); + double getDoubleValue(unsigned short unitType); + double getDoubleValue() const { return m_value.num; } + + void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&); + float getFloatValue(unsigned short unitType, ExceptionCode& ec) { return static_cast<float>(getDoubleValue(unitType, ec)); } + float getFloatValue(unsigned short unitType) { return static_cast<float>(getDoubleValue(unitType)); } + float getFloatValue() const { return static_cast<float>(m_value.num); } + + int getIntValue(unsigned short unitType, ExceptionCode& ec) { return static_cast<int>(getDoubleValue(unitType, ec)); } + int getIntValue(unsigned short unitType) { return static_cast<int>(getDoubleValue(unitType)); } + int getIntValue() const { return static_cast<int>(m_value.num); } + + void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&); + String getStringValue(ExceptionCode&) const; + String getStringValue() const; + + Counter* getCounterValue(ExceptionCode&) const; + Counter* getCounterValue() const { return m_type != CSS_COUNTER ? 0 : m_value.counter; } + + Rect* getRectValue(ExceptionCode&) const; + Rect* getRectValue() const { return m_type != CSS_RECT ? 0 : m_value.rect; } + + unsigned getRGBColorValue(ExceptionCode&) const; + unsigned getRGBColorValue() const { return m_type != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; } + + Pair* getPairValue(ExceptionCode&) const; + Pair* getPairValue() const { return m_type != CSS_PAIR ? 0 : m_value.pair; } + + DashboardRegion* getDashboardRegionValue() const { return m_type != CSS_DASHBOARD_REGION ? 0 : m_value.region; } + + virtual bool isPrimitiveValue() const { return true; } + + virtual unsigned short cssValueType() const; + + int getIdent(); + template<typename T> operator T() const; // Defined in CSSPrimitiveValueMappings.h + + virtual bool parseString(const String&, bool = false); + virtual String cssText() const; + + virtual bool isQuirkValue() { return false; } + +protected: + int m_type; + union { + int ident; + double num; + StringImpl* string; + Counter* counter; + Rect* rect; + unsigned rgbcolor; + Pair* pair; + DashboardRegion* region; + } m_value; + +private: + template<typename T> operator T*(); // compile-time guard + + void init(PassRefPtr<Counter>); + void init(PassRefPtr<Rect>); + void init(PassRefPtr<Pair>); + void init(PassRefPtr<DashboardRegion>); // FIXME: Why is dashboard region a primitive value? This makes no sense. +}; + +} // namespace WebCore + +#endif // CSSPrimitiveValue_h diff --git a/WebCore/css/CSSPrimitiveValue.idl b/WebCore/css/CSSPrimitiveValue.idl new file mode 100644 index 0000000..b049c29 --- /dev/null +++ b/WebCore/css/CSSPrimitiveValue.idl @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +module css { + + interface [ + GenerateConstructor, + InterfaceUUID=a286b0cb-4ff0-4482-aa6e-7c5fb39afaba, + ImplementationUUID=c310c84d-480f-4bbb-9187-28e00956ac47 + ] CSSPrimitiveValue : CSSValue { + + // UnitTypes + const unsigned short CSS_UNKNOWN = 0; + const unsigned short CSS_NUMBER = 1; + const unsigned short CSS_PERCENTAGE = 2; + const unsigned short CSS_EMS = 3; + const unsigned short CSS_EXS = 4; + const unsigned short CSS_PX = 5; + const unsigned short CSS_CM = 6; + const unsigned short CSS_MM = 7; + const unsigned short CSS_IN = 8; + const unsigned short CSS_PT = 9; + const unsigned short CSS_PC = 10; + const unsigned short CSS_DEG = 11; + const unsigned short CSS_RAD = 12; + const unsigned short CSS_GRAD = 13; + const unsigned short CSS_MS = 14; + const unsigned short CSS_S = 15; + const unsigned short CSS_HZ = 16; + const unsigned short CSS_KHZ = 17; + const unsigned short CSS_DIMENSION = 18; + const unsigned short CSS_STRING = 19; + const unsigned short CSS_URI = 20; + const unsigned short CSS_IDENT = 21; + const unsigned short CSS_ATTR = 22; + const unsigned short CSS_COUNTER = 23; + const unsigned short CSS_RECT = 24; + const unsigned short CSS_RGBCOLOR = 25; + + readonly attribute unsigned short primitiveType; + + [OldStyleObjC] void setFloatValue(in unsigned short unitType, + in float floatValue) + raises(DOMException); + float getFloatValue(in unsigned short unitType) + raises(DOMException); + [OldStyleObjC] void setStringValue(in unsigned short stringType, + in DOMString stringValue) + raises(DOMException); + DOMString getStringValue() + raises(DOMException); + Counter getCounterValue() + raises(DOMException); + Rect getRectValue() + raises(DOMException); +#if !defined(LANGUAGE_COM) + RGBColor getRGBColorValue() + raises(DOMException); +#endif + + }; + +} diff --git a/WebCore/css/CSSPrimitiveValueMappings.h b/WebCore/css/CSSPrimitiveValueMappings.h new file mode 100644 index 0000000..3feb19f --- /dev/null +++ b/WebCore/css/CSSPrimitiveValueMappings.h @@ -0,0 +1,2212 @@ +/* + * Copyright (C) 2007 Alexey Proskuryakov <ap@nypop.com>. + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSPrimitiveValueMappings_h +#define CSSPrimitiveValueMappings_h + +#include "CSSPrimitiveValue.h" +#include "CSSValueKeywords.h" +#include "RenderStyle.h" + +namespace WebCore { + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBorderStyle e) + : m_type(CSS_IDENT) +{ + switch (e) { + case BNONE: + m_value.ident = CSS_VAL_NONE; + break; + case BHIDDEN: + m_value.ident = CSS_VAL_HIDDEN; + break; + case INSET: + m_value.ident = CSS_VAL_INSET; + break; + case GROOVE: + m_value.ident = CSS_VAL_GROOVE; + break; + case RIDGE: + m_value.ident = CSS_VAL_RIDGE; + break; + case OUTSET: + m_value.ident = CSS_VAL_OUTSET; + break; + case DOTTED: + m_value.ident = CSS_VAL_DOTTED; + break; + case DASHED: + m_value.ident = CSS_VAL_DASHED; + break; + case SOLID: + m_value.ident = CSS_VAL_SOLID; + break; + case DOUBLE: + m_value.ident = CSS_VAL_DOUBLE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBorderStyle() const +{ + return (EBorderStyle)(m_value.ident - CSS_VAL_NONE); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CompositeOperator e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CompositeClear: + m_value.ident = CSS_VAL_CLEAR; + break; + case CompositeCopy: + m_value.ident = CSS_VAL_COPY; + break; + case CompositeSourceOver: + m_value.ident = CSS_VAL_SOURCE_OVER; + break; + case CompositeSourceIn: + m_value.ident = CSS_VAL_SOURCE_IN; + break; + case CompositeSourceOut: + m_value.ident = CSS_VAL_SOURCE_OUT; + break; + case CompositeSourceAtop: + m_value.ident = CSS_VAL_SOURCE_ATOP; + break; + case CompositeDestinationOver: + m_value.ident = CSS_VAL_DESTINATION_OVER; + break; + case CompositeDestinationIn: + m_value.ident = CSS_VAL_DESTINATION_IN; + break; + case CompositeDestinationOut: + m_value.ident = CSS_VAL_DESTINATION_OUT; + break; + case CompositeDestinationAtop: + m_value.ident = CSS_VAL_DESTINATION_ATOP; + break; + case CompositeXOR: + m_value.ident = CSS_VAL_XOR; + break; + case CompositePlusDarker: + m_value.ident = CSS_VAL_PLUS_DARKER; + break; + case CompositeHighlight: + m_value.ident = CSS_VAL_HIGHLIGHT; + break; + case CompositePlusLighter: + m_value.ident = CSS_VAL_PLUS_LIGHTER; + break; + } +} + +template<> inline CSSPrimitiveValue::operator CompositeOperator() const +{ + switch (m_value.ident) { + case CSS_VAL_CLEAR: + return CompositeClear; + case CSS_VAL_COPY: + return CompositeCopy; + case CSS_VAL_SOURCE_OVER: + return CompositeSourceOver; + case CSS_VAL_SOURCE_IN: + return CompositeSourceIn; + case CSS_VAL_SOURCE_OUT: + return CompositeSourceOut; + case CSS_VAL_SOURCE_ATOP: + return CompositeSourceAtop; + case CSS_VAL_DESTINATION_OVER: + return CompositeDestinationOver; + case CSS_VAL_DESTINATION_IN: + return CompositeDestinationIn; + case CSS_VAL_DESTINATION_OUT: + return CompositeDestinationOut; + case CSS_VAL_DESTINATION_ATOP: + return CompositeDestinationAtop; + case CSS_VAL_XOR: + return CompositeXOR; + case CSS_VAL_PLUS_DARKER: + return CompositePlusDarker; + case CSS_VAL_HIGHLIGHT: + return CompositeHighlight; + case CSS_VAL_PLUS_LIGHTER: + return CompositePlusLighter; + default: + ASSERT_NOT_REACHED(); + return CompositeClear; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EAppearance e) + : m_type(CSS_IDENT) +{ + switch (e) { + case NoAppearance: + m_value.ident = CSS_VAL_NONE; + break; + case CheckboxAppearance: + m_value.ident = CSS_VAL_CHECKBOX; + break; + case RadioAppearance: + m_value.ident = CSS_VAL_RADIO; + break; + case PushButtonAppearance: + m_value.ident = CSS_VAL_PUSH_BUTTON; + break; + case SquareButtonAppearance: + m_value.ident = CSS_VAL_SQUARE_BUTTON; + break; + case ButtonAppearance: + m_value.ident = CSS_VAL_BUTTON; + break; + case ButtonBevelAppearance: + m_value.ident = CSS_VAL_BUTTON_BEVEL; + break; + case ListboxAppearance: + m_value.ident = CSS_VAL_LISTBOX; + break; + case ListItemAppearance: + m_value.ident = CSS_VAL_LISTITEM; + break; + case MediaFullscreenButtonAppearance: + m_value.ident = CSS_VAL_MEDIA_FULLSCREEN_BUTTON; + break; + case MediaPlayButtonAppearance: + m_value.ident = CSS_VAL_MEDIA_PLAY_BUTTON; + break; + case MediaMuteButtonAppearance: + m_value.ident = CSS_VAL_MEDIA_MUTE_BUTTON; + break; + case MediaSeekBackButtonAppearance: + m_value.ident = CSS_VAL_MEDIA_SEEK_BACK_BUTTON; + break; + case MediaSeekForwardButtonAppearance: + m_value.ident = CSS_VAL_MEDIA_SEEK_FORWARD_BUTTON; + break; + case MediaSliderAppearance: + m_value.ident = CSS_VAL_MEDIA_SLIDER; + break; + case MediaSliderThumbAppearance: + m_value.ident = CSS_VAL_MEDIA_SLIDERTHUMB; + break; + case MenulistAppearance: + m_value.ident = CSS_VAL_MENULIST; + break; + case MenulistButtonAppearance: + m_value.ident = CSS_VAL_MENULIST_BUTTON; + break; + case MenulistTextAppearance: + m_value.ident = CSS_VAL_MENULIST_TEXT; + break; + case MenulistTextFieldAppearance: + m_value.ident = CSS_VAL_MENULIST_TEXTFIELD; + break; + case ScrollbarButtonUpAppearance: + m_value.ident = CSS_VAL_SCROLLBARBUTTON_UP; + break; + case ScrollbarButtonDownAppearance: + m_value.ident = CSS_VAL_SCROLLBARBUTTON_DOWN; + break; + case ScrollbarButtonLeftAppearance: + m_value.ident = CSS_VAL_SCROLLBARBUTTON_LEFT; + break; + case ScrollbarButtonRightAppearance: + m_value.ident = CSS_VAL_SCROLLBARBUTTON_RIGHT; + break; + case ScrollbarTrackHorizontalAppearance: + m_value.ident = CSS_VAL_SCROLLBARTRACK_HORIZONTAL; + break; + case ScrollbarTrackVerticalAppearance: + m_value.ident = CSS_VAL_SCROLLBARTRACK_VERTICAL; + break; + case ScrollbarThumbHorizontalAppearance: + m_value.ident = CSS_VAL_SCROLLBARTHUMB_HORIZONTAL; + break; + case ScrollbarThumbVerticalAppearance: + m_value.ident = CSS_VAL_SCROLLBARTHUMB_VERTICAL; + break; + case ScrollbarGripperHorizontalAppearance: + m_value.ident = CSS_VAL_SCROLLBARGRIPPER_HORIZONTAL; + break; + case ScrollbarGripperVerticalAppearance: + m_value.ident = CSS_VAL_SCROLLBARGRIPPER_VERTICAL; + break; + case SliderHorizontalAppearance: + m_value.ident = CSS_VAL_SLIDER_HORIZONTAL; + break; + case SliderVerticalAppearance: + m_value.ident = CSS_VAL_SLIDER_VERTICAL; + break; + case SliderThumbHorizontalAppearance: + m_value.ident = CSS_VAL_SLIDERTHUMB_HORIZONTAL; + break; + case SliderThumbVerticalAppearance: + m_value.ident = CSS_VAL_SLIDERTHUMB_VERTICAL; + break; + case CaretAppearance: + m_value.ident = CSS_VAL_CARET; + break; + case SearchFieldAppearance: + m_value.ident = CSS_VAL_SEARCHFIELD; + break; + case SearchFieldDecorationAppearance: + m_value.ident = CSS_VAL_SEARCHFIELD_DECORATION; + break; + case SearchFieldResultsDecorationAppearance: + m_value.ident = CSS_VAL_SEARCHFIELD_RESULTS_DECORATION; + break; + case SearchFieldResultsButtonAppearance: + m_value.ident = CSS_VAL_SEARCHFIELD_RESULTS_BUTTON; + break; + case SearchFieldCancelButtonAppearance: + m_value.ident = CSS_VAL_SEARCHFIELD_CANCEL_BUTTON; + break; + case TextFieldAppearance: + m_value.ident = CSS_VAL_TEXTFIELD; + break; + case TextAreaAppearance: + m_value.ident = CSS_VAL_TEXTAREA; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EAppearance() const +{ + if (m_value.ident == CSS_VAL_NONE) + return NoAppearance; + else + return EAppearance(m_value.ident - CSS_VAL_CHECKBOX + 1); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBackgroundBox e) + : m_type(CSS_IDENT) +{ + switch (e) { + case BGBORDER: + m_value.ident = CSS_VAL_BORDER; + break; + case BGPADDING: + m_value.ident = CSS_VAL_PADDING; + break; + case BGCONTENT: + m_value.ident = CSS_VAL_CONTENT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBackgroundBox() const +{ + switch (m_value.ident) { + case CSS_VAL_BORDER: + return BGBORDER; + case CSS_VAL_PADDING: + return BGPADDING; + case CSS_VAL_CONTENT: + return BGCONTENT; + default: + ASSERT_NOT_REACHED(); + return BGBORDER; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBackgroundRepeat e) + : m_type(CSS_IDENT) +{ + switch (e) { + case REPEAT: + m_value.ident = CSS_VAL_REPEAT; + break; + case REPEAT_X: + m_value.ident = CSS_VAL_REPEAT_X; + break; + case REPEAT_Y: + m_value.ident = CSS_VAL_REPEAT_Y; + break; + case NO_REPEAT: + m_value.ident = CSS_VAL_NO_REPEAT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBackgroundRepeat() const +{ + switch (m_value.ident) { + case CSS_VAL_REPEAT: + return REPEAT; + case CSS_VAL_REPEAT_X: + return REPEAT_X; + case CSS_VAL_REPEAT_Y: + return REPEAT_Y; + case CSS_VAL_NO_REPEAT: + return NO_REPEAT; + default: + ASSERT_NOT_REACHED(); + return REPEAT; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxAlignment e) + : m_type(CSS_IDENT) +{ + switch (e) { + case BSTRETCH: + m_value.ident = CSS_VAL_STRETCH; + break; + case BSTART: + m_value.ident = CSS_VAL_START; + break; + case BCENTER: + m_value.ident = CSS_VAL_CENTER; + break; + case BEND: + m_value.ident = CSS_VAL_END; + break; + case BBASELINE: + m_value.ident = CSS_VAL_BASELINE; + break; + case BJUSTIFY: + m_value.ident = CSS_VAL_JUSTIFY; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBoxAlignment() const +{ + switch (m_value.ident) { + case CSS_VAL_STRETCH: + return BSTRETCH; + case CSS_VAL_START: + return BSTART; + case CSS_VAL_END: + return BEND; + case CSS_VAL_CENTER: + return BCENTER; + case CSS_VAL_BASELINE: + return BBASELINE; + case CSS_VAL_JUSTIFY: + return BJUSTIFY; + default: + ASSERT_NOT_REACHED(); + return BSTRETCH; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxDirection e) + : m_type(CSS_IDENT) +{ + switch (e) { + case BNORMAL: + m_value.ident = CSS_VAL_NORMAL; + break; + case BREVERSE: + m_value.ident = CSS_VAL_REVERSE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBoxDirection() const +{ + switch (m_value.ident) { + case CSS_VAL_NORMAL: + return BNORMAL; + case CSS_VAL_REVERSE: + return BREVERSE; + default: + ASSERT_NOT_REACHED(); + return BNORMAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxLines e) + : m_type(CSS_IDENT) +{ + switch (e) { + case SINGLE: + m_value.ident = CSS_VAL_SINGLE; + break; + case MULTIPLE: + m_value.ident = CSS_VAL_MULTIPLE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBoxLines() const +{ + switch (m_value.ident) { + case CSS_VAL_SINGLE: + return SINGLE; + case CSS_VAL_MULTIPLE: + return MULTIPLE; + default: + ASSERT_NOT_REACHED(); + return SINGLE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxOrient e) + : m_type(CSS_IDENT) +{ + switch (e) { + case HORIZONTAL: + m_value.ident = CSS_VAL_HORIZONTAL; + break; + case VERTICAL: + m_value.ident = CSS_VAL_VERTICAL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EBoxOrient() const +{ + switch (m_value.ident) { + case CSS_VAL_HORIZONTAL: + case CSS_VAL_INLINE_AXIS: + return HORIZONTAL; + case CSS_VAL_VERTICAL: + return VERTICAL; + default: + ASSERT_NOT_REACHED(); + return HORIZONTAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECaptionSide e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CAPLEFT: + m_value.ident = CSS_VAL_LEFT; + break; + case CAPRIGHT: + m_value.ident = CSS_VAL_RIGHT; + break; + case CAPTOP: + m_value.ident = CSS_VAL_TOP; + break; + case CAPBOTTOM: + m_value.ident = CSS_VAL_BOTTOM; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ECaptionSide() const +{ + switch (m_value.ident) { + case CSS_VAL_LEFT: + return CAPLEFT; + case CSS_VAL_RIGHT: + return CAPRIGHT; + case CSS_VAL_TOP: + return CAPTOP; + case CSS_VAL_BOTTOM: + return CAPBOTTOM; + default: + ASSERT_NOT_REACHED(); + return CAPTOP; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EClear e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CNONE: + m_value.ident = CSS_VAL_NONE; + break; + case CLEFT: + m_value.ident = CSS_VAL_LEFT; + break; + case CRIGHT: + m_value.ident = CSS_VAL_RIGHT; + break; + case CBOTH: + m_value.ident = CSS_VAL_BOTH; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EClear() const +{ + switch (m_value.ident) { + case CSS_VAL_NONE: + return CNONE; + case CSS_VAL_LEFT: + return CLEFT; + case CSS_VAL_RIGHT: + return CRIGHT; + case CSS_VAL_BOTH: + return CBOTH; + default: + ASSERT_NOT_REACHED(); + return CNONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECursor e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CURSOR_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case CURSOR_CROSS: + m_value.ident = CSS_VAL_CROSSHAIR; + break; + case CURSOR_DEFAULT: + m_value.ident = CSS_VAL_DEFAULT; + break; + case CURSOR_POINTER: + m_value.ident = CSS_VAL_POINTER; + break; + case CURSOR_MOVE: + m_value.ident = CSS_VAL_MOVE; + break; + case CURSOR_CELL: + m_value.ident = CSS_VAL_CELL; + break; + case CURSOR_VERTICAL_TEXT: + m_value.ident = CSS_VAL_VERTICAL_TEXT; + break; + case CURSOR_CONTEXT_MENU: + m_value.ident = CSS_VAL_CONTEXT_MENU; + break; + case CURSOR_ALIAS: + m_value.ident = CSS_VAL_ALIAS; + break; + case CURSOR_COPY: + m_value.ident = CSS_VAL_COPY; + break; + case CURSOR_NONE: + m_value.ident = CSS_VAL_NONE; + break; + case CURSOR_PROGRESS: + m_value.ident = CSS_VAL_PROGRESS; + break; + case CURSOR_NO_DROP: + m_value.ident = CSS_VAL_NO_DROP; + break; + case CURSOR_NOT_ALLOWED: + m_value.ident = CSS_VAL_NOT_ALLOWED; + break; + case CURSOR_WEBKIT_ZOOM_IN: + m_value.ident = CSS_VAL__WEBKIT_ZOOM_IN; + break; + case CURSOR_WEBKIT_ZOOM_OUT: + m_value.ident = CSS_VAL__WEBKIT_ZOOM_OUT; + break; + case CURSOR_E_RESIZE: + m_value.ident = CSS_VAL_E_RESIZE; + break; + case CURSOR_NE_RESIZE: + m_value.ident = CSS_VAL_NE_RESIZE; + break; + case CURSOR_NW_RESIZE: + m_value.ident = CSS_VAL_NW_RESIZE; + break; + case CURSOR_N_RESIZE: + m_value.ident = CSS_VAL_N_RESIZE; + break; + case CURSOR_SE_RESIZE: + m_value.ident = CSS_VAL_SE_RESIZE; + break; + case CURSOR_SW_RESIZE: + m_value.ident = CSS_VAL_SW_RESIZE; + break; + case CURSOR_S_RESIZE: + m_value.ident = CSS_VAL_S_RESIZE; + break; + case CURSOR_W_RESIZE: + m_value.ident = CSS_VAL_W_RESIZE; + break; + case CURSOR_EW_RESIZE: + m_value.ident = CSS_VAL_EW_RESIZE; + break; + case CURSOR_NS_RESIZE: + m_value.ident = CSS_VAL_NS_RESIZE; + break; + case CURSOR_NESW_RESIZE: + m_value.ident = CSS_VAL_NESW_RESIZE; + break; + case CURSOR_NWSE_RESIZE: + m_value.ident = CSS_VAL_NWSE_RESIZE; + break; + case CURSOR_COL_RESIZE: + m_value.ident = CSS_VAL_COL_RESIZE; + break; + case CURSOR_ROW_RESIZE: + m_value.ident = CSS_VAL_ROW_RESIZE; + break; + case CURSOR_TEXT: + m_value.ident = CSS_VAL_TEXT; + break; + case CURSOR_WAIT: + m_value.ident = CSS_VAL_WAIT; + break; + case CURSOR_HELP: + m_value.ident = CSS_VAL_HELP; + break; + case CURSOR_ALL_SCROLL: + m_value.ident = CSS_VAL_ALL_SCROLL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ECursor() const +{ + if (m_value.ident == CSS_VAL_COPY) + return CURSOR_COPY; + if (m_value.ident == CSS_VAL_NONE) + return CURSOR_NONE; + return static_cast<ECursor>(m_value.ident - CSS_VAL_AUTO); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EDisplay e) + : m_type(CSS_IDENT) +{ + switch (e) { + case INLINE: + m_value.ident = CSS_VAL_INLINE; + break; + case BLOCK: + m_value.ident = CSS_VAL_BLOCK; + break; + case LIST_ITEM: + m_value.ident = CSS_VAL_LIST_ITEM; + break; + case RUN_IN: + m_value.ident = CSS_VAL_RUN_IN; + break; + case COMPACT: + m_value.ident = CSS_VAL_COMPACT; + break; + case INLINE_BLOCK: + m_value.ident = CSS_VAL_INLINE_BLOCK; + break; + case TABLE: + m_value.ident = CSS_VAL_TABLE; + break; + case INLINE_TABLE: + m_value.ident = CSS_VAL_INLINE_TABLE; + break; + case TABLE_ROW_GROUP: + m_value.ident = CSS_VAL_TABLE_ROW_GROUP; + break; + case TABLE_HEADER_GROUP: + m_value.ident = CSS_VAL_TABLE_HEADER_GROUP; + break; + case TABLE_FOOTER_GROUP: + m_value.ident = CSS_VAL_TABLE_FOOTER_GROUP; + break; + case TABLE_ROW: + m_value.ident = CSS_VAL_TABLE_ROW; + break; + case TABLE_COLUMN_GROUP: + m_value.ident = CSS_VAL_TABLE_COLUMN_GROUP; + break; + case TABLE_COLUMN: + m_value.ident = CSS_VAL_TABLE_COLUMN; + break; + case TABLE_CELL: + m_value.ident = CSS_VAL_TABLE_CELL; + break; + case TABLE_CAPTION: + m_value.ident = CSS_VAL_TABLE_CAPTION; + break; + case BOX: + m_value.ident = CSS_VAL__WEBKIT_BOX; + break; + case INLINE_BOX: + m_value.ident = CSS_VAL__WEBKIT_INLINE_BOX; + break; + case NONE: + m_value.ident = CSS_VAL_NONE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EDisplay() const +{ + if (m_value.ident == CSS_VAL_NONE) + return NONE; + return static_cast<EDisplay>(m_value.ident - CSS_VAL_INLINE); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EEmptyCell e) + : m_type(CSS_IDENT) +{ + switch (e) { + case SHOW: + m_value.ident = CSS_VAL_SHOW; + break; + case HIDE: + m_value.ident = CSS_VAL_HIDE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EEmptyCell() const +{ + switch (m_value.ident) { + case CSS_VAL_SHOW: + return SHOW; + case CSS_VAL_HIDE: + return HIDE; + default: + ASSERT_NOT_REACHED(); + return SHOW; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFloat e) + : m_type(CSS_IDENT) +{ + switch (e) { + case FNONE: + m_value.ident = CSS_VAL_NONE; + break; + case FLEFT: + m_value.ident = CSS_VAL_LEFT; + break; + case FRIGHT: + m_value.ident = CSS_VAL_RIGHT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EFloat() const +{ + switch (m_value.ident) { + case CSS_VAL_LEFT: + return FLEFT; + case CSS_VAL_RIGHT: + return FRIGHT; + case CSS_VAL_NONE: + case CSS_VAL_CENTER: // Non-standard CSS value + return FNONE; + default: + ASSERT_NOT_REACHED(); + return FNONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EKHTMLLineBreak e) + : m_type(CSS_IDENT) +{ + switch (e) { + case LBNORMAL: + m_value.ident = CSS_VAL_NORMAL; + break; + case AFTER_WHITE_SPACE: + m_value.ident = CSS_VAL_AFTER_WHITE_SPACE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EKHTMLLineBreak() const +{ + switch (m_value.ident) { + case CSS_VAL_AFTER_WHITE_SPACE: + return AFTER_WHITE_SPACE; + case CSS_VAL_NORMAL: + return LBNORMAL; + default: + ASSERT_NOT_REACHED(); + return LBNORMAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EListStylePosition e) + : m_type(CSS_IDENT) +{ + switch (e) { + case OUTSIDE: + m_value.ident = CSS_VAL_OUTSIDE; + break; + case INSIDE: + m_value.ident = CSS_VAL_INSIDE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EListStylePosition() const +{ + return (EListStylePosition)(m_value.ident - CSS_VAL_OUTSIDE); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EListStyleType e) + : m_type(CSS_IDENT) +{ + switch (e) { + case LNONE: + m_value.ident = CSS_VAL_NONE; + break; + case DISC: + m_value.ident = CSS_VAL_DISC; + break; + case CIRCLE: + m_value.ident = CSS_VAL_CIRCLE; + break; + case SQUARE: + m_value.ident = CSS_VAL_SQUARE; + break; + case LDECIMAL: + m_value.ident = CSS_VAL_DECIMAL; + break; + case DECIMAL_LEADING_ZERO: + m_value.ident = CSS_VAL_DECIMAL_LEADING_ZERO; + break; + case LOWER_ROMAN: + m_value.ident = CSS_VAL_LOWER_ROMAN; + break; + case UPPER_ROMAN: + m_value.ident = CSS_VAL_UPPER_ROMAN; + break; + case LOWER_GREEK: + m_value.ident = CSS_VAL_LOWER_GREEK; + break; + case LOWER_ALPHA: + m_value.ident = CSS_VAL_LOWER_ALPHA; + break; + case LOWER_LATIN: + m_value.ident = CSS_VAL_LOWER_LATIN; + break; + case UPPER_ALPHA: + m_value.ident = CSS_VAL_UPPER_ALPHA; + break; + case UPPER_LATIN: + m_value.ident = CSS_VAL_UPPER_LATIN; + break; + case HEBREW: + m_value.ident = CSS_VAL_HEBREW; + break; + case ARMENIAN: + m_value.ident = CSS_VAL_ARMENIAN; + break; + case GEORGIAN: + m_value.ident = CSS_VAL_GEORGIAN; + break; + case CJK_IDEOGRAPHIC: + m_value.ident = CSS_VAL_CJK_IDEOGRAPHIC; + break; + case HIRAGANA: + m_value.ident = CSS_VAL_HIRAGANA; + break; + case KATAKANA: + m_value.ident = CSS_VAL_KATAKANA; + break; + case HIRAGANA_IROHA: + m_value.ident = CSS_VAL_HIRAGANA_IROHA; + break; + case KATAKANA_IROHA: + m_value.ident = CSS_VAL_KATAKANA_IROHA; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EListStyleType() const +{ + switch (m_value.ident) { + case CSS_VAL_NONE: + return LNONE; + default: + return static_cast<EListStyleType>(m_value.ident - CSS_VAL_DISC); + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarginCollapse e) + : m_type(CSS_IDENT) +{ + switch (e) { + case MCOLLAPSE: + m_value.ident = CSS_VAL_COLLAPSE; + break; + case MSEPARATE: + m_value.ident = CSS_VAL_SEPARATE; + break; + case MDISCARD: + m_value.ident = CSS_VAL_DISCARD; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EMarginCollapse() const +{ + switch (m_value.ident) { + case CSS_VAL_COLLAPSE: + return MCOLLAPSE; + case CSS_VAL_SEPARATE: + return MSEPARATE; + case CSS_VAL_DISCARD: + return MDISCARD; + default: + ASSERT_NOT_REACHED(); + return MCOLLAPSE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarqueeBehavior e) + : m_type(CSS_IDENT) +{ + switch (e) { + case MNONE: + m_value.ident = CSS_VAL_NONE; + break; + case MSCROLL: + m_value.ident = CSS_VAL_SCROLL; + break; + case MSLIDE: + m_value.ident = CSS_VAL_SLIDE; + break; + case MALTERNATE: + m_value.ident = CSS_VAL_ALTERNATE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EMarqueeBehavior() const +{ + switch (m_value.ident) { + case CSS_VAL_NONE: + return MNONE; + case CSS_VAL_SCROLL: + return MSCROLL; + case CSS_VAL_SLIDE: + return MSLIDE; + case CSS_VAL_ALTERNATE: + return MALTERNATE; + default: + ASSERT_NOT_REACHED(); + return MNONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarqueeDirection e) + : m_type(CSS_IDENT) +{ + switch (e) { + case MFORWARD: + m_value.ident = CSS_VAL_FORWARDS; + break; + case MBACKWARD: + m_value.ident = CSS_VAL_BACKWARDS; + break; + case MAUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case MUP: + m_value.ident = CSS_VAL_UP; + break; + case MDOWN: + m_value.ident = CSS_VAL_DOWN; + break; + case MLEFT: + m_value.ident = CSS_VAL_LEFT; + break; + case MRIGHT: + m_value.ident = CSS_VAL_RIGHT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EMarqueeDirection() const +{ + switch (m_value.ident) { + case CSS_VAL_FORWARDS: + return MFORWARD; + case CSS_VAL_BACKWARDS: + return MBACKWARD; + case CSS_VAL_AUTO: + return MAUTO; + case CSS_VAL_AHEAD: + case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP. + return MUP; + case CSS_VAL_REVERSE: + case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text. + return MDOWN; + case CSS_VAL_LEFT: + return MLEFT; + case CSS_VAL_RIGHT: + return MRIGHT; + default: + ASSERT_NOT_REACHED(); + return MAUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMatchNearestMailBlockquoteColor e) + : m_type(CSS_IDENT) +{ + switch (e) { + case BCNORMAL: + m_value.ident = CSS_VAL_NORMAL; + break; + case MATCH: + m_value.ident = CSS_VAL_MATCH; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EMatchNearestMailBlockquoteColor() const +{ + switch (m_value.ident) { + case CSS_VAL_NORMAL: + return BCNORMAL; + case CSS_VAL_MATCH: + return MATCH; + default: + ASSERT_NOT_REACHED(); + return BCNORMAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ENBSPMode e) + : m_type(CSS_IDENT) +{ + switch (e) { + case NBNORMAL: + m_value.ident = CSS_VAL_NORMAL; + break; + case SPACE: + m_value.ident = CSS_VAL_SPACE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ENBSPMode() const +{ + switch (m_value.ident) { + case CSS_VAL_SPACE: + return SPACE; + case CSS_VAL_NORMAL: + return NBNORMAL; + default: + ASSERT_NOT_REACHED(); + return NBNORMAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EOverflow e) + : m_type(CSS_IDENT) +{ + switch (e) { + case OVISIBLE: + m_value.ident = CSS_VAL_VISIBLE; + break; + case OHIDDEN: + m_value.ident = CSS_VAL_HIDDEN; + break; + case OSCROLL: + m_value.ident = CSS_VAL_SCROLL; + break; + case OAUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case OMARQUEE: + m_value.ident = CSS_VAL__WEBKIT_MARQUEE; + break; + case OOVERLAY: + m_value.ident = CSS_VAL_OVERLAY; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EOverflow() const +{ + switch (m_value.ident) { + case CSS_VAL_VISIBLE: + return OVISIBLE; + case CSS_VAL_HIDDEN: + return OHIDDEN; + case CSS_VAL_SCROLL: + return OSCROLL; + case CSS_VAL_AUTO: + return OAUTO; + case CSS_VAL__WEBKIT_MARQUEE: + return OMARQUEE; + case CSS_VAL_OVERLAY: + return OOVERLAY; + default: + ASSERT_NOT_REACHED(); + return OVISIBLE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPageBreak e) + : m_type(CSS_IDENT) +{ + switch (e) { + case PBAUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case PBALWAYS: + m_value.ident = CSS_VAL_ALWAYS; + break; + case PBAVOID: + m_value.ident = CSS_VAL_AVOID; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EPageBreak() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return PBAUTO; + case CSS_VAL_LEFT: + case CSS_VAL_RIGHT: + case CSS_VAL_ALWAYS: + return PBALWAYS; // CSS2.1: "Conforming user agents may map left/right to always." + case CSS_VAL_AVOID: + return PBAVOID; + default: + ASSERT_NOT_REACHED(); + return PBAUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPosition e) + : m_type(CSS_IDENT) +{ + switch (e) { + case StaticPosition: + m_value.ident = CSS_VAL_STATIC; + break; + case RelativePosition: + m_value.ident = CSS_VAL_RELATIVE; + break; + case AbsolutePosition: + m_value.ident = CSS_VAL_ABSOLUTE; + break; + case FixedPosition: + m_value.ident = CSS_VAL_FIXED; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EPosition() const +{ + switch (m_value.ident) { + case CSS_VAL_STATIC: + return StaticPosition; + case CSS_VAL_RELATIVE: + return RelativePosition; + case CSS_VAL_ABSOLUTE: + return AbsolutePosition; + case CSS_VAL_FIXED: + return FixedPosition; + default: + ASSERT_NOT_REACHED(); + return StaticPosition; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EResize e) + : m_type(CSS_IDENT) +{ + switch (e) { + case RESIZE_BOTH: + m_value.ident = CSS_VAL_BOTH; + break; + case RESIZE_HORIZONTAL: + m_value.ident = CSS_VAL_HORIZONTAL; + break; + case RESIZE_VERTICAL: + m_value.ident = CSS_VAL_VERTICAL; + break; + case RESIZE_NONE: + m_value.ident = CSS_VAL_NONE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EResize() const +{ + switch (m_value.ident) { + case CSS_VAL_BOTH: + return RESIZE_BOTH; + case CSS_VAL_HORIZONTAL: + return RESIZE_HORIZONTAL; + case CSS_VAL_VERTICAL: + return RESIZE_VERTICAL; + case CSS_VAL_AUTO: + ASSERT_NOT_REACHED(); // Depends on settings, thus should be handled by the caller. + return RESIZE_NONE; + case CSS_VAL_NONE: + return RESIZE_NONE; + default: + ASSERT_NOT_REACHED(); + return RESIZE_NONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETableLayout e) + : m_type(CSS_IDENT) +{ + switch (e) { + case TAUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case TFIXED: + m_value.ident = CSS_VAL_FIXED; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETableLayout() const +{ + switch (m_value.ident) { + case CSS_VAL_FIXED: + return TFIXED; + case CSS_VAL_AUTO: + return TAUTO; + default: + ASSERT_NOT_REACHED(); + return TAUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextAlign e) + : m_type(CSS_IDENT) +{ + switch (e) { + case TAAUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case LEFT: + m_value.ident = CSS_VAL_LEFT; + break; + case RIGHT: + m_value.ident = CSS_VAL_RIGHT; + break; + case CENTER: + m_value.ident = CSS_VAL_CENTER; + break; + case JUSTIFY: + m_value.ident = CSS_VAL_JUSTIFY; + break; + case WEBKIT_LEFT: + m_value.ident = CSS_VAL__WEBKIT_LEFT; + break; + case WEBKIT_RIGHT: + m_value.ident = CSS_VAL__WEBKIT_RIGHT; + break; + case WEBKIT_CENTER: + m_value.ident = CSS_VAL__WEBKIT_CENTER; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETextAlign() const +{ + switch (m_value.ident) { + case CSS_VAL_START: + case CSS_VAL_END: + ASSERT_NOT_REACHED(); // Depends on direction, thus should be handled by the caller. + return LEFT; + default: + return static_cast<ETextAlign>(m_value.ident - CSS_VAL__WEBKIT_AUTO); + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextSecurity e) + : m_type(CSS_IDENT) +{ + switch (e) { + case TSNONE: + m_value.ident = CSS_VAL_NONE; + break; + case TSDISC: + m_value.ident = CSS_VAL_DISC; + break; + case TSCIRCLE: + m_value.ident = CSS_VAL_CIRCLE; + break; + case TSSQUARE: + m_value.ident = CSS_VAL_SQUARE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETextSecurity() const +{ + switch (m_value.ident) { + case CSS_VAL_NONE: + return TSNONE; + case CSS_VAL_DISC: + return TSDISC; + case CSS_VAL_CIRCLE: + return TSCIRCLE; + case CSS_VAL_SQUARE: + return TSSQUARE; + default: + ASSERT_NOT_REACHED(); + return TSNONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextTransform e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CAPITALIZE: + m_value.ident = CSS_VAL_CAPITALIZE; + break; + case UPPERCASE: + m_value.ident = CSS_VAL_UPPERCASE; + break; + case LOWERCASE: + m_value.ident = CSS_VAL_LOWERCASE; + break; + case TTNONE: + m_value.ident = CSS_VAL_NONE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETextTransform() const +{ + switch (m_value.ident) { + case CSS_VAL_CAPITALIZE: + return CAPITALIZE; + case CSS_VAL_UPPERCASE: + return UPPERCASE; + case CSS_VAL_LOWERCASE: + return LOWERCASE; + case CSS_VAL_NONE: + return TTNONE; + default: + ASSERT_NOT_REACHED(); + return TTNONE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUnicodeBidi e) + : m_type(CSS_IDENT) +{ + switch (e) { + case UBNormal: + m_value.ident = CSS_VAL_NORMAL; + break; + case Embed: + m_value.ident = CSS_VAL_EMBED; + break; + case Override: + m_value.ident = CSS_VAL_BIDI_OVERRIDE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EUnicodeBidi() const +{ + switch (m_value.ident) { + case CSS_VAL_NORMAL: + return UBNormal; + case CSS_VAL_EMBED: + return Embed; + case CSS_VAL_BIDI_OVERRIDE: + return Override; + default: + ASSERT_NOT_REACHED(); + return UBNormal; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserDrag e) + : m_type(CSS_IDENT) +{ + switch (e) { + case DRAG_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case DRAG_NONE: + m_value.ident = CSS_VAL_NONE; + break; + case DRAG_ELEMENT: + m_value.ident = CSS_VAL_ELEMENT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EUserDrag() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return DRAG_AUTO; + case CSS_VAL_NONE: + return DRAG_NONE; + case CSS_VAL_ELEMENT: + return DRAG_ELEMENT; + default: + ASSERT_NOT_REACHED(); + return DRAG_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserModify e) + : m_type(CSS_IDENT) +{ + switch (e) { + case READ_ONLY: + m_value.ident = CSS_VAL_READ_ONLY; + break; + case READ_WRITE: + m_value.ident = CSS_VAL_READ_WRITE; + break; + case READ_WRITE_PLAINTEXT_ONLY: + m_value.ident = CSS_VAL_READ_WRITE_PLAINTEXT_ONLY; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EUserModify() const +{ + return static_cast<EUserModify>(m_value.ident - CSS_VAL_READ_ONLY); +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserSelect e) + : m_type(CSS_IDENT) +{ + switch (e) { + case SELECT_NONE: + m_value.ident = CSS_VAL_NONE; + break; + case SELECT_TEXT: + m_value.ident = CSS_VAL_TEXT; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EUserSelect() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return SELECT_TEXT; + case CSS_VAL_NONE: + return SELECT_NONE; + case CSS_VAL_TEXT: + return SELECT_TEXT; + default: + ASSERT_NOT_REACHED(); + return SELECT_TEXT; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EVisibility e) + : m_type(CSS_IDENT) +{ + switch (e) { + case VISIBLE: + m_value.ident = CSS_VAL_VISIBLE; + break; + case HIDDEN: + m_value.ident = CSS_VAL_HIDDEN; + break; + case COLLAPSE: + m_value.ident = CSS_VAL_COLLAPSE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EVisibility() const +{ + switch (m_value.ident) { + case CSS_VAL_HIDDEN: + return HIDDEN; + case CSS_VAL_VISIBLE: + return VISIBLE; + case CSS_VAL_COLLAPSE: + return COLLAPSE; + default: + ASSERT_NOT_REACHED(); + return VISIBLE; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWhiteSpace e) + : m_type(CSS_IDENT) +{ + switch (e) { + case NORMAL: + m_value.ident = CSS_VAL_NORMAL; + break; + case PRE: + m_value.ident = CSS_VAL_PRE; + break; + case PRE_WRAP: + m_value.ident = CSS_VAL_PRE_WRAP; + break; + case PRE_LINE: + m_value.ident = CSS_VAL_PRE_LINE; + break; + case NOWRAP: + m_value.ident = CSS_VAL_NOWRAP; + break; + case KHTML_NOWRAP: + m_value.ident = CSS_VAL__WEBKIT_NOWRAP; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EWhiteSpace() const +{ + switch (m_value.ident) { + case CSS_VAL__WEBKIT_NOWRAP: + return KHTML_NOWRAP; + case CSS_VAL_NOWRAP: + return NOWRAP; + case CSS_VAL_PRE: + return PRE; + case CSS_VAL_PRE_WRAP: + return PRE_WRAP; + case CSS_VAL_PRE_LINE: + return PRE_LINE; + case CSS_VAL_NORMAL: + return NORMAL; + default: + ASSERT_NOT_REACHED(); + return NORMAL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWordBreak e) + : m_type(CSS_IDENT) +{ + switch (e) { + case NormalWordBreak: + m_value.ident = CSS_VAL_NORMAL; + break; + case BreakAllWordBreak: + m_value.ident = CSS_VAL_BREAK_ALL; + break; + case BreakWordBreak: + m_value.ident = CSS_VAL_BREAK_WORD; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EWordBreak() const +{ + switch (m_value.ident) { + case CSS_VAL_BREAK_ALL: + return BreakAllWordBreak; + case CSS_VAL_BREAK_WORD: + return BreakWordBreak; + case CSS_VAL_NORMAL: + return NormalWordBreak; + default: + ASSERT_NOT_REACHED(); + return NormalWordBreak; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWordWrap e) + : m_type(CSS_IDENT) +{ + switch (e) { + case NormalWordWrap: + m_value.ident = CSS_VAL_NORMAL; + break; + case BreakWordWrap: + m_value.ident = CSS_VAL_BREAK_WORD; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EWordWrap() const +{ + switch (m_value.ident) { + case CSS_VAL_BREAK_WORD: + return BreakWordWrap; + case CSS_VAL_NORMAL: + return NormalWordWrap; + default: + ASSERT_NOT_REACHED(); + return NormalWordWrap; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextDirection e) + : m_type(CSS_IDENT) +{ + switch (e) { + case LTR: + m_value.ident = CSS_VAL_LTR; + break; + case RTL: + m_value.ident = CSS_VAL_RTL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator TextDirection() const +{ + switch (m_value.ident) { + case CSS_VAL_LTR: + return LTR; + case CSS_VAL_RTL: + return RTL; + default: + ASSERT_NOT_REACHED(); + return LTR; + } +} + +#if ENABLE(SVG) + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineCap e) + : m_type(CSS_IDENT) +{ + switch (e) { + case ButtCap: + m_value.ident = CSS_VAL_BUTT; + break; + case RoundCap: + m_value.ident = CSS_VAL_ROUND; + break; + case SquareCap: + m_value.ident = CSS_VAL_SQUARE; + break; + } +} + +template<> inline CSSPrimitiveValue::operator LineCap() const +{ + switch (m_value.ident) { + case CSS_VAL_BUTT: + return ButtCap; + case CSS_VAL_ROUND: + return RoundCap; + case CSS_VAL_SQUARE: + return SquareCap; + default: + ASSERT_NOT_REACHED(); + return ButtCap; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineJoin e) + : m_type(CSS_IDENT) +{ + switch (e) { + case MiterJoin: + m_value.ident = CSS_VAL_MITER; + break; + case RoundJoin: + m_value.ident = CSS_VAL_ROUND; + break; + case BevelJoin: + m_value.ident = CSS_VAL_BEVEL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator LineJoin() const +{ + switch (m_value.ident) { + case CSS_VAL_MITER: + return MiterJoin; + case CSS_VAL_ROUND: + return RoundJoin; + case CSS_VAL_BEVEL: + return BevelJoin; + default: + ASSERT_NOT_REACHED(); + return MiterJoin; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WindRule e) + : m_type(CSS_IDENT) +{ + switch (e) { + case RULE_NONZERO: + m_value.ident = CSS_VAL_NONZERO; + break; + case RULE_EVENODD: + m_value.ident = CSS_VAL_EVENODD; + break; + } +} + +template<> inline CSSPrimitiveValue::operator WindRule() const +{ + switch (m_value.ident) { + case CSS_VAL_NONZERO: + return RULE_NONZERO; + case CSS_VAL_EVENODD: + return RULE_EVENODD; + default: + ASSERT_NOT_REACHED(); + return RULE_NONZERO; + } +} + + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EAlignmentBaseline e) + : m_type(CSS_IDENT) +{ + switch (e) { + case AB_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case AB_BASELINE: + m_value.ident = CSS_VAL_BASELINE; + break; + case AB_BEFORE_EDGE: + m_value.ident = CSS_VAL_BEFORE_EDGE; + break; + case AB_TEXT_BEFORE_EDGE: + m_value.ident = CSS_VAL_TEXT_BEFORE_EDGE; + break; + case AB_MIDDLE: + m_value.ident = CSS_VAL_MIDDLE; + break; + case AB_CENTRAL: + m_value.ident = CSS_VAL_CENTRAL; + break; + case AB_AFTER_EDGE: + m_value.ident = CSS_VAL_AFTER_EDGE; + break; + case AB_TEXT_AFTER_EDGE: + m_value.ident = CSS_VAL_TEXT_AFTER_EDGE; + break; + case AB_IDEOGRAPHIC: + m_value.ident = CSS_VAL_IDEOGRAPHIC; + break; + case AB_ALPHABETIC: + m_value.ident = CSS_VAL_ALPHABETIC; + break; + case AB_HANGING: + m_value.ident = CSS_VAL_HANGING; + break; + case AB_MATHEMATICAL: + m_value.ident = CSS_VAL_MATHEMATICAL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EAlignmentBaseline() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return AB_AUTO; + case CSS_VAL_BASELINE: + return AB_BASELINE; + case CSS_VAL_BEFORE_EDGE: + return AB_BEFORE_EDGE; + case CSS_VAL_TEXT_BEFORE_EDGE: + return AB_TEXT_BEFORE_EDGE; + case CSS_VAL_MIDDLE: + return AB_MIDDLE; + case CSS_VAL_CENTRAL: + return AB_CENTRAL; + case CSS_VAL_AFTER_EDGE: + return AB_AFTER_EDGE; + case CSS_VAL_TEXT_AFTER_EDGE: + return AB_TEXT_AFTER_EDGE; + case CSS_VAL_IDEOGRAPHIC: + return AB_IDEOGRAPHIC; + case CSS_VAL_ALPHABETIC: + return AB_ALPHABETIC; + case CSS_VAL_HANGING: + return AB_HANGING; + case CSS_VAL_MATHEMATICAL: + return AB_MATHEMATICAL; + default: + ASSERT_NOT_REACHED(); + return AB_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EColorInterpolation e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CI_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case CI_SRGB: + m_value.ident = CSS_VAL_SRGB; + break; + case CI_LINEARRGB: + m_value.ident = CSS_VAL_LINEARRGB; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EColorInterpolation() const +{ + switch (m_value.ident) { + case CSS_VAL_SRGB: + return CI_SRGB; + case CSS_VAL_LINEARRGB: + return CI_LINEARRGB; + case CSS_VAL_AUTO: + return CI_AUTO; + default: + ASSERT_NOT_REACHED(); + return CI_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EColorRendering e) + : m_type(CSS_IDENT) +{ + switch (e) { + case CR_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case CR_OPTIMIZESPEED: + m_value.ident = CSS_VAL_OPTIMIZESPEED; + break; + case CR_OPTIMIZEQUALITY: + m_value.ident = CSS_VAL_OPTIMIZEQUALITY; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EColorRendering() const +{ + switch (m_value.ident) { + case CSS_VAL_OPTIMIZESPEED: + return CR_OPTIMIZESPEED; + case CSS_VAL_OPTIMIZEQUALITY: + return CR_OPTIMIZEQUALITY; + case CSS_VAL_AUTO: + return CR_AUTO; + default: + ASSERT_NOT_REACHED(); + return CR_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EDominantBaseline e) + : m_type(CSS_IDENT) +{ + switch (e) { + case DB_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case DB_USE_SCRIPT: + m_value.ident = CSS_VAL_USE_SCRIPT; + break; + case DB_NO_CHANGE: + m_value.ident = CSS_VAL_NO_CHANGE; + break; + case DB_RESET_SIZE: + m_value.ident = CSS_VAL_RESET_SIZE; + break; + case DB_CENTRAL: + m_value.ident = CSS_VAL_CENTRAL; + break; + case DB_MIDDLE: + m_value.ident = CSS_VAL_MIDDLE; + break; + case DB_TEXT_BEFORE_EDGE: + m_value.ident = CSS_VAL_TEXT_BEFORE_EDGE; + break; + case DB_TEXT_AFTER_EDGE: + m_value.ident = CSS_VAL_TEXT_AFTER_EDGE; + break; + case DB_IDEOGRAPHIC: + m_value.ident = CSS_VAL_IDEOGRAPHIC; + break; + case DB_ALPHABETIC: + m_value.ident = CSS_VAL_ALPHABETIC; + break; + case DB_HANGING: + m_value.ident = CSS_VAL_HANGING; + break; + case DB_MATHEMATICAL: + m_value.ident = CSS_VAL_MATHEMATICAL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EDominantBaseline() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return DB_AUTO; + case CSS_VAL_USE_SCRIPT: + return DB_USE_SCRIPT; + case CSS_VAL_NO_CHANGE: + return DB_NO_CHANGE; + case CSS_VAL_RESET_SIZE: + return DB_RESET_SIZE; + case CSS_VAL_IDEOGRAPHIC: + return DB_IDEOGRAPHIC; + case CSS_VAL_ALPHABETIC: + return DB_ALPHABETIC; + case CSS_VAL_HANGING: + return DB_HANGING; + case CSS_VAL_MATHEMATICAL: + return DB_MATHEMATICAL; + case CSS_VAL_CENTRAL: + return DB_CENTRAL; + case CSS_VAL_MIDDLE: + return DB_MIDDLE; + case CSS_VAL_TEXT_AFTER_EDGE: + return DB_TEXT_AFTER_EDGE; + case CSS_VAL_TEXT_BEFORE_EDGE: + return DB_TEXT_BEFORE_EDGE; + default: + ASSERT_NOT_REACHED(); + return DB_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EImageRendering e) + : m_type(CSS_IDENT) +{ + switch (e) { + case IR_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case IR_OPTIMIZESPEED: + m_value.ident = CSS_VAL_OPTIMIZESPEED; + break; + case IR_OPTIMIZEQUALITY: + m_value.ident = CSS_VAL_OPTIMIZEQUALITY; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EImageRendering() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return IR_AUTO; + case CSS_VAL_OPTIMIZESPEED: + return IR_OPTIMIZESPEED; + case CSS_VAL_OPTIMIZEQUALITY: + return IR_OPTIMIZEQUALITY; + default: + ASSERT_NOT_REACHED(); + return IR_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPointerEvents e) + : m_type(CSS_IDENT) +{ + switch (e) { + case PE_NONE: + m_value.ident = CSS_VAL_NONE; + break; + case PE_STROKE: + m_value.ident = CSS_VAL_STROKE; + break; + case PE_FILL: + m_value.ident = CSS_VAL_FILL; + break; + case PE_PAINTED: + m_value.ident = CSS_VAL_PAINTED; + break; + case PE_VISIBLE: + m_value.ident = CSS_VAL_VISIBLE; + break; + case PE_VISIBLE_STROKE: + m_value.ident = CSS_VAL_VISIBLESTROKE; + break; + case PE_VISIBLE_FILL: + m_value.ident = CSS_VAL_VISIBLEFILL; + break; + case PE_VISIBLE_PAINTED: + m_value.ident = CSS_VAL_VISIBLEPAINTED; + break; + case PE_ALL: + m_value.ident = CSS_VAL_ALL; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EPointerEvents() const +{ + switch (m_value.ident) { + case CSS_VAL_ALL: + return PE_ALL; + case CSS_VAL_NONE: + return PE_NONE; + case CSS_VAL_VISIBLEPAINTED: + return PE_VISIBLE_PAINTED; + case CSS_VAL_VISIBLEFILL: + return PE_VISIBLE_FILL; + case CSS_VAL_VISIBLESTROKE: + return PE_VISIBLE_STROKE; + case CSS_VAL_VISIBLE: + return PE_VISIBLE; + case CSS_VAL_PAINTED: + return PE_PAINTED; + case CSS_VAL_FILL: + return PE_FILL; + case CSS_VAL_STROKE: + return PE_STROKE; + default: + ASSERT_NOT_REACHED(); + return PE_ALL; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EShapeRendering e) + : m_type(CSS_IDENT) +{ + switch (e) { + case IR_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case IR_OPTIMIZESPEED: + m_value.ident = CSS_VAL_OPTIMIZESPEED; + break; + case SR_CRISPEDGES: + m_value.ident = CSS_VAL_CRISPEDGES; + break; + case SR_GEOMETRICPRECISION: + m_value.ident = CSS_VAL_GEOMETRICPRECISION; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EShapeRendering() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return SR_AUTO; + case CSS_VAL_OPTIMIZESPEED: + return SR_OPTIMIZESPEED; + case CSS_VAL_CRISPEDGES: + return SR_CRISPEDGES; + case CSS_VAL_GEOMETRICPRECISION: + return SR_GEOMETRICPRECISION; + default: + ASSERT_NOT_REACHED(); + return SR_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextAnchor e) + : m_type(CSS_IDENT) +{ + switch (e) { + case TA_START: + m_value.ident = CSS_VAL_START; + break; + case TA_MIDDLE: + m_value.ident = CSS_VAL_MIDDLE; + break; + case TA_END: + m_value.ident = CSS_VAL_END; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETextAnchor() const +{ + switch (m_value.ident) { + case CSS_VAL_START: + return TA_START; + case CSS_VAL_MIDDLE: + return TA_MIDDLE; + case CSS_VAL_END: + return TA_END; + default: + ASSERT_NOT_REACHED(); + return TA_START; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextRendering e) + : m_type(CSS_IDENT) +{ + switch (e) { + case TR_AUTO: + m_value.ident = CSS_VAL_AUTO; + break; + case TR_OPTIMIZESPEED: + m_value.ident = CSS_VAL_OPTIMIZESPEED; + break; + case TR_OPTIMIZELEGIBILITY: + m_value.ident = CSS_VAL_OPTIMIZELEGIBILITY; + break; + case TR_GEOMETRICPRECISION: + m_value.ident = CSS_VAL_GEOMETRICPRECISION; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ETextRendering() const +{ + switch (m_value.ident) { + case CSS_VAL_AUTO: + return TR_AUTO; + case CSS_VAL_OPTIMIZESPEED: + return TR_OPTIMIZESPEED; + case CSS_VAL_OPTIMIZELEGIBILITY: + return TR_OPTIMIZELEGIBILITY; + case CSS_VAL_GEOMETRICPRECISION: + return TR_GEOMETRICPRECISION; + default: + ASSERT_NOT_REACHED(); + return TR_AUTO; + } +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWritingMode e) + : m_type(CSS_IDENT) +{ + switch (e) { + case WM_LRTB: + m_value.ident = CSS_VAL_LR_TB; + break; + case WM_LR: + m_value.ident = CSS_VAL_LR; + break; + case WM_RLTB: + m_value.ident = CSS_VAL_RL_TB; + break; + case WM_RL: + m_value.ident = CSS_VAL_RL; + break; + case WM_TBRL: + m_value.ident = CSS_VAL_TB_RL; + break; + case WM_TB: + m_value.ident = CSS_VAL_TB; + break; + } +} + +template<> inline CSSPrimitiveValue::operator EWritingMode() const +{ + return static_cast<EWritingMode>(m_value.ident - CSS_VAL_LR_TB); +} + +#endif + +} + +#endif diff --git a/WebCore/css/CSSProperty.cpp b/WebCore/css/CSSProperty.cpp new file mode 100644 index 0000000..d25ddf6 --- /dev/null +++ b/WebCore/css/CSSProperty.cpp @@ -0,0 +1,41 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSProperty.h" + +#include "CSSPropertyNames.h" +#include "PlatformString.h" + +namespace WebCore { + +String CSSProperty::cssText() const +{ + return String(getPropertyName(static_cast<CSSPropertyID>(id()))) + ": " + m_value->cssText() + (isImportant() ? " !important" : "") + "; "; +} + +bool operator==(const CSSProperty& a, const CSSProperty& b) +{ + return a.m_id == b.m_id && a.m_important == b.m_important && a.m_value == b.m_value; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSProperty.h b/WebCore/css/CSSProperty.h new file mode 100644 index 0000000..0b06da3 --- /dev/null +++ b/WebCore/css/CSSProperty.h @@ -0,0 +1,75 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSProperty_h +#define CSSProperty_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSProperty { +public: + CSSProperty(int propID, PassRefPtr<CSSValue> value, bool important = false, int shorthandID = 0, bool implicit = false) + : m_id(propID) + , m_shorthandID(shorthandID) + , m_important(important) + , m_implicit(implicit) + , m_value(value) + { + } + + CSSProperty& operator=(const CSSProperty& other) + { + m_id = other.m_id; + m_shorthandID = other.m_shorthandID; + m_important = other.m_important; + m_value = other.m_value; + return *this; + } + + int id() const { return m_id; } + int shorthandID() const { return m_shorthandID; } + + bool isImportant() const { return m_important; } + bool isImplicit() const { return m_implicit; } + + CSSValue* value() const { return m_value.get(); } + + String cssText() const; + + friend bool operator==(const CSSProperty&, const CSSProperty&); + + // make sure the following fits in 4 bytes. + int m_id; + int m_shorthandID; // If this property was set as part of a shorthand, gives the shorthand. + bool m_important : 1; + bool m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand. + + RefPtr<CSSValue> m_value; +}; + +} // namespace WebCore + +#endif // CSSProperty_h diff --git a/WebCore/css/CSSPropertyNames.in b/WebCore/css/CSSPropertyNames.in new file mode 100644 index 0000000..03f8ca2 --- /dev/null +++ b/WebCore/css/CSSPropertyNames.in @@ -0,0 +1,217 @@ +# +# CSS property names +# +# Some properties are used internally, but are not part of CSS. They are used to get +# HTML4 compatibility in the rendering engine. +# +# Microsoft extensions are documented here: +# http://msdn.microsoft.com/workshop/author/css/reference/attributes.asp +# + +background +background-attachment +background-color +background-image +background-position +background-position-x +background-position-y +background-repeat +border +border-bottom +border-bottom-color +border-bottom-style +border-bottom-width +border-collapse +border-color +border-left +border-left-color +border-left-style +border-left-width +border-right +border-right-color +border-right-style +border-right-width +border-spacing +border-style +border-top +border-top-color +border-top-style +border-top-width +border-width +bottom +caption-side +clear +clip +color +content +counter-increment +counter-reset +cursor +direction +display +empty-cells +float +font +font-family +font-size +font-stretch +font-style +font-variant +font-weight +height +left +letter-spacing +line-height +list-style +list-style-image +list-style-position +list-style-type +margin +margin-bottom +margin-left +margin-right +margin-top +max-height +max-width +min-height +min-width +opacity +orphans +outline +outline-color +outline-offset +outline-style +outline-width +overflow +overflow-x +overflow-y +padding +padding-bottom +padding-left +padding-right +padding-top +page +page-break-after +page-break-before +page-break-inside +position +quotes +resize +right +scrollbar-3dlight-color +scrollbar-arrow-color +scrollbar-darkshadow-color +scrollbar-face-color +scrollbar-highlight-color +scrollbar-shadow-color +scrollbar-track-color +size +src +table-layout +text-align +text-decoration +text-indent +text-line-through +text-line-through-color +text-line-through-mode +text-line-through-style +text-line-through-width +text-overflow +text-overline +text-overline-color +text-overline-mode +text-overline-style +text-overline-width +text-shadow +text-transform +text-underline +text-underline-color +text-underline-mode +text-underline-style +text-underline-width +top +unicode-bidi +unicode-range +vertical-align +visibility +white-space +widows +width +word-break +word-spacing +word-wrap +z-index +-webkit-transition +-webkit-transition-duration +-webkit-transition-property +-webkit-transition-repeat-count +-webkit-transition-timing-function +-webkit-appearance +-webkit-background-clip +-webkit-background-composite +-webkit-background-origin +-webkit-background-size +-webkit-binding +-webkit-border-bottom-left-radius +-webkit-border-bottom-right-radius +-webkit-border-fit +-webkit-border-horizontal-spacing +-webkit-border-image +-webkit-border-radius +-webkit-border-top-left-radius +-webkit-border-top-right-radius +-webkit-border-vertical-spacing +-webkit-box-align +-webkit-box-direction +-webkit-box-flex +-webkit-box-flex-group +-webkit-box-lines +-webkit-box-ordinal-group +-webkit-box-orient +-webkit-box-pack +-webkit-box-shadow +-webkit-box-sizing +-webkit-column-break-after +-webkit-column-break-before +-webkit-column-break-inside +-webkit-column-count +-webkit-column-gap +-webkit-column-rule +-webkit-column-rule-color +-webkit-column-rule-style +-webkit-column-rule-width +-webkit-column-width +-webkit-columns +-webkit-dashboard-region +-webkit-font-size-delta +-webkit-highlight +-webkit-line-break +-webkit-line-clamp +-webkit-margin-bottom-collapse +-webkit-margin-collapse +-webkit-margin-start +-webkit-margin-top-collapse +-webkit-marquee +-webkit-marquee-direction +-webkit-marquee-increment +-webkit-marquee-repetition +-webkit-marquee-speed +-webkit-marquee-style +-webkit-match-nearest-mail-blockquote-color +-webkit-nbsp-mode +-webkit-padding-start +-webkit-rtl-ordering +-webkit-text-decorations-in-effect +-webkit-text-fill-color +-webkit-text-security +-webkit-text-size-adjust +-webkit-text-stroke +-webkit-text-stroke-color +-webkit-text-stroke-width +-webkit-transform +-webkit-transform-origin +-webkit-transform-origin-x +-webkit-transform-origin-y +-webkit-user-drag +-webkit-user-modify +-webkit-user-select diff --git a/WebCore/css/CSSQuirkPrimitiveValue.h b/WebCore/css/CSSQuirkPrimitiveValue.h new file mode 100644 index 0000000..3655ca5 --- /dev/null +++ b/WebCore/css/CSSQuirkPrimitiveValue.h @@ -0,0 +1,46 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSQuirkPrimitiveValue_h +#define CSSQuirkPrimitiveValue_h + +#include "CSSPrimitiveValue.h" + +namespace WebCore { + +// This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE. +// The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em +// in a stylesheet. When the quirky value is used, if you're in quirks mode, the margin will +// collapse away inside a table cell. +class CSSQuirkPrimitiveValue : public CSSPrimitiveValue { +public: + CSSQuirkPrimitiveValue(double num, UnitTypes type) + : CSSPrimitiveValue(num, type) + { + } + + virtual bool isQuirkValue() { return true; } +}; + +} // namespace WebCore + +#endif // CSSQuirkPrimitiveValue_h diff --git a/WebCore/css/CSSRule.cpp b/WebCore/css/CSSRule.cpp new file mode 100644 index 0000000..0b141b1 --- /dev/null +++ b/WebCore/css/CSSRule.cpp @@ -0,0 +1,52 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006, 2007 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSRule.h" + +#include "CSSStyleSheet.h" + +namespace WebCore { + +CSSStyleSheet* CSSRule::parentStyleSheet() const +{ + return (parent() && parent()->isCSSStyleSheet()) ? static_cast<CSSStyleSheet*>(parent()) : 0; +} + +CSSRule* CSSRule::parentRule() const +{ + return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0; +} + +String CSSRule::cssText() const +{ + // FIXME: Implement! + return String(); +} + +void CSSRule::setCssText(String /*cssText*/, ExceptionCode& /*ec*/) +{ + // FIXME: Implement! +} + +} // namespace WebCore diff --git a/WebCore/css/CSSRule.h b/WebCore/css/CSSRule.h new file mode 100644 index 0000000..ad865b3 --- /dev/null +++ b/WebCore/css/CSSRule.h @@ -0,0 +1,65 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSRule_h +#define CSSRule_h + +#include "StyleBase.h" + +namespace WebCore { + +class CSSStyleSheet; + +typedef int ExceptionCode; + +class CSSRule : public StyleBase { +public: + enum CSSRuleType { + UNKNOWN_RULE, + STYLE_RULE, + CHARSET_RULE, + IMPORT_RULE, + MEDIA_RULE, + FONT_FACE_RULE, + PAGE_RULE + }; + + CSSRule(StyleBase* parent) + : StyleBase(parent) + { + } + + virtual bool isRule() { return true; } + + virtual unsigned short type() const = 0; + + CSSStyleSheet* parentStyleSheet() const; + CSSRule* parentRule() const; + + virtual String cssText() const; + void setCssText(String, ExceptionCode&); +}; + +} // namespace WebCore + +#endif // CSSRule_h diff --git a/WebCore/css/CSSRule.idl b/WebCore/css/CSSRule.idl new file mode 100644 index 0000000..d36c059 --- /dev/null +++ b/WebCore/css/CSSRule.idl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + ObjCCustomInternalImpl, + InterfaceUUID=548139b4-31ab-4978-b1d5-cfcfdfbaea0e, + ImplementationUUID=0268e673-2489-4743-9a3a-197dae4b4d9c + ] CSSRule { + + // RuleType + const unsigned short UNKNOWN_RULE = 0; + const unsigned short STYLE_RULE = 1; + const unsigned short CHARSET_RULE = 2; + const unsigned short IMPORT_RULE = 3; + const unsigned short MEDIA_RULE = 4; + const unsigned short FONT_FACE_RULE = 5; + const unsigned short PAGE_RULE = 6; + + readonly attribute unsigned short type; + + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + setter raises (DOMException); + + readonly attribute CSSStyleSheet parentStyleSheet; + readonly attribute CSSRule parentRule; + + }; + +} diff --git a/WebCore/css/CSSRuleList.cpp b/WebCore/css/CSSRuleList.cpp new file mode 100644 index 0000000..89058fd --- /dev/null +++ b/WebCore/css/CSSRuleList.cpp @@ -0,0 +1,100 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSRuleList.h" + +#include "CSSRule.h" +#include "StyleList.h" + +namespace WebCore { + +CSSRuleList::CSSRuleList() + : RefCounted<CSSRuleList>(0) +{ +} + +CSSRuleList::CSSRuleList(StyleList* list, bool omitCharsetRules) + : RefCounted<CSSRuleList>(0) +{ + m_list = list; + if (list && omitCharsetRules) { + m_list = 0; + unsigned len = list->length(); + for (unsigned i = 0; i < len; ++i) { + StyleBase* style = list->item(i); + if (style->isRule() && !style->isCharsetRule()) + append(static_cast<CSSRule*>(style)); + } + } +} + +CSSRuleList::~CSSRuleList() +{ + CSSRule* rule; + while (!m_lstCSSRules.isEmpty() && (rule = m_lstCSSRules.take(0))) + rule->deref(); +} + +unsigned CSSRuleList::length() const +{ + return m_list ? m_list->length() : m_lstCSSRules.count(); +} + +CSSRule* CSSRuleList::item(unsigned index) +{ + if (m_list) { + StyleBase* rule = m_list->item(index); + ASSERT(!rule || rule->isRule()); + return static_cast<CSSRule*>(rule); + } + return m_lstCSSRules.at(index); +} + +void CSSRuleList::deleteRule(unsigned index) +{ + ASSERT(!m_list); + CSSRule* rule = m_lstCSSRules.take(index); + if (rule) + rule->deref(); + // FIXME: Throw INDEX_SIZE_ERR exception here if !rule +} + +void CSSRuleList::append(CSSRule* rule) +{ + insertRule(rule, m_lstCSSRules.count()) ; +} + +unsigned CSSRuleList::insertRule(CSSRule* rule, unsigned index) +{ + ASSERT(!m_list); + if (rule && m_lstCSSRules.insert(index, rule)) { + rule->ref(); + return index; + } + + // FIXME: Should throw INDEX_SIZE_ERR exception instead! + return 0; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSRuleList.h b/WebCore/css/CSSRuleList.h new file mode 100644 index 0000000..721696f --- /dev/null +++ b/WebCore/css/CSSRuleList.h @@ -0,0 +1,58 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSRuleList_h +#define CSSRuleList_h + +#include "DeprecatedPtrList.h" +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSRule; +class StyleList; + +class CSSRuleList : public RefCounted<CSSRuleList> { +public: + CSSRuleList(); + CSSRuleList(StyleList*, bool omitCharsetRules = false); + ~CSSRuleList(); + + unsigned length() const; + CSSRule* item(unsigned index); + + // FIXME: Not part of the DOM. Only used by media rules. We should be able to remove them if we changed media rules to work + // as StyleLists instead. + unsigned insertRule(CSSRule*, unsigned index); + void deleteRule(unsigned index); + void append(CSSRule*); + +protected: + RefPtr<StyleList> m_list; + DeprecatedPtrList<CSSRule> m_lstCSSRules; // FIXME: Want to eliminate, but used by IE rules() extension and still used by media rules. +}; + +} // namespace WebCore + +#endif // CSSRuleList_h diff --git a/WebCore/css/CSSRuleList.idl b/WebCore/css/CSSRuleList.idl new file mode 100644 index 0000000..224d6a1 --- /dev/null +++ b/WebCore/css/CSSRuleList.idl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + HasIndexGetter, + InterfaceUUID=64c346a0-1e34-49d3-9472-57ec8e0fdccb, + ImplementationUUID=971a28e0-d0da-4570-9b71-e39fc2cf9a1b + ] CSSRuleList { + readonly attribute unsigned long length; + CSSRule item(in unsigned long index); + }; + +} diff --git a/WebCore/css/CSSSegmentedFontFace.cpp b/WebCore/css/CSSSegmentedFontFace.cpp new file mode 100644 index 0000000..8ecfea9 --- /dev/null +++ b/WebCore/css/CSSSegmentedFontFace.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSSegmentedFontFace.h" + +#include "CSSFontFace.h" +#include "CSSFontSelector.h" +#include "FontDescription.h" +#include "SegmentedFontData.h" +#include "SimpleFontData.h" + +namespace WebCore { + +CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector) + : RefCounted<CSSSegmentedFontFace>(0) + , m_fontSelector(fontSelector) +{ +} + +CSSSegmentedFontFace::~CSSSegmentedFontFace() +{ + pruneTable(); +} + +void CSSSegmentedFontFace::pruneTable() +{ + // Make sure the glyph page tree prunes out all uses of this custom font. + if (m_fontDataTable.isEmpty()) + return; + HashMap<unsigned, SegmentedFontData*>::iterator end = m_fontDataTable.end(); + for (HashMap<unsigned, SegmentedFontData*>::iterator it = m_fontDataTable.begin(); it != end; ++it) + GlyphPageTreeNode::pruneTreeCustomFontData(it->second); + deleteAllValues(m_fontDataTable); + m_fontDataTable.clear(); +} + +bool CSSSegmentedFontFace::isLoaded() const +{ + unsigned size = m_ranges.size(); + for (unsigned i = 0; i < size; i++) { + if (!m_ranges[i].fontFace()->isLoaded()) + return false; + } + return true; +} + +bool CSSSegmentedFontFace::isValid() const +{ + unsigned size = m_ranges.size(); + for (unsigned i = 0; i < size; i++) { + if (!m_ranges[i].fontFace()->isValid()) + return false; + } + return true; +} + +void CSSSegmentedFontFace::fontLoaded(CSSFontFace*) +{ + pruneTable(); + m_fontSelector->fontLoaded(this); +} + +void CSSSegmentedFontFace::overlayRange(UChar32 from, UChar32 to, PassRefPtr<CSSFontFace> fontFace) +{ + pruneTable(); + fontFace->setSegmentedFontFace(this); + + unsigned size = m_ranges.size(); + if (size) { + Vector<FontFaceRange, 8> oldRanges = m_ranges; + m_ranges.clear(); + for (unsigned i = 0; i < size; i++) { + const FontFaceRange& range = oldRanges[i]; + if (range.from() > to || range.to() < from) + m_ranges.append(range); + else if (range.from() < from) { + m_ranges.append(FontFaceRange(range.from(), from - 1, range.fontFace())); + if (range.to() > to) + m_ranges.append(FontFaceRange(to + 1, range.to(), range.fontFace())); + } else if (range.to() > to) + m_ranges.append(FontFaceRange(to + 1, range.to(), range.fontFace())); + } + } + m_ranges.append(FontFaceRange(from, to, fontFace)); +} + +FontData* CSSSegmentedFontFace::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic) +{ + if (!isValid()) + return 0; + + unsigned hashKey = fontDescription.computedPixelSize() << 2 | (syntheticBold ? 0 : 2) | (syntheticItalic ? 0 : 1); + + SegmentedFontData* fontData = m_fontDataTable.get(hashKey); + if (fontData) + return fontData; + + fontData = new SegmentedFontData(); + + unsigned size = m_ranges.size(); + for (unsigned i = 0; i < size; i++) { + if (const FontData* rangeFontData = m_ranges[i].fontFace()->getFontData(fontDescription, syntheticBold, syntheticItalic)) { + ASSERT(!rangeFontData->isSegmented()); + fontData->appendRange(FontDataRange(m_ranges[i].from(), m_ranges[i].to(), static_cast<const SimpleFontData*>(rangeFontData))); + } + } + if (fontData->numRanges()) + m_fontDataTable.set(hashKey, fontData); + else { + delete fontData; + fontData = 0; + } + + return fontData; +} + +} diff --git a/WebCore/css/CSSSegmentedFontFace.h b/WebCore/css/CSSSegmentedFontFace.h new file mode 100644 index 0000000..55a9da5 --- /dev/null +++ b/WebCore/css/CSSSegmentedFontFace.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSSegmentedFontFace_h +#define CSSSegmentedFontFace_h + +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> +#include <wtf/unicode/Unicode.h> + +namespace WebCore { + +class CSSFontFace; +class CSSFontSelector; +class FontData; +class FontDescription; +class SegmentedFontData; + +struct FontFaceRange { + FontFaceRange(UChar32 from, UChar32 to, PassRefPtr<CSSFontFace> fontFace) + : m_from(from) + , m_to(to) + , m_fontFace(fontFace) + { + } + + UChar32 from() const { return m_from; } + UChar32 to() const { return m_to; } + CSSFontFace* fontFace() const { return m_fontFace.get(); } + +private: + UChar32 m_from; + UChar32 m_to; + RefPtr<CSSFontFace> m_fontFace; +}; + +class CSSSegmentedFontFace : public RefCounted<CSSSegmentedFontFace> { +public: + CSSSegmentedFontFace(CSSFontSelector*); + ~CSSSegmentedFontFace(); + + bool isLoaded() const; + bool isValid() const; + CSSFontSelector* fontSelector() const { return m_fontSelector; } + + void fontLoaded(CSSFontFace*); + + unsigned numRanges() const { return m_ranges.size(); } + void overlayRange(UChar32 from, UChar32 to, PassRefPtr<CSSFontFace>); + + FontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic); + +private: + void pruneTable(); + + CSSFontSelector* m_fontSelector; + HashMap<unsigned, SegmentedFontData*> m_fontDataTable; + Vector<FontFaceRange, 1> m_ranges; +}; + +} // namespace WebCore + +#endif // CSSSegmentedFontFace_h diff --git a/WebCore/css/CSSSelector.cpp b/WebCore/css/CSSSelector.cpp new file mode 100644 index 0000000..2fd8d21 --- /dev/null +++ b/WebCore/css/CSSSelector.cpp @@ -0,0 +1,364 @@ +/* + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) + * 2001-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSSelector.h" + +namespace WebCore { + +void CSSSelector::print() +{ + if (m_tagHistory) + m_tagHistory->print(); +} + +unsigned int CSSSelector::specificity() +{ + // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function + // isn't quite correct. + int s = (m_tag.localName() == starAtom ? 0 : 1); + switch (m_match) { + case Id: + s += 0x10000; + break; + case Exact: + case Class: + case Set: + case List: + case Hyphen: + case PseudoClass: + case PseudoElement: + case Contain: + case Begin: + case End: + s += 0x100; + case None: + break; + } + + if (m_tagHistory) + s += m_tagHistory->specificity(); + + // make sure it doesn't overflow + return s & 0xffffff; +} + +void CSSSelector::extractPseudoType() const +{ + if (m_match != PseudoClass && m_match != PseudoElement) + return; + + static AtomicString active("active"); + static AtomicString after("after"); + static AtomicString anyLink("-webkit-any-link"); + static AtomicString autofill("-webkit-autofill"); + static AtomicString before("before"); + static AtomicString checked("checked"); + static AtomicString fileUploadButton("-webkit-file-upload-button"); + static AtomicString disabled("disabled"); + static AtomicString drag("-webkit-drag"); + static AtomicString dragAlias("-khtml-drag"); // was documented with this name in Apple documentation, so keep an alias + static AtomicString empty("empty"); + static AtomicString enabled("enabled"); + static AtomicString firstChild("first-child"); + static AtomicString firstLetter("first-letter"); + static AtomicString firstLine("first-line"); + static AtomicString firstOfType("first-of-type"); + static AtomicString nthChild("nth-child("); + static AtomicString nthOfType("nth-of-type("); + static AtomicString nthLastChild("nth-last-child("); + static AtomicString nthLastOfType("nth-last-of-type("); + static AtomicString focus("focus"); + static AtomicString hover("hover"); + static AtomicString indeterminate("indeterminate"); + static AtomicString lastChild("last-child"); + static AtomicString lastOfType("last-of-type"); + static AtomicString link("link"); + static AtomicString lang("lang("); + static AtomicString mediaControlsPanel("-webkit-media-controls-panel"); + static AtomicString mediaControlsMuteButton("-webkit-media-controls-mute-button"); + static AtomicString mediaControlsPlayButton("-webkit-media-controls-play-button"); + static AtomicString mediaControlsTimeDisplay("-webkit-media-controls-time-display"); + static AtomicString mediaControlsTimeline("-webkit-media-controls-timeline"); + static AtomicString mediaControlsSeekBackButton("-webkit-media-controls-seek-back-button"); + static AtomicString mediaControlsSeekForwardButton("-webkit-media-controls-seek-forward-button"); + static AtomicString mediaControlsFullscreenButton("-webkit-media-controls-fullscreen-button"); + static AtomicString notStr("not("); + static AtomicString onlyChild("only-child"); + static AtomicString onlyOfType("only-of-type"); + static AtomicString root("root"); + static AtomicString searchCancelButton("-webkit-search-cancel-button"); + static AtomicString searchDecoration("-webkit-search-decoration"); + static AtomicString searchResultsDecoration("-webkit-search-results-decoration"); + static AtomicString searchResultsButton("-webkit-search-results-button"); + static AtomicString selection("selection"); + static AtomicString sliderThumb("-webkit-slider-thumb"); + static AtomicString target("target"); + static AtomicString visited("visited"); + + bool element = false; // pseudo-element + bool compat = false; // single colon compatbility mode + + m_pseudoType = PseudoUnknown; + if (m_value == active) + m_pseudoType = PseudoActive; + else if (m_value == after) { + m_pseudoType = PseudoAfter; + element = true; + compat = true; + } else if (m_value == anyLink) + m_pseudoType = PseudoAnyLink; + else if (m_value == autofill) + m_pseudoType = PseudoAutofill; + else if (m_value == before) { + m_pseudoType = PseudoBefore; + element = true; + compat = true; + } else if (m_value == checked) + m_pseudoType = PseudoChecked; + else if (m_value == fileUploadButton) { + m_pseudoType = PseudoFileUploadButton; + element = true; + } else if (m_value == disabled) + m_pseudoType = PseudoDisabled; + else if (m_value == drag || m_value == dragAlias) + m_pseudoType = PseudoDrag; + else if (m_value == enabled) + m_pseudoType = PseudoEnabled; + else if (m_value == empty) + m_pseudoType = PseudoEmpty; + else if (m_value == firstChild) + m_pseudoType = PseudoFirstChild; + else if (m_value == lastChild) + m_pseudoType = PseudoLastChild; + else if (m_value == lastOfType) + m_pseudoType = PseudoLastOfType; + else if (m_value == onlyChild) + m_pseudoType = PseudoOnlyChild; + else if (m_value == onlyOfType) + m_pseudoType = PseudoOnlyOfType; + else if (m_value == firstLetter) { + m_pseudoType = PseudoFirstLetter; + element = true; + compat = true; + } else if (m_value == firstLine) { + m_pseudoType = PseudoFirstLine; + element = true; + compat = true; + } else if (m_value == firstOfType) + m_pseudoType = PseudoFirstOfType; + else if (m_value == focus) + m_pseudoType = PseudoFocus; + else if (m_value == hover) + m_pseudoType = PseudoHover; + else if (m_value == indeterminate) + m_pseudoType = PseudoIndeterminate; + else if (m_value == link) + m_pseudoType = PseudoLink; + else if (m_value == lang) + m_pseudoType = PseudoLang; + else if (m_value == mediaControlsPanel) { + m_pseudoType = PseudoMediaControlsPanel; + element = true; + } else if (m_value == mediaControlsMuteButton) { + m_pseudoType = PseudoMediaControlsMuteButton; + element = true; + } else if (m_value == mediaControlsPlayButton) { + m_pseudoType = PseudoMediaControlsPlayButton; + element = true; + } else if (m_value == mediaControlsTimeDisplay) { + m_pseudoType = PseudoMediaControlsTimeDisplay; + element = true; + } else if (m_value == mediaControlsTimeline) { + m_pseudoType = PseudoMediaControlsTimeline; + element = true; + } else if (m_value == mediaControlsSeekBackButton) { + m_pseudoType = PseudoMediaControlsSeekBackButton; + element = true; + } else if (m_value == mediaControlsSeekForwardButton) { + m_pseudoType = PseudoMediaControlsSeekForwardButton; + element = true; + } else if (m_value == mediaControlsFullscreenButton) { + m_pseudoType = PseudoMediaControlsFullscreenButton; + element = true; + } else if (m_value == notStr) + m_pseudoType = PseudoNot; + else if (m_value == nthChild) + m_pseudoType = PseudoNthChild; + else if (m_value == nthOfType) + m_pseudoType = PseudoNthOfType; + else if (m_value == nthLastChild) + m_pseudoType = PseudoNthLastChild; + else if (m_value == nthLastOfType) + m_pseudoType = PseudoNthLastOfType; + else if (m_value == root) + m_pseudoType = PseudoRoot; + else if (m_value == searchCancelButton) { + m_pseudoType = PseudoSearchCancelButton; + element = true; + } else if (m_value == searchDecoration) { + m_pseudoType = PseudoSearchDecoration; + element = true; + } else if (m_value == searchResultsDecoration) { + m_pseudoType = PseudoSearchResultsDecoration; + element = true; + } else if (m_value == searchResultsButton) { + m_pseudoType = PseudoSearchResultsButton; + element = true; + } else if (m_value == selection) { + m_pseudoType = PseudoSelection; + element = true; + } else if (m_value == sliderThumb) { + m_pseudoType = PseudoSliderThumb; + element = true; + } else if (m_value == target) + m_pseudoType = PseudoTarget; + else if (m_value == visited) + m_pseudoType = PseudoVisited; + + if (m_match == PseudoClass && element) { + if (!compat) + m_pseudoType = PseudoUnknown; + else + m_match = PseudoElement; + } else if (m_match == PseudoElement && !element) + m_pseudoType = PseudoUnknown; +} + +bool CSSSelector::operator==(const CSSSelector& other) +{ + const CSSSelector* sel1 = this; + const CSSSelector* sel2 = &other; + + while (sel1 && sel2) { + if (sel1->m_tag != sel2->m_tag || sel1->m_attr != sel2->m_attr || + sel1->relation() != sel2->relation() || sel1->m_match != sel2->m_match || + sel1->m_value != sel2->m_value || + sel1->pseudoType() != sel2->pseudoType() || + sel1->m_argument != sel2->m_argument) + return false; + sel1 = sel1->m_tagHistory; + sel2 = sel2->m_tagHistory; + } + + if (sel1 || sel2) + return false; + + return true; +} + +String CSSSelector::selectorText() const +{ + String str = ""; + + const AtomicString& prefix = m_tag.prefix(); + const AtomicString& localName = m_tag.localName(); + if (m_match == CSSSelector::None || !prefix.isNull() || localName != starAtom) { + if (prefix.isNull()) + str = localName; + else + str = prefix + "|" + localName; + } + + const CSSSelector* cs = this; + while (true) { + if (cs->m_match == CSSSelector::Id) { + str += "#"; + str += cs->m_value; + } else if (cs->m_match == CSSSelector::Class) { + str += "."; + str += cs->m_value; + } else if (cs->m_match == CSSSelector::PseudoClass) { + str += ":"; + str += cs->m_value; + if (cs->pseudoType() == PseudoNot) { + if (CSSSelector* subSel = cs->m_simpleSelector) + str += subSel->selectorText(); + str += ")"; + } else if (cs->pseudoType() == PseudoLang) { + str += cs->m_argument; + str += ")"; + } + } else if (cs->m_match == CSSSelector::PseudoElement) { + str += "::"; + str += cs->m_value; + } else if (cs->hasAttribute()) { + str += "["; + const AtomicString& prefix = cs->m_attr.prefix(); + if (!prefix.isNull()) + str += prefix + "|"; + str += cs->m_attr.localName(); + switch (cs->m_match) { + case CSSSelector::Exact: + str += "="; + break; + case CSSSelector::Set: + // set has no operator or value, just the attrName + str += "]"; + break; + case CSSSelector::List: + str += "~="; + break; + case CSSSelector::Hyphen: + str += "|="; + break; + case CSSSelector::Begin: + str += "^="; + break; + case CSSSelector::End: + str += "$="; + break; + case CSSSelector::Contain: + str += "*="; + break; + default: + break; + } + if (cs->m_match != CSSSelector::Set) { + str += "\""; + str += cs->m_value; + str += "\"]"; + } + } + if (cs->relation() != CSSSelector::SubSelector || !cs->m_tagHistory) + break; + cs = cs->m_tagHistory; + } + + if (cs->m_tagHistory) { + String tagHistoryText = cs->m_tagHistory->selectorText(); + if (cs->relation() == CSSSelector::DirectAdjacent) + str = tagHistoryText + " + " + str; + else if (cs->relation() == CSSSelector::IndirectAdjacent) + str = tagHistoryText + " ~ " + str; + else if (cs->relation() == CSSSelector::Child) + str = tagHistoryText + " > " + str; + else + // Descendant + str = tagHistoryText + " " + str; + } + + return str; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSSelector.h b/WebCore/css/CSSSelector.h new file mode 100644 index 0000000..32d7978 --- /dev/null +++ b/WebCore/css/CSSSelector.h @@ -0,0 +1,200 @@ +/* + * This file is part of the CSS implementation for KDE. + * + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSSelector_h +#define CSSSelector_h + +#include "QualifiedName.h" + +namespace WebCore { + + // this class represents a selector for a StyleRule + class CSSSelector { + public: + CSSSelector() + : m_tagHistory(0) + , m_simpleSelector(0) + , m_nextSelector(0) + , m_argument(nullAtom) + , m_attr(anyQName()) + , m_tag(anyQName()) + , m_relation(Descendant) + , m_match(None) + , m_pseudoType(PseudoNotParsed) + { + } + + CSSSelector(const QualifiedName& qName) + : m_tagHistory(0) + , m_simpleSelector(0) + , m_nextSelector(0) + , m_argument(nullAtom) + , m_attr(anyQName()) + , m_tag(qName) + , m_relation(Descendant) + , m_match(None) + , m_pseudoType(PseudoNotParsed) + { + } + + ~CSSSelector() + { + delete m_tagHistory; + delete m_simpleSelector; + delete m_nextSelector; + } + + void append(CSSSelector* n) + { + CSSSelector* end = this; + while (end->m_nextSelector) + end = end->m_nextSelector; + end->m_nextSelector = n; + } + + CSSSelector* next() { return m_nextSelector; } + + /** + * Print debug output for this selector + */ + void print(); + + /** + * Re-create selector text from selector's data + */ + String selectorText() const; + + // checks if the 2 selectors (including sub selectors) agree. + bool operator==(const CSSSelector&); + + // tag == -1 means apply to all elements (Selector = *) + + unsigned specificity(); + + /* how the attribute value has to match.... Default is Exact */ + enum Match { + None = 0, + Id, + Class, + Exact, + Set, + List, + Hyphen, + PseudoClass, + PseudoElement, + Contain, // css3: E[foo*="bar"] + Begin, // css3: E[foo^="bar"] + End // css3: E[foo$="bar"] + }; + + enum Relation { + Descendant = 0, + Child, + DirectAdjacent, + IndirectAdjacent, + SubSelector + }; + + enum PseudoType { + PseudoNotParsed = 0, + PseudoUnknown, + PseudoEmpty, + PseudoFirstChild, + PseudoFirstOfType, + PseudoLastChild, + PseudoLastOfType, + PseudoOnlyChild, + PseudoOnlyOfType, + PseudoFirstLine, + PseudoFirstLetter, + PseudoNthChild, + PseudoNthOfType, + PseudoNthLastChild, + PseudoNthLastOfType, + PseudoLink, + PseudoVisited, + PseudoAnyLink, + PseudoAutofill, + PseudoHover, + PseudoDrag, + PseudoFocus, + PseudoActive, + PseudoChecked, + PseudoEnabled, + PseudoDisabled, + PseudoIndeterminate, + PseudoTarget, + PseudoBefore, + PseudoAfter, + PseudoLang, + PseudoNot, + PseudoRoot, + PseudoSelection, + PseudoFileUploadButton, + PseudoSliderThumb, + PseudoSearchCancelButton, + PseudoSearchDecoration, + PseudoSearchResultsDecoration, + PseudoSearchResultsButton, + PseudoMediaControlsPanel, + PseudoMediaControlsMuteButton, + PseudoMediaControlsPlayButton, + PseudoMediaControlsTimeDisplay, + PseudoMediaControlsTimeline, + PseudoMediaControlsSeekBackButton, + PseudoMediaControlsSeekForwardButton, + PseudoMediaControlsFullscreenButton + }; + + PseudoType pseudoType() const + { + if (m_pseudoType == PseudoNotParsed) + extractPseudoType(); + return static_cast<PseudoType>(m_pseudoType); + } + + bool hasTag() const { return m_tag != anyQName(); } + bool hasAttribute() const { return m_attr != anyQName(); } + + Relation relation() const { return static_cast<Relation>(m_relation); } + + mutable AtomicString m_value; + CSSSelector* m_tagHistory; + CSSSelector* m_simpleSelector; // Used for :not. + CSSSelector* m_nextSelector; // used for ,-chained selectors + AtomicString m_argument; // Used for :contains, :lang and :nth-* + + QualifiedName m_attr; + QualifiedName m_tag; + + unsigned m_relation : 3; // enum Relation + mutable unsigned m_match : 4; // enum Match + mutable unsigned m_pseudoType : 8; // PseudoType + + private: + void extractPseudoType() const; + }; + +} // namespace WebCore + +#endif // CSSSelector_h diff --git a/WebCore/css/CSSStyleDeclaration.cpp b/WebCore/css/CSSStyleDeclaration.cpp new file mode 100644 index 0000000..4e1fb68 --- /dev/null +++ b/WebCore/css/CSSStyleDeclaration.cpp @@ -0,0 +1,156 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSStyleDeclaration.h" + +#include "CSSMutableStyleDeclaration.h" +#include "CSSParser.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSRule.h" +#include "DeprecatedValueList.h" +#include <wtf/ASCIICType.h> + +using namespace WTF; + +namespace WebCore { + +CSSStyleDeclaration::CSSStyleDeclaration(CSSRule* parent) + : StyleBase(parent) +{ +} + +bool CSSStyleDeclaration::isStyleDeclaration() +{ + return true; +} + +PassRefPtr<CSSValue> CSSStyleDeclaration::getPropertyCSSValue(const String& propertyName) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return 0; + return getPropertyCSSValue(propID); +} + +String CSSStyleDeclaration::getPropertyValue(const String &propertyName) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return String(); + return getPropertyValue(propID); +} + +String CSSStyleDeclaration::getPropertyPriority(const String& propertyName) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return String(); + return getPropertyPriority(propID) ? "important" : ""; +} + +String CSSStyleDeclaration::getPropertyShorthand(const String& propertyName) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return String(); + int shorthandID = getPropertyShorthand(propID); + if (!shorthandID) + return String(); + return getPropertyName(static_cast<CSSPropertyID>(shorthandID)); +} + +bool CSSStyleDeclaration::isPropertyImplicit(const String& propertyName) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return false; + return isPropertyImplicit(propID); +} + +void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, ExceptionCode& ec) +{ + int important = value.find("!important", 0, false); + if (important == -1) + setProperty(propertyName, value, "", ec); + else + setProperty(propertyName, value.left(important - 1), "important", ec); +} + +void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec) +{ + int propID = cssPropertyID(propertyName); + if (!propID) { + // FIXME: Should we raise an exception here? + return; + } + bool important = priority.find("important", 0, false) != -1; + setProperty(propID, value, important, ec); +} + +String CSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionCode& ec) +{ + int propID = cssPropertyID(propertyName); + if (!propID) + return String(); + return removeProperty(propID, ec); +} + +bool CSSStyleDeclaration::isPropertyName(const String& propertyName) +{ + return cssPropertyID(propertyName); +} + +CSSRule* CSSStyleDeclaration::parentRule() const +{ + return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0; +} + +void CSSStyleDeclaration::diff(CSSMutableStyleDeclaration* style) const +{ + if (!style) + return; + + Vector<int> properties; + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it(style->valuesIterator()); it != end; ++it) { + const CSSProperty& property = *it; + RefPtr<CSSValue> value = getPropertyCSSValue(property.id()); + if (value && (value->cssText() == property.value()->cssText())) + properties.append(property.id()); + } + + for (unsigned i = 0; i < properties.size(); i++) + style->removeProperty(properties[i]); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSStyleDeclaration::copyPropertiesInSet(const int* set, unsigned length) const +{ + DeprecatedValueList<CSSProperty> list; + for (unsigned i = 0; i < length; i++) { + RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); + if (value) + list.append(CSSProperty(set[i], value.release(), false)); + } + return new CSSMutableStyleDeclaration(0, list); +} + +} // namespace WebCore diff --git a/WebCore/css/CSSStyleDeclaration.h b/WebCore/css/CSSStyleDeclaration.h new file mode 100644 index 0000000..2153c67 --- /dev/null +++ b/WebCore/css/CSSStyleDeclaration.h @@ -0,0 +1,80 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSStyleDeclaration_h +#define CSSStyleDeclaration_h + +#include "StyleBase.h" +#include <wtf/Forward.h> + +namespace WebCore { + +class CSSMutableStyleDeclaration; +class CSSRule; +class CSSValue; + +typedef int ExceptionCode; + +class CSSStyleDeclaration : public StyleBase { +public: + virtual bool isStyleDeclaration(); + + static bool isPropertyName(const String&); + + CSSRule* parentRule() const; + + virtual String cssText() const = 0; + virtual void setCssText(const String&, ExceptionCode&) = 0; + + virtual unsigned length() const = 0; + virtual String item(unsigned index) const = 0; + + PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName); + String getPropertyValue(const String& propertyName); + String getPropertyPriority(const String& propertyName); + String getPropertyShorthand(const String& propertyName); + bool isPropertyImplicit(const String& propertyName); + + virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const = 0; + virtual String getPropertyValue(int propertyID) const = 0; + virtual bool getPropertyPriority(int propertyID) const = 0; + virtual int getPropertyShorthand(int propertyID) const = 0; + virtual bool isPropertyImplicit(int propertyID) const = 0; + + void setProperty(const String& propertyName, const String& value, ExceptionCode&); + void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&); + String removeProperty(const String& propertyName, ExceptionCode&); + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&) = 0; + virtual String removeProperty(int propertyID, ExceptionCode&) = 0; + + virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const = 0; + virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable() = 0; + + void diff(CSSMutableStyleDeclaration*) const; + + PassRefPtr<CSSMutableStyleDeclaration> copyPropertiesInSet(const int* set, unsigned length) const; + +protected: + CSSStyleDeclaration(CSSRule* parentRule = 0); +}; + +} // namespace WebCore + +#endif // CSSStyleDeclaration_h diff --git a/WebCore/css/CSSStyleDeclaration.idl b/WebCore/css/CSSStyleDeclaration.idl new file mode 100644 index 0000000..60020d9 --- /dev/null +++ b/WebCore/css/CSSStyleDeclaration.idl @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + CustomPutFunction, + HasNameGetter, + HasIndexGetter, + InterfaceUUID=9989b2c3-a2b6-449b-abf9-c60d2260b1d7, + ImplementationUUID=985c50c7-9f19-436a-9e45-c0aa02996d0e + ] CSSStyleDeclaration { + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + setter raises(DOMException); + + [ConvertNullStringTo=Null] DOMString getPropertyValue(in DOMString propertyName); + CSSValue getPropertyCSSValue(in DOMString propertyName); + [ConvertNullStringTo=Null] DOMString removeProperty(in DOMString propertyName) + raises(DOMException); + [ConvertNullStringTo=Null] DOMString getPropertyPriority(in DOMString propertyName); + [OldStyleObjC] void setProperty(in DOMString propertyName, + in [ConvertNullToNullString] DOMString value, + in DOMString priority) + raises(DOMException); + + readonly attribute unsigned long length; + [ConvertNullStringTo=Null] DOMString item(in unsigned long index); + readonly attribute CSSRule parentRule; + + // Extensions + [ConvertNullStringTo=Null] DOMString getPropertyShorthand(in DOMString propertyName); + boolean isPropertyImplicit(in DOMString propertyName); + }; + +} diff --git a/WebCore/css/CSSStyleRule.cpp b/WebCore/css/CSSStyleRule.cpp new file mode 100644 index 0000000..913c18f --- /dev/null +++ b/WebCore/css/CSSStyleRule.cpp @@ -0,0 +1,86 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "CSSStyleRule.h" + +#include "CSSMutableStyleDeclaration.h" +#include "CSSSelector.h" + +namespace WebCore { + +CSSStyleRule::CSSStyleRule(StyleBase* parent) + : CSSRule(parent) + , m_selector(0) +{ +} + +CSSStyleRule::~CSSStyleRule() +{ + if (m_style) + m_style->setParent(0); + delete m_selector; +} + +String CSSStyleRule::selectorText() const +{ + if (m_selector) { + String str; + for (CSSSelector* s = m_selector; s; s = s->next()) { + if (s != m_selector) + str += ", "; + str += s->selectorText(); + } + return str; + } + return String(); +} + +void CSSStyleRule::setSelectorText(const String& /*selectorText*/, ExceptionCode& /*ec*/) +{ + // FIXME: Implement! +} + +String CSSStyleRule::cssText() const +{ + String result = selectorText(); + + result += " { "; + result += m_style->cssText(); + result += "}"; + + return result; +} + +bool CSSStyleRule::parseString(const String& /*string*/, bool /*strict*/) +{ + // FIXME + return false; +} + +void CSSStyleRule::setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) +{ + m_style = style; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSStyleRule.h b/WebCore/css/CSSStyleRule.h new file mode 100644 index 0000000..f5dd928 --- /dev/null +++ b/WebCore/css/CSSStyleRule.h @@ -0,0 +1,71 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSStyleRule_h +#define CSSStyleRule_h + +#include "CSSRule.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSMutableStyleDeclaration; +class CSSSelector; + +typedef int ExceptionCode; + +class CSSStyleRule : public CSSRule { +public: + CSSStyleRule(StyleBase* parent); + virtual ~CSSStyleRule(); + + virtual bool isStyleRule() { return true; } + + String selectorText() const; + void setSelectorText(const String&, ExceptionCode&); + + CSSMutableStyleDeclaration* style() const { return m_style.get(); } + + // Inherited from CSSRule + virtual unsigned short type() const { return STYLE_RULE; } + + virtual String cssText() const; + + // Not part of the CSSOM + virtual bool parseString(const String&, bool = false); + + void setSelector(CSSSelector* selector) { m_selector = selector; } + void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration>); + + CSSSelector* selector() { return m_selector; } + CSSMutableStyleDeclaration* declaration() { return m_style.get(); } + +protected: + RefPtr<CSSMutableStyleDeclaration> m_style; + CSSSelector* m_selector; +}; + +} // namespace WebCore + +#endif // CSSStyleRule_h diff --git a/WebCore/css/CSSStyleRule.idl b/WebCore/css/CSSStyleRule.idl new file mode 100644 index 0000000..0240dd0 --- /dev/null +++ b/WebCore/css/CSSStyleRule.idl @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=ce4e3330-c40b-4430-8ed4-030ab4ddbc93, + ImplementationUUID=c3d2f1b8-3970-4b36-882e-ce7f5668d8e2 + ] CSSStyleRule : CSSRule { + + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText + setter raises(DOMException); + + readonly attribute CSSStyleDeclaration style; + + }; + +} diff --git a/WebCore/css/CSSStyleSelector.cpp b/WebCore/css/CSSStyleSelector.cpp new file mode 100644 index 0000000..3deb314 --- /dev/null +++ b/WebCore/css/CSSStyleSelector.cpp @@ -0,0 +1,5177 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) + * (C) 2006 Nicholas Shanks (webkit@nickshanks.com) + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> + * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> + * + * 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 "config.h" +#include "CSSStyleSelector.h" + +#include "CSSBorderImageValue.h" +#include "CSSCursorImageValue.h" +#include "CSSFontFace.h" +#include "CSSFontFaceRule.h" +#include "CSSFontFaceSource.h" +#include "CSSImageValue.h" +#include "CSSImportRule.h" +#include "CSSMediaRule.h" +#include "CSSPrimitiveValueMappings.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSRuleList.h" +#include "CSSSelector.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "CSSTimingFunctionValue.h" +#include "CSSValueList.h" +#include "CachedImage.h" +#include "Counter.h" +#include "DashboardRegion.h" +#include "FontFamilyValue.h" +#include "FontValue.h" +#include "Frame.h" +#include "FrameView.h" +#include "GlobalHistory.h" +#include "HTMLDocument.h" +#include "HTMLElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "MediaList.h" +#include "MediaQueryEvaluator.h" +#include "Pair.h" +#include "Rect.h" +#include "RenderTheme.h" +#include "SelectionController.h" +#include "Settings.h" +#include "ShadowValue.h" +#include "StyleSheetList.h" +#include "Text.h" +#include "UserAgentStyleSheets.h" +#include "XMLNames.h" +#include "loader.h" +#include <wtf/Vector.h> + +#if ENABLE(SVG) +#include "XLinkNames.h" +#include "SVGNames.h" +#endif + +using namespace std; + +namespace WebCore { + +using namespace HTMLNames; + +// #define STYLE_SHARING_STATS 1 + +#define HANDLE_INHERIT(prop, Prop) \ +if (isInherit) { \ + m_style->set##Prop(m_parentStyle->prop()); \ + return; \ +} + +#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ +HANDLE_INHERIT(prop, Prop) \ +if (isInitial) { \ + m_style->set##Prop(RenderStyle::initial##Prop()); \ + return; \ +} + +#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ +HANDLE_INHERIT(prop, Prop) \ +if (isInitial) { \ + m_style->set##Prop(RenderStyle::initial##Value());\ + return;\ +} + +#define HANDLE_MULTILAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ +if (isInherit) { \ + LayerType* currChild = m_style->access##LayerType##s(); \ + LayerType* prevChild = 0; \ + const LayerType* currParent = m_parentStyle->layerType##s(); \ + while (currParent && currParent->is##Prop##Set()) { \ + if (!currChild) { \ + /* Need to make a new layer.*/ \ + currChild = new LayerType(); \ + prevChild->setNext(currChild); \ + } \ + currChild->set##Prop(currParent->prop()); \ + prevChild = currChild; \ + currChild = prevChild->next(); \ + currParent = currParent->next(); \ + } \ + \ + while (currChild) { \ + /* Reset any remaining layers to not have the property set. */ \ + currChild->clear##Prop(); \ + currChild = currChild->next(); \ + } \ + return; \ +} \ +if (isInitial) { \ + LayerType* currChild = m_style->access##LayerType##s(); \ + currChild->set##Prop(RenderStyle::initial##Prop()); \ + for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ + currChild->clear##Prop(); \ + return; \ +} + +#define HANDLE_MULTILAYER_VALUE(layerType, LayerType, prop, Prop, value) { \ +HANDLE_MULTILAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ +LayerType* currChild = m_style->access##LayerType##s(); \ +LayerType* prevChild = 0; \ +if (value->isValueList()) { \ + /* Walk each value and put it into a layer, creating new layers as needed. */ \ + CSSValueList* valueList = static_cast<CSSValueList*>(value); \ + for (unsigned int i = 0; i < valueList->length(); i++) { \ + if (!currChild) { \ + /* Need to make a new layer to hold this value */ \ + currChild = new LayerType(); \ + prevChild->setNext(currChild); \ + } \ + map##Prop(currChild, valueList->item(i)); \ + prevChild = currChild; \ + currChild = currChild->next(); \ + } \ +} else { \ + map##Prop(currChild, value); \ + currChild = currChild->next(); \ +} \ +while (currChild) { \ + /* Reset all remaining layers to not have the property set. */ \ + currChild->clear##Prop(); \ + currChild = currChild->next(); \ +} } + +#define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ +HANDLE_MULTILAYER_INHERIT_AND_INITIAL(backgroundLayer, BackgroundLayer, prop, Prop) + +#define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \ +HANDLE_MULTILAYER_VALUE(backgroundLayer, BackgroundLayer, prop, Prop, value) + +#define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ +HANDLE_MULTILAYER_INHERIT_AND_INITIAL(transition, Transition, prop, Prop) + +#define HANDLE_TRANSITION_VALUE(prop, Prop, value) \ +HANDLE_MULTILAYER_VALUE(transition, Transition, prop, Prop, value) + +#define HANDLE_INHERIT_COND(propID, prop, Prop) \ +if (id == propID) { \ + m_style->set##Prop(m_parentStyle->prop()); \ + return; \ +} + +#define HANDLE_INITIAL_COND(propID, Prop) \ +if (id == propID) { \ + m_style->set##Prop(RenderStyle::initial##Prop()); \ + return; \ +} + +#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ +if (id == propID) { \ + m_style->set##Prop(RenderStyle::initial##Value()); \ + return; \ +} + +class CSSRuleSet +{ +public: + CSSRuleSet(); + ~CSSRuleSet(); + + typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap; + + void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0); + + void addRule(CSSStyleRule* rule, CSSSelector* sel); + void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, + CSSStyleRule* rule, CSSSelector* sel); + + CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); } + CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); } + CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); } + CSSRuleDataList* getUniversalRules() { return m_universalRules; } + +public: + AtomRuleMap m_idRules; + AtomRuleMap m_classRules; + AtomRuleMap m_tagRules; + CSSRuleDataList* m_universalRules; + unsigned m_ruleCount; +}; + +CSSRuleSet* CSSStyleSelector::m_defaultStyle = 0; +CSSRuleSet* CSSStyleSelector::m_defaultQuirksStyle = 0; +CSSRuleSet* CSSStyleSelector::m_defaultPrintStyle = 0; +CSSRuleSet* CSSStyleSelector::m_defaultViewSourceStyle = 0; + +CSSStyleSheet* CSSStyleSelector::m_defaultSheet = 0; +RenderStyle* CSSStyleSelector::m_styleNotYetAvailable = 0; +CSSStyleSheet* CSSStyleSelector::m_quirksSheet = 0; +CSSStyleSheet* CSSStyleSelector::m_viewSourceSheet = 0; + +#if ENABLE(SVG) +CSSStyleSheet *CSSStyleSelector::m_svgSheet = 0; +#endif + +static CSSStyleSelector::EncodedURL* currentEncodedURL = 0; +static PseudoState pseudoState; + +static const MediaQueryEvaluator& screenEval() +{ + static const MediaQueryEvaluator staticScreenEval("screen"); + return staticScreenEval; +} + +static const MediaQueryEvaluator& printEval() +{ + static const MediaQueryEvaluator staticPrintEval("print"); + return staticPrintEval; +} + +CSSStyleSelector::CSSStyleSelector(Document* doc, const String& userStyleSheet, StyleSheetList *styleSheets, CSSStyleSheet* mappedElementSheet, bool _strictParsing, bool matchAuthorAndUserStyles) +{ + init(); + + m_document = doc; + m_fontSelector = new CSSFontSelector(doc); + + m_matchAuthorAndUserStyles = matchAuthorAndUserStyles; + + strictParsing = _strictParsing; + if (!m_defaultStyle) + loadDefaultStyle(); + + m_userStyle = 0; + + // construct document root element default style. this is needed + // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" + // This is here instead of constructor, because when constructor is run, + // document doesn't have documentElement + // NOTE: this assumes that element that gets passed to styleForElement -call + // is always from the document that owns the style selector + FrameView* view = m_document->view(); + if (view) + m_medium = new MediaQueryEvaluator(view->mediaType()); + else + m_medium = new MediaQueryEvaluator("all"); + + Element* root = doc->documentElement(); + + if (root) + m_rootDefaultStyle = styleForElement(root, 0, false, true); // dont ref, because the RenderStyle is allocated from global heap + + if (m_rootDefaultStyle && view) { + delete m_medium; + m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle); + } + + // FIXME: This sucks! The user sheet is reparsed every time! + if (!userStyleSheet.isEmpty()) { + m_userSheet = new CSSStyleSheet(doc); + m_userSheet->parseString(userStyleSheet, strictParsing); + + m_userStyle = new CSSRuleSet(); + m_userStyle->addRulesFromSheet(m_userSheet.get(), *m_medium, this); + } + + // add stylesheets from document + m_authorStyle = new CSSRuleSet(); + + // Add rules from elments like SVG's <font-face> + if (mappedElementSheet) + m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this); + + DeprecatedPtrListIterator<StyleSheet> it(styleSheets->styleSheets); + for (; it.current(); ++it) + if (it.current()->isCSSStyleSheet() && !it.current()->disabled()) + m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(it.current()), *m_medium, this); +} + +void CSSStyleSelector::init() +{ + m_element = 0; + m_matchedDecls.clear(); + m_ruleList = 0; + m_collectRulesOnly = false; + m_rootDefaultStyle = 0; + m_medium = 0; +} + +void CSSStyleSelector::setEncodedURL(const KURL& url) +{ + KURL u = url; + + u.setQuery(String()); + u.setRef(String()); + m_encodedURL.file = u.string(); + int pos = m_encodedURL.file.reverseFind('/'); + m_encodedURL.path = m_encodedURL.file; + if (pos > 0) { + m_encodedURL.path.truncate(pos); + m_encodedURL.path.append('/'); + } + u.setPath(String()); + m_encodedURL.prefix = u.string(); +} + +CSSStyleSelector::~CSSStyleSelector() +{ + delete m_medium; + ::delete m_rootDefaultStyle; + + delete m_authorStyle; + delete m_userStyle; +} + +static CSSStyleSheet* parseUASheet(const char* characters, unsigned size) +{ + CSSStyleSheet* const parent = 0; + CSSStyleSheet* sheet = new CSSStyleSheet(parent); + sheet->ref(); // leak the sheet on purpose since it will be stored in a global variable + sheet->parseString(String(characters, size)); + return sheet; +} + +template<typename T> CSSStyleSheet* parseUASheet(const T& array) +{ + return parseUASheet(array, sizeof(array)); +} + +void CSSStyleSelector::loadDefaultStyle() +{ + if (m_defaultStyle) + return; + + m_defaultStyle = new CSSRuleSet; + m_defaultPrintStyle = new CSSRuleSet; + m_defaultQuirksStyle = new CSSRuleSet; + m_defaultViewSourceStyle = new CSSRuleSet; + + // Strict-mode rules. + m_defaultSheet = parseUASheet(html4UserAgentStyleSheet); + m_defaultStyle->addRulesFromSheet(m_defaultSheet, screenEval()); + m_defaultPrintStyle->addRulesFromSheet(m_defaultSheet, printEval()); + + // Quirks-mode rules. + m_quirksSheet = parseUASheet(quirksUserAgentStyleSheet); + m_defaultQuirksStyle->addRulesFromSheet(m_quirksSheet, screenEval()); + + // View source rules. + m_viewSourceSheet = parseUASheet(sourceUserAgentStyleSheet); + m_defaultViewSourceStyle->addRulesFromSheet(m_viewSourceSheet, screenEval()); +} + +void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex) +{ + m_matchedRules.clear(); + + if (!rules || !m_element) + return; + + // We need to collect the rules for id, class, tag, and everything else into a buffer and + // then sort the buffer. + if (m_element->hasID()) + matchRulesForList(rules->getIDRules(m_element->getIDAttribute().impl()), firstRuleIndex, lastRuleIndex); + if (m_element->hasClass()) { + const ClassNames& classNames = *m_element->getClassNames(); + size_t classNamesSize = classNames.size(); + for (size_t i = 0; i < classNamesSize; ++i) + matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex); + } + matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex); + matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex); + + // If we didn't match any rules, we're done. + if (m_matchedRules.isEmpty()) + return; + + // Sort the set of matched rules. + sortMatchedRules(0, m_matchedRules.size()); + + // Now transfer the set of matched rules over to our list of decls. + if (!m_collectRulesOnly) { + for (unsigned i = 0; i < m_matchedRules.size(); i++) + addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); + } else { + for (unsigned i = 0; i < m_matchedRules.size(); i++) { + if (!m_ruleList) + m_ruleList = new CSSRuleList(); + m_ruleList->append(m_matchedRules[i]->rule()); + } + } +} + +void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex) +{ + if (!rules) + return; + + for (CSSRuleData* d = rules->first(); d; d = d->next()) { + CSSStyleRule* rule = d->rule(); + const AtomicString& localName = m_element->localName(); + const AtomicString& selectorLocalName = d->selector()->m_tag.localName(); + if ((localName == selectorLocalName || selectorLocalName == starAtom) && checkSelector(d->selector())) { + // If the rule has no properties to apply, then ignore it. + CSSMutableStyleDeclaration* decl = rule->declaration(); + if (!decl || !decl->length()) + continue; + + // If we're matching normal rules, set a pseudo bit if + // we really just matched a pseudo-element. + if (dynamicPseudo != RenderStyle::NOPSEUDO && m_pseudoStyle == RenderStyle::NOPSEUDO) { + if (m_collectRulesOnly) + return; + if (dynamicPseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID) + m_style->setHasPseudoStyle(dynamicPseudo); + } else { + // Update our first/last rule indices in the matched rules array. + lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size(); + if (firstRuleIndex == -1) + firstRuleIndex = lastRuleIndex; + + // Add this rule to our list of matched rules. + addMatchedRule(d); + } + } + } +} + +bool operator >(CSSRuleData& r1, CSSRuleData& r2) +{ + int spec1 = r1.selector()->specificity(); + int spec2 = r2.selector()->specificity(); + return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; +} +bool operator <=(CSSRuleData& r1, CSSRuleData& r2) +{ + return !(r1 > r2); +} + +void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) +{ + if (start >= end || (end - start == 1)) + return; // Sanity check. + + if (end - start <= 6) { + // Apply a bubble sort for smaller lists. + for (unsigned i = end - 1; i > start; i--) { + bool sorted = true; + for (unsigned j = start; j < i; j++) { + CSSRuleData* elt = m_matchedRules[j]; + CSSRuleData* elt2 = m_matchedRules[j + 1]; + if (*elt > *elt2) { + sorted = false; + m_matchedRules[j] = elt2; + m_matchedRules[j + 1] = elt; + } + } + if (sorted) + return; + } + return; + } + + // Peform a merge sort for larger lists. + unsigned mid = (start + end) / 2; + sortMatchedRules(start, mid); + sortMatchedRules(mid, end); + + CSSRuleData* elt = m_matchedRules[mid - 1]; + CSSRuleData* elt2 = m_matchedRules[mid]; + + // Handle the fast common case (of equal specificity). The list may already + // be completely sorted. + if (*elt <= *elt2) + return; + + // We have to merge sort. Ensure our merge buffer is big enough to hold + // all the items. + Vector<CSSRuleData*> rulesMergeBuffer; + rulesMergeBuffer.reserveCapacity(end - start); + + unsigned i1 = start; + unsigned i2 = mid; + + elt = m_matchedRules[i1]; + elt2 = m_matchedRules[i2]; + + while (i1 < mid || i2 < end) { + if (i1 < mid && (i2 == end || *elt <= *elt2)) { + rulesMergeBuffer.append(elt); + if (++i1 < mid) + elt = m_matchedRules[i1]; + } else { + rulesMergeBuffer.append(elt2); + if (++i2 < end) + elt2 = m_matchedRules[i2]; + } + } + + for (unsigned i = start; i < end; i++) + m_matchedRules[i] = rulesMergeBuffer[i - start]; +} + +void CSSStyleSelector::initElementAndPseudoState(Element* e) +{ + m_element = e; + if (m_element && m_element->isStyledElement()) + m_styledElement = static_cast<StyledElement*>(m_element); + else + m_styledElement = 0; + currentEncodedURL = &m_encodedURL; + pseudoState = PseudoUnknown; +} + +void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParent) +{ + // set some variables we will need + m_pseudoStyle = RenderStyle::NOPSEUDO; + + m_parentNode = e->parentNode(); + +#if ENABLE(SVG) + if (!m_parentNode && e->isSVGElement() && e->isShadowNode()) + m_parentNode = e->shadowParentNode(); +#endif + + if (defaultParent) + m_parentStyle = defaultParent; + else + m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0; + m_isXMLDoc = !m_element->document()->isHTMLDocument(); + + m_style = 0; + + m_matchedDecls.clear(); + + m_ruleList = 0; + + m_fontDirty = false; +} + +static inline int findSlashDotDotSlash(const UChar* characters, size_t length) +{ + unsigned loopLimit = length < 4 ? 0 : length - 3; + for (unsigned i = 0; i < loopLimit; ++i) { + if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '.' && characters[i + 3] == '/') + return i; + } + return -1; +} + +static inline int findSlashSlash(const UChar* characters, size_t length, int position) +{ + unsigned loopLimit = length < 2 ? 0 : length - 1; + for (unsigned i = position; i < loopLimit; ++i) { + if (characters[i] == '/' && characters[i + 1] == '/') + return i; + } + return -1; +} + +static inline int findSlashDotSlash(const UChar* characters, size_t length) +{ + unsigned loopLimit = length < 3 ? 0 : length - 2; + for (unsigned i = 0; i < loopLimit; ++i) { + if (characters[i] == '/' && characters[i + 1] == '.' && characters[i + 2] == '/') + return i; + } + return -1; +} + +static inline bool containsColonSlashSlash(const UChar* characters, unsigned length) +{ + unsigned loopLimit = length < 3 ? 0 : length - 2; + for (unsigned i = 0; i < loopLimit; ++i) + if (characters[i] == ':' && characters[i + 1] == '/' && characters[i + 2] == '/') + return true; + return false; +} + +static void cleanPath(Vector<UChar, 512>& path) +{ + int pos; + while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) { + int prev = reverseFind(path.data(), path.size(), '/', pos - 1); + // don't remove the host, i.e. http://foo.org/../foo.html + if (prev < 0 || (prev > 3 && path[prev - 2] == ':' && path[prev - 1] == '/')) + path.remove(pos, 3); + else + path.remove(prev, pos - prev + 3); + } + + // Don't remove "//" from an anchor identifier. -rjw + // Set refPos to -2 to mean "I haven't looked for the anchor yet". + // We don't want to waste a function call on the search for the the anchor + // in the vast majority of cases where there is no "//" in the path. + pos = 0; + int refPos = -2; + while ((pos = findSlashSlash(path.data(), path.size(), pos)) != -1) { + if (refPos == -2) + refPos = find(path.data(), path.size(), '#'); + if (refPos > 0 && pos >= refPos) + break; + + if (pos == 0 || path[pos - 1] != ':') + path.remove(pos); + else + pos += 2; + } + + // FIXME: We don't want to remove "/./" from an anchor identifier either. + while ((pos = findSlashDotSlash(path.data(), path.size())) != -1) + path.remove(pos, 2); +} + +static void checkPseudoState(Element *e, bool checkVisited = true) +{ + if (!e->isLink()) { + pseudoState = PseudoNone; + return; + } + + const AtomicString* attr; + if (e->isHTMLElement()) + attr = &e->getAttribute(hrefAttr); +#if ENABLE(SVG) + else if (e->isSVGElement()) + attr = &e->getAttribute(XLinkNames::hrefAttr); +#endif + else { + pseudoState = PseudoNone; + return; + } + + if (attr->isNull()) { + pseudoState = PseudoNone; + return; + } + + if (!checkVisited) { + pseudoState = PseudoAnyLink; + return; + } + + const UChar* characters = attr->characters(); + unsigned length = attr->length(); + + if (containsColonSlashSlash(characters, length)) { + // FIXME: Strange to not clean the path just beacause it has "://" in it. + pseudoState = historyContains(characters, length) ? PseudoVisited : PseudoLink; + return; + } + + Vector<UChar, 512> buffer; + if (length && characters[0] == '/') { + buffer.append(currentEncodedURL->prefix.characters(), currentEncodedURL->prefix.length()); + } else if (length && characters[0] == '#') { + buffer.append(currentEncodedURL->file.characters(), currentEncodedURL->file.length()); + } else { + buffer.append(currentEncodedURL->path.characters(), currentEncodedURL->path.length()); + } + buffer.append(characters, length); + cleanPath(buffer); + pseudoState = historyContains(buffer.data(), buffer.size()) ? PseudoVisited : PseudoLink; +} + +// a helper function for parsing nth-arguments +static bool parseNth(const String& nth, int &a, int &b) +{ + if (nth.isEmpty()) + return false; + a = 0; + b = 0; + if (nth == "odd") { + a = 2; + b = 1; + } else if (nth == "even") { + a = 2; + b = 0; + } else { + int n = nth.find('n'); + if (n != -1) { + if (nth[0] == '-') { + if (n == 1) + a = -1; // -n == -1n + else + a = nth.substring(0, n).toInt(); + } else if (!n) + a = 1; // n == 1n + else + a = nth.substring(0, n).toInt(); + + int p = nth.find('+', n); + if (p != -1) + b = nth.substring(p + 1, nth.length() - p - 1).toInt(); + else { + p = nth.find('-', n); + b = -nth.substring(p + 1, nth.length() - p - 1).toInt(); + } + } else + b = nth.toInt(); + } + return true; +} + +// a helper function for checking nth-arguments +static bool matchNth(int count, int a, int b) +{ + if (!a) + return count == b; + else if (a > 0) { + if (count < b) + return false; + return (count - b) % a == 0; + } else { + if (count > b) + return false; + return (b - count) % (-a) == 0; + } +} + + +#ifdef STYLE_SHARING_STATS +static int fraction = 0; +static int total = 0; +#endif + +static const unsigned cStyleSearchThreshold = 10; + +Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) +{ + if (parent && parent->isStyledElement()) { + StyledElement* p = static_cast<StyledElement*>(parent); + if (!p->inlineStyleDecl() && !p->hasID()) { + Node* r = p->previousSibling(); + unsigned subcount = 0; + RenderStyle* st = p->renderStyle(); + while (r) { + if (r->renderStyle() == st) + return r->lastChild(); + if (subcount++ == cStyleSearchThreshold) + return 0; + r = r->previousSibling(); + } + if (!r && depth < cStyleSearchThreshold) + r = locateCousinList(static_cast<Element*>(parent->parentNode()), depth + 1); + while (r) { + if (r->renderStyle() == st) + return r->lastChild(); + if (subcount++ == cStyleSearchThreshold) + return 0; + r = r->previousSibling(); + } + } + } + return 0; +} + +bool CSSStyleSelector::canShareStyleWithElement(Node* n) +{ + if (n->isStyledElement()) { + StyledElement* s = static_cast<StyledElement*>(n); + RenderStyle* style = s->renderStyle(); + if (style && !style->unique() && + (s->tagQName() == m_element->tagQName()) && !s->hasID() && + (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() && + (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) && + (s->isLink() == m_element->isLink()) && + !style->affectedByAttributeSelectors() && + (s->hovered() == m_element->hovered()) && + (s->active() == m_element->active()) && + (s->focused() == m_element->focused()) && + (s != s->document()->getCSSTarget() && m_element != m_element->document()->getCSSTarget()) && + (s->getAttribute(typeAttr) == m_element->getAttribute(typeAttr)) && + (s->getAttribute(XMLNames::langAttr) == m_element->getAttribute(XMLNames::langAttr)) && + (s->getAttribute(langAttr) == m_element->getAttribute(langAttr)) && + (s->getAttribute(readonlyAttr) == m_element->getAttribute(readonlyAttr)) && + (s->getAttribute(cellpaddingAttr) == m_element->getAttribute(cellpaddingAttr))) { + bool isControl = s->isControl(); + if (isControl != m_element->isControl()) + return false; + if (isControl && (s->isEnabled() != m_element->isEnabled()) || + (s->isIndeterminate() != m_element->isIndeterminate()) || + (s->isChecked() != m_element->isChecked())) + return false; + + if (style->transitions()) + return false; + + bool classesMatch = true; + if (s->hasClass()) { + const AtomicString& class1 = m_element->getAttribute(classAttr); + const AtomicString& class2 = s->getAttribute(classAttr); + classesMatch = (class1 == class2); + } + + if (classesMatch) { + bool mappedAttrsMatch = true; + if (s->hasMappedAttributes()) + mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes()); + if (mappedAttrsMatch) { + bool linksMatch = true; + if (s->isLink()) { + // We need to check to see if the visited state matches. + Color linkColor = m_element->document()->linkColor(); + Color visitedColor = m_element->document()->visitedLinkColor(); + if (pseudoState == PseudoUnknown) + checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor); + linksMatch = (pseudoState == style->pseudoState()); + } + + if (linksMatch) + return true; + } + } + } + } + return false; +} + +RenderStyle* CSSStyleSelector::locateSharedStyle() +{ + if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) { + // Check previous siblings. + unsigned count = 0; + Node* n; + for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } + while (n) { + if (canShareStyleWithElement(n)) + return n->renderStyle(); + if (count++ == cStyleSearchThreshold) + return 0; + for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } + } + if (!n) + n = locateCousinList(static_cast<Element*>(m_element->parentNode())); + while (n) { + if (canShareStyleWithElement(n)) + return n->renderStyle(); + if (count++ == cStyleSearchThreshold) + return 0; + for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { } + } + } + return 0; +} + +void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule) +{ + // First we match rules from the user agent sheet. + CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") + ? m_defaultPrintStyle : m_defaultStyle; + matchRules(userAgentStyleSheet, firstUARule, lastUARule); + + // In quirks mode, we match rules from the quirks user agent sheet. + if (!strictParsing) + matchRules(m_defaultQuirksStyle, firstUARule, lastUARule); + + // If we're in view source mode, then we match rules from the view source style sheet. + if (m_document->frame() && m_document->frame()->inViewSourceMode()) + matchRules(m_defaultViewSourceStyle, firstUARule, lastUARule); +} + +// If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where +// relative units are interpreted according to document root element style, styled only with UA stylesheet + +RenderStyle* CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault) +{ + // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer + // will vanish if a style recalc happens during loading. + if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) { + if (!m_styleNotYetAvailable) { + m_styleNotYetAvailable = ::new RenderStyle; + m_styleNotYetAvailable->ref(); + m_styleNotYetAvailable->setDisplay(NONE); + m_styleNotYetAvailable->font().update(m_fontSelector); + } + m_styleNotYetAvailable->ref(); + e->document()->setHasNodesWithPlaceholderStyle(); + return m_styleNotYetAvailable; + } + + initElementAndPseudoState(e); + if (allowSharing) { + m_style = locateSharedStyle(); +#ifdef STYLE_SHARING_STATS + fraction += m_style != 0; + total++; + printf("Sharing %d out of %d\n", fraction, total); +#endif + if (m_style) { + m_style->ref(); + return m_style; + } + } + initForStyleResolve(e, defaultParent); + + if (resolveForRootDefault) { + m_style = ::new RenderStyle(); + // don't ref, because we want to delete this, but we cannot unref it + } else { + m_style = new (e->document()->renderArena()) RenderStyle(); + m_style->ref(); + } + if (m_parentStyle) + m_style->inheritFrom(m_parentStyle); + else + m_parentStyle = m_style; + +#if ENABLE(SVG) + if (e->isSVGElement() && !m_svgSheet) { + // SVG rules. + m_svgSheet = parseUASheet(svgUserAgentStyleSheet); + m_defaultStyle->addRulesFromSheet(m_svgSheet, screenEval()); + m_defaultPrintStyle->addRulesFromSheet(m_svgSheet, printEval()); + } +#endif + + int firstUARule = -1, lastUARule = -1; + int firstUserRule = -1, lastUserRule = -1; + int firstAuthorRule = -1, lastAuthorRule = -1; + matchUARules(firstUARule, lastUARule); + + if (!resolveForRootDefault) { + // 4. Now we check user sheet rules. + if (m_matchAuthorAndUserStyles) + matchRules(m_userStyle, firstUserRule, lastUserRule); + + // 5. Now check author rules, beginning first with presentational attributes + // mapped from HTML. + if (m_styledElement) { + // Ask if the HTML element has mapped attributes. + if (m_styledElement->hasMappedAttributes()) { + // Walk our attribute list and add in each decl. + const NamedMappedAttrMap* map = m_styledElement->mappedAttributes(); + for (unsigned i = 0; i < map->length(); i++) { + MappedAttribute* attr = map->attributeItem(i); + if (attr->decl()) { + lastAuthorRule = m_matchedDecls.size(); + if (firstAuthorRule == -1) + firstAuthorRule = lastAuthorRule; + addMatchedDeclaration(attr->decl()); + } + } + } + + // Now we check additional mapped declarations. + // Tables and table cells share an additional mapped rule that must be applied + // after all attributes, since their mapped style depends on the values of multiple attributes. + if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) { + m_additionalAttributeStyleDecls.clear(); + m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls); + if (!m_additionalAttributeStyleDecls.isEmpty()) { + unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size(); + if (firstAuthorRule == -1) + firstAuthorRule = m_matchedDecls.size(); + lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1; + for (unsigned i = 0; i < additionalDeclsSize; i++) + addMatchedDeclaration(m_additionalAttributeStyleDecls[i]); + } + } + } + + // 6. Check the rules in author sheets next. + if (m_matchAuthorAndUserStyles) + matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); + + // 7. Now check our inline style attribute. + if (m_matchAuthorAndUserStyles && m_styledElement) { + CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl(); + if (inlineDecl) { + lastAuthorRule = m_matchedDecls.size(); + if (firstAuthorRule == -1) + firstAuthorRule = lastAuthorRule; + addMatchedDeclaration(inlineDecl); + } + } + } + + // Now we have all of the matched rules in the appropriate order. Walk the rules and apply + // high-priority properties first, i.e., those properties that other properties depend on. + // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important + // and (4) normal important. + m_lineHeightValue = 0; + applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); + if (!resolveForRootDefault) { + applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); + applyDeclarations(true, true, firstUserRule, lastUserRule); + } + applyDeclarations(true, true, firstUARule, lastUARule); + + // If our font got dirtied, go ahead and update it now. + if (m_fontDirty) + updateFont(); + + // Line-height is set when we are sure we decided on the font-size + if (m_lineHeightValue) + applyProperty(CSS_PROP_LINE_HEIGHT, m_lineHeightValue); + + // Now do the normal priority UA properties. + applyDeclarations(false, false, firstUARule, lastUARule); + + // Cache our border and background so that we can examine them later. + cacheBorderAndBackground(); + + // Now do the author and user normal priority properties and all the !important properties. + if (!resolveForRootDefault) { + applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1); + applyDeclarations(false, true, firstAuthorRule, lastAuthorRule); + applyDeclarations(false, true, firstUserRule, lastUserRule); + } + applyDeclarations(false, true, firstUARule, lastUARule); + + // If our font got dirtied by one of the non-essential font props, + // go ahead and update it a second time. + if (m_fontDirty) + updateFont(); + + // Clean up our style object's display and text decorations (among other fixups). + adjustRenderStyle(m_style, e); + + // If we are a link, cache the determined pseudo-state. + if (e->isLink()) + m_style->setPseudoState(pseudoState); + + // If we have first-letter pseudo style, do not share this style + if (m_style->hasPseudoStyle(RenderStyle::FIRST_LETTER)) + m_style->setUnique(); + + // Now return the style. + return m_style; +} + +RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, Element* e, RenderStyle* parentStyle) +{ + if (!e) + return 0; + + initElementAndPseudoState(e); + initForStyleResolve(e, parentStyle); + m_pseudoStyle = pseudo; + + // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking + // those rules. + + // Check UA, user and author rules. + int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1; + matchUARules(firstUARule, lastUARule); + + if (m_matchAuthorAndUserStyles) { + matchRules(m_userStyle, firstUserRule, lastUserRule); + matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); + } + + if (m_matchedDecls.isEmpty()) + return 0; + + m_style = new (e->document()->renderArena()) RenderStyle(); + m_style->ref(); + if (parentStyle) + m_style->inheritFrom(parentStyle); + else + parentStyle = m_style; + m_style->noninherited_flags._styleType = m_pseudoStyle; + + m_lineHeightValue = 0; + // High-priority properties. + applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); + applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); + applyDeclarations(true, true, firstUserRule, lastUserRule); + applyDeclarations(true, true, firstUARule, lastUARule); + + // If our font got dirtied, go ahead and update it now. + if (m_fontDirty) + updateFont(); + + // Line-height is set when we are sure we decided on the font-size + if (m_lineHeightValue) + applyProperty(CSS_PROP_LINE_HEIGHT, m_lineHeightValue); + + // Now do the normal priority properties. + applyDeclarations(false, false, firstUARule, lastUARule); + + // Cache our border and background so that we can examine them later. + cacheBorderAndBackground(); + + applyDeclarations(false, false, lastUARule + 1, m_matchedDecls.size() - 1); + applyDeclarations(false, true, firstAuthorRule, lastAuthorRule); + applyDeclarations(false, true, firstUserRule, lastUserRule); + applyDeclarations(false, true, firstUARule, lastUARule); + + // If our font got dirtied by one of the non-essential font props, + // go ahead and update it a second time. + if (m_fontDirty) + updateFont(); + // Clean up our style object's display and text decorations (among other fixups). + adjustRenderStyle(m_style, 0); + + // Now return the style. + return m_style; +} + +static void addIntrinsicMargins(RenderStyle* style) +{ + // Intrinsic margin value. + const int intrinsicMargin = 2; + + // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed. + // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame. + if (style->width().isIntrinsicOrAuto()) { + if (style->marginLeft().quirk()) + style->setMarginLeft(Length(intrinsicMargin, Fixed)); + if (style->marginRight().quirk()) + style->setMarginRight(Length(intrinsicMargin, Fixed)); + } + + if (style->height().isAuto()) { + if (style->marginTop().quirk()) + style->setMarginTop(Length(intrinsicMargin, Fixed)); + if (style->marginBottom().quirk()) + style->setMarginBottom(Length(intrinsicMargin, Fixed)); + } +} + +void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e) +{ + // Cache our original display. + style->setOriginalDisplay(style->display()); + + if (style->display() != NONE) { + // If we have a <td> that specifies a float property, in quirks mode we just drop the float + // property. + // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force + // these tags to retain their display types. + if (!strictParsing && e) { + if (e->hasTagName(tdTag)) { + style->setDisplay(TABLE_CELL); + style->setFloating(FNONE); + } + else if (e->hasTagName(tableTag)) + style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); + } + + // Tables never support the -webkit-* values for text-align and will reset back to the default. + if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) + style->setTextAlign(TAAUTO); + + // Frames and framesets never honor position:relative or position:absolute. This is necessary to + // fix a crash where a site tries to position these objects. They also never honor display. + if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { + style->setPosition(StaticPosition); + style->setDisplay(BLOCK); + } + + // Table headers with a text-align of auto will change the text-align to center. + if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO) + style->setTextAlign(CENTER); + + // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to + // position or float an inline, compact, or run-in. Cache the original display, since it + // may be needed for positioned elements that have to compute their static normal flow + // positions. We also force inline-level roots to be block-level. + if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX && + (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE || + (e && e->document()->documentElement() == e))) { + if (style->display() == INLINE_TABLE) + style->setDisplay(TABLE); + else if (style->display() == INLINE_BOX) + style->setDisplay(BOX); + else if (style->display() == LIST_ITEM) { + // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, + // but only in quirks mode. + if (!strictParsing && style->floating() != FNONE) + style->setDisplay(BLOCK); + } + else + style->setDisplay(BLOCK); + } + + // After performing the display mutation, check table rows. We do not honor position:relative on + // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock() + // on some sites). + if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP || + style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) && + style->position() == RelativePosition) + style->setPosition(StaticPosition); + } + + // Make sure our z-index value is only applied if the object is positioned, + // relatively positioned, transparent, or has a transform. + if (style->position() == StaticPosition && style->opacity() == 1.0f && !style->hasTransform()) + style->setHasAutoZIndex(); + + // Auto z-index becomes 0 for the root element and transparent objects. This prevents + // cases where objects that should be blended as a single unit end up with a non-transparent + // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms. + if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || style->hasTransform())) + style->setZIndex(0); + + // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'. + // This will be important when we use block flows for all form controls. + if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) || + e->hasTagName(selectTag) || e->hasTagName(textareaTag))) { + if (style->width().isAuto()) + style->setWidth(Length(Intrinsic)); + } + + // Finally update our text decorations in effect, but don't allow text-decoration to percolate through + // tables, inline blocks, inline tables, or run-ins. + if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN + || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX) + style->setTextDecorationsInEffect(style->textDecoration()); + else + style->addToTextDecorationsInEffect(style->textDecoration()); + + // If either overflow value is not visible, change to auto. + if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) + style->setOverflowY(OMARQUEE); + else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) + style->setOverflowX(OMARQUEE); + else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) + style->setOverflowX(OAUTO); + else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) + style->setOverflowY(OAUTO); + + // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. + // FIXME: Eventually table sections will support auto and scroll. + if (style->display() == TABLE || style->display() == INLINE_TABLE || + style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { + if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) + style->setOverflowX(OVISIBLE); + if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) + style->setOverflowY(OVISIBLE); + } + + // Cull out any useless layers and also repeat patterns into additional layers. + style->adjustBackgroundLayers(); + + // Do the same for transitions. + style->adjustTransitions(); + + // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will + // alter fonts and heights/widths. + if (e && e->isControl() && style->fontSize() >= 11) { + // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, + // so we have to treat all image buttons as though they were explicitly sized. + if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE) + addIntrinsicMargins(style); + } + + // Let the theme also have a crack at adjusting the style. + if (style->hasAppearance()) + theme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor); + +#if ENABLE(SVG) + if (e && e->isSVGElement()) { + // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty + if (style->overflowY() == OSCROLL) + style->setOverflowY(OHIDDEN); + else if (style->overflowY() == OAUTO) + style->setOverflowY(OVISIBLE); + + if (style->overflowX() == OSCROLL) + style->setOverflowX(OHIDDEN); + else if (style->overflowX() == OAUTO) + style->setOverflowX(OVISIBLE); + + // Only the root <svg> element in an SVG document fragment tree honors css position + if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) + style->setPosition(RenderStyle::initialPosition()); + } +#endif +} + +void CSSStyleSelector::updateFont() +{ + checkForTextSizeAdjust(); + checkForGenericFamilyChange(m_style, m_parentStyle); + m_style->font().update(m_fontSelector); + m_fontDirty = false; +} + +void CSSStyleSelector::cacheBorderAndBackground() +{ + m_hasUAAppearance = m_style->hasAppearance(); + if (m_hasUAAppearance) { + m_borderData = m_style->border(); + m_backgroundData = *m_style->backgroundLayers(); + m_backgroundColor = m_style->backgroundColor(); + } +} + +RefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly) +{ + if (!e || !e->document()->haveStylesheetsLoaded()) + return 0; + + m_collectRulesOnly = true; + + initElementAndPseudoState(e); + initForStyleResolve(e, 0); + + if (!authorOnly) { + int firstUARule = -1, lastUARule = -1; + // First we match rules from the user agent sheet. + matchUARules(firstUARule, lastUARule); + + // Now we check user sheet rules. + if (m_matchAuthorAndUserStyles) { + int firstUserRule = -1, lastUserRule = -1; + matchRules(m_userStyle, firstUserRule, lastUserRule); + } + } + + if (m_matchAuthorAndUserStyles) { + // Check the rules in author sheets. + int firstAuthorRule = -1, lastAuthorRule = -1; + matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); + } + + m_collectRulesOnly = false; + + return m_ruleList; +} + +RefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, StringImpl* pseudoStyle, bool authorOnly) +{ + // FIXME: Implement this. + return 0; +} + +bool CSSStyleSelector::checkSelector(CSSSelector* sel) +{ + dynamicPseudo = RenderStyle::NOPSEUDO; + + // Check the selector + SelectorMatch match = checkSelector(sel, m_element, true, false); + if (match != SelectorMatches) + return false; + + if (m_pseudoStyle != RenderStyle::NOPSEUDO && m_pseudoStyle != dynamicPseudo) + return false; + + return true; +} + +// Recursive check of selectors and combinators +// It can return 3 different values: +// * SelectorMatches - the selector matches the element e +// * SelectorFailsLocally - the selector fails for the element e +// * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e +CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(CSSSelector* sel, Element* e, bool isAncestor, bool isSubSelector) +{ +#if ENABLE(SVG) + // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree + // because its contents are not part of the formal document structure. + if (e->isSVGElement() && e->isShadowNode()) + return SelectorFailsCompletely; +#endif + + // first selector has to match + if (!checkOneSelector(sel, e, isAncestor, isSubSelector)) + return SelectorFailsLocally; + + // The rest of the selectors has to match + CSSSelector::Relation relation = sel->relation(); + + // Prepare next sel + sel = sel->m_tagHistory; + if (!sel) + return SelectorMatches; + + if (relation != CSSSelector::SubSelector) + // Bail-out if this selector is irrelevant for the pseudoStyle + if (m_pseudoStyle != RenderStyle::NOPSEUDO && m_pseudoStyle != dynamicPseudo) + return SelectorFailsCompletely; + + switch (relation) { + case CSSSelector::Descendant: + while (true) { + Node* n = e->parentNode(); + if (!n || !n->isElementNode()) + return SelectorFailsCompletely; + e = static_cast<Element*>(n); + SelectorMatch match = checkSelector(sel, e, true, false); + if (match != SelectorFailsLocally) + return match; + } + break; + case CSSSelector::Child: + { + Node* n = e->parentNode(); + if (!n || !n->isElementNode()) + return SelectorFailsCompletely; + e = static_cast<Element*>(n); + return checkSelector(sel, e, true, false); + } + case CSSSelector::DirectAdjacent: + { + if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByDirectAdjacentRules(); + } + Node* n = e->previousSibling(); + while (n && !n->isElementNode()) + n = n->previousSibling(); + if (!n) + return SelectorFailsLocally; + e = static_cast<Element*>(n); + return checkSelector(sel, e, false, false); + } + case CSSSelector::IndirectAdjacent: + if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByForwardPositionalRules(); + } + while (true) { + Node* n = e->previousSibling(); + while (n && !n->isElementNode()) + n = n->previousSibling(); + if (!n) + return SelectorFailsLocally; + e = static_cast<Element*>(n); + SelectorMatch match = checkSelector(sel, e, false, false); + if (match != SelectorFailsLocally) + return match; + }; + break; + case CSSSelector::SubSelector: + // a selector is invalid if something follows a pseudo-element + if (e == m_element && dynamicPseudo != RenderStyle::NOPSEUDO) + return SelectorFailsCompletely; + return checkSelector(sel, e, isAncestor, true); + } + + return SelectorFailsCompletely; +} + +static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName) +{ + set->add(qName.localName().impl()); +} + +static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet() +{ + // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive + // Mozilla treats all other values as case-sensitive, thus so do we. + HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>; + + addLocalNameToSet(attrSet, accept_charsetAttr); + addLocalNameToSet(attrSet, acceptAttr); + addLocalNameToSet(attrSet, alignAttr); + addLocalNameToSet(attrSet, alinkAttr); + addLocalNameToSet(attrSet, axisAttr); + addLocalNameToSet(attrSet, bgcolorAttr); + addLocalNameToSet(attrSet, charsetAttr); + addLocalNameToSet(attrSet, checkedAttr); + addLocalNameToSet(attrSet, clearAttr); + addLocalNameToSet(attrSet, codetypeAttr); + addLocalNameToSet(attrSet, colorAttr); + addLocalNameToSet(attrSet, compactAttr); + addLocalNameToSet(attrSet, declareAttr); + addLocalNameToSet(attrSet, deferAttr); + addLocalNameToSet(attrSet, dirAttr); + addLocalNameToSet(attrSet, disabledAttr); + addLocalNameToSet(attrSet, enctypeAttr); + addLocalNameToSet(attrSet, faceAttr); + addLocalNameToSet(attrSet, frameAttr); + addLocalNameToSet(attrSet, hreflangAttr); + addLocalNameToSet(attrSet, http_equivAttr); + addLocalNameToSet(attrSet, langAttr); + addLocalNameToSet(attrSet, languageAttr); + addLocalNameToSet(attrSet, linkAttr); + addLocalNameToSet(attrSet, mediaAttr); + addLocalNameToSet(attrSet, methodAttr); + addLocalNameToSet(attrSet, multipleAttr); + addLocalNameToSet(attrSet, nohrefAttr); + addLocalNameToSet(attrSet, noresizeAttr); + addLocalNameToSet(attrSet, noshadeAttr); + addLocalNameToSet(attrSet, nowrapAttr); + addLocalNameToSet(attrSet, readonlyAttr); + addLocalNameToSet(attrSet, relAttr); + addLocalNameToSet(attrSet, revAttr); + addLocalNameToSet(attrSet, rulesAttr); + addLocalNameToSet(attrSet, scopeAttr); + addLocalNameToSet(attrSet, scrollingAttr); + addLocalNameToSet(attrSet, selectedAttr); + addLocalNameToSet(attrSet, shapeAttr); + addLocalNameToSet(attrSet, targetAttr); + addLocalNameToSet(attrSet, textAttr); + addLocalNameToSet(attrSet, typeAttr); + addLocalNameToSet(attrSet, valignAttr); + addLocalNameToSet(attrSet, valuetypeAttr); + addLocalNameToSet(attrSet, vlinkAttr); + + return attrSet; +} + +static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr) +{ + static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet(); + bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom); + return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl()); +} + +bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isAncestor, bool isSubSelector) +{ + if (!e) + return false; + + if (sel->hasTag()) { + const AtomicString& localName = e->localName(); + const AtomicString& ns = e->namespaceURI(); + const AtomicString& selLocalName = sel->m_tag.localName(); + const AtomicString& selNS = sel->m_tag.namespaceURI(); + + if ((selLocalName != starAtom && localName != selLocalName) || + (selNS != starAtom && ns != selNS)) + return false; + } + + if (sel->hasAttribute()) { + if (sel->m_match == CSSSelector::Class) { + if (!e->hasClass()) + return false; + return e->getClassNames()->contains(sel->m_value); + } else if (sel->m_match == CSSSelector::Id) + return e->hasID() && e->getIDAttribute() == sel->m_value; + else if (m_style && (e != m_element || !m_styledElement || (!m_styledElement->isMappedAttribute(sel->m_attr) && sel->m_attr != typeAttr && sel->m_attr != readonlyAttr))) { + m_style->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style. + m_selectorAttrs.add(sel->m_attr.localName().impl()); + } + + const AtomicString& value = e->getAttribute(sel->m_attr); + if (value.isNull()) + return false; // attribute is not set + + bool caseSensitive = m_isXMLDoc || !htmlAttributeHasCaseInsensitiveValue(sel->m_attr); + + switch (sel->m_match) { + case CSSSelector::Exact: + if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value)) + return false; + break; + case CSSSelector::List: + { + // The selector's value can't contain a space, or it's totally bogus. + if (sel->m_value.contains(' ')) + return false; + + int startSearchAt = 0; + while (true) { + int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive); + if (foundPos == -1) + return false; + if (foundPos == 0 || value[foundPos-1] == ' ') { + unsigned endStr = foundPos + sel->m_value.length(); + if (endStr == value.length() || value[endStr] == ' ') + break; // We found a match. + } + + // No match. Keep looking. + startSearchAt = foundPos + 1; + } + break; + } + case CSSSelector::Contain: + if (!value.contains(sel->m_value, caseSensitive)) + return false; + break; + case CSSSelector::Begin: + if (!value.startsWith(sel->m_value, caseSensitive)) + return false; + break; + case CSSSelector::End: + if (!value.endsWith(sel->m_value, caseSensitive)) + return false; + break; + case CSSSelector::Hyphen: + if (value.length() < sel->m_value.length()) + return false; + if (!value.startsWith(sel->m_value, caseSensitive)) + return false; + // It they start the same, check for exact match or following '-': + if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-') + return false; + break; + case CSSSelector::PseudoClass: + case CSSSelector::PseudoElement: + default: + break; + } + } + if (sel->m_match == CSSSelector::PseudoClass) { + switch (sel->pseudoType()) { + // Pseudo classes: + case CSSSelector::PseudoEmpty: { + bool result = true; + for (Node* n = e->firstChild(); n; n = n->nextSibling()) { + if (n->isElementNode()) { + result = false; + break; + } else if (n->isTextNode()) { + Text* textNode = static_cast<Text*>(n); + if (!textNode->data().isEmpty()) { + result = false; + break; + } + } + } + if (!m_collectRulesOnly) { + if (m_element == e && m_style) + m_style->setEmptyState(result); + else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique())) + e->renderStyle()->setEmptyState(result); + } + return result; + } + case CSSSelector::PseudoFirstChild: { + // first-child matches the first child that is an element + if (e->parentNode() && e->parentNode()->isElementNode()) { + bool result = false; + Node* n = e->previousSibling(); + while (n && !n->isElementNode()) + n = n->previousSibling(); + if (!n) + result = true; + if (!m_collectRulesOnly) { + RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle(); + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByFirstChildRules(); + if (result && childStyle) + childStyle->setFirstChildState(); + } + return result; + } + break; + } + case CSSSelector::PseudoFirstOfType: { + // first-of-type matches the first element of its type + if (e->parentNode() && e->parentNode()->isElementNode()) { + bool result = false; + const QualifiedName& type = e->tagQName(); + Node* n = e->previousSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + break; + n = n->previousSibling(); + } + if (!n) + result = true; + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByForwardPositionalRules(); + } + return result; + } + break; + } + case CSSSelector::PseudoLastChild: { + // last-child matches the last child that is an element + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + bool result = false; + if (parentNode->isFinishedParsingChildren()) { + Node* n = e->nextSibling(); + while (n && !n->isElementNode()) + n = n->nextSibling(); + if (!n) + result = true; + } + if (!m_collectRulesOnly) { + RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle(); + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByLastChildRules(); + if (result && childStyle) + childStyle->setLastChildState(); + } + return result; + } + break; + } + case CSSSelector::PseudoLastOfType: { + // last-of-type matches the last element of its type + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByBackwardPositionalRules(); + } + if (!parentNode->isFinishedParsingChildren()) + return false; + bool result = false; + const QualifiedName& type = e->tagQName(); + Node* n = e->nextSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + break; + n = n->nextSibling(); + } + if (!n) + result = true; + return result; + } + break; + } + case CSSSelector::PseudoOnlyChild: { + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + bool firstChild = false; + bool lastChild = false; + + Node* n = e->previousSibling(); + while (n && !n->isElementNode()) + n = n->previousSibling(); + if (!n) + firstChild = true; + if (firstChild && parentNode->isFinishedParsingChildren()) { + n = e->nextSibling(); + while (n && !n->isElementNode()) + n = n->nextSibling(); + if (!n) + lastChild = true; + } + if (!m_collectRulesOnly) { + RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle(); + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) { + parentStyle->setChildrenAffectedByFirstChildRules(); + parentStyle->setChildrenAffectedByLastChildRules(); + } + if (firstChild && childStyle) + childStyle->setFirstChildState(); + if (lastChild && childStyle) + childStyle->setLastChildState(); + } + return firstChild && lastChild; + } + break; + } + case CSSSelector::PseudoOnlyOfType: { + // FIXME: This selector is very slow. + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) { + parentStyle->setChildrenAffectedByForwardPositionalRules(); + parentStyle->setChildrenAffectedByBackwardPositionalRules(); + } + } + if (!parentNode->isFinishedParsingChildren()) + return false; + bool firstChild = false; + bool lastChild = false; + const QualifiedName& type = e->tagQName(); + Node* n = e->previousSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + break; + n = n->previousSibling(); + } + if (!n) + firstChild = true; + if (firstChild) { + n = e->nextSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + break; + n = n->nextSibling(); + } + if (!n) + lastChild = true; + } + return firstChild && lastChild; + } + break; + } + case CSSSelector::PseudoNthChild: { + int a, b; + // calculate a and b every time we run through checkOneSelector + // this should probably be saved after we calculate it once, but currently + // would require increasing the size of CSSSelector + if (!parseNth(sel->m_argument, a, b)) + break; + if (e->parentNode() && e->parentNode()->isElementNode()) { + int count = 1; + Node* n = e->previousSibling(); + while (n) { + if (n->isElementNode()) { + RenderStyle* s = n->renderStyle(); + unsigned index = s ? s->childIndex() : 0; + if (index) { + count += index; + break; + } + count++; + } + n = n->previousSibling(); + } + + if (!m_collectRulesOnly) { + RenderStyle* childStyle = (m_element == e) ? m_style : e->renderStyle(); + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (childStyle) + childStyle->setChildIndex(count); + if (parentStyle) + parentStyle->setChildrenAffectedByForwardPositionalRules(); + } + + if (matchNth(count, a, b)) + return true; + } + break; + } + case CSSSelector::PseudoNthOfType: { + // FIXME: This selector is very slow. + int a, b; + // calculate a and b every time we run through checkOneSelector (see above) + if (!parseNth(sel->m_argument, a, b)) + break; + if (e->parentNode() && e->parentNode()->isElementNode()) { + int count = 1; + const QualifiedName& type = e->tagQName(); + Node* n = e->previousSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + count++; + n = n->previousSibling(); + } + + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : e->parentNode()->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByForwardPositionalRules(); + } + + if (matchNth(count, a, b)) + return true; + } + break; + } + case CSSSelector::PseudoNthLastChild: { + int a, b; + // calculate a and b every time we run through checkOneSelector + // this should probably be saved after we calculate it once, but currently + // would require increasing the size of CSSSelector + if (!parseNth(sel->m_argument, a, b)) + break; + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByBackwardPositionalRules(); + } + if (!parentNode->isFinishedParsingChildren()) + return false; + int count = 1; + Node* n = e->nextSibling(); + while (n) { + if (n->isElementNode()) + count++; + n = n->nextSibling(); + } + if (matchNth(count, a, b)) + return true; + } + break; + } + case CSSSelector::PseudoNthLastOfType: { + // FIXME: This selector is very slow. + int a, b; + // calculate a and b every time we run through checkOneSelector (see above) + if (!parseNth(sel->m_argument, a, b)) + break; + if (e->parentNode() && e->parentNode()->isElementNode()) { + Element* parentNode = static_cast<Element*>(e->parentNode()); + if (!m_collectRulesOnly) { + RenderStyle* parentStyle = (m_element == e) ? m_parentStyle : parentNode->renderStyle(); + if (parentStyle) + parentStyle->setChildrenAffectedByBackwardPositionalRules(); + } + if (!parentNode->isFinishedParsingChildren()) + return false; + int count = 1; + const QualifiedName& type = e->tagQName(); + Node* n = e->nextSibling(); + while (n) { + if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type)) + count++; + n = n->nextSibling(); + } + if (matchNth(count, a, b)) + return true; + } + break; + } + case CSSSelector::PseudoTarget: + if (e == e->document()->getCSSTarget()) + return true; + break; + case CSSSelector::PseudoAnyLink: + if (pseudoState == PseudoUnknown) + checkPseudoState(e, false); + if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited) + return true; + break; + case CSSSelector::PseudoAutofill: + if (e && e->hasTagName(inputTag)) + return static_cast<HTMLInputElement*>(e)->autofilled(); + break; + case CSSSelector::PseudoLink: + if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) + checkPseudoState(e); + if (pseudoState == PseudoLink) + return true; + break; + case CSSSelector::PseudoVisited: + if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) + checkPseudoState(e); + if (pseudoState == PseudoVisited) + return true; + break; + case CSSSelector::PseudoDrag: { + if (m_element == e && m_style) + m_style->setAffectedByDragRules(true); + if (m_element != e && e->renderStyle()) + e->renderStyle()->setAffectedByDragRules(true); + if (e->renderer() && e->renderer()->isDragging()) + return true; + break; + } + case CSSSelector::PseudoFocus: + if (e && e->focused() && e->document()->frame()->selectionController()->isFocusedAndActive()) + return true; + break; + case CSSSelector::PseudoHover: { + // If we're in quirks mode, then hover should never match anchors with no + // href and *:hover should not match anything. This is important for sites like wsj.com. + if (strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { + if (m_element == e && m_style) + m_style->setAffectedByHoverRules(true); + if (m_element != e && e->renderStyle()) + e->renderStyle()->setAffectedByHoverRules(true); + if (e->hovered()) + return true; + } + break; + } + case CSSSelector::PseudoActive: + // If we're in quirks mode, then :active should never match anchors with no + // href and *:active should not match anything. + if (strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) { + if (m_element == e && m_style) + m_style->setAffectedByActiveRules(true); + else if (e->renderStyle()) + e->renderStyle()->setAffectedByActiveRules(true); + if (e->active()) + return true; + } + break; + case CSSSelector::PseudoEnabled: + if (e && e->isControl() && !e->isInputTypeHidden()) + // The UI spec states that you can't match :enabled unless you are an object that can + // "receive focus and be activated." We will limit matching of this pseudo-class to elements + // that are non-"hidden" controls. + return e->isEnabled(); + break; + case CSSSelector::PseudoDisabled: + if (e && e->isControl() && !e->isInputTypeHidden()) + // The UI spec states that you can't match :enabled unless you are an object that can + // "receive focus and be activated." We will limit matching of this pseudo-class to elements + // that are non-"hidden" controls. + return !e->isEnabled(); + break; + case CSSSelector::PseudoChecked: + // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that + // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just + // obey the CSS spec here in the test for matching the pseudo. + if (e && e->isChecked() && !e->isIndeterminate()) + return true; + break; + case CSSSelector::PseudoIndeterminate: + if (e && e->isIndeterminate()) + return true; + break; + case CSSSelector::PseudoRoot: + if (e == e->document()->documentElement()) + return true; + break; + case CSSSelector::PseudoLang: { + Node* n = e; + AtomicString value; + // The language property is inherited, so we iterate over the parents + // to find the first language. + while (n && value.isEmpty()) { + if (n->isElementNode()) { + // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7 + value = static_cast<Element*>(n)->getAttribute(XMLNames::langAttr); + if (value.isEmpty()) + value = static_cast<Element*>(n)->getAttribute(langAttr); + } else if (n->isDocumentNode()) + // checking the MIME content-language + value = static_cast<Document*>(n)->contentLanguage(); + + n = n->parent(); + } + if (value.isEmpty() || !value.startsWith(sel->m_argument, false)) + break; + if (value.length() != sel->m_argument.length() && value[sel->m_argument.length()] != '-') + break; + return true; + } + case CSSSelector::PseudoNot: { + // check the simple selector + for (CSSSelector* subSel = sel->m_simpleSelector; subSel; subSel = subSel->m_tagHistory) { + // :not cannot nest. I don't really know why this is a + // restriction in CSS3, but it is, so let's honour it. + if (subSel->m_simpleSelector) + break; + if (!checkOneSelector(subSel, e, isAncestor, true)) + return true; + } + break; + } + case CSSSelector::PseudoUnknown: + case CSSSelector::PseudoNotParsed: + default: + ASSERT_NOT_REACHED(); + break; + } + return false; + } + if (sel->m_match == CSSSelector::PseudoElement) { + if (e != m_element) return false; + + switch (sel->pseudoType()) { + // Pseudo-elements: + case CSSSelector::PseudoFirstLine: + dynamicPseudo = RenderStyle::FIRST_LINE; + return true; + case CSSSelector::PseudoFirstLetter: + dynamicPseudo = RenderStyle::FIRST_LETTER; + if (Document* doc = e->document()) + doc->setUsesFirstLetterRules(true); + return true; + case CSSSelector::PseudoSelection: + dynamicPseudo = RenderStyle::SELECTION; + return true; + case CSSSelector::PseudoBefore: + dynamicPseudo = RenderStyle::BEFORE; + return true; + case CSSSelector::PseudoAfter: + dynamicPseudo = RenderStyle::AFTER; + return true; + case CSSSelector::PseudoFileUploadButton: + dynamicPseudo = RenderStyle::FILE_UPLOAD_BUTTON; + return true; + case CSSSelector::PseudoSliderThumb: + dynamicPseudo = RenderStyle::SLIDER_THUMB; + return true; + case CSSSelector::PseudoSearchCancelButton: + dynamicPseudo = RenderStyle::SEARCH_CANCEL_BUTTON; + return true; + case CSSSelector::PseudoSearchDecoration: + dynamicPseudo = RenderStyle::SEARCH_DECORATION; + return true; + case CSSSelector::PseudoSearchResultsDecoration: + dynamicPseudo = RenderStyle::SEARCH_RESULTS_DECORATION; + return true; + case CSSSelector::PseudoSearchResultsButton: + dynamicPseudo = RenderStyle::SEARCH_RESULTS_BUTTON; + return true; + case CSSSelector::PseudoMediaControlsPanel: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PANEL; + return true; + case CSSSelector::PseudoMediaControlsMuteButton: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON; + return true; + case CSSSelector::PseudoMediaControlsPlayButton: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON; + return true; + case CSSSelector::PseudoMediaControlsTimeDisplay: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIME_DISPLAY; + return true; + case CSSSelector::PseudoMediaControlsTimeline: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_TIMELINE; + return true; + case CSSSelector::PseudoMediaControlsSeekBackButton: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON; + return true; + case CSSSelector::PseudoMediaControlsSeekForwardButton: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON; + return true; + case CSSSelector::PseudoMediaControlsFullscreenButton: + dynamicPseudo = RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON; + return true; + case CSSSelector::PseudoUnknown: + case CSSSelector::PseudoNotParsed: + default: + ASSERT_NOT_REACHED(); + break; + } + return false; + } + // ### add the rest of the checks... + return true; +} + +// ----------------------------------------------------------------- + +CSSRuleSet::CSSRuleSet() +{ + m_universalRules = 0; + m_ruleCount = 0; +} + +CSSRuleSet::~CSSRuleSet() +{ + deleteAllValues(m_idRules); + deleteAllValues(m_classRules); + deleteAllValues(m_tagRules); + + delete m_universalRules; +} + + +void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, + CSSStyleRule* rule, CSSSelector* sel) +{ + if (!key) return; + CSSRuleDataList* rules = map.get(key); + if (!rules) { + rules = new CSSRuleDataList(m_ruleCount++, rule, sel); + map.set(key, rules); + } else + rules->append(m_ruleCount++, rule, sel); +} + +void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) +{ + if (sel->m_match == CSSSelector::Id) { + addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel); + return; + } + if (sel->m_match == CSSSelector::Class) { + addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel); + return; + } + + const AtomicString& localName = sel->m_tag.localName(); + if (localName != starAtom) { + addToRuleSet(localName.impl(), m_tagRules, rule, sel); + return; + } + + // Just put it in the universal rule set. + if (!m_universalRules) + m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel); + else + m_universalRules->append(m_ruleCount++, rule, sel); +} + +void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector) +{ + if (!sheet || !sheet->isCSSStyleSheet()) + return; + + // No media implies "all", but if a media list exists it must + // contain our current medium + if (sheet->media() && !medium.eval(sheet->media(), styleSelector)) + return; // the style sheet doesn't apply + + int len = sheet->length(); + + for (int i = 0; i < len; i++) { + StyleBase* item = sheet->item(i); + if (item->isStyleRule()) { + CSSStyleRule* rule = static_cast<CSSStyleRule*>(item); + for (CSSSelector* s = rule->selector(); s; s = s->next()) + addRule(rule, s); + } + else if (item->isImportRule()) { + CSSImportRule* import = static_cast<CSSImportRule*>(item); + if (!import->media() || medium.eval(import->media(), styleSelector)) + addRulesFromSheet(import->styleSheet(), medium, styleSelector); + } + else if (item->isMediaRule()) { + CSSMediaRule* r = static_cast<CSSMediaRule*>(item); + CSSRuleList* rules = r->cssRules(); + + if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) { + // Traverse child elements of the @media rule. + for (unsigned j = 0; j < rules->length(); j++) { + CSSRule *childItem = rules->item(j); + if (childItem->isStyleRule()) { + // It is a StyleRule, so append it to our list + CSSStyleRule* rule = static_cast<CSSStyleRule*>(childItem); + for (CSSSelector* s = rule->selector(); s; s = s->next()) + addRule(rule, s); + } else if (item->isFontFaceRule() && styleSelector) { + // Add this font face to our set. + const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item); + styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); + } + } // for rules + } // if rules + } else if (item->isFontFaceRule() && styleSelector) { + // Add this font face to our set. + const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item); + styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); + } + } +} + +// ------------------------------------------------------------------------------------- +// this is mostly boring stuff on how to apply a certain rule to the renderstyle... + +static Length convertToLength(CSSPrimitiveValue *primitiveValue, RenderStyle *style, bool *ok = 0) +{ + Length l; + if (!primitiveValue) { + if (ok) + *ok = false; + } else { + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else if (type == CSSPrimitiveValue::CSS_NUMBER) + l = Length(primitiveValue->getDoubleValue() * 100.0, Percent); + else if (ok) + *ok = false; + } + return l; +} + +void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant, + int startIndex, int endIndex) +{ + if (startIndex == -1) return; + for (int i = startIndex; i <= endIndex; i++) { + CSSMutableStyleDeclaration* decl = m_matchedDecls[i]; + DeprecatedValueListConstIterator<CSSProperty> end; + for (DeprecatedValueListConstIterator<CSSProperty> it = decl->valuesIterator(); it != end; ++it) { + const CSSProperty& current = *it; + // give special priority to font-xxx, color properties + if (isImportant == current.isImportant()) { + bool first; + switch (current.id()) { + case CSS_PROP_LINE_HEIGHT: + m_lineHeightValue = current.value(); + first = !applyFirst; // we apply line-height later + break; + case CSS_PROP_COLOR: + case CSS_PROP_DIRECTION: + case CSS_PROP_DISPLAY: + case CSS_PROP_FONT: + case CSS_PROP_FONT_SIZE: + case CSS_PROP_FONT_STYLE: + case CSS_PROP_FONT_FAMILY: + case CSS_PROP_FONT_WEIGHT: + case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: + case CSS_PROP_FONT_VARIANT: + // these have to be applied first, because other properties use the computed + // values of these porperties. + first = true; + break; + default: + first = false; + break; + } + if (first == applyFirst) + applyProperty(current.id(), current.value()); + } + } + } +} + +static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset) +{ + CounterDirectiveMap& map = style->accessCounterDirectives(); + typedef CounterDirectiveMap::iterator Iterator; + + Iterator end = map.end(); + for (Iterator it = map.begin(); it != end; ++it) + if (isReset) + it->second.m_reset = false; + else + it->second.m_increment = false; + + int length = list ? list->length() : 0; + for (int i = 0; i < length; ++i) { + Pair* pair = static_cast<CSSPrimitiveValue*>(list->item(i))->getPairValue(); + AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue(); + // FIXME: What about overflow? + int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue(); + CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second; + if (isReset) { + directives.m_reset = true; + directives.m_resetValue = value; + } else { + if (directives.m_increment) + directives.m_incrementValue += value; + else { + directives.m_increment = true; + directives.m_incrementValue = value; + } + } + } +} + +void CSSStyleSelector::applyProperty(int id, CSSValue *value) +{ + CSSPrimitiveValue* primitiveValue = 0; + if (value->isPrimitiveValue()) + primitiveValue = static_cast<CSSPrimitiveValue*>(value); + + Length l; + bool apply = false; + + unsigned short valueType = value->cssValueType(); + + bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT; + bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT); + + // These properties are used to set the correct margins/padding on RTL lists. + if (id == CSS_PROP__WEBKIT_MARGIN_START) + id = m_style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT; + else if (id == CSS_PROP__WEBKIT_PADDING_START) + id = m_style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT; + + // What follows is a list that maps the CSS properties into their corresponding front-end + // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and + // are only hit when mapping "inherit" or "initial" into front-end values. + switch (static_cast<CSSPropertyID>(id)) { +// ident only properties + case CSS_PROP_BACKGROUND_ATTACHMENT: + HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value) + return; + case CSS_PROP__WEBKIT_BACKGROUND_CLIP: + HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value) + return; + case CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: + HANDLE_BACKGROUND_VALUE(backgroundComposite, BackgroundComposite, value) + return; + case CSS_PROP__WEBKIT_BACKGROUND_ORIGIN: + HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value) + return; + case CSS_PROP_BACKGROUND_REPEAT: + HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value) + return; + case CSS_PROP__WEBKIT_BACKGROUND_SIZE: + HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value) + return; + case CSS_PROP_BORDER_COLLAPSE: + HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) + if (!primitiveValue) + return; + switch (primitiveValue->getIdent()) { + case CSS_VAL_COLLAPSE: + m_style->setBorderCollapse(true); + break; + case CSS_VAL_SEPARATE: + m_style->setBorderCollapse(false); + break; + default: + return; + } + return; + + case CSS_PROP_BORDER_TOP_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) + if (primitiveValue) + m_style->setBorderTopStyle(*primitiveValue); + return; + case CSS_PROP_BORDER_RIGHT_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) + if (primitiveValue) + m_style->setBorderRightStyle(*primitiveValue); + return; + case CSS_PROP_BORDER_BOTTOM_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) + if (primitiveValue) + m_style->setBorderBottomStyle(*primitiveValue); + return; + case CSS_PROP_BORDER_LEFT_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) + if (primitiveValue) + m_style->setBorderLeftStyle(*primitiveValue); + return; + case CSS_PROP_OUTLINE_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) + if (primitiveValue) { + if (primitiveValue->getIdent() == CSS_VAL_AUTO) + m_style->setOutlineStyle(DOTTED, true); + else + m_style->setOutlineStyle(*primitiveValue); + } + return; + case CSS_PROP_CAPTION_SIDE: + { + HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide) + if (primitiveValue) + m_style->setCaptionSide(*primitiveValue); + return; + } + case CSS_PROP_CLEAR: + { + HANDLE_INHERIT_AND_INITIAL(clear, Clear) + if (primitiveValue) + m_style->setClear(*primitiveValue); + return; + } + case CSS_PROP_DIRECTION: + { + HANDLE_INHERIT_AND_INITIAL(direction, Direction) + if (primitiveValue) + m_style->setDirection(*primitiveValue); + return; + } + case CSS_PROP_DISPLAY: + { + HANDLE_INHERIT_AND_INITIAL(display, Display) + if (primitiveValue) + m_style->setDisplay(*primitiveValue); + return; + } + + case CSS_PROP_EMPTY_CELLS: + { + HANDLE_INHERIT_AND_INITIAL(emptyCells, EmptyCells) + if (primitiveValue) + m_style->setEmptyCells(*primitiveValue); + return; + } + case CSS_PROP_FLOAT: + { + HANDLE_INHERIT_AND_INITIAL(floating, Floating) + if (primitiveValue) + m_style->setFloating(*primitiveValue); + return; + } + + case CSS_PROP_FONT_STYLE: + { + FontDescription fontDescription = m_style->fontDescription(); + if (isInherit) + fontDescription.setItalic(m_parentStyle->fontDescription().italic()); + else if (isInitial) + fontDescription.setItalic(false); + else { + if (!primitiveValue) + return; + switch (primitiveValue->getIdent()) { + case CSS_VAL_OBLIQUE: + // FIXME: oblique is the same as italic for the moment... + case CSS_VAL_ITALIC: + fontDescription.setItalic(true); + break; + case CSS_VAL_NORMAL: + fontDescription.setItalic(false); + break; + default: + return; + } + } + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + + case CSS_PROP_FONT_VARIANT: + { + FontDescription fontDescription = m_style->fontDescription(); + if (isInherit) + fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps()); + else if (isInitial) + fontDescription.setSmallCaps(false); + else { + if (!primitiveValue) + return; + int id = primitiveValue->getIdent(); + if (id == CSS_VAL_NORMAL) + fontDescription.setSmallCaps(false); + else if (id == CSS_VAL_SMALL_CAPS) + fontDescription.setSmallCaps(true); + else + return; + } + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + + case CSS_PROP_FONT_WEIGHT: + { + FontDescription fontDescription = m_style->fontDescription(); + if (isInherit) + fontDescription.setWeight(m_parentStyle->fontDescription().weight()); + else if (isInitial) + fontDescription.setWeight(cNormalWeight); + else { + if (!primitiveValue) + return; + if (primitiveValue->getIdent()) { + switch (primitiveValue->getIdent()) { + // FIXME: We aren't genuinely supporting specific weight values. + case CSS_VAL_BOLD: + case CSS_VAL_BOLDER: + case CSS_VAL_600: + case CSS_VAL_700: + case CSS_VAL_800: + case CSS_VAL_900: + fontDescription.setWeight(cBoldWeight); + break; + case CSS_VAL_NORMAL: + case CSS_VAL_LIGHTER: + case CSS_VAL_100: + case CSS_VAL_200: + case CSS_VAL_300: + case CSS_VAL_400: + case CSS_VAL_500: + fontDescription.setWeight(cNormalWeight); + break; + default: + return; + } + } + else + { + // ### fix parsing of 100-900 values in parser, apply them here + } + } + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + + case CSS_PROP_LIST_STYLE_POSITION: + { + HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition) + if (primitiveValue) + m_style->setListStylePosition(*primitiveValue); + return; + } + + case CSS_PROP_LIST_STYLE_TYPE: + { + HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType) + if (primitiveValue) + m_style->setListStyleType(*primitiveValue); + return; + } + + case CSS_PROP_OVERFLOW: + { + if (isInherit) { + m_style->setOverflowX(m_parentStyle->overflowX()); + m_style->setOverflowY(m_parentStyle->overflowY()); + return; + } + + if (isInitial) { + m_style->setOverflowX(RenderStyle::initialOverflowX()); + m_style->setOverflowY(RenderStyle::initialOverflowY()); + return; + } + + EOverflow o = *primitiveValue; + + m_style->setOverflowX(o); + m_style->setOverflowY(o); + return; + } + + case CSS_PROP_OVERFLOW_X: + { + HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX) + m_style->setOverflowX(*primitiveValue); + return; + } + + case CSS_PROP_OVERFLOW_Y: + { + HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY) + m_style->setOverflowY(*primitiveValue); + return; + } + + case CSS_PROP_PAGE_BREAK_BEFORE: + { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) + if (primitiveValue) + m_style->setPageBreakBefore(*primitiveValue); + return; + } + + case CSS_PROP_PAGE_BREAK_AFTER: + { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak) + if (primitiveValue) + m_style->setPageBreakAfter(*primitiveValue); + return; + } + + case CSS_PROP_PAGE_BREAK_INSIDE: { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak) + if (!primitiveValue) + return; + EPageBreak pageBreak = *primitiveValue; + if (pageBreak != PBALWAYS) + m_style->setPageBreakInside(pageBreak); + return; + } + + case CSS_PROP_POSITION: + { + HANDLE_INHERIT_AND_INITIAL(position, Position) + if (primitiveValue) + m_style->setPosition(*primitiveValue); + return; + } + + case CSS_PROP_TABLE_LAYOUT: { + HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout) + + ETableLayout l = *primitiveValue; + if (l == TAUTO) + l = RenderStyle::initialTableLayout(); + + m_style->setTableLayout(l); + return; + } + + case CSS_PROP_UNICODE_BIDI: { + HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi) + m_style->setUnicodeBidi(*primitiveValue); + return; + } + case CSS_PROP_TEXT_TRANSFORM: { + HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform) + m_style->setTextTransform(*primitiveValue); + return; + } + + case CSS_PROP_VISIBILITY: + { + HANDLE_INHERIT_AND_INITIAL(visibility, Visibility) + m_style->setVisibility(*primitiveValue); + return; + } + case CSS_PROP_WHITE_SPACE: + HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace) + m_style->setWhiteSpace(*primitiveValue); + return; + + case CSS_PROP_BACKGROUND_POSITION: + HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition); + HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition); + return; + case CSS_PROP_BACKGROUND_POSITION_X: { + HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value) + return; + } + case CSS_PROP_BACKGROUND_POSITION_Y: { + HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value) + return; + } + case CSS_PROP_BORDER_SPACING: { + if (isInherit) { + m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing()); + m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing()); + } + else if (isInitial) { + m_style->setHorizontalBorderSpacing(0); + m_style->setVerticalBorderSpacing(0); + } + return; + } + case CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING: { + HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing) + if (!primitiveValue) + return; + short spacing = primitiveValue->computeLengthShort(m_style); + m_style->setHorizontalBorderSpacing(spacing); + return; + } + case CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING: { + HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing) + if (!primitiveValue) + return; + short spacing = primitiveValue->computeLengthShort(m_style); + m_style->setVerticalBorderSpacing(spacing); + return; + } + case CSS_PROP_CURSOR: + if (isInherit) { + m_style->setCursor(m_parentStyle->cursor()); + m_style->setCursorList(m_parentStyle->cursors()); + return; + } + m_style->clearCursorList(); + if (isInitial) { + m_style->setCursor(RenderStyle::initialCursor()); + return; + } + if (value->isValueList()) { + CSSValueList* list = static_cast<CSSValueList*>(value); + int len = list->length(); + m_style->setCursor(CURSOR_AUTO); + for (int i = 0; i < len; i++) { + CSSValue* item = list->item(i); + if (!item->isPrimitiveValue()) + continue; + primitiveValue = static_cast<CSSPrimitiveValue*>(item); + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) { + CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue); + if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style. + m_style->setUnique(); + m_style->addCursor(image->image(m_element->document()->docLoader()), image->hotspot()); + } else if (type == CSSPrimitiveValue::CSS_IDENT) + m_style->setCursor(*primitiveValue); + } + } else if (primitiveValue) { + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_IDENT) + m_style->setCursor(*primitiveValue); + } + return; +// colors || inherit + case CSS_PROP_BACKGROUND_COLOR: + case CSS_PROP_BORDER_TOP_COLOR: + case CSS_PROP_BORDER_RIGHT_COLOR: + case CSS_PROP_BORDER_BOTTOM_COLOR: + case CSS_PROP_BORDER_LEFT_COLOR: + case CSS_PROP_COLOR: + case CSS_PROP_OUTLINE_COLOR: + case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: + case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: + case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: { + Color col; + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor) + HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color) + HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_COLUMN_RULE_COLOR, columnRuleColor, ColumnRuleColor) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, textStrokeColor, TextStrokeColor) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_TEXT_FILL_COLOR, textFillColor, TextFillColor) + return; + } + if (isInitial) { + // The border/outline colors will just map to the invalid color |col| above. This will have the + // effect of forcing the use of the currentColor when it comes time to draw the borders (and of + // not painting the background since the color won't be valid). + if (id == CSS_PROP_COLOR) + col = RenderStyle::initialColor(); + } else { + if (!primitiveValue) + return; + col = getColorFromPrimitiveValue(primitiveValue); + } + + switch (id) { + case CSS_PROP_BACKGROUND_COLOR: + m_style->setBackgroundColor(col); + break; + case CSS_PROP_BORDER_TOP_COLOR: + m_style->setBorderTopColor(col); + break; + case CSS_PROP_BORDER_RIGHT_COLOR: + m_style->setBorderRightColor(col); + break; + case CSS_PROP_BORDER_BOTTOM_COLOR: + m_style->setBorderBottomColor(col); + break; + case CSS_PROP_BORDER_LEFT_COLOR: + m_style->setBorderLeftColor(col); + break; + case CSS_PROP_COLOR: + m_style->setColor(col); + break; + case CSS_PROP_OUTLINE_COLOR: + m_style->setOutlineColor(col); + break; + case CSS_PROP__WEBKIT_COLUMN_RULE_COLOR: + m_style->setColumnRuleColor(col); + break; + case CSS_PROP__WEBKIT_TEXT_STROKE_COLOR: + m_style->setTextStrokeColor(col); + break; + case CSS_PROP__WEBKIT_TEXT_FILL_COLOR: + m_style->setTextFillColor(col); + break; + } + + return; + } + +// uri || inherit + case CSS_PROP_BACKGROUND_IMAGE: + HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value) + return; + case CSS_PROP_LIST_STYLE_IMAGE: + { + HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) + if (!primitiveValue) + return; + m_style->setListStyleImage(static_cast<CSSImageValue*>(primitiveValue)->image(m_element->document()->docLoader())); + return; + } + +// length + case CSS_PROP_BORDER_TOP_WIDTH: + case CSS_PROP_BORDER_RIGHT_WIDTH: + case CSS_PROP_BORDER_BOTTOM_WIDTH: + case CSS_PROP_BORDER_LEFT_WIDTH: + case CSS_PROP_OUTLINE_WIDTH: + case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: + { + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth) + HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth) + HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, columnRuleWidth, ColumnRuleWidth) + return; + } + else if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH, ColumnRuleWidth, BorderWidth) + return; + } + + if (!primitiveValue) + return; + short width = 3; + switch (primitiveValue->getIdent()) { + case CSS_VAL_THIN: + width = 1; + break; + case CSS_VAL_MEDIUM: + width = 3; + break; + case CSS_VAL_THICK: + width = 5; + break; + case CSS_VAL_INVALID: + width = primitiveValue->computeLengthShort(m_style); + break; + default: + return; + } + + if (width < 0) return; + switch (id) { + case CSS_PROP_BORDER_TOP_WIDTH: + m_style->setBorderTopWidth(width); + break; + case CSS_PROP_BORDER_RIGHT_WIDTH: + m_style->setBorderRightWidth(width); + break; + case CSS_PROP_BORDER_BOTTOM_WIDTH: + m_style->setBorderBottomWidth(width); + break; + case CSS_PROP_BORDER_LEFT_WIDTH: + m_style->setBorderLeftWidth(width); + break; + case CSS_PROP_OUTLINE_WIDTH: + m_style->setOutlineWidth(width); + break; + case CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH: + m_style->setColumnRuleWidth(width); + break; + default: + return; + } + return; + } + + case CSS_PROP_LETTER_SPACING: + case CSS_PROP_WORD_SPACING: + { + + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing) + HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing) + return; + } + else if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing) + return; + } + + int width = 0; + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NORMAL){ + width = 0; + } else { + if (!primitiveValue) + return; + width = primitiveValue->computeLengthInt(m_style); + } + switch (id) { + case CSS_PROP_LETTER_SPACING: + m_style->setLetterSpacing(width); + break; + case CSS_PROP_WORD_SPACING: + m_style->setWordSpacing(width); + break; + // ### needs the definitions in renderstyle + default: break; + } + return; + } + + case CSS_PROP_WORD_BREAK: { + HANDLE_INHERIT_AND_INITIAL(wordBreak, WordBreak) + m_style->setWordBreak(*primitiveValue); + return; + } + + case CSS_PROP_WORD_WRAP: { + HANDLE_INHERIT_AND_INITIAL(wordWrap, WordWrap) + m_style->setWordWrap(*primitiveValue); + return; + } + + case CSS_PROP__WEBKIT_NBSP_MODE: + { + HANDLE_INHERIT_AND_INITIAL(nbspMode, NBSPMode) + m_style->setNBSPMode(*primitiveValue); + return; + } + + case CSS_PROP__WEBKIT_LINE_BREAK: + { + HANDLE_INHERIT_AND_INITIAL(khtmlLineBreak, KHTMLLineBreak) + m_style->setKHTMLLineBreak(*primitiveValue); + return; + } + + case CSS_PROP__WEBKIT_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: + { + HANDLE_INHERIT_AND_INITIAL(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor) + m_style->setMatchNearestMailBlockquoteColor(*primitiveValue); + return; + } + + case CSS_PROP_RESIZE: + { + HANDLE_INHERIT_AND_INITIAL(resize, Resize) + + if (!primitiveValue->getIdent()) + return; + + EResize r = RESIZE_NONE; + if (primitiveValue->getIdent() == CSS_VAL_AUTO) { + if (Settings* settings = m_document->settings()) + r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; + } else + r = *primitiveValue; + + m_style->setResize(r); + return; + } + + // length, percent + case CSS_PROP_MAX_WIDTH: + // +none +inherit + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) + apply = true; + case CSS_PROP_TOP: + case CSS_PROP_LEFT: + case CSS_PROP_RIGHT: + case CSS_PROP_BOTTOM: + case CSS_PROP_WIDTH: + case CSS_PROP_MIN_WIDTH: + case CSS_PROP_MARGIN_TOP: + case CSS_PROP_MARGIN_RIGHT: + case CSS_PROP_MARGIN_BOTTOM: + case CSS_PROP_MARGIN_LEFT: + // +inherit +auto + if (id == CSS_PROP_WIDTH || id == CSS_PROP_MIN_WIDTH || id == CSS_PROP_MAX_WIDTH) { + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) { + l = Length(Intrinsic); + apply = true; + } + else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) { + l = Length(MinIntrinsic); + apply = true; + } + } + if (id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) + apply = true; + case CSS_PROP_PADDING_TOP: + case CSS_PROP_PADDING_RIGHT: + case CSS_PROP_PADDING_BOTTOM: + case CSS_PROP_PADDING_LEFT: + case CSS_PROP_TEXT_INDENT: + // +inherit + { + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth) + HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom) + HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top) + HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left) + HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right) + HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width) + HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth) + HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop) + HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight) + HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom) + HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft) + HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop) + HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight) + HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom) + HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft) + HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent) + return; + } + else if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin) + HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent) + return; + } + + if (primitiveValue && !apply) { + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + // Handle our quirky margin units if we have them. + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed, + primitiveValue->isQuirkValue()); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + if (id == CSS_PROP_PADDING_LEFT || id == CSS_PROP_PADDING_RIGHT || + id == CSS_PROP_PADDING_TOP || id == CSS_PROP_PADDING_BOTTOM) + // Padding can't be negative + apply = !((l.isFixed() || l.isPercent()) && l.calcValue(100) < 0); + else + apply = true; + } + if (!apply) return; + switch (id) { + case CSS_PROP_MAX_WIDTH: + m_style->setMaxWidth(l); + break; + case CSS_PROP_BOTTOM: + m_style->setBottom(l); + break; + case CSS_PROP_TOP: + m_style->setTop(l); + break; + case CSS_PROP_LEFT: + m_style->setLeft(l); + break; + case CSS_PROP_RIGHT: + m_style->setRight(l); + break; + case CSS_PROP_WIDTH: + m_style->setWidth(l); + break; + case CSS_PROP_MIN_WIDTH: + m_style->setMinWidth(l); + break; + case CSS_PROP_PADDING_TOP: + m_style->setPaddingTop(l); + break; + case CSS_PROP_PADDING_RIGHT: + m_style->setPaddingRight(l); + break; + case CSS_PROP_PADDING_BOTTOM: + m_style->setPaddingBottom(l); + break; + case CSS_PROP_PADDING_LEFT: + m_style->setPaddingLeft(l); + break; + case CSS_PROP_MARGIN_TOP: + m_style->setMarginTop(l); + break; + case CSS_PROP_MARGIN_RIGHT: + m_style->setMarginRight(l); + break; + case CSS_PROP_MARGIN_BOTTOM: + m_style->setMarginBottom(l); + break; + case CSS_PROP_MARGIN_LEFT: + m_style->setMarginLeft(l); + break; + case CSS_PROP_TEXT_INDENT: + m_style->setTextIndent(l); + break; + default: + break; + } + return; + } + + case CSS_PROP_MAX_HEIGHT: + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { + l = Length(undefinedLength, Fixed); + apply = true; + } + case CSS_PROP_HEIGHT: + case CSS_PROP_MIN_HEIGHT: + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_INTRINSIC) { + l = Length(Intrinsic); + apply = true; + } else if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_MIN_INTRINSIC) { + l = Length(MinIntrinsic); + apply = true; + } else if (id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) + apply = true; + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight) + HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height) + HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight) + return; + } + if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize) + return; + } + + if (primitiveValue && !apply) { + unsigned short type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + apply = true; + } + if (apply) + switch (id) { + case CSS_PROP_MAX_HEIGHT: + m_style->setMaxHeight(l); + break; + case CSS_PROP_HEIGHT: + m_style->setHeight(l); + break; + case CSS_PROP_MIN_HEIGHT: + m_style->setMinHeight(l); + break; + } + return; + + case CSS_PROP_VERTICAL_ALIGN: + HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign) + if (!primitiveValue) + return; + if (primitiveValue->getIdent()) { + EVerticalAlign align; + + switch (primitiveValue->getIdent()) { + case CSS_VAL_TOP: + align = TOP; break; + case CSS_VAL_BOTTOM: + align = BOTTOM; break; + case CSS_VAL_MIDDLE: + align = MIDDLE; break; + case CSS_VAL_BASELINE: + align = BASELINE; break; + case CSS_VAL_TEXT_BOTTOM: + align = TEXT_BOTTOM; break; + case CSS_VAL_TEXT_TOP: + align = TEXT_TOP; break; + case CSS_VAL_SUB: + align = SUB; break; + case CSS_VAL_SUPER: + align = SUPER; break; + case CSS_VAL__WEBKIT_BASELINE_MIDDLE: + align = BASELINE_MIDDLE; break; + default: + return; + } + m_style->setVerticalAlign(align); + return; + } else { + int type = primitiveValue->primitiveType(); + Length l; + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + + m_style->setVerticalAlign(LENGTH); + m_style->setVerticalAlignLength(l); + } + return; + + case CSS_PROP_FONT_SIZE: + { + FontDescription fontDescription = m_style->fontDescription(); + fontDescription.setKeywordSize(0); + bool familyIsFixed = fontDescription.genericFamily() == FontDescription::MonospaceFamily; + float oldSize = 0; + float size = 0; + + bool parentIsAbsoluteSize = false; + if (m_parentNode) { + oldSize = m_parentStyle->fontDescription().specifiedSize(); + parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize(); + } + + if (isInherit) { + size = oldSize; + if (m_parentNode) + fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize()); + } else if (isInitial) { + size = fontSizeForKeyword(CSS_VAL_MEDIUM, m_style->htmlHacks(), familyIsFixed); + fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1); + } else if (primitiveValue->getIdent()) { + // Keywords are being used. + switch (primitiveValue->getIdent()) { + case CSS_VAL_XX_SMALL: + case CSS_VAL_X_SMALL: + case CSS_VAL_SMALL: + case CSS_VAL_MEDIUM: + case CSS_VAL_LARGE: + case CSS_VAL_X_LARGE: + case CSS_VAL_XX_LARGE: + case CSS_VAL__WEBKIT_XXX_LARGE: + size = fontSizeForKeyword(primitiveValue->getIdent(), m_style->htmlHacks(), familyIsFixed); + fontDescription.setKeywordSize(primitiveValue->getIdent() - CSS_VAL_XX_SMALL + 1); + break; + case CSS_VAL_LARGER: + size = largerFontSize(oldSize, m_style->htmlHacks()); + break; + case CSS_VAL_SMALLER: + size = smallerFontSize(oldSize, m_style->htmlHacks()); + break; + default: + return; + } + + fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && + (primitiveValue->getIdent() == CSS_VAL_LARGER || + primitiveValue->getIdent() == CSS_VAL_SMALLER)); + } else { + int type = primitiveValue->primitiveType(); + fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || + (type != CSSPrimitiveValue::CSS_PERCENTAGE && + type != CSSPrimitiveValue::CSS_EMS && + type != CSSPrimitiveValue::CSS_EXS)); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + size = primitiveValue->computeLengthFloat(m_parentStyle, false); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + size = (primitiveValue->getFloatValue() * oldSize) / 100.0f; + else + return; + } + + if (size < 0) + return; + + setFontSize(fontDescription, size); + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + + case CSS_PROP_Z_INDEX: { + if (isInherit) { + if (m_parentStyle->hasAutoZIndex()) + m_style->setHasAutoZIndex(); + else + m_style->setZIndex(m_parentStyle->zIndex()); + return; + } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { + m_style->setHasAutoZIndex(); + return; + } + + // FIXME: Should clamp all sorts of other integer properties too. + const double minIntAsDouble = INT_MIN; + const double maxIntAsDouble = INT_MAX; + m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble)))); + return; + } + case CSS_PROP_WIDOWS: + { + HANDLE_INHERIT_AND_INITIAL(widows, Widows) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; + m_style->setWidows(primitiveValue->getIntValue()); + return; + } + + case CSS_PROP_ORPHANS: + { + HANDLE_INHERIT_AND_INITIAL(orphans, Orphans) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; + m_style->setOrphans(primitiveValue->getIntValue()); + return; + } + +// length, percent, number + case CSS_PROP_LINE_HEIGHT: + { + HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight) + if (!primitiveValue) + return; + Length lineHeight; + int type = primitiveValue->primitiveType(); + if (primitiveValue->getIdent() == CSS_VAL_NORMAL) + lineHeight = Length(-100.0, Percent); + else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { + double multiplier = 1.0; + // Scale for the font zoom factor only for types other than "em" and "ex", since those are + // already based on the font size. + if (type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && m_style->textSizeAdjust() && m_document->frame()) { + multiplier = m_document->frame()->zoomFactor() / 100.0; + } + lineHeight = Length(primitiveValue->computeLengthIntForLength(m_style, multiplier), Fixed); + } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed); + else if (type == CSSPrimitiveValue::CSS_NUMBER) + lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); + else + return; + m_style->setLineHeight(lineHeight); + return; + } + +// string + case CSS_PROP_TEXT_ALIGN: + { + HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) + if (!primitiveValue) + return; + int id = primitiveValue->getIdent(); + if (id == CSS_VAL_START) + m_style->setTextAlign(m_style->direction() == LTR ? LEFT : RIGHT); + else if (id == CSS_VAL_END) + m_style->setTextAlign(m_style->direction() == LTR ? RIGHT : LEFT); + else + m_style->setTextAlign(*primitiveValue); + return; + } + +// rect + case CSS_PROP_CLIP: + { + Length top; + Length right; + Length bottom; + Length left; + bool hasClip = true; + if (isInherit) { + if (m_parentStyle->hasClip()) { + top = m_parentStyle->clipTop(); + right = m_parentStyle->clipRight(); + bottom = m_parentStyle->clipBottom(); + left = m_parentStyle->clipLeft(); + } + else { + hasClip = false; + top = right = bottom = left = Length(); + } + } else if (isInitial) { + hasClip = false; + top = right = bottom = left = Length(); + } else if (!primitiveValue) { + return; + } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { + Rect* rect = primitiveValue->getRectValue(); + if (!rect) + return; + top = convertToLength(rect->top(), m_style); + right = convertToLength(rect->right(), m_style); + bottom = convertToLength(rect->bottom(), m_style); + left = convertToLength(rect->left(), m_style); + + } else if (primitiveValue->getIdent() != CSS_VAL_AUTO) { + return; + } + m_style->setClip(top, right, bottom, left); + m_style->setHasClip(hasClip); + + // rect, ident + return; + } + +// lists + case CSS_PROP_CONTENT: + // list of string, uri, counter, attr, i + { + // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This + // note is a reminder that eventually "inherit" needs to be supported. + + if (isInitial) { + m_style->clearContent(); + return; + } + + if (!value->isValueList()) + return; + + CSSValueList* list = static_cast<CSSValueList*>(value); + int len = list->length(); + + bool didSet = false; + for (int i = 0; i < len; i++) { + CSSValue* item = list->item(i); + if (!item->isPrimitiveValue()) + continue; + + CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item); + switch (val->primitiveType()) { + case CSSPrimitiveValue::CSS_STRING: + m_style->setContent(val->getStringValue().impl(), didSet); + didSet = true; + break; + case CSSPrimitiveValue::CSS_ATTR: { + // FIXME: Can a namespace be specified for an attr(foo)? + if (m_style->styleType() == RenderStyle::NOPSEUDO) + m_style->setUnique(); + else + m_parentStyle->setUnique(); + QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom); + m_style->setContent(m_element->getAttribute(attr).impl(), didSet); + didSet = true; + // register the fact that the attribute value affects the style + m_selectorAttrs.add(attr.localName().impl()); + break; + } + case CSSPrimitiveValue::CSS_URI: { + CSSImageValue *image = static_cast<CSSImageValue*>(val); + m_style->setContent(image->image(m_element->document()->docLoader()), didSet); + didSet = true; + break; + } + case CSSPrimitiveValue::CSS_COUNTER: { + Counter* counterValue = val->getCounterValue(); + CounterContent* counter = new CounterContent(counterValue->identifier(), + (EListStyleType)counterValue->listStyleNumber(), counterValue->separator()); + m_style->setContent(counter, didSet); + didSet = true; + } + } + } + if (!didSet) + m_style->clearContent(); + return; + } + + case CSS_PROP_COUNTER_INCREMENT: + applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false); + return; + case CSS_PROP_COUNTER_RESET: + applyCounterList(m_style, value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true); + return; + + case CSS_PROP_FONT_FAMILY: { + // list of strings and ids + if (isInherit) { + FontDescription parentFontDescription = m_parentStyle->fontDescription(); + FontDescription fontDescription = m_style->fontDescription(); + fontDescription.setGenericFamily(parentFontDescription.genericFamily()); + fontDescription.setFamily(parentFontDescription.firstFamily()); + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + else if (isInitial) { + FontDescription initialDesc = FontDescription(); + FontDescription fontDescription = m_style->fontDescription(); + // We need to adjust the size to account for the generic family change from monospace + // to non-monospace. + if (fontDescription.keywordSize() && fontDescription.genericFamily() == FontDescription::MonospaceFamily) + setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, m_style->htmlHacks(), false)); + fontDescription.setGenericFamily(initialDesc.genericFamily()); + fontDescription.setFamily(initialDesc.firstFamily()); + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + return; + } + + if (!value->isValueList()) return; + FontDescription fontDescription = m_style->fontDescription(); + CSSValueList *list = static_cast<CSSValueList*>(value); + int len = list->length(); + FontFamily& firstFamily = fontDescription.firstFamily(); + FontFamily *currFamily = 0; + + // Before mapping in a new font-family property, we should reset the generic family. + bool oldFamilyIsMonospace = fontDescription.genericFamily() == FontDescription::MonospaceFamily; + fontDescription.setGenericFamily(FontDescription::NoFamily); + + for (int i = 0; i < len; i++) { + CSSValue *item = list->item(i); + if (!item->isPrimitiveValue()) continue; + CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item); + AtomicString face; + Settings* settings = m_document->settings(); + if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING) + face = static_cast<FontFamilyValue*>(val)->familyName(); + else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) { + switch (val->getIdent()) { + case CSS_VAL__WEBKIT_BODY: + face = settings->standardFontFamily(); + break; + case CSS_VAL_SERIF: + face = "-webkit-serif"; + fontDescription.setGenericFamily(FontDescription::SerifFamily); + break; + case CSS_VAL_SANS_SERIF: + face = "-webkit-sans-serif"; + fontDescription.setGenericFamily(FontDescription::SansSerifFamily); + break; + case CSS_VAL_CURSIVE: + face = "-webkit-cursive"; + fontDescription.setGenericFamily(FontDescription::CursiveFamily); + break; + case CSS_VAL_FANTASY: + face = "-webkit-fantasy"; + fontDescription.setGenericFamily(FontDescription::FantasyFamily); + break; + case CSS_VAL_MONOSPACE: + face = "-webkit-monospace"; + fontDescription.setGenericFamily(FontDescription::MonospaceFamily); + break; + } + } + + if (!face.isEmpty()) { + if (!currFamily) { + // Filling in the first family. + firstFamily.setFamily(face); + currFamily = &firstFamily; + } + else { + FontFamily *newFamily = new FontFamily; + newFamily->setFamily(face); + currFamily->appendFamily(newFamily); + currFamily = newFamily; + } + + if (fontDescription.keywordSize() && (fontDescription.genericFamily() == FontDescription::MonospaceFamily) != oldFamilyIsMonospace) + setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_XX_SMALL + fontDescription.keywordSize() - 1, m_style->htmlHacks(), !oldFamilyIsMonospace)); + + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + } + } + return; + } + case CSS_PROP_TEXT_DECORATION: { + // list of ident + HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration) + int t = RenderStyle::initialTextDecoration(); + if (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { + // do nothing + } else { + if (!value->isValueList()) return; + CSSValueList *list = static_cast<CSSValueList*>(value); + int len = list->length(); + for (int i = 0; i < len; i++) + { + CSSValue *item = list->item(i); + if (!item->isPrimitiveValue()) continue; + primitiveValue = static_cast<CSSPrimitiveValue*>(item); + switch (primitiveValue->getIdent()) { + case CSS_VAL_NONE: + t = TDNONE; break; + case CSS_VAL_UNDERLINE: + t |= UNDERLINE; break; + case CSS_VAL_OVERLINE: + t |= OVERLINE; break; + case CSS_VAL_LINE_THROUGH: + t |= LINE_THROUGH; break; + case CSS_VAL_BLINK: + t |= BLINK; break; + default: + return; + } + } + } + + m_style->setTextDecoration(t); + return; + } + +// shorthand properties + case CSS_PROP_BACKGROUND: + if (isInitial) { + m_style->clearBackgroundLayers(); + m_style->setBackgroundColor(Color()); + return; + } + else if (isInherit) { + m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers()); + m_style->setBackgroundColor(m_parentStyle->backgroundColor()); + } + return; + case CSS_PROP_BORDER: + case CSS_PROP_BORDER_STYLE: + case CSS_PROP_BORDER_WIDTH: + case CSS_PROP_BORDER_COLOR: + if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR) + { + if (isInherit) { + m_style->setBorderTopColor(m_parentStyle->borderTopColor()); + m_style->setBorderBottomColor(m_parentStyle->borderBottomColor()); + m_style->setBorderLeftColor(m_parentStyle->borderLeftColor()); + m_style->setBorderRightColor(m_parentStyle->borderRightColor()); + } + else if (isInitial) { + m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead. + m_style->setBorderBottomColor(Color()); + m_style->setBorderLeftColor(Color()); + m_style->setBorderRightColor(Color()); + } + } + if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE) + { + if (isInherit) { + m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); + m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); + m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); + m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); + } + else if (isInitial) { + m_style->setBorderTopStyle(RenderStyle::initialBorderStyle()); + m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); + m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); + m_style->setBorderRightStyle(RenderStyle::initialBorderStyle()); + } + } + if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH) + { + if (isInherit) { + m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); + m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); + m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); + m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); + } + else if (isInitial) { + m_style->setBorderTopWidth(RenderStyle::initialBorderWidth()); + m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); + m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); + m_style->setBorderRightWidth(RenderStyle::initialBorderWidth()); + } + } + return; + case CSS_PROP_BORDER_TOP: + if (isInherit) { + m_style->setBorderTopColor(m_parentStyle->borderTopColor()); + m_style->setBorderTopStyle(m_parentStyle->borderTopStyle()); + m_style->setBorderTopWidth(m_parentStyle->borderTopWidth()); + } + else if (isInitial) + m_style->resetBorderTop(); + return; + case CSS_PROP_BORDER_RIGHT: + if (isInherit) { + m_style->setBorderRightColor(m_parentStyle->borderRightColor()); + m_style->setBorderRightStyle(m_parentStyle->borderRightStyle()); + m_style->setBorderRightWidth(m_parentStyle->borderRightWidth()); + } + else if (isInitial) + m_style->resetBorderRight(); + return; + case CSS_PROP_BORDER_BOTTOM: + if (isInherit) { + m_style->setBorderBottomColor(m_parentStyle->borderBottomColor()); + m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle()); + m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth()); + } + else if (isInitial) + m_style->resetBorderBottom(); + return; + case CSS_PROP_BORDER_LEFT: + if (isInherit) { + m_style->setBorderLeftColor(m_parentStyle->borderLeftColor()); + m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle()); + m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth()); + } + else if (isInitial) + m_style->resetBorderLeft(); + return; + case CSS_PROP_MARGIN: + if (isInherit) { + m_style->setMarginTop(m_parentStyle->marginTop()); + m_style->setMarginBottom(m_parentStyle->marginBottom()); + m_style->setMarginLeft(m_parentStyle->marginLeft()); + m_style->setMarginRight(m_parentStyle->marginRight()); + } + else if (isInitial) + m_style->resetMargin(); + return; + case CSS_PROP_PADDING: + if (isInherit) { + m_style->setPaddingTop(m_parentStyle->paddingTop()); + m_style->setPaddingBottom(m_parentStyle->paddingBottom()); + m_style->setPaddingLeft(m_parentStyle->paddingLeft()); + m_style->setPaddingRight(m_parentStyle->paddingRight()); + } + else if (isInitial) + m_style->resetPadding(); + return; + case CSS_PROP_FONT: + if (isInherit) { + FontDescription fontDescription = m_parentStyle->fontDescription(); + m_style->setLineHeight(m_parentStyle->lineHeight()); + m_lineHeightValue = 0; + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + } else if (isInitial) { + Settings* settings = m_document->settings(); + FontDescription fontDescription; + fontDescription.setGenericFamily(FontDescription::StandardFamily); + fontDescription.setRenderingMode(settings->fontRenderingMode()); + fontDescription.setUsePrinterFont(m_document->printing()); + const AtomicString& standardFontFamily = m_document->settings()->standardFontFamily(); + if (!standardFontFamily.isEmpty()) { + fontDescription.firstFamily().setFamily(standardFontFamily); + fontDescription.firstFamily().appendFamily(0); + } + fontDescription.setKeywordSize(CSS_VAL_MEDIUM - CSS_VAL_XX_SMALL + 1); + setFontSize(fontDescription, fontSizeForKeyword(CSS_VAL_MEDIUM, m_style->htmlHacks(), false)); + m_style->setLineHeight(RenderStyle::initialLineHeight()); + m_lineHeightValue = 0; + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + } else if (primitiveValue) { + m_style->setLineHeight(RenderStyle::initialLineHeight()); + m_lineHeightValue = 0; + FontDescription fontDescription; + theme()->systemFont(primitiveValue->getIdent(), fontDescription); + // Double-check and see if the theme did anything. If not, don't bother updating the font. + if (fontDescription.isAbsoluteSize()) { + // Handle the zoom factor. + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), fontDescription.specifiedSize())); + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + } + } else if (value->isFontValue()) { + FontValue *font = static_cast<FontValue*>(value); + if (!font->style || !font->variant || !font->weight || + !font->size || !font->lineHeight || !font->family) + return; + applyProperty(CSS_PROP_FONT_STYLE, font->style.get()); + applyProperty(CSS_PROP_FONT_VARIANT, font->variant.get()); + applyProperty(CSS_PROP_FONT_WEIGHT, font->weight.get()); + applyProperty(CSS_PROP_FONT_SIZE, font->size.get()); + + m_lineHeightValue = font->lineHeight.get(); + + applyProperty(CSS_PROP_FONT_FAMILY, font->family.get()); + } + return; + + case CSS_PROP_LIST_STYLE: + if (isInherit) { + m_style->setListStyleType(m_parentStyle->listStyleType()); + m_style->setListStyleImage(m_parentStyle->listStyleImage()); + m_style->setListStylePosition(m_parentStyle->listStylePosition()); + } + else if (isInitial) { + m_style->setListStyleType(RenderStyle::initialListStyleType()); + m_style->setListStyleImage(RenderStyle::initialListStyleImage()); + m_style->setListStylePosition(RenderStyle::initialListStylePosition()); + } + return; + case CSS_PROP_OUTLINE: + if (isInherit) { + m_style->setOutlineWidth(m_parentStyle->outlineWidth()); + m_style->setOutlineColor(m_parentStyle->outlineColor()); + m_style->setOutlineStyle(m_parentStyle->outlineStyle()); + } + else if (isInitial) + m_style->resetOutline(); + return; + + // CSS3 Properties + case CSS_PROP__WEBKIT_APPEARANCE: { + HANDLE_INHERIT_AND_INITIAL(appearance, Appearance) + if (!primitiveValue) + return; + m_style->setAppearance(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_BINDING: { +#if ENABLE(XBL) + if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE)) { + m_style->deleteBindingURIs(); + return; + } + else if (isInherit) { + if (m_parentStyle->bindingURIs()) + m_style->inheritBindingURIs(m_parentStyle->bindingURIs()); + else + m_style->deleteBindingURIs(); + return; + } + + if (!value->isValueList()) return; + CSSValueList* list = static_cast<CSSValueList*>(value); + bool firstBinding = true; + for (unsigned int i = 0; i < list->length(); i++) { + CSSValue *item = list->item(i); + CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item); + if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) { + if (firstBinding) { + firstBinding = false; + m_style->deleteBindingURIs(); + } + m_style->addBindingURI(val->getStringValue()); + } + } +#endif + return; + } + + case CSS_PROP__WEBKIT_BORDER_IMAGE: { + HANDLE_INHERIT_AND_INITIAL(borderImage, BorderImage) + BorderImage image; + if (primitiveValue) { + if (primitiveValue->getIdent() == CSS_VAL_NONE) + m_style->setBorderImage(image); + } else { + // Retrieve the border image value. + CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); + + // Set the image (this kicks off the load). + image.m_image = borderImage->m_image->image(m_element->document()->docLoader()); + + // Set up a length box to represent our image slices. + LengthBox& l = image.m_slices; + Rect* r = borderImage->m_imageSliceRect.get(); + if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + l.top = Length(r->top()->getDoubleValue(), Percent); + else + l.top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); + if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + l.bottom = Length(r->bottom()->getDoubleValue(), Percent); + else + l.bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); + if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + l.left = Length(r->left()->getDoubleValue(), Percent); + else + l.left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); + if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + l.right = Length(r->right()->getDoubleValue(), Percent); + else + l.right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); + + // Set the appropriate rules for stretch/round/repeat of the slices + switch (borderImage->m_horizontalSizeRule) { + case CSS_VAL_STRETCH: + image.m_horizontalRule = BI_STRETCH; + break; + case CSS_VAL_ROUND: + image.m_horizontalRule = BI_ROUND; + break; + default: // CSS_VAL_REPEAT + image.m_horizontalRule = BI_REPEAT; + break; + } + + switch (borderImage->m_verticalSizeRule) { + case CSS_VAL_STRETCH: + image.m_verticalRule = BI_STRETCH; + break; + case CSS_VAL_ROUND: + image.m_verticalRule = BI_ROUND; + break; + default: // CSS_VAL_REPEAT + image.m_verticalRule = BI_REPEAT; + break; + } + + m_style->setBorderImage(image); + } + return; + } + + case CSS_PROP__WEBKIT_BORDER_RADIUS: + if (isInherit) { + m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius()); + m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius()); + m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius()); + m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius()); + return; + } + if (isInitial) { + m_style->resetBorderRadius(); + return; + } + // Fall through + case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: + case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: { + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, borderTopLeftRadius, BorderTopLeftRadius) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, borderTopRightRadius, BorderTopRightRadius) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, borderBottomLeftRadius, BorderBottomLeftRadius) + HANDLE_INHERIT_COND(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, borderBottomRightRadius, BorderBottomRightRadius) + return; + } + + if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS, BorderTopLeftRadius, BorderRadius) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS, BorderTopRightRadius, BorderRadius) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS, BorderBottomLeftRadius, BorderRadius) + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS, BorderBottomRightRadius, BorderRadius) + return; + } + + if (!primitiveValue) + return; + + Pair* pair = primitiveValue->getPairValue(); + if (!pair) + return; + + int width = pair->first()->computeLengthInt(m_style); + int height = pair->second()->computeLengthInt(m_style); + if (width < 0 || height < 0) + return; + + if (width == 0) + height = 0; // Null out the other value. + else if (height == 0) + width = 0; // Null out the other value. + + IntSize size(width, height); + switch (id) { + case CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS: + m_style->setBorderTopLeftRadius(size); + break; + case CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS: + m_style->setBorderTopRightRadius(size); + break; + case CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS: + m_style->setBorderBottomLeftRadius(size); + break; + case CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS: + m_style->setBorderBottomRightRadius(size); + break; + default: + m_style->setBorderRadius(size); + break; + } + return; + } + + case CSS_PROP_OUTLINE_OFFSET: + HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset) + m_style->setOutlineOffset(primitiveValue->computeLengthInt(m_style)); + return; + + case CSS_PROP_TEXT_SHADOW: + case CSS_PROP__WEBKIT_BOX_SHADOW: { + if (isInherit) { + if (id == CSS_PROP_TEXT_SHADOW) + return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0); + return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0); + } + if (isInitial || primitiveValue) // initial | none + return id == CSS_PROP_TEXT_SHADOW ? m_style->setTextShadow(0) : m_style->setBoxShadow(0); + + if (!value->isValueList()) + return; + + CSSValueList *list = static_cast<CSSValueList*>(value); + int len = list->length(); + for (int i = 0; i < len; i++) { + ShadowValue* item = static_cast<ShadowValue*>(list->item(i)); + int x = item->x->computeLengthInt(m_style); + int y = item->y->computeLengthInt(m_style); + int blur = item->blur ? item->blur->computeLengthInt(m_style) : 0; + Color color; + if (item->color) + color = getColorFromPrimitiveValue(item->color.get()); + ShadowData* shadowData = new ShadowData(x, y, blur, color.isValid() ? color : Color::transparent); + if (id == CSS_PROP_TEXT_SHADOW) + m_style->setTextShadow(shadowData, i != 0); + else + m_style->setBoxShadow(shadowData, i != 0); + } + return; + } + case CSS_PROP_OPACITY: + HANDLE_INHERIT_AND_INITIAL(opacity, Opacity) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; // Error case. + // Clamp opacity to the range 0-1 + m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue()))); + return; + case CSS_PROP__WEBKIT_BOX_ALIGN: + { + HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign) + if (!primitiveValue) + return; + EBoxAlignment boxAlignment = *primitiveValue; + if (boxAlignment != BJUSTIFY) + m_style->setBoxAlign(boxAlignment); + return; + } + case CSS_PROP_SRC: // Only used in @font-face rules. + return; + case CSS_PROP_UNICODE_RANGE: // Only used in @font-face rules. + return; + case CSS_PROP__WEBKIT_BOX_DIRECTION: + HANDLE_INHERIT_AND_INITIAL(boxDirection, BoxDirection) + if (primitiveValue) + m_style->setBoxDirection(*primitiveValue); + return; + case CSS_PROP__WEBKIT_BOX_LINES: + HANDLE_INHERIT_AND_INITIAL(boxLines, BoxLines) + if (primitiveValue) + m_style->setBoxLines(*primitiveValue); + return; + case CSS_PROP__WEBKIT_BOX_ORIENT: + HANDLE_INHERIT_AND_INITIAL(boxOrient, BoxOrient) + if (primitiveValue) + m_style->setBoxOrient(*primitiveValue); + return; + case CSS_PROP__WEBKIT_BOX_PACK: + { + HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack) + if (!primitiveValue) + return; + EBoxAlignment boxPack = *primitiveValue; + if (boxPack != BSTRETCH && boxPack != BBASELINE) + m_style->setBoxPack(boxPack); + return; + } + case CSS_PROP__WEBKIT_BOX_FLEX: + HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; // Error case. + m_style->setBoxFlex(primitiveValue->getFloatValue()); + return; + case CSS_PROP__WEBKIT_BOX_FLEX_GROUP: + HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; // Error case. + m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue())); + return; + case CSS_PROP__WEBKIT_BOX_ORDINAL_GROUP: + HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup) + if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return; // Error case. + m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue())); + return; + case CSS_PROP__WEBKIT_BOX_SIZING: + HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing) + if (!primitiveValue) + return; + if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX) + m_style->setBoxSizing(CONTENT_BOX); + else + m_style->setBoxSizing(BORDER_BOX); + return; + case CSS_PROP__WEBKIT_COLUMN_COUNT: { + if (isInherit) { + if (m_parentStyle->hasAutoColumnCount()) + m_style->setHasAutoColumnCount(); + else + m_style->setColumnCount(m_parentStyle->columnCount()); + return; + } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { + m_style->setHasAutoColumnCount(); + return; + } + m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue())); + return; + } + case CSS_PROP__WEBKIT_COLUMN_GAP: { + if (isInherit) { + if (m_parentStyle->hasNormalColumnGap()) + m_style->setHasNormalColumnGap(); + else + m_style->setColumnGap(m_parentStyle->columnGap()); + return; + } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_NORMAL) { + m_style->setHasNormalColumnGap(); + return; + } + m_style->setColumnGap(primitiveValue->computeLengthFloat(m_style)); + return; + } + case CSS_PROP__WEBKIT_COLUMN_WIDTH: { + if (isInherit) { + if (m_parentStyle->hasAutoColumnWidth()) + m_style->setHasAutoColumnWidth(); + else + m_style->setColumnWidth(m_parentStyle->columnWidth()); + return; + } else if (isInitial || primitiveValue->getIdent() == CSS_VAL_AUTO) { + m_style->setHasAutoColumnWidth(); + return; + } + m_style->setColumnWidth(primitiveValue->computeLengthFloat(m_style)); + return; + } + case CSS_PROP__WEBKIT_COLUMN_RULE_STYLE: + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle) + m_style->setColumnRuleStyle(*primitiveValue); + return; + case CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE: { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak) + m_style->setColumnBreakBefore(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER: { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak) + m_style->setColumnBreakAfter(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE: { + HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak) + EPageBreak pb = *primitiveValue; + if (pb != PBALWAYS) + m_style->setColumnBreakInside(pb); + return; + } + case CSS_PROP__WEBKIT_COLUMN_RULE: + if (isInherit) { + m_style->setColumnRuleColor(m_parentStyle->columnRuleColor()); + m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle()); + m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth()); + } + else if (isInitial) + m_style->resetColumnRule(); + return; + case CSS_PROP__WEBKIT_COLUMNS: + if (isInherit) { + if (m_parentStyle->hasAutoColumnWidth()) + m_style->setHasAutoColumnWidth(); + else + m_style->setColumnWidth(m_parentStyle->columnWidth()); + m_style->setColumnCount(m_parentStyle->columnCount()); + } else if (isInitial) { + m_style->setHasAutoColumnWidth(); + m_style->setColumnCount(RenderStyle::initialColumnCount()); + } + return; + case CSS_PROP__WEBKIT_MARQUEE: + if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return; + m_style->setMarqueeDirection(m_parentStyle->marqueeDirection()); + m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement()); + m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed()); + m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount()); + m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior()); + return; + case CSS_PROP__WEBKIT_MARQUEE_REPETITION: { + HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount) + if (!primitiveValue) + return; + if (primitiveValue->getIdent() == CSS_VAL_INFINITE) + m_style->setMarqueeLoopCount(-1); // -1 means repeat forever. + else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + m_style->setMarqueeLoopCount(primitiveValue->getIntValue()); + return; + } + case CSS_PROP__WEBKIT_MARQUEE_SPEED: { + HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) + if (!primitiveValue) + return; + if (primitiveValue->getIdent()) { + switch (primitiveValue->getIdent()) { + case CSS_VAL_SLOW: + m_style->setMarqueeSpeed(500); // 500 msec. + break; + case CSS_VAL_NORMAL: + m_style->setMarqueeSpeed(85); // 85msec. The WinIE default. + break; + case CSS_VAL_FAST: + m_style->setMarqueeSpeed(10); // 10msec. Super fast. + break; + } + } + else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) + m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue()); + else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) + m_style->setMarqueeSpeed(primitiveValue->getIntValue()); + else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. + m_style->setMarqueeSpeed(primitiveValue->getIntValue()); + return; + } + case CSS_PROP__WEBKIT_MARQUEE_INCREMENT: { + HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement) + if (!primitiveValue) + return; + if (primitiveValue->getIdent()) { + switch (primitiveValue->getIdent()) { + case CSS_VAL_SMALL: + m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px. + break; + case CSS_VAL_NORMAL: + m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. + break; + case CSS_VAL_LARGE: + m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px. + break; + } + } + else { + bool ok = true; + Length l = convertToLength(primitiveValue, m_style, &ok); + if (ok) + m_style->setMarqueeIncrement(l); + } + return; + } + case CSS_PROP__WEBKIT_MARQUEE_STYLE: { + HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior) + if (primitiveValue) + m_style->setMarqueeBehavior(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_MARQUEE_DIRECTION: { + HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection) + if (primitiveValue) + m_style->setMarqueeDirection(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_USER_DRAG: { + HANDLE_INHERIT_AND_INITIAL(userDrag, UserDrag) + if (primitiveValue) + m_style->setUserDrag(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_USER_MODIFY: { + HANDLE_INHERIT_AND_INITIAL(userModify, UserModify) + if (primitiveValue) + m_style->setUserModify(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_USER_SELECT: { + HANDLE_INHERIT_AND_INITIAL(userSelect, UserSelect) + if (primitiveValue) + m_style->setUserSelect(*primitiveValue); + return; + } + case CSS_PROP_TEXT_OVERFLOW: { + // This property is supported by WinIE, and so we leave off the "-webkit-" in order to + // work with WinIE-specific pages that use the property. + HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow) + if (!primitiveValue || !primitiveValue->getIdent()) + return; + m_style->setTextOverflow(primitiveValue->getIdent() == CSS_VAL_ELLIPSIS); + return; + } + case CSS_PROP__WEBKIT_MARGIN_COLLAPSE: { + if (isInherit) { + m_style->setMarginTopCollapse(m_parentStyle->marginTopCollapse()); + m_style->setMarginBottomCollapse(m_parentStyle->marginBottomCollapse()); + } + else if (isInitial) { + m_style->setMarginTopCollapse(MCOLLAPSE); + m_style->setMarginBottomCollapse(MCOLLAPSE); + } + return; + } + case CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE: { + HANDLE_INHERIT_AND_INITIAL(marginTopCollapse, MarginTopCollapse) + if (primitiveValue) + m_style->setMarginTopCollapse(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE: { + HANDLE_INHERIT_AND_INITIAL(marginBottomCollapse, MarginBottomCollapse) + if (primitiveValue) + m_style->setMarginBottomCollapse(*primitiveValue); + return; + } + + // Apple-specific changes. Do not merge these properties into KHTML. + case CSS_PROP__WEBKIT_LINE_CLAMP: { + HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp) + if (!primitiveValue) + return; + m_style->setLineClamp(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE)); + return; + } + case CSS_PROP__WEBKIT_HIGHLIGHT: { + HANDLE_INHERIT_AND_INITIAL(highlight, Highlight); + if (primitiveValue->getIdent() == CSS_VAL_NONE) + m_style->setHighlight(nullAtom); + else + m_style->setHighlight(primitiveValue->getStringValue()); + return; + } + case CSS_PROP__WEBKIT_BORDER_FIT: { + HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit); + if (primitiveValue->getIdent() == CSS_VAL_BORDER) + m_style->setBorderFit(BorderFitBorder); + else + m_style->setBorderFit(BorderFitLines); + return; + } + case CSS_PROP__WEBKIT_TEXT_SIZE_ADJUST: { + HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust) + if (!primitiveValue || !primitiveValue->getIdent()) return; + m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSS_VAL_AUTO); + m_fontDirty = true; + return; + } + case CSS_PROP__WEBKIT_TEXT_SECURITY: { + HANDLE_INHERIT_AND_INITIAL(textSecurity, TextSecurity) + if (primitiveValue) + m_style->setTextSecurity(*primitiveValue); + return; + } + case CSS_PROP__WEBKIT_DASHBOARD_REGION: { + HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions) + if (!primitiveValue) + return; + + if (primitiveValue->getIdent() == CSS_VAL_NONE) { + m_style->setDashboardRegions(RenderStyle::noneDashboardRegions()); + return; + } + + DashboardRegion *region = primitiveValue->getDashboardRegionValue(); + if (!region) + return; + + DashboardRegion *first = region; + while (region) { + Length top = convertToLength (region->top(), m_style); + Length right = convertToLength (region->right(), m_style); + Length bottom = convertToLength (region->bottom(), m_style); + Length left = convertToLength (region->left(), m_style); + if (region->m_isCircle) + m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); + else if (region->m_isRectangle) + m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true); + region = region->m_next.get(); + } + + m_element->document()->setHasDashboardRegions(true); + + return; + } + case CSS_PROP__WEBKIT_RTL_ORDERING: + HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered) + if (!primitiveValue || !primitiveValue->getIdent()) + return; + m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSS_VAL_VISUAL); + return; + case CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH: { + HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) + float width = 0; + switch (primitiveValue->getIdent()) { + case CSS_VAL_THIN: + case CSS_VAL_MEDIUM: + case CSS_VAL_THICK: { + double result = 1.0 / 48; + if (primitiveValue->getIdent() == CSS_VAL_MEDIUM) + result *= 3; + else if (primitiveValue->getIdent() == CSS_VAL_THICK) + result *= 5; + CSSPrimitiveValue val(result, CSSPrimitiveValue::CSS_EMS); + width = val.computeLengthFloat(m_style); + break; + } + default: + width = primitiveValue->computeLengthFloat(m_style); + break; + } + m_style->setTextStrokeWidth(width); + return; + } + case CSS_PROP__WEBKIT_TRANSFORM: { + HANDLE_INHERIT_AND_INITIAL(transform, Transform); + TransformOperations operations; + if (!value->isPrimitiveValue()) { + CSSValueList* list = static_cast<CSSValueList*>(value); + unsigned size = list->length(); + for (unsigned i = 0; i < size; i++) { + CSSTransformValue* val = static_cast<CSSTransformValue*>(list->item(i)); + CSSValueList* values = val->values(); + + CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(values->item(0)); + + switch (val->type()) { + case CSSTransformValue::ScaleTransformOperation: + case CSSTransformValue::ScaleXTransformOperation: + case CSSTransformValue::ScaleYTransformOperation: { + double sx = 1.0; + double sy = 1.0; + if (val->type() == CSSTransformValue::ScaleYTransformOperation) + sy = firstValue->getDoubleValue(); + else { + sx = firstValue->getDoubleValue(); + if (val->type() == CSSTransformValue::ScaleTransformOperation) { + if (values->length() > 1) { + CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(values->item(1)); + sy = secondValue->getDoubleValue(); + } else + sy = sx; + } + } + + ScaleTransformOperation* scale = new ScaleTransformOperation(sx, sy); + operations.append(scale); + break; + } + case CSSTransformValue::TranslateTransformOperation: + case CSSTransformValue::TranslateXTransformOperation: + case CSSTransformValue::TranslateYTransformOperation: { + bool ok; + Length tx = Length(0, Fixed); + Length ty = Length(0, Fixed); + if (val->type() == CSSTransformValue::TranslateYTransformOperation) + ty = convertToLength(firstValue, m_style, &ok); + else { + tx = convertToLength(firstValue, m_style, &ok); + if (val->type() == CSSTransformValue::TranslateTransformOperation) { + if (values->length() > 1) { + CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(values->item(1)); + ty = convertToLength(secondValue, m_style, &ok); + } else + ty = tx; + } + } + + TranslateTransformOperation* translate = new TranslateTransformOperation(tx, ty); + operations.append(translate); + break; + } + case CSSTransformValue::RotateTransformOperation: { + double angle = firstValue->getDoubleValue(); + if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) + angle = rad2deg(angle); + else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) + angle = grad2deg(angle); + RotateTransformOperation* rotate = new RotateTransformOperation(angle); + operations.append(rotate); + break; + } + case CSSTransformValue::SkewTransformOperation: + case CSSTransformValue::SkewXTransformOperation: + case CSSTransformValue::SkewYTransformOperation: { + double angleX = 0; + double angleY = 0; + double angle = firstValue->getDoubleValue(); + if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) + angle = rad2deg(angle); + else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) + angle = grad2deg(angle); + if (val->type() == CSSTransformValue::SkewYTransformOperation) + angleY = angle; + else { + angleX = angle; + if (val->type() == CSSTransformValue::SkewTransformOperation) { + if (values->length() > 1) { + CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(values->item(1)); + angleY = secondValue->getDoubleValue(); + if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) + angleY = rad2deg(angle); + else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) + angleY = grad2deg(angle); + } else + angleY = angleX; + } + } + + SkewTransformOperation* skew = new SkewTransformOperation(angleX, angleY); + operations.append(skew); + break; + } + case CSSTransformValue::MatrixTransformOperation: { + CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(values->item(1)); + CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(values->item(2)); + CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(values->item(3)); + CSSPrimitiveValue* fifthValue = static_cast<CSSPrimitiveValue*>(values->item(4)); + CSSPrimitiveValue* sixthValue = static_cast<CSSPrimitiveValue*>(values->item(5)); + MatrixTransformOperation* matrix = new MatrixTransformOperation(firstValue->getDoubleValue(), + secondValue->getDoubleValue(), + thirdValue->getDoubleValue(), + fourthValue->getDoubleValue(), + fifthValue->getDoubleValue(), + sixthValue->getDoubleValue()); + operations.append(matrix); + break; + } + + default: + break; + } + } + } + m_style->setTransform(operations); + return; + } + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN: + HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) + HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) + return; + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_X: { + HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX) + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + Length l; + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + m_style->setTransformOriginX(l); + break; + } + case CSS_PROP__WEBKIT_TRANSFORM_ORIGIN_Y: { + HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY) + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + Length l; + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + m_style->setTransformOriginY(l); + break; + } + case CSS_PROP__WEBKIT_TRANSITION: + if (isInitial) + m_style->clearTransitions(); + else if (isInherit) + m_style->inheritTransitions(m_parentStyle->transitions()); + return; + case CSS_PROP__WEBKIT_TRANSITION_DURATION: + HANDLE_TRANSITION_VALUE(transitionDuration, TransitionDuration, value) + return; + case CSS_PROP__WEBKIT_TRANSITION_REPEAT_COUNT: + HANDLE_TRANSITION_VALUE(transitionRepeatCount, TransitionRepeatCount, value) + return; + case CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION: + HANDLE_TRANSITION_VALUE(transitionTimingFunction, TransitionTimingFunction, value) + return; + case CSS_PROP__WEBKIT_TRANSITION_PROPERTY: + HANDLE_TRANSITION_VALUE(transitionProperty, TransitionProperty, value) + return; + case CSS_PROP_INVALID: + return; + case CSS_PROP_FONT_STRETCH: + case CSS_PROP_PAGE: + case CSS_PROP_QUOTES: + case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: + case CSS_PROP_SCROLLBAR_ARROW_COLOR: + case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: + case CSS_PROP_SCROLLBAR_FACE_COLOR: + case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: + case CSS_PROP_SCROLLBAR_SHADOW_COLOR: + case CSS_PROP_SCROLLBAR_TRACK_COLOR: + case CSS_PROP_SIZE: + case CSS_PROP_TEXT_LINE_THROUGH: + case CSS_PROP_TEXT_LINE_THROUGH_COLOR: + case CSS_PROP_TEXT_LINE_THROUGH_MODE: + case CSS_PROP_TEXT_LINE_THROUGH_STYLE: + case CSS_PROP_TEXT_LINE_THROUGH_WIDTH: + case CSS_PROP_TEXT_OVERLINE: + case CSS_PROP_TEXT_OVERLINE_COLOR: + case CSS_PROP_TEXT_OVERLINE_MODE: + case CSS_PROP_TEXT_OVERLINE_STYLE: + case CSS_PROP_TEXT_OVERLINE_WIDTH: + case CSS_PROP_TEXT_UNDERLINE: + case CSS_PROP_TEXT_UNDERLINE_COLOR: + case CSS_PROP_TEXT_UNDERLINE_MODE: + case CSS_PROP_TEXT_UNDERLINE_STYLE: + case CSS_PROP_TEXT_UNDERLINE_WIDTH: + case CSS_PROP__WEBKIT_FONT_SIZE_DELTA: + case CSS_PROP__WEBKIT_MARGIN_START: + case CSS_PROP__WEBKIT_PADDING_START: + case CSS_PROP__WEBKIT_TEXT_DECORATIONS_IN_EFFECT: + case CSS_PROP__WEBKIT_TEXT_STROKE: + return; +#if ENABLE(SVG) + default: + // Try the SVG properties + applySVGProperty(id, value); +#endif + } +} + +void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + switch (primitiveValue->getIdent()) { + case CSS_VAL_FIXED: + layer->setBackgroundAttachment(false); + break; + case CSS_VAL_SCROLL: + layer->setBackgroundAttachment(true); + break; + default: + return; + } +} + +void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundClip(RenderStyle::initialBackgroundClip()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + layer->setBackgroundClip(*primitiveValue); +} + +void CSSStyleSelector::mapBackgroundComposite(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundComposite(RenderStyle::initialBackgroundComposite()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + layer->setBackgroundComposite(*primitiveValue); +} + +void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + layer->setBackgroundOrigin(*primitiveValue); +} + +void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundImage(RenderStyle::initialBackgroundImage()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + layer->setBackgroundImage(static_cast<CSSImageValue*>(primitiveValue)->image(m_element->document()->docLoader())); +} + +void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + layer->setBackgroundRepeat(*primitiveValue); +} + +void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValue* value) +{ + LengthSize b = RenderStyle::initialBackgroundSize(); + + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundSize(b); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + Pair* pair = primitiveValue->getPairValue(); + if (!pair) + return; + + CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first()); + CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second()); + + if (!first || !second) + return; + + Length firstLength, secondLength; + int firstType = first->primitiveType(); + int secondType = second->primitiveType(); + + if (firstType == CSSPrimitiveValue::CSS_UNKNOWN) + firstLength = Length(Auto); + else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG) + firstLength = Length(first->computeLengthIntForLength(m_style), Fixed); + else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) + firstLength = Length(first->getDoubleValue(), Percent); + else + return; + + if (secondType == CSSPrimitiveValue::CSS_UNKNOWN) + secondLength = Length(Auto); + else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG) + secondLength = Length(second->computeLengthIntForLength(m_style), Fixed); + else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) + secondLength = Length(second->getDoubleValue(), Percent); + else + return; + + b.width = firstLength; + b.height = secondLength; + layer->setBackgroundSize(b); +} + +void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + Length l; + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + layer->setBackgroundXPosition(l); +} + +void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + Length l; + int type = primitiveValue->primitiveType(); + if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) + l = Length(primitiveValue->computeLengthIntForLength(m_style), Fixed); + else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + l = Length(primitiveValue->getDoubleValue(), Percent); + else + return; + layer->setBackgroundYPosition(l); +} + +void CSSStyleSelector::mapTransitionDuration(Transition* transition, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + transition->setTransitionDuration(RenderStyle::initialTransitionDuration()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) + transition->setTransitionDuration(int(1000*primitiveValue->getFloatValue())); + else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) + transition->setTransitionDuration(int(primitiveValue->getFloatValue())); +} + +void CSSStyleSelector::mapTransitionRepeatCount(Transition* transition, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + transition->setTransitionRepeatCount(RenderStyle::initialTransitionRepeatCount()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + if (primitiveValue->getIdent() == CSS_VAL_INFINITE) + transition->setTransitionRepeatCount(-1); + else + transition->setTransitionRepeatCount(int(primitiveValue->getFloatValue())); +} + +void CSSStyleSelector::mapTransitionTimingFunction(Transition* transition, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + transition->setTransitionTimingFunction(RenderStyle::initialTransitionTimingFunction()); + return; + } + + if (value->isPrimitiveValue()) { + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + switch (primitiveValue->getIdent()) { + case CSS_VAL_LINEAR: + transition->setTransitionTimingFunction(TimingFunction(LinearTimingFunction)); + break; + case CSS_VAL_AUTO: + transition->setTransitionTimingFunction(TimingFunction()); + break; + case CSS_VAL_EASE_IN: + transition->setTransitionTimingFunction(TimingFunction(CubicBezierTimingFunction, .42, .0, 1.0, 1.0)); + break; + case CSS_VAL_EASE_OUT: + transition->setTransitionTimingFunction(TimingFunction(CubicBezierTimingFunction, .0, .0, .58, 1.0)); + break; + case CSS_VAL_EASE_IN_OUT: + transition->setTransitionTimingFunction(TimingFunction(CubicBezierTimingFunction, .42, .0, .58, 1.0)); + break; + } + return; + } + + if (value->isTransitionTimingFunctionValue()) { + CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value); + transition->setTransitionTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2())); + } +} + +void CSSStyleSelector::mapTransitionProperty(Transition* transition, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + transition->setTransitionProperty(RenderStyle::initialTransitionProperty()); + return; + } + + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + transition->setTransitionProperty(primitiveValue->getIdent()); +} + +void CSSStyleSelector::checkForTextSizeAdjust() +{ + if (m_style->textSizeAdjust()) + return; + + FontDescription newFontDescription(m_style->fontDescription()); + newFontDescription.setComputedSize(newFontDescription.specifiedSize()); + m_style->setFontDescription(newFontDescription); +} + +void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle) +{ + const FontDescription& childFont = style->fontDescription(); + + if (childFont.isAbsoluteSize() || !parentStyle) + return; + + const FontDescription& parentFont = parentStyle->fontDescription(); + + if (childFont.genericFamily() == parentFont.genericFamily()) + return; + + // For now, lump all families but monospace together. + if (childFont.genericFamily() != FontDescription::MonospaceFamily && + parentFont.genericFamily() != FontDescription::MonospaceFamily) + return; + + // We know the parent is monospace or the child is monospace, and that font + // size was unspecified. We want to scale our font size as appropriate. + // If the font uses a keyword size, then we refetch from the table rather than + // multiplying by our scale factor. + float size; + if (childFont.keywordSize()) { + size = fontSizeForKeyword(CSS_VAL_XX_SMALL + childFont.keywordSize() - 1, style->htmlHacks(), + childFont.genericFamily() == FontDescription::MonospaceFamily); + } else { + Settings* settings = m_document->settings(); + float fixedScaleFactor = settings + ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize() + : 1; + size = (parentFont.genericFamily() == FontDescription::MonospaceFamily) ? + childFont.specifiedSize()/fixedScaleFactor : + childFont.specifiedSize()*fixedScaleFactor; + } + + FontDescription newFontDescription(childFont); + setFontSize(newFontDescription, size); + style->setFontDescription(newFontDescription); +} + +void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) +{ + fontDescription.setSpecifiedSize(size); + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription.isAbsoluteSize(), size)); +} + +float CSSStyleSelector::getComputedSizeFromSpecifiedSize(bool isAbsoluteSize, float specifiedSize) +{ + // We support two types of minimum font size. The first is a hard override that applies to + // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum" + // that is applied only when the Web page can't know what size it really asked for, e.g., + // when it uses logical sizes like "small" or expresses the font-size as a percentage of + // the user's default font setting. + + // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable. + // However we always allow the page to set an explicit pixel size that is smaller, + // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum). + + Settings* settings = m_document->settings(); + if (!settings) + return 1.0f; + + int minSize = settings->minimumFontSize(); + int minLogicalSize = settings->minimumLogicalFontSize(); + + float zoomPercent = m_document->frame() ? m_document->frame()->zoomFactor() / 100.0f : 1.0f; + float zoomedSize = specifiedSize * zoomPercent; + + // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small. + if (zoomedSize < minSize) + zoomedSize = minSize; + + // Now apply the "smart minimum." This minimum is also only applied if we're still too small + // after zooming. The font size must either be relative to the user default or the original size + // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive + // doing so won't disrupt the layout. + if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize)) + zoomedSize = minLogicalSize; + + // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various + // platforms (I'm looking at you, Windows.) + return min(1000000.0f, max(zoomedSize, 1.0f)); +} + +const int fontSizeTableMax = 16; +const int fontSizeTableMin = 9; +const int totalKeywords = 8; + +// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML. +static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = +{ + { 9, 9, 9, 9, 11, 14, 18, 28 }, + { 9, 9, 9, 10, 12, 15, 20, 31 }, + { 9, 9, 9, 11, 13, 17, 22, 34 }, + { 9, 9, 10, 12, 14, 18, 24, 37 }, + { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13) + { 9, 9, 11, 14, 17, 21, 28, 42 }, + { 9, 10, 12, 15, 17, 23, 30, 45 }, + { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) +}; +// HTML 1 2 3 4 5 6 7 +// CSS xxs xs s m l xl xxl +// | +// user pref + +// Strict mode table matches MacIE and Mozilla's settings exactly. +static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] = +{ + { 9, 9, 9, 9, 11, 14, 18, 27 }, + { 9, 9, 9, 10, 12, 15, 20, 30 }, + { 9, 9, 10, 11, 13, 17, 22, 33 }, + { 9, 9, 10, 12, 14, 18, 24, 36 }, + { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13) + { 9, 10, 12, 14, 17, 21, 28, 42 }, + { 9, 10, 13, 15, 18, 23, 30, 45 }, + { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16) +}; +// HTML 1 2 3 4 5 6 7 +// CSS xxs xs s m l xl xxl +// | +// user pref + +// For values outside the range of the table, we use Todd Fahrner's suggested scale +// factors for each keyword value. +static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f }; + +float CSSStyleSelector::fontSizeForKeyword(int keyword, bool quirksMode, bool fixed) const +{ + Settings* settings = m_document->settings(); + if (!settings) + return 1.0f; + + int mediumSize = fixed ? settings->defaultFixedFontSize() : settings->defaultFontSize(); + if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) { + // Look up the entry in the table. + int row = mediumSize - fontSizeTableMin; + int col = (keyword - CSS_VAL_XX_SMALL); + return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col]; + } + + // Value is outside the range of the table. Apply the scale factor instead. + float minLogicalSize = max(settings->minimumLogicalFontSize(), 1); + return max(fontSizeFactors[keyword - CSS_VAL_XX_SMALL]*mediumSize, minLogicalSize); +} + +float CSSStyleSelector::largerFontSize(float size, bool quirksMode) const +{ + // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to + // the next size level. + return size * 1.2f; +} + +float CSSStyleSelector::smallerFontSize(float size, bool quirksMode) const +{ + // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to + // the next size level. + return size / 1.2f; +} + +struct ColorValue { + int cssValueId; + RGBA32 color; +}; + +static const ColorValue colorValues[] = { + { CSS_VAL_AQUA, 0xFF00FFFF }, + { CSS_VAL_BLACK, 0xFF000000 }, + { CSS_VAL_BLUE, 0xFF0000FF }, + { CSS_VAL_FUCHSIA, 0xFFFF00FF }, + { CSS_VAL_GRAY, 0xFF808080 }, + { CSS_VAL_GREEN, 0xFF008000 }, + { CSS_VAL_LIME, 0xFF00FF00 }, + { CSS_VAL_MAROON, 0xFF800000 }, + { CSS_VAL_NAVY, 0xFF000080 }, + { CSS_VAL_OLIVE, 0xFF808000 }, + { CSS_VAL_ORANGE, 0xFFFFA500 }, + { CSS_VAL_PURPLE, 0xFF800080 }, + { CSS_VAL_RED, 0xFFFF0000 }, + { CSS_VAL_SILVER, 0xFFC0C0C0 }, + { CSS_VAL_TEAL, 0xFF008080 }, + { CSS_VAL_WHITE, 0xFFFFFFFF }, + { CSS_VAL_YELLOW, 0xFFFFFF00 }, + { CSS_VAL_TRANSPARENT, 0x00000000 }, + { CSS_VAL_GREY, 0xFF808080 }, + { 0, 0 } +}; + +static Color colorForCSSValue(int cssValueId) +{ + for (const ColorValue* col = colorValues; col->cssValueId; ++col) + if (col->cssValueId == cssValueId) + return col->color; + return theme()->systemColor(cssValueId); +} + +Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue) +{ + Color col; + int ident = primitiveValue->getIdent(); + if (ident) { + if (ident == CSS_VAL__WEBKIT_TEXT) + col = m_element->document()->textColor(); + else if (ident == CSS_VAL__WEBKIT_LINK) { + Color linkColor = m_element->document()->linkColor(); + Color visitedColor = m_element->document()->visitedLinkColor(); + if (linkColor == visitedColor) + col = linkColor; + else { + if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) + checkPseudoState(m_element); + col = (pseudoState == PseudoLink) ? linkColor : visitedColor; + } + } else if (ident == CSS_VAL__WEBKIT_ACTIVELINK) + col = m_element->document()->activeLinkColor(); + else if (ident == CSS_VAL__WEBKIT_FOCUS_RING_COLOR) + col = focusRingColor(); + else + col = colorForCSSValue(ident); + } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) + col.setRGB(primitiveValue->getRGBColorValue()); + return col; +} + +bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) +{ + return m_selectorAttrs.contains(attrname.impl()); +} + +void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result) +{ + m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result)); +} + +bool CSSStyleSelector::affectedByViewportChange() const +{ + unsigned s = m_viewportDependentMediaQueryResults.size(); + for (unsigned i = 0; i < s; i++) { + if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result) + return true; + } + return false; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSStyleSelector.h b/WebCore/css/CSSStyleSelector.h new file mode 100644 index 0000000..b5ba49b --- /dev/null +++ b/WebCore/css/CSSStyleSelector.h @@ -0,0 +1,318 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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. + * + */ + +#ifndef CSSStyleSelector_h +#define CSSStyleSelector_h + +#include "CSSFontSelector.h" +#include "MediaQueryExp.h" +#include "RenderStyle.h" +#include <wtf/HashSet.h> +#include <wtf/Vector.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSMutableStyleDeclaration; +class CSSPrimitiveValue; +class CSSProperty; +class CSSFontFace; +class CSSFontFaceRule; +class CSSRuleData; +class CSSRuleDataList; +class CSSRuleList; +class CSSRuleSet; +class CSSSelector; +class CSSStyleRule; +class CSSStyleSheet; +class CSSValue; +class Document; +class Element; +class Frame; +class FrameView; +class KURL; +class MediaQueryEvaluator; +class Node; +class Settings; +class StyleSheet; +class StyleSheetList; +class StyledElement; + +class MediaQueryResult +{ +public: + MediaQueryResult(const MediaQueryExp& expr, bool result) + : m_expression(expr) + , m_result(result) + {} + + MediaQueryExp m_expression; + bool m_result; +}; + + /** + * this class selects a RenderStyle for a given Element based on the + * collection of styleshets it contains. This is just a vrtual base class + * for specific implementations of the Selector. At the moment only CSSStyleSelector + * exists, but someone may wish to implement XSL. + */ + class StyleSelector { + public: + enum State { + None = 0x00, + Hover = 0x01, + Focus = 0x02, + Active = 0x04, + Drag = 0x08 + }; + }; + + /** + * the StyleSelector implementation for CSS. + */ + class CSSStyleSelector : public StyleSelector { + public: + CSSStyleSelector(Document*, const String& userStyleSheet, StyleSheetList*, CSSStyleSheet*, bool strictParsing, bool matchAuthorAndUserStyles); + ~CSSStyleSelector(); + + static void loadDefaultStyle(); + + void initElementAndPseudoState(Element*); + void initForStyleResolve(Element*, RenderStyle* parentStyle); + RenderStyle* styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false); + RenderStyle* pseudoStyleForElement(RenderStyle::PseudoId, Element*, RenderStyle* parentStyle = 0); + + RenderStyle* locateSharedStyle(); + Node* locateCousinList(Element* parent, unsigned depth = 1); + bool canShareStyleWithElement(Node* n); + + // These methods will give back the set of rules that matched for a given element (or a pseudo-element). + RefPtr<CSSRuleList> styleRulesForElement(Element*, bool authorOnly); + RefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, StringImpl* pseudoStyle, bool authorOnly); + + bool strictParsing; + + struct EncodedURL { + String prefix; // protocol, host, etc. + String path; + String file; + } m_encodedURL; + + void setEncodedURL(const KURL& url); + + // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return + // the correct font size scaled relative to the user's default (medium). + float fontSizeForKeyword(int keyword, bool quirksMode, bool monospace) const; + + // When the CSS keyword "larger" is used, this function will attempt to match within the keyword + // table, and failing that, will simply multiply by 1.2. + float largerFontSize(float size, bool quirksMode) const; + + // Like the previous function, but for the keyword "smaller". + float smallerFontSize(float size, bool quirksMode) const; + + void setFontSize(FontDescription&, float size); + float getComputedSizeFromSpecifiedSize(bool isAbsoluteSize, float specifiedSize); + + Color getColorFromPrimitiveValue(CSSPrimitiveValue*); + + bool hasSelectorForAttribute(const AtomicString&); + + CSSFontSelector* fontSelector() { return m_fontSelector.get(); } + + /* checks if a compound selector (which can consist of multiple simple selectors) + matches the given Element */ + bool checkSelector(CSSSelector*); + + void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result); + bool affectedByViewportChange() const; + + protected: + enum SelectorMatch { + SelectorMatches = 0, + SelectorFailsLocally, + SelectorFailsCompletely + }; + + SelectorMatch checkSelector(CSSSelector*, Element *, bool isAncestor, bool isSubSelector); + + /* checks if the selector matches the given Element */ + bool checkOneSelector(CSSSelector*, Element*, bool isAncestor, bool isSubSelector = false); + + /* This function fixes up the default font size if it detects that the + current generic font family has changed. -dwh */ + void checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle); + void checkForTextSizeAdjust(); + + void adjustRenderStyle(RenderStyle*, Element*); + + void addMatchedRule(CSSRuleData* rule) { m_matchedRules.append(rule); } + void addMatchedDeclaration(CSSMutableStyleDeclaration* decl) { m_matchedDecls.append(decl); } + + void matchRules(CSSRuleSet*, int& firstRuleIndex, int& lastRuleIndex); + void matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex); + void sortMatchedRules(unsigned start, unsigned end); + + void applyDeclarations(bool firstPass, bool important, int startIndex, int endIndex); + + static CSSStyleSheet* m_defaultSheet; + static CSSStyleSheet* m_quirksSheet; + static CSSStyleSheet* m_viewSourceSheet; +#if ENABLE(SVG) + static CSSStyleSheet* m_svgSheet; +#endif + + static CSSRuleSet* m_defaultStyle; + static CSSRuleSet* m_defaultQuirksStyle; + static CSSRuleSet* m_defaultPrintStyle; + static CSSRuleSet* m_defaultViewSourceStyle; + + CSSRuleSet* m_authorStyle; + CSSRuleSet* m_userStyle; + RefPtr<CSSStyleSheet> m_userSheet; + + bool m_hasUAAppearance; + BorderData m_borderData; + BackgroundLayer m_backgroundData; + Color m_backgroundColor; + + public: + static RenderStyle* m_styleNotYetAvailable; + + private: + void init(); + + void matchUARules(int& firstUARule, int& lastUARule); + void updateFont(); + void cacheBorderAndBackground(); + + void mapBackgroundAttachment(BackgroundLayer*, CSSValue*); + void mapBackgroundClip(BackgroundLayer*, CSSValue*); + void mapBackgroundComposite(BackgroundLayer*, CSSValue*); + void mapBackgroundOrigin(BackgroundLayer*, CSSValue*); + void mapBackgroundImage(BackgroundLayer*, CSSValue*); + void mapBackgroundRepeat(BackgroundLayer*, CSSValue*); + void mapBackgroundSize(BackgroundLayer*, CSSValue*); + void mapBackgroundXPosition(BackgroundLayer*, CSSValue*); + void mapBackgroundYPosition(BackgroundLayer*, CSSValue*); + + void mapTransitionDuration(Transition*, CSSValue*); + void mapTransitionRepeatCount(Transition*, CSSValue*); + void mapTransitionTimingFunction(Transition*, CSSValue*); + void mapTransitionProperty(Transition*, CSSValue*); + + // We collect the set of decls that match in |m_matchedDecls|. We then walk the + // set of matched decls four times, once for those properties that others depend on (like font-size), + // and then a second time for all the remaining properties. We then do the same two passes + // for any !important rules. + Vector<CSSMutableStyleDeclaration*> m_matchedDecls; + + // A buffer used to hold the set of matched rules for an element, and a temporary buffer used for + // merge sorting. + Vector<CSSRuleData*> m_matchedRules; + + CSSRuleList* m_ruleList; + bool m_collectRulesOnly; + + MediaQueryEvaluator* m_medium; + RenderStyle* m_rootDefaultStyle; + + RenderStyle::PseudoId dynamicPseudo; + + Document* m_document; // back pointer to owner document + RenderStyle* m_style; + RenderStyle* m_parentStyle; + Element* m_element; + StyledElement* m_styledElement; + Node* m_parentNode; + RenderStyle::PseudoId m_pseudoStyle; + CSSValue* m_lineHeightValue; + bool m_fontDirty; + bool m_isXMLDoc; + bool m_matchAuthorAndUserStyles; + + RefPtr<CSSFontSelector> m_fontSelector; + + HashSet<AtomicStringImpl*> m_selectorAttrs; + + Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls; + + Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults; + + void applyProperty(int id, CSSValue*); + +#if ENABLE(SVG) + void applySVGProperty(int id, CSSValue*); +#endif + + friend class CSSRuleSet; + friend class Node; + }; + + class CSSRuleData { + public: + CSSRuleData(unsigned pos, CSSStyleRule* r, CSSSelector* sel, CSSRuleData* prev = 0) + : m_position(pos) + , m_rule(r) + , m_selector(sel) + , m_next(0) + { + if (prev) + prev->m_next = this; + } + + ~CSSRuleData() { delete m_next; } + + unsigned position() { return m_position; } + CSSStyleRule* rule() { return m_rule; } + CSSSelector* selector() { return m_selector; } + CSSRuleData* next() { return m_next; } + + private: + unsigned m_position; + CSSStyleRule* m_rule; + CSSSelector* m_selector; + CSSRuleData* m_next; + }; + + class CSSRuleDataList { + public: + CSSRuleDataList(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) + : m_first(new CSSRuleData(pos, rule, sel)) + , m_last(m_first) + { + } + + ~CSSRuleDataList() { delete m_first; } + + CSSRuleData* first() { return m_first; } + CSSRuleData* last() { return m_last; } + + void append(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) { m_last = new CSSRuleData(pos, rule, sel, m_last); } + + private: + CSSRuleData* m_first; + CSSRuleData* m_last; + }; + +} // namespace WebCore + +#endif // CSSStyleSelector_h diff --git a/WebCore/css/CSSStyleSheet.cpp b/WebCore/css/CSSStyleSheet.cpp new file mode 100644 index 0000000..acd0955 --- /dev/null +++ b/WebCore/css/CSSStyleSheet.cpp @@ -0,0 +1,206 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSStyleSheet.h" + +#include "CSSImportRule.h" +#include "CSSNamespace.h" +#include "CSSParser.h" +#include "CSSRuleList.h" +#include "Document.h" +#include "ExceptionCode.h" +#include "Node.h" + +namespace WebCore { + +CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, const String& charset) + : StyleSheet(parentSheet, href) + , m_doc(parentSheet ? parentSheet->doc() : 0) + , m_namespaces(0) + , m_charset(charset) + , m_loadCompleted(false) +{ +} + +CSSStyleSheet::CSSStyleSheet(Node *parentNode, const String& href, const String& charset) + : StyleSheet(parentNode, href) + , m_doc(parentNode->document()) + , m_namespaces(0) + , m_charset(charset) + , m_loadCompleted(false) +{ +} + +CSSStyleSheet::CSSStyleSheet(CSSRule *ownerRule, const String& href, const String& charset) + : StyleSheet(ownerRule, href) + , m_doc(0) + , m_namespaces(0) + , m_charset(charset) + , m_loadCompleted(false) +{ +} + +CSSStyleSheet::~CSSStyleSheet() +{ + delete m_namespaces; +} + +CSSRule *CSSStyleSheet::ownerRule() const +{ + return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0; +} + +unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, ExceptionCode& ec) +{ + ec = 0; + if (index > length()) { + ec = INDEX_SIZE_ERR; + return 0; + } + CSSParser p(useStrictParsing()); + RefPtr<CSSRule> r = p.parseRule(this, rule); + + if (!r) { + ec = SYNTAX_ERR; + return 0; + } + + // ### + // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an + //@import rule is inserted after a standard rule set or other at-rule. + insert(index, r.release()); + + styleSheetChanged(); + + return index; +} + +int CSSStyleSheet::addRule(const String& selector, const String& style, int index, ExceptionCode& ec) +{ + insertRule(selector + " { " + style + " }", index, ec); + + // As per Microsoft documentation, always return -1. + return -1; +} + +int CSSStyleSheet::addRule(const String& selector, const String& style, ExceptionCode& ec) +{ + return addRule(selector, style, length(), ec); +} + + +CSSRuleList* CSSStyleSheet::cssRules(bool omitCharsetRules) +{ + return new CSSRuleList(this, omitCharsetRules); +} + +void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec) +{ + if (index >= length()) { + ec = INDEX_SIZE_ERR; + return; + } + + ec = 0; + remove(index); + styleSheetChanged(); +} + +void CSSStyleSheet::addNamespace(CSSParser* p, const AtomicString& prefix, const AtomicString& uri) +{ + if (uri.isEmpty()) + return; + + m_namespaces = new CSSNamespace(prefix, uri, m_namespaces); + + if (prefix.isEmpty()) + // Set the default namespace on the parser so that selectors that omit namespace info will + // be able to pick it up easily. + p->defaultNamespace = uri; +} + +const AtomicString& CSSStyleSheet::determineNamespace(const AtomicString& prefix) +{ + if (prefix.isEmpty()) + return nullAtom; // No namespace. If an element/attribute has a namespace, we won't match it. + else if (prefix == starAtom) + return starAtom; // We'll match any namespace. + else if (m_namespaces) { + CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix); + if (ns) + return ns->uri(); + } + return nullAtom; // Assume we wont match any namespaces. +} + +bool CSSStyleSheet::parseString(const String &string, bool strict) +{ + setStrictParsing(strict); + CSSParser p(strict); + p.parseSheet(this, string); + return true; +} + +bool CSSStyleSheet::isLoading() +{ + unsigned len = length(); + for (unsigned i = 0; i < len; ++i) { + StyleBase* rule = item(i); + if (rule->isImportRule() && static_cast<CSSImportRule*>(rule)->isLoading()) + return true; + } + return false; +} + +void CSSStyleSheet::checkLoaded() +{ + if (isLoading()) + return; + if (parent()) + parent()->checkLoaded(); + m_loadCompleted = m_parentNode ? m_parentNode->sheetLoaded() : true; +} + +DocLoader *CSSStyleSheet::docLoader() +{ + if (!m_doc) // doc is 0 for the user- and default-sheet! + return 0; + + // ### remove? (clients just use sheet->doc()->docLoader()) + return m_doc->docLoader(); +} + +void CSSStyleSheet::styleSheetChanged() +{ + StyleBase* root = this; + while (StyleBase* parent = root->parent()) + root = parent; + Document* documentToUpdate = (root && root->isCSSStyleSheet()) ? static_cast<CSSStyleSheet*>(root)->doc() : 0; + + /* FIXME: We don't need to do everything updateStyleSelector does, + * basically we just need to recreate the document's selector with the + * already existing style sheets. + */ + if (documentToUpdate) + documentToUpdate->updateStyleSelector(); +} + +} diff --git a/WebCore/css/CSSStyleSheet.h b/WebCore/css/CSSStyleSheet.h new file mode 100644 index 0000000..30cbd2a --- /dev/null +++ b/WebCore/css/CSSStyleSheet.h @@ -0,0 +1,85 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSStyleSheet_h +#define CSSStyleSheet_h + +#include "StyleSheet.h" + +namespace WebCore { + +class CSSNamespace; +class CSSParser; +class CSSRule; +class CSSRuleList; +class DocLoader; +class Document; + +typedef int ExceptionCode; + +class CSSStyleSheet : public StyleSheet { +public: + CSSStyleSheet(Node* parentNode, const String& href = String(), const String& charset = String()); + CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href = String(), const String& charset = String()); + CSSStyleSheet(CSSRule* ownerRule, const String& href = String(), const String& charset = String()); + + ~CSSStyleSheet(); + + virtual bool isCSSStyleSheet() const { return true; } + + virtual String type() const { return "text/css"; } + + CSSRule* ownerRule() const; + CSSRuleList* cssRules(bool omitCharsetRules = false); + unsigned insertRule(const String& rule, unsigned index, ExceptionCode&); + void deleteRule(unsigned index, ExceptionCode&); + + // IE Extensions + CSSRuleList* rules() { return cssRules(true); } + int addRule(const String& selector, const String& style, int index, ExceptionCode&); + int addRule(const String& selector, const String& style, ExceptionCode&); + void removeRule(unsigned index, ExceptionCode& ec) { deleteRule(index, ec); } + + void addNamespace(CSSParser*, const AtomicString& prefix, const AtomicString& uri); + const AtomicString& determineNamespace(const AtomicString& prefix); + + virtual void styleSheetChanged(); + + virtual bool parseString(const String&, bool strict = true); + + virtual bool isLoading(); + + virtual void checkLoaded(); + DocLoader* docLoader(); + Document* doc() { return m_doc; } + const String& charset() const { return m_charset; } + + bool loadCompleted() const { return m_loadCompleted; } + +protected: + Document* m_doc; + CSSNamespace* m_namespaces; + String m_charset; + bool m_loadCompleted; +}; + +} // namespace + +#endif diff --git a/WebCore/css/CSSStyleSheet.idl b/WebCore/css/CSSStyleSheet.idl new file mode 100644 index 0000000..dacaeb5 --- /dev/null +++ b/WebCore/css/CSSStyleSheet.idl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + InterfaceUUID=2f547f65-f8c4-4f13-8724-ed10ed79dcc4, + ImplementationUUID=1b5c24b3-8b6f-43a9-8891-654ba858f42f + ] CSSStyleSheet : stylesheets::StyleSheet { + readonly attribute CSSRule ownerRule; + readonly attribute CSSRuleList cssRules; + + [OldStyleObjC] unsigned long insertRule(in DOMString rule, + in unsigned long index) + raises(DOMException); + void deleteRule(in unsigned long index) + raises(DOMException); + + // IE Extensions + readonly attribute CSSRuleList rules; + + long addRule(in DOMString selector, + in DOMString style, + in [Optional] unsigned long index) + raises(DOMException); + void removeRule(in unsigned long index) + raises(DOMException); + }; + +} diff --git a/WebCore/css/CSSTimingFunctionValue.cpp b/WebCore/css/CSSTimingFunctionValue.cpp new file mode 100644 index 0000000..e576d36 --- /dev/null +++ b/WebCore/css/CSSTimingFunctionValue.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSTimingFunctionValue.h" + +#include "PlatformString.h" + +namespace WebCore { + +String CSSTimingFunctionValue::cssText() const +{ + String text("cubic-bezier("); + text += String::number(m_x1); + text += ", "; + text += String::number(m_y1); + text += ", "; + text += String::number(m_x2); + text += ", "; + text += String::number(m_y2); + text += ")"; + return text; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSTimingFunctionValue.h b/WebCore/css/CSSTimingFunctionValue.h new file mode 100644 index 0000000..5d808be --- /dev/null +++ b/WebCore/css/CSSTimingFunctionValue.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CSSTimingFunctionValue_h +#define CSSTimingFunctionValue_h + +#include "CSSValue.h" +#include "FloatPoint.h" + +namespace WebCore { + +class CSSTimingFunctionValue : public CSSValue +{ +public: + CSSTimingFunctionValue(double x1, double y1, double x2, double y2) + : m_x1(x1) + , m_y1(y1) + , m_x2(x2) + , m_y2(y2) + { + } + + virtual String cssText() const; + + virtual bool isTransitionTimingFunctionValue() { return true; } + + double x1() const { return m_x1; } + double y1() const { return m_y1; } + double x2() const { return m_x2; } + double y2() const { return m_y2; } + +private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; +}; + +} // namespace + +#endif diff --git a/WebCore/css/CSSTransformValue.cpp b/WebCore/css/CSSTransformValue.cpp new file mode 100644 index 0000000..34f4dae --- /dev/null +++ b/WebCore/css/CSSTransformValue.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSTransformValue.h" +#include "PlatformString.h" + +namespace WebCore { + +CSSTransformValue::CSSTransformValue(TransformOperationType op) +: m_type(op) +{} + +CSSTransformValue::~CSSTransformValue() +{} + +void CSSTransformValue::addValue(CSSValue* val) +{ + if (!m_values) + m_values = new CSSValueList; + m_values->append(val); +} + +String CSSTransformValue::cssText() const +{ + String result; + switch(m_type) { + case ScaleTransformOperation: + result += "scale("; + break; + case ScaleXTransformOperation: + result += "scaleX("; + break; + case ScaleYTransformOperation: + result += "scaleY("; + break; + case RotateTransformOperation: + result += "rotate("; + break; + case SkewTransformOperation: + result += "skew("; + break; + case SkewXTransformOperation: + result += "skewX("; + break; + case SkewYTransformOperation: + result += "skewY("; + break; + case TranslateTransformOperation: + result += "translate("; + break; + case TranslateXTransformOperation: + result += "translateX("; + break; + case TranslateYTransformOperation: + result += "translateY("; + break; + case MatrixTransformOperation: + result += "matrix("; + break; + default: + break; + } + + if (m_values) + result += m_values->cssText(); + + result += ")"; + return result; +} + +} diff --git a/WebCore/css/CSSTransformValue.h b/WebCore/css/CSSTransformValue.h new file mode 100644 index 0000000..6a35d39 --- /dev/null +++ b/WebCore/css/CSSTransformValue.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CSSValue.h" +#include "CSSValueList.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSTransformValue : public CSSValue +{ +public: + enum TransformOperationType { + UnknownTransformOperation, + ScaleTransformOperation, + ScaleXTransformOperation, + ScaleYTransformOperation, + RotateTransformOperation, + SkewTransformOperation, + SkewXTransformOperation, + SkewYTransformOperation, + TranslateTransformOperation, + TranslateXTransformOperation, + TranslateYTransformOperation, + MatrixTransformOperation + }; + + CSSTransformValue(TransformOperationType); + virtual ~CSSTransformValue(); + + void addValue(CSSValue*); + + virtual String cssText() const; + + TransformOperationType type() const { return m_type; } + CSSValueList* values() const { return m_values.get(); } + +protected: + TransformOperationType m_type; + RefPtr<CSSValueList> m_values; +}; + +} diff --git a/WebCore/css/CSSUnicodeRangeValue.cpp b/WebCore/css/CSSUnicodeRangeValue.cpp new file mode 100644 index 0000000..599c078 --- /dev/null +++ b/WebCore/css/CSSUnicodeRangeValue.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSUnicodeRangeValue.h" + +#include "PlatformString.h" + +namespace WebCore { + +CSSUnicodeRangeValue::~CSSUnicodeRangeValue() +{ +} + +String CSSUnicodeRangeValue::cssText() const +{ + String result; + // FIXME: Implement. + return result; +} + +} diff --git a/WebCore/css/CSSUnicodeRangeValue.h b/WebCore/css/CSSUnicodeRangeValue.h new file mode 100644 index 0000000..8eca31e --- /dev/null +++ b/WebCore/css/CSSUnicodeRangeValue.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSUnicodeRangeValue_h +#define CSSUnicodeRangeValue_h + +#include "CSSValue.h" +#include <wtf/unicode/Unicode.h> + +namespace WebCore { + +class CSSUnicodeRangeValue : public CSSValue { +public: + CSSUnicodeRangeValue(UChar32 from, UChar32 to) + : m_from(from) + , m_to(to) + { + } + + virtual ~CSSUnicodeRangeValue(); + + UChar32 from() const { return m_from; } + UChar32 to() const { return m_to; } + + virtual String cssText() const; + +private: + UChar32 m_from; + UChar32 m_to; +}; + +} // namespace WebCore + +#endif // CSSUnicodeRangeValue_h diff --git a/WebCore/css/CSSUnknownRule.h b/WebCore/css/CSSUnknownRule.h new file mode 100644 index 0000000..4396eb7 --- /dev/null +++ b/WebCore/css/CSSUnknownRule.h @@ -0,0 +1,45 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef CSSUnknownRule_h +#define CSSUnknownRule_h + +#include "CSSRule.h" + +namespace WebCore { + +class CSSUnknownRule : public CSSRule { +public: + CSSUnknownRule(StyleBase* parent) + : CSSRule(parent) + { + } + + virtual bool isUnknownRule() { return true; } + + virtual unsigned short type() const { return UNKNOWN_RULE; } +}; + +} // namespace WebCore + +#endif // CSSUnknownRule_h diff --git a/WebCore/css/CSSUnknownRule.idl b/WebCore/css/CSSUnknownRule.idl new file mode 100644 index 0000000..2365cd2 --- /dev/null +++ b/WebCore/css/CSSUnknownRule.idl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + InterfaceUUID=35670098-b732-419c-b7cd-dc0d5e26d5e3, + ImplementationUUID=4b755f87-2509-4b98-a953-8ecb88fe4b21 + ] CSSUnknownRule : CSSRule { + }; + +} diff --git a/WebCore/css/CSSValue.h b/WebCore/css/CSSValue.h new file mode 100644 index 0000000..b24f605 --- /dev/null +++ b/WebCore/css/CSSValue.h @@ -0,0 +1,55 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSValue_h +#define CSSValue_h + +#include "StyleBase.h" + +namespace WebCore { + +typedef int ExceptionCode; + +class CSSValue : public StyleBase { +public: + enum UnitTypes { + CSS_INHERIT = 0, + CSS_PRIMITIVE_VALUE = 1, + CSS_VALUE_LIST = 2, + CSS_CUSTOM = 3, + CSS_INITIAL = 4 + }; + + CSSValue() : StyleBase(0) { } + + virtual unsigned short cssValueType() const { return CSS_CUSTOM; } + + virtual String cssText() const = 0; + void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented. + + virtual bool isValue() { return true; } + virtual bool isFontValue() { return false; } + virtual bool isImplicitInitialValue() const { return false; } + virtual bool isTransitionTimingFunctionValue() { return false; } +}; + +} // namespace WebCore + +#endif // CSSValue_h diff --git a/WebCore/css/CSSValue.idl b/WebCore/css/CSSValue.idl new file mode 100644 index 0000000..8979b61 --- /dev/null +++ b/WebCore/css/CSSValue.idl @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + interface [ + GenerateConstructor, + ObjCCustomInternalImpl, + InterfaceUUID=9fd62a7b-539d-4500-bd6c-ec075abbc404, + ImplementationUUID=e10a2860-f98e-4bd3-96b4-1493ad941dfe + ] CSSValue { + + // UnitTypes + const unsigned short CSS_INHERIT = 0; + const unsigned short CSS_PRIMITIVE_VALUE = 1; + const unsigned short CSS_VALUE_LIST = 2; + const unsigned short CSS_CUSTOM = 3; + + attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + setter raises(DOMException); + + readonly attribute unsigned short cssValueType; + + }; + +} diff --git a/WebCore/css/CSSValueKeywords.in b/WebCore/css/CSSValueKeywords.in new file mode 100644 index 0000000..a8c0062 --- /dev/null +++ b/WebCore/css/CSSValueKeywords.in @@ -0,0 +1,567 @@ +# These are all values accepted for CSS2. +# +# WARNING: +# -------- +# +# The Values are sorted according to the properties they belong to, +# and have to be in the same order as the enums in RenderStyle.h. +# +# If not, the optimizations in the cssparser and style selector will fail, +# and produce incorrect results. +# +inherit +initial +# +# CSS_PROP_OUTLINE_STYLE +# CSS_PROP_BORDER_TOP_STYLE +# CSS_PROP_BORDER_BOTTOM_STYLE +# CSS_PROP_BORDER_LEFT_STYLE +none +hidden +inset +groove +ridge +outset +dotted +dashed +solid +double +# +# CSS_PROP_FONT: +# +caption +icon +menu +message-box +small-caption +-webkit-mini-control +-webkit-small-control +-webkit-control +status-bar + +# +# CSS_PROP_FONT_STYLE: +# +#normal +italic +oblique +# +# CSS_PROP_FONT_VARIANT: +# +#normal +small-caps +# +# CSS_PROP_FONT_WEIGHT: +# +normal +bold +bolder +lighter +100 +200 +300 +400 +500 +600 +700 +800 +900 +# +# CSS_PROP_FONT_SIZE: +# +xx-small +x-small +small +medium +large +x-large +xx-large +-webkit-xxx-large +smaller +larger +# +# CSS_PROP_FONT_STRETCH: +# +#normal +wider +narrower +ultra-condensed +extra-condensed +condensed +semi-condensed +semi-expanded +expanded +extra-expanded +ultra-expanded +# +# CSS_PROP_GENERIC_FONT_FAMILY: +# +serif +sans-serif +cursive +fantasy +monospace +-webkit-body +# +# +# CSS_PROP_*_COLOR +# +aqua +black +blue +fuchsia +gray +green +lime +maroon +navy +olive +orange +purple +red +silver +teal +white +yellow +transparent +-webkit-link +-webkit-activelink +activeborder +activecaption +appworkspace +background +buttonface +buttonhighlight +buttonshadow +buttontext +captiontext +graytext +highlight +highlighttext +inactiveborder +inactivecaption +inactivecaptiontext +infobackground +infotext +match +menutext +scrollbar +threeddarkshadow +threedface +threedhighlight +threedlightshadow +threedshadow +window +windowframe +windowtext +-webkit-focus-ring-color +# +# colors in non strict mode +grey +-webkit-text +# +# CSS_PROP_BACKGROUND_REPEAT: +# +repeat +repeat-x +repeat-y +no-repeat +# +# CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: +# +clear +copy +source-over +source-in +source-out +source-atop +destination-over +destination-in +destination-out +destination-atop +xor +plus-darker +# highlight +plus-lighter +# +# CSS_PROP_VERTICAL_ALIGN: +# +baseline +middle +sub +super +text-top +text-bottom +top +bottom +# HTML alignment MIDDLE has no corresponding CSS alignment +-webkit-baseline-middle +# +# CSS_PROP_TEXT_ALIGN: +# +-webkit-auto +left +right +center +justify +-webkit-left +-webkit-right +-webkit-center +# +# CSS_PROP_LIST_STYLE_POSITION: +# +outside +inside +# +# CSS_PROP_LIST_STYLE_TYPE: +# +disc +circle +square +decimal +decimal-leading-zero +lower-roman +upper-roman +lower-greek +lower-alpha +lower-latin +upper-alpha +upper-latin +hebrew +armenian +georgian +cjk-ideographic +hiragana +katakana +hiragana-iroha +katakana-iroha +#none +# +# CSS_PROP_DISPLAY: +# +inline +block +list-item +run-in +compact +inline-block +table +inline-table +table-row-group +table-header-group +table-footer-group +table-row +table-column-group +table-column +table-cell +table-caption +-webkit-box +-webkit-inline-box +#none +# +# CSS_PROP_CURSOR: +# +auto +crosshair +default +pointer +move +vertical-text +cell +context-menu +alias +# copy +progress +no-drop +not-allowed +-webkit-zoom-in +-webkit-zoom-out +e-resize +ne-resize +nw-resize +n-resize +se-resize +sw-resize +s-resize +w-resize +ew-resize +ns-resize +nesw-resize +nwse-resize +col-resize +row-resize +text +wait +help +all-scroll +# none +# +# CSS_PROP_DIRECTION: +# +ltr +rtl +# +# CSS_PROP_TEXT_TRANSFORM: +# +capitalize +uppercase +lowercase +#none +# +# CSS_PROP_VISIBILITY: +# +visible +#hidden +collapse +# +# Unordered rest +# +above +absolute +always +avoid +below +bidi-override +blink +both +close-quote +crop +cross +embed +fixed +hand +hide +higher +invert +landscape +level +line-through +loud +lower +-webkit-marquee +mix +no-close-quote +no-open-quote +nowrap +open-quote +overlay +overline +portrait +pre +pre-line +pre-wrap +relative +scroll +separate +show +static +thick +thin +underline +-webkit-nowrap + +# CSS3 Values +# CSS_PROP_BOX_ALIGN +stretch +start +end +#center +#baseline + +# CSS_PROP_BOX_DIRECTION +# normal +reverse + +# CSS_PROP_BOX_ORIENT +horizontal +vertical +inline-axis +block-axis + +# CSS_PROP_BOX_PACK +# start +# end +# center +# justify + +# CSS_PROP_BOX_LINES +single +multiple + +# CSS_PROP_MARQUEE_DIRECTION +forwards +backwards +ahead +# reverse +# left +# right +up +down +# auto + +# CSS_PROP_MARQUEE_SPEED +slow +# normal +fast + +# CSS_PROP_MARQUEE_REPETITION +infinite + +# CSS_PROP_MARQUEE_STYLE +# none +slide +# scroll +alternate + +# +# CSS_PROP__KHTML_USER_MODIFY +# +read-only +read-write +read-write-plaintext-only + +# +# CSS_PROP__KHTML_USER_DRAG +# +element + +# +# CSS_PROP__KHTML_USER_SELECT +# +ignore + +# +# CSS_PROP_WIDTH/MIN_WIDTH/MAX_WIDTH +# +intrinsic +min-intrinsic + +# +# CSS_PROP_TEXT_OVERFLOW +# +clip +ellipsis + +# +# CSS_PROP__KHTML_MARGIN_COLLAPSE +# +# collapse +# separate +discard + +# +# CSS_PROP_TEXT_*_COLOR +# +dot-dash +dot-dot-dash +wave + +# +# CSS_PROP_TEXT_*_MODE +# +continuous +skip-white-space + +# +# CSS_PROP_WORD_BREAK +# +break-all + +# +# CSS_PROP_WORD_WRAP +# +break-word + +# +# CSS_PROP__KHTML_NBSP_MODE +# +space + +# +# CSS_PROP__KHTML_LINE_BREAK +# +after-white-space + +# +# CSS_PROP__KHTML_APPEARANCE +# +checkbox +radio +push-button +square-button +button +button-bevel +listbox +listitem +media-fullscreen-button +media-mute-button +media-play-button +media-seek-back-button +media-seek-forward-button +media-slider +media-sliderthumb +menulist +menulist-button +menulist-text +menulist-textfield +scrollbarbutton-up +scrollbarbutton-down +scrollbarbutton-left +scrollbarbutton-right +scrollbartrack-horizontal +scrollbartrack-vertical +scrollbarthumb-horizontal +scrollbarthumb-vertical +scrollbargripper-horizontal +scrollbargripper-vertical +slider-horizontal +slider-vertical +sliderthumb-horizontal +sliderthumb-vertical +caret +searchfield +searchfield-decoration +searchfield-results-decoration +searchfield-results-button +searchfield-cancel-button +textfield +textarea + +# +# CSS_PROP_BORDER_IMAGE +# +# stretch +# repeat +round + +# +# CSS_PROP_BACKGROUND_CLIP/ORIGIN +# +border +content +padding + +# +# CSS_PROP_BOX_SIZING +# +border-box +content-box + +# +# CSS_PROP__KHTML_RTL_ORDERING +# +logical +visual + +# +# CSS_PROP__WEBKIT_BORDER_FIT +# +lines + +# +# CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION +# +linear +ease-in +ease-out +ease-in-out diff --git a/WebCore/css/CSSValueList.cpp b/WebCore/css/CSSValueList.cpp new file mode 100644 index 0000000..c845ab9 --- /dev/null +++ b/WebCore/css/CSSValueList.cpp @@ -0,0 +1,66 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "CSSValueList.h" + +#include "PlatformString.h" + +namespace WebCore { + +CSSValueList::CSSValueList(bool isSpaceSeparated) + : m_isSpaceSeparated(isSpaceSeparated) +{ +} + +CSSValueList::~CSSValueList() +{ +} + +unsigned short CSSValueList::cssValueType() const +{ + return CSS_VALUE_LIST; +} + +void CSSValueList::append(PassRefPtr<CSSValue> val) +{ + m_values.append(val); +} + +String CSSValueList::cssText() const +{ + String result = ""; + + unsigned size = m_values.size(); + for (unsigned i = 0; i < size; i++) { + if (!result.isEmpty()) { + if (m_isSpaceSeparated) + result += " "; + else + result += ", "; + } + result += m_values[i]->cssText(); + } + + return result; +} + +} // namespace WebCore diff --git a/WebCore/css/CSSValueList.h b/WebCore/css/CSSValueList.h new file mode 100644 index 0000000..405df52 --- /dev/null +++ b/WebCore/css/CSSValueList.h @@ -0,0 +1,54 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef CSSValueList_h +#define CSSValueList_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class CSSValueList : public CSSValue { +public: + CSSValueList(bool isSpaceSeparated = false); + virtual ~CSSValueList(); + + unsigned length() const { return m_values.size(); } + CSSValue* item (unsigned index) { return m_values[index].get(); } + + virtual bool isValueList() { return true; } + + virtual unsigned short cssValueType() const; + + void append(PassRefPtr<CSSValue>); + virtual String cssText() const; + +protected: + Vector<RefPtr<CSSValue> > m_values; + bool m_isSpaceSeparated; +}; + +} // namespace WebCore + +#endif // CSSValueList_h diff --git a/WebCore/css/CSSValueList.idl b/WebCore/css/CSSValueList.idl new file mode 100644 index 0000000..8ddfaae --- /dev/null +++ b/WebCore/css/CSSValueList.idl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + HasIndexGetter, + InterfaceUUID=2fb74620-9029-400c-bc4b-4ce8e25b081f, + ImplementationUUID=1d8fc822-f89a-48d5-a2ac-827e5a24357e + ] CSSValueList : CSSValue { + readonly attribute unsigned long length; + CSSValue item(in unsigned long index); + }; + +} diff --git a/WebCore/css/Counter.h b/WebCore/css/Counter.h new file mode 100644 index 0000000..9bca29b --- /dev/null +++ b/WebCore/css/Counter.h @@ -0,0 +1,61 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef Counter_h +#define Counter_h + +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" +#include <wtf/RefCounted.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class Counter : public RefCounted<Counter> { +public: + Counter(PassRefPtr<CSSPrimitiveValue> identifier, PassRefPtr<CSSPrimitiveValue> listStyle, PassRefPtr<CSSPrimitiveValue> separator) + : RefCounted<Counter>(0) + , m_identifier(identifier) + , m_listStyle(listStyle) + , m_separator(separator) + { + } + + String identifier() const { return m_identifier ? m_identifier->getStringValue() : String(); } + String listStyle() const { return m_listStyle ? m_listStyle->getStringValue() : String(); } + String separator() const { return m_separator ? m_separator->getStringValue() : String(); } + + int listStyleNumber() const { return m_listStyle ? m_listStyle->getIntValue() : 0; } + + void setIdentifier(PassRefPtr<CSSPrimitiveValue> identifier) { m_identifier = identifier; } + void setListStyle(PassRefPtr<CSSPrimitiveValue> listStyle) { m_listStyle = listStyle; } + void setSeparator(PassRefPtr<CSSPrimitiveValue> separator) { m_separator = separator; } + +protected: + RefPtr<CSSPrimitiveValue> m_identifier; // String + RefPtr<CSSPrimitiveValue> m_listStyle; // int + RefPtr<CSSPrimitiveValue> m_separator; // String +}; + +} // namespace WebCore + +#endif // Counter_h diff --git a/WebCore/css/Counter.idl b/WebCore/css/Counter.idl new file mode 100644 index 0000000..5be8f0d --- /dev/null +++ b/WebCore/css/Counter.idl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + InterfaceUUID=365d0f26-3a6e-457c-a34c-174d98f79798, + ImplementationUUID=8bfdc968-9a1b-4e4f-8d36-732d49b48eaa + ] Counter { + readonly attribute DOMString identifier; + readonly attribute DOMString listStyle; + readonly attribute DOMString separator; + }; + +} diff --git a/WebCore/css/DashboardRegion.h b/WebCore/css/DashboardRegion.h new file mode 100644 index 0000000..338b6aa --- /dev/null +++ b/WebCore/css/DashboardRegion.h @@ -0,0 +1,43 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef DashboardRegion_h +#define DashboardRegion_h + +#include "Rect.h" + +namespace WebCore { + +class DashboardRegion : public Rect { +public: + DashboardRegion() : m_isCircle(0), m_isRectangle(0) { } + + RefPtr<DashboardRegion> m_next; + String m_label; + String m_geometryType; + bool m_isCircle : 1; + bool m_isRectangle : 1; +}; + +} // namespace + +#endif diff --git a/WebCore/css/FontFamilyValue.cpp b/WebCore/css/FontFamilyValue.cpp new file mode 100644 index 0000000..f9bd75c --- /dev/null +++ b/WebCore/css/FontFamilyValue.cpp @@ -0,0 +1,106 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "FontFamilyValue.h" + +namespace WebCore { + +static bool isValidCSSIdentifier(const String& string) +{ + unsigned length = string.length(); + if (!length) + return false; + + const UChar* characters = string.characters(); + UChar c = characters[0]; + if (!(c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c >= 0x80)) + return false; + + for (unsigned i = 1; i < length; ++i) { + c = characters[i]; + if (!(c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c >= 0x80)) + return false; + } + + return true; +} + +// Quotes the string if it needs quoting. +// We use single quotes because serialization code uses double quotes, and it's nice to +// avoid having to turn all the quote marks into " as we would have to. +static String quoteStringIfNeeded(const String& string) +{ + if (isValidCSSIdentifier(string)) + return string; + + // FIXME: Also need to transform control characters (00-1F) into \ sequences. + // FIXME: This is inefficient -- should use a Vector<UChar> instead. + String quotedString = string; + quotedString.replace('\\', "\\\\"); + quotedString.replace('\'', "\\'"); + return "'" + quotedString + "'"; +} + +FontFamilyValue::FontFamilyValue(const String& familyName) + : CSSPrimitiveValue(String(), CSS_STRING) + , m_familyName(familyName) +{ + // If there is anything in parentheses or square brackets at the end, delete it. + // FIXME: Do we really need this? The original code mentioned "a language tag in + // braces at the end" and "[Xft] qualifiers", but it's not clear either of those + // is in active use on the web. + unsigned length = m_familyName.length(); + while (length >= 3) { + UChar startCharacter = 0; + switch (m_familyName[length - 1]) { + case ']': + startCharacter = '['; + break; + case ')': + startCharacter = '('; + break; + } + if (!startCharacter) + break; + unsigned first = 0; + for (unsigned i = length - 2; i > 0; --i) { + if (m_familyName[i - 1] == ' ' && m_familyName[i] == startCharacter) + first = i - 1; + } + if (!first) + break; + length = first; + } + m_familyName.truncate(length); +} + +void FontFamilyValue::appendSpaceSeparated(const UChar* characters, unsigned length) +{ + m_familyName.append(' '); + m_familyName.append(characters, length); +} + +String FontFamilyValue::cssText() const +{ + return quoteStringIfNeeded(m_familyName); +} + +} diff --git a/WebCore/css/FontFamilyValue.h b/WebCore/css/FontFamilyValue.h new file mode 100644 index 0000000..9e3cef4 --- /dev/null +++ b/WebCore/css/FontFamilyValue.h @@ -0,0 +1,44 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef FontFamilyValue_h +#define FontFamilyValue_h + +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" + +namespace WebCore { + +class FontFamilyValue : public CSSPrimitiveValue { +public: + FontFamilyValue(const String& familyName); + void appendSpaceSeparated(const UChar* characters, unsigned length); + + const String& familyName() const { return m_familyName; } + + virtual String cssText() const; + +private: + String m_familyName; +}; + +} // namespace + +#endif diff --git a/WebCore/css/FontValue.cpp b/WebCore/css/FontValue.cpp new file mode 100644 index 0000000..231ac64 --- /dev/null +++ b/WebCore/css/FontValue.cpp @@ -0,0 +1,69 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "FontValue.h" + +#include "CSSValueList.h" +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" + +namespace WebCore { + +String FontValue::cssText() const +{ + // font variant weight size / line-height family + + String result(""); + + if (style) + result += style->cssText(); + if (variant) { + if (!result.isEmpty()) + result += " "; + result += variant->cssText(); + } + if (weight) { + if (!result.isEmpty()) + result += " "; + result += weight->cssText(); + } + if (size) { + if (!result.isEmpty()) + result += " "; + result += size->cssText(); + } + if (lineHeight) { + if (!size) + result += " "; + result += "/"; + result += lineHeight->cssText(); + } + if (family) { + if (!result.isEmpty()) + result += " "; + result += family->cssText(); + } + + return result; +} + +} diff --git a/WebCore/css/FontValue.h b/WebCore/css/FontValue.h new file mode 100644 index 0000000..d52bfdd --- /dev/null +++ b/WebCore/css/FontValue.h @@ -0,0 +1,51 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef FontValue_h +#define FontValue_h + +#include "CSSValue.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSPrimitiveValue; +class CSSValueList; + +class FontValue : public CSSValue +{ +public: + virtual String cssText() const; + + virtual bool isFontValue() { return true; } + + RefPtr<CSSPrimitiveValue> style; + RefPtr<CSSPrimitiveValue> variant; + RefPtr<CSSPrimitiveValue> weight; + RefPtr<CSSPrimitiveValue> size; + RefPtr<CSSPrimitiveValue> lineHeight; + RefPtr<CSSValueList> family; +}; + +} // namespace + +#endif diff --git a/WebCore/css/MediaFeatureNames.cpp b/WebCore/css/MediaFeatureNames.cpp new file mode 100644 index 0000000..958436d --- /dev/null +++ b/WebCore/css/MediaFeatureNames.cpp @@ -0,0 +1,55 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2005 Apple Computer, Inc. + * + * 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 "config.h" + +#ifdef AVOID_STATIC_CONSTRUCTORS +#define CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS 1 +#endif + +#include "MediaFeatureNames.h" +#include "StaticConstructors.h" + +namespace WebCore { +namespace MediaFeatureNames { + +#define DEFINE_MEDIAFEATURE_GLOBAL(name, str) \ + DEFINE_GLOBAL(AtomicString, name##MediaFeature, str) +CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(DEFINE_MEDIAFEATURE_GLOBAL) +#undef DEFINE_MEDIAFEATURE_GLOBAL + +void init() +{ + static bool initialized; + if (!initialized) { + // Use placement new to initialize the globals. + + AtomicString::init(); + #define INITIALIZE_GLOBAL(name, str) new ((void*)&name##MediaFeature) AtomicString(str); + CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(INITIALIZE_GLOBAL) + #undef INITIALIZE_GLOBAL + initialized = true; + } +} + +} // namespace MediaFeatureNames +} // namespace WebCore diff --git a/WebCore/css/MediaFeatureNames.h b/WebCore/css/MediaFeatureNames.h new file mode 100644 index 0000000..54b61b1 --- /dev/null +++ b/WebCore/css/MediaFeatureNames.h @@ -0,0 +1,69 @@ +/* + * This file is part of the CSS implementation for KDE. + * + * Copyright (C) 2005 Apple Computer, Inc. + * + * 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. + * + */ +#ifndef MediaFeatureNames_h +#define MediaFeatureNames_h + +#include "AtomicString.h" + +namespace WebCore { + namespace MediaFeatureNames { + +#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \ + macro(color, "color") \ + macro(grid, "grid") \ + macro(monochrome, "monochrome") \ + macro(height, "height") \ + macro(width, "width") \ + macro(device_aspect_ratio, "device-aspect-ratio") \ + macro(device_pixel_ratio, "-webkit-device-pixel-ratio") \ + macro(device_height, "device-height") \ + macro(device_width, "device-width") \ + macro(max_color, "max-color") \ + macro(max_device_aspect_ratio, "max-device-aspect-ratio") \ + macro(max_device_pixel_ratio, "-webkit-max-device-pixel-ratio") \ + macro(max_device_height, "max-device-height") \ + macro(max_device_width, "max-device-width") \ + macro(max_height, "max-height") \ + macro(max_monochrome, "max-monochrome") \ + macro(max_width, "max-width") \ + macro(min_color, "min-color") \ + macro(min_device_aspect_ratio, "min-device-aspect-ratio") \ + macro(min_device_pixel_ratio, "-webkit-min-device-pixel-ratio") \ + macro(min_device_height, "min-device-height") \ + macro(min_device_width, "min-device-width") \ + macro(min_height, "min-height") \ + macro(min_monochrome, "min-monochrome") \ + macro(min_width, "min-width") \ +// end of macro + +#ifndef CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS + #define CSS_MEDIAQUERY_NAMES_DECLARE(name, str) extern const AtomicString name##MediaFeature; + CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(CSS_MEDIAQUERY_NAMES_DECLARE) + #undef CSS_MEDIAQUERY_NAMES_DECLARE +#endif + + void init(); + + } // namespace MediaFeatureNames +} // namespace WebCore + +#endif // MediaFeatureNames_h diff --git a/WebCore/css/MediaList.cpp b/WebCore/css/MediaList.cpp new file mode 100644 index 0000000..397eb1b --- /dev/null +++ b/WebCore/css/MediaList.cpp @@ -0,0 +1,271 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "MediaList.h" + +#include "CSSParser.h" +#include "CSSRule.h" +#include "CSSStyleSheet.h" +#include "ExceptionCode.h" +#include "MediaQuery.h" + +namespace WebCore { + +/* MediaList is used to store 3 types of media related entities which mean the same: + * Media Queries, Media Types and Media Descriptors. + * Currently MediaList always tries to parse media queries and if parsing fails, + * tries to fallback to Media Descriptors if m_fallback flag is set. + * Slight problem with syntax error handling: + * CSS 2.1 Spec (http://www.w3.org/TR/CSS21/media.html) + * specifies that failing media type parsing is a syntax error + * CSS 3 Media Queries Spec (http://www.w3.org/TR/css3-mediaqueries/) + * specifies that failing media query is a syntax error + * HTML 4.01 spec (http://www.w3.org/TR/REC-html40/present/styles.html#adef-media) + * specifies that Media Descriptors should be parsed with forward-compatible syntax + * DOM Level 2 Style Sheet spec (http://www.w3.org/TR/DOM-Level-2-Style/) + * talks about MediaList.mediaText and refers + * - to Media Descriptors of HTML 4.0 in context of StyleSheet + * - to Media Types of CSS 2.0 in context of CSSMediaRule and CSSImportRule + * + * These facts create situation where same (illegal) media specification may result in + * different parses depending on whether it is media attr of style element or part of + * css @media rule. + * <style media="screen and resolution > 40dpi"> ..</style> will be enabled on screen devices where as + * @media screen and resolution > 40dpi {..} will not. + * This gets more counter-intuitive in JavaScript: + * document.styleSheets[0].media.mediaText = "screen and resolution > 40dpi" will be ok and + * enabled, while + * document.styleSheets[0].cssRules[0].media.mediaText = "screen and resolution > 40dpi" will + * throw SYNTAX_ERR exception. + */ + +MediaList::MediaList(CSSStyleSheet* parentSheet, bool fallbackToDescriptor) + : StyleBase(parentSheet) + , m_fallback(fallbackToDescriptor) +{ +} + +MediaList::MediaList(CSSStyleSheet* parentSheet, const String& media, bool fallbackToDescriptor) + : StyleBase(parentSheet) + , m_fallback(fallbackToDescriptor) +{ + ExceptionCode ec = 0; + setMediaText(media, ec); + // FIXME: parsing can fail. The problem with failing constructor is that + // we would need additional flag saying MediaList is not valid + // Parse can fail only when fallbackToDescriptor == false, i.e when HTML4 media descriptor + // forward-compatible syntax is not in use. + // DOMImplementationCSS seems to mandate that media descriptors are used + // for both html and svg, even though svg:style doesn't use media descriptors + // Currently the only places where parsing can fail are + // creating <svg:style>, creating css media / import rules from js + if (ec) + setMediaText("invalid", ec); +} + +MediaList::MediaList(CSSRule* parentRule, const String& media, bool fallbackToDescriptor) + : StyleBase(parentRule) + , m_fallback(fallbackToDescriptor) +{ + ExceptionCode ec = 0; + setMediaText(media, ec); + //FIXME: parsing can fail. + if (ec) + setMediaText("invalid", ec); +} + +MediaList::~MediaList() +{ + deleteAllValues(m_queries); +} + +CSSStyleSheet *MediaList::parentStyleSheet() const +{ + return parent()->isCSSStyleSheet() ? static_cast<CSSStyleSheet*>(parent()) : 0; +} + +CSSRule *MediaList::parentRule() const +{ + return parent()->isRule() ? static_cast<CSSRule*>(parent()) : 0; +} + +static String parseMediaDescriptor(const String& s) +{ + int len = s.length(); + + // http://www.w3.org/TR/REC-html40/types.html#type-media-descriptors + // "Each entry is truncated just before the first character that isn't a + // US ASCII letter [a-zA-Z] (ISO 10646 hex 41-5a, 61-7a), digit [0-9] (hex 30-39), + // or hyphen (hex 2d)." + int i; + unsigned short c; + for (i = 0; i < len; ++i) { + c = s[i]; + if (! ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || (c >= '1' && c <= '9') + || (c == '-'))) + break; + } + return s.left(i); +} + +void MediaList::deleteMedium(const String& oldMedium, ExceptionCode& ec) +{ + MediaList tempMediaList; + CSSParser p(true); + + MediaQuery* oldQuery = 0; + bool deleteOldQuery = false; + + if (p.parseMediaQuery(&tempMediaList, oldMedium)) { + if (tempMediaList.m_queries.size() > 0) + oldQuery = tempMediaList.m_queries[0]; + } else if (m_fallback) { + String medium = parseMediaDescriptor(oldMedium); + if (!medium.isNull()) { + oldQuery = new MediaQuery(MediaQuery::None, medium, 0); + deleteOldQuery = true; + } + } + + // DOM Style Sheets spec doesn't allow SYNTAX_ERR to be thrown in deleteMedium + ec = NOT_FOUND_ERR; + + if (oldQuery) { + for(size_t i = 0; i < m_queries.size(); ++i) { + MediaQuery* a = m_queries[i]; + if (*a == *oldQuery) { + m_queries.remove(i); + delete a; + ec = 0; + break; + } + } + if (deleteOldQuery) + delete oldQuery; + } + + if (!ec) + notifyChanged(); +} + +String MediaList::mediaText() const +{ + String text(""); + + bool first = true; + for (size_t i = 0; i < m_queries.size(); ++i) { + if (!first) + text += ", "; + else + first = false; + text += m_queries[i]->cssText(); + } + + return text; +} + +void MediaList::setMediaText(const String& value, ExceptionCode& ec) +{ + MediaList tempMediaList; + CSSParser p(true); + + Vector<String> list; + value.split(',', list); + Vector<String>::const_iterator end = list.end(); + for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) { + String medium = (*it).stripWhiteSpace(); + if (!medium.isEmpty()) { + if (!p.parseMediaQuery(&tempMediaList, medium)) { + if (m_fallback) { + String mediaDescriptor = parseMediaDescriptor(medium); + if (!mediaDescriptor.isNull()) + tempMediaList.m_queries.append(new MediaQuery(MediaQuery::None, mediaDescriptor, 0)); + } else { + ec = SYNTAX_ERR; + return; + } + } + } else if (!m_fallback) { + ec = SYNTAX_ERR; + return; + } + } + // ",,,," falls straight through, but is not valid unless fallback + if (!m_fallback && list.begin() == list.end()) { + String s = value.stripWhiteSpace(); + if (!s.isEmpty()) { + ec = SYNTAX_ERR; + return; + } + } + + ec = 0; + deleteAllValues(m_queries); + m_queries = tempMediaList.m_queries; + tempMediaList.m_queries.clear(); + notifyChanged(); +} + +String MediaList::item(unsigned index) const +{ + if (index < m_queries.size()) { + MediaQuery* query = m_queries[index]; + return query->cssText(); + } + + return String(); +} + +void MediaList::appendMedium(const String& newMedium, ExceptionCode& ec) +{ + ec = INVALID_CHARACTER_ERR; + CSSParser p(true); + if (p.parseMediaQuery(this, newMedium)) { + ec = 0; + } else if (m_fallback) { + String medium = parseMediaDescriptor(newMedium); + if (!medium.isNull()) { + m_queries.append(new MediaQuery(MediaQuery::None, medium, 0)); + ec = 0; + } + } + + if (!ec) + notifyChanged(); +} + +void MediaList::appendMediaQuery(MediaQuery* mediaQuery) +{ + m_queries.append(mediaQuery); +} + +void MediaList::notifyChanged() +{ + for (StyleBase* p = parent(); p; p = p->parent()) { + if (p->isCSSStyleSheet()) + return static_cast<CSSStyleSheet*>(p)->styleSheetChanged(); + } +} + +} diff --git a/WebCore/css/MediaList.h b/WebCore/css/MediaList.h new file mode 100644 index 0000000..3b27e1f --- /dev/null +++ b/WebCore/css/MediaList.h @@ -0,0 +1,70 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef MediaList_h +#define MediaList_h + +#include "StyleBase.h" +#include <wtf/Vector.h> +#include "PlatformString.h" + +namespace WebCore { +typedef int ExceptionCode; +class CSSStyleSheet; +class MediaQuery; +class CSSRule; + +class MediaList : public StyleBase +{ +public: + MediaList(bool fallbackToDescription = false) : StyleBase(0), m_fallback(fallbackToDescription) {} + MediaList(CSSStyleSheet* parentSheet, bool fallbackToDescription = false); + MediaList(CSSStyleSheet* parentSheet, const String& media, bool fallbackToDescription = false); + MediaList(CSSRule* parentRule, const String& media, bool fallbackToDescription = false); + ~MediaList(); + + virtual bool isMediaList() { return true; } + + CSSStyleSheet* parentStyleSheet() const; + CSSRule* parentRule() const; + unsigned length() const { return (unsigned) m_queries.size(); } + String item(unsigned index) const; + void deleteMedium(const String& oldMedium, ExceptionCode&); + void appendMedium(const String& newMedium, ExceptionCode&); + + String mediaText() const; + void setMediaText(const String&, ExceptionCode&xo); + + void appendMediaQuery(MediaQuery* mediaQuery); + const Vector<MediaQuery*>* mediaQueries() const { return &m_queries; } + +private: + void notifyChanged(); + +protected: + Vector<MediaQuery*> m_queries; + bool m_fallback; // true if failed media query parsing should fallback to media description parsing +}; + +} // namespace + +#endif diff --git a/WebCore/css/MediaList.idl b/WebCore/css/MediaList.idl new file mode 100644 index 0000000..dc10e63 --- /dev/null +++ b/WebCore/css/MediaList.idl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module stylesheets { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + HasIndexGetter, + InterfaceUUID=4ed02a0b-15b3-4a20-8f16-d91295aaf2cb, + ImplementationUUID=6c5095d8-fdcc-4f9a-b04a-23c2a6d2cf49 + ] MediaList { + + attribute [ConvertNullToNullString, ConvertNullStringTo=Null] DOMString mediaText + setter raises(DOMException); + readonly attribute unsigned long length; + + [ConvertNullStringTo=Null] DOMString item(in unsigned long index); + void deleteMedium(in DOMString oldMedium) + raises(DOMException); + void appendMedium(in DOMString newMedium) + raises(DOMException); + + }; + +} diff --git a/WebCore/css/MediaQuery.cpp b/WebCore/css/MediaQuery.cpp new file mode 100644 index 0000000..ff57372 --- /dev/null +++ b/WebCore/css/MediaQuery.cpp @@ -0,0 +1,97 @@ +/* + * CSS Media Query + * + * Copyright (C) 2005, 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MediaQuery.h" + +#include "MediaQueryExp.h" + +namespace WebCore { + +MediaQuery::MediaQuery(Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs) + : m_restrictor(r) + , m_mediaType(mediaType) + , m_expressions(exprs) +{ + if (!m_expressions) + m_expressions = new Vector<MediaQueryExp*>; +} + +MediaQuery::~MediaQuery() +{ + if (m_expressions) { + deleteAllValues(*m_expressions); + delete m_expressions; + } +} + +bool MediaQuery::operator==(const MediaQuery& other) const +{ + if (m_restrictor != other.m_restrictor + || m_mediaType != other.m_mediaType + || m_expressions->size() != other.m_expressions->size()) + return false; + + for (size_t i = 0; i < m_expressions->size(); ++i) { + MediaQueryExp* exp = m_expressions->at(i); + MediaQueryExp* oexp = other.m_expressions->at(i); + if (!(*exp == *oexp)) + return false; + } + + return true; +} + +String MediaQuery::cssText() const +{ + String text; + switch (m_restrictor) { + case MediaQuery::Only: + text += "only "; + break; + case MediaQuery::Not: + text += "not "; + break; + case MediaQuery::None: + default: + break; + } + text += m_mediaType; + for (size_t i = 0; i < m_expressions->size(); ++i) { + MediaQueryExp* exp = m_expressions->at(i); + text += " and ("; + text += exp->mediaFeature(); + if (exp->value()) { + text += ": "; + text += exp->value()->cssText(); + } + text += ")"; + } + return text; +} + +} //namespace diff --git a/WebCore/css/MediaQuery.h b/WebCore/css/MediaQuery.h new file mode 100644 index 0000000..0aa0da1 --- /dev/null +++ b/WebCore/css/MediaQuery.h @@ -0,0 +1,62 @@ +/* + * CSS Media Query + * + * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaQuery_h +#define MediaQuery_h + +#include "PlatformString.h" +#include <wtf/Vector.h> + +namespace WebCore { +class MediaQueryExp; + +class MediaQuery +{ +public: + enum Restrictor { + Only, Not, None + }; + + MediaQuery(Restrictor r, const String& mediaType, Vector<MediaQueryExp*>* exprs); + ~MediaQuery(); + + Restrictor restrictor() const { return m_restrictor; } + const Vector<MediaQueryExp*>* expressions() const { return m_expressions; } + String mediaType() const { return m_mediaType; } + bool operator==(const MediaQuery& other) const; + void append(MediaQueryExp* newExp) { m_expressions->append(newExp); } + String cssText() const; + + private: + Restrictor m_restrictor; + String m_mediaType; + Vector<MediaQueryExp*>* m_expressions; +}; + +} // namespace + +#endif diff --git a/WebCore/css/MediaQueryEvaluator.cpp b/WebCore/css/MediaQueryEvaluator.cpp new file mode 100644 index 0000000..d5ea65e --- /dev/null +++ b/WebCore/css/MediaQueryEvaluator.cpp @@ -0,0 +1,414 @@ +/* + * CSS Media Query Evaluator + * + * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MediaQueryEvaluator.h" + +#include "Chrome.h" +#include "CSSPrimitiveValue.h" +#include "CSSStyleSelector.h" +#include "CSSValueList.h" +#include "FloatRect.h" +#include "Frame.h" +#include "FrameView.h" +#include "IntRect.h" +#include "MediaFeatureNames.h" +#include "MediaList.h" +#include "MediaQuery.h" +#include "MediaQueryExp.h" +#include "Page.h" +#include "RenderStyle.h" +#include "PlatformScreen.h" +#include <wtf/HashMap.h> + +namespace WebCore { + +using namespace MediaFeatureNames; + +enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix }; + +typedef bool (*EvalFunc)(CSSValue*, RenderStyle*, Frame*, MediaFeaturePrefix); +typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap; +static FunctionMap* gFunctionMap; + +/* + * FIXME: following media features are not implemented: color_index, scan, resolution + * + * color_index, min-color-index, max_color_index: It's unknown how to retrieve + * the information if the display mode is indexed + * scan: The "scan" media feature describes the scanning process of + * tv output devices. It's unknown how to retrieve this information from + * the platform + * resolution, min-resolution, max-resolution: css parser doesn't seem to + * support CSS_DIMENSION + */ + +MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult) + : m_frame(0) + , m_style(0) + , m_expResult(mediaFeatureResult) +{ +} + +MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult) + : m_mediaType(acceptedMediaType) + , m_frame(0) + , m_style(0) + , m_expResult(mediaFeatureResult) +{ +} + +MediaQueryEvaluator:: MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult) + : m_mediaType(acceptedMediaType) + , m_frame(0) + , m_style(0) + , m_expResult(mediaFeatureResult) +{ +} + +MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, Frame* frame, RenderStyle* style) + : m_mediaType(acceptedMediaType.lower()) + , m_frame(frame) + , m_style(style) + , m_expResult(false) // doesn't matter when we have m_frame and m_style +{ +} + +MediaQueryEvaluator::~MediaQueryEvaluator() +{ +} + +bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const +{ + return mediaTypeToMatch.isEmpty() + || equalIgnoringCase(mediaTypeToMatch, "all") + || equalIgnoringCase(mediaTypeToMatch, m_mediaType); +} + +bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) const +{ + // Like mediaTypeMatch, but without the special cases for "" and "all". + ASSERT(mediaTypeToMatch); + ASSERT(mediaTypeToMatch[0] != '\0'); + ASSERT(!equalIgnoringCase(mediaTypeToMatch, String("all"))); + return equalIgnoringCase(mediaTypeToMatch, m_mediaType); +} + +static bool applyRestrictor(MediaQuery::Restrictor r, bool value) +{ + return r == MediaQuery::Not ? !value : value; +} + +bool MediaQueryEvaluator::eval(const MediaList* mediaList, CSSStyleSelector* styleSelector) const +{ + if (!mediaList) + return true; + + const Vector<MediaQuery*>* queries = mediaList->mediaQueries(); + if (!queries->size()) + return true; // empty query list evaluates to true + + // iterate over queries, stop if any of them eval to true (OR semantics) + bool result = false; + for (size_t i = 0; i < queries->size() && !result; ++i) { + MediaQuery* query = queries->at(i); + + if (mediaTypeMatch(query->mediaType())) { + const Vector<MediaQueryExp*>* exps = query->expressions(); + // iterate through expressions, stop if any of them eval to false + // (AND semantics) + size_t j = 0; + for (; j < exps->size(); ++j) { + bool exprResult = eval(exps->at(j)); + if (styleSelector && exps->at(j)->isViewportDependent()) + styleSelector->addViewportDependentMediaQueryResult(exps->at(j), exprResult); + if (!exprResult) + break; + } + + // assume true if we are at the end of the list, + // otherwise assume false + result = applyRestrictor(query->restrictor(), exps->size() == j); + } else + result = applyRestrictor(query->restrictor(), false); + } + + return result; +} + +static bool parseAspectRatio(CSSValue* value, int& h, int& v) +{ + if (value->isValueList()){ + CSSValueList* valueList = static_cast<CSSValueList*>(value); + if (valueList->length() == 3) { + CSSValue* i0 = valueList->item(0); + CSSValue* i1 = valueList->item(1); + CSSValue* i2 = valueList->item(2); + if (i0->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i0)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER + && i1->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i1)->primitiveType() == CSSPrimitiveValue::CSS_STRING + && i2->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i2)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + String str = static_cast<CSSPrimitiveValue*>(i1)->getStringValue(); + if (!str.isNull() && str.length() == 1 && str[0] == '/') { + h = static_cast<CSSPrimitiveValue*>(i0)->getIntValue(CSSPrimitiveValue::CSS_NUMBER); + v = static_cast<CSSPrimitiveValue*>(i2)->getIntValue(CSSPrimitiveValue::CSS_NUMBER); + return true; + } + } + } + } + return false; +} + +template<typename T> +bool compareValue(T a, T b, MediaFeaturePrefix op) +{ + switch (op) { + case MinPrefix: + return a >= b; + case MaxPrefix: + return a <= b; + case NoPrefix: + return a == b; + } + return false; +} + +static bool numberValue(CSSValue* value, float& result) +{ + if (value->isPrimitiveValue() + && static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + result = static_cast<CSSPrimitiveValue*>(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER); + return true; + } + return false; +} + +static bool colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame()->view()); + float number; + if (value) + return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op); + + return bitsPerComponent != 0; +} + +static bool monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + if (!screenIsMonochrome(frame->page()->mainFrame()->view())) + return false; + + return colorMediaFeatureEval(value, style, frame, op); +} + +static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + if (value) { + FloatRect sg = screenRect(frame->page()->mainFrame()->view()); + int h = 0; + int v = 0; + if (parseAspectRatio(value, h, v)) + return v != 0 && compareValue(static_cast<int>(sg.width()) * v, static_cast<int>(sg.height()) * h, op); + return false; + } + + // ({,min-,max-}device-aspect-ratio) + // assume if we have a device, its aspect ratio is non-zero + return true; +} + +static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + if (value) + return value->isPrimitiveValue() && compareValue(frame->page()->chrome()->scaleFactor(), static_cast<CSSPrimitiveValue*>(value)->getFloatValue(), op); + + return frame->page()->chrome()->scaleFactor() != 0; +} + +static bool gridMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + // if output device is bitmap, grid: 0 == true + // assume we have bitmap device + float number; + if (value && numberValue(value, number)) + return compareValue(static_cast<int>(number), 0, op); + return false; +} + +static bool device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + if (value) { + FloatRect sg = screenRect(frame->page()->mainFrame()->view()); + return value->isPrimitiveValue() && compareValue(static_cast<int>(sg.height()), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style), op); + } + // ({,min-,max-}device-height) + // assume if we have a device, assume non-zero + return true; +} + +static bool device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + if (value) { + FloatRect sg = screenRect(frame->page()->mainFrame()->view()); + return value->isPrimitiveValue() && compareValue(static_cast<int>(sg.width()), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style), op); + } + // ({,min-,max-}device-width) + // assume if we have a device, assume non-zero + return true; +} + +static bool heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + FrameView* view = frame->view(); + + if (value) + return value->isPrimitiveValue() && compareValue(view->visibleHeight(), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style), op); + + return view->visibleHeight() != 0; +} + +static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +{ + FrameView* view = frame->view(); + + if (value) + return value->isPrimitiveValue() && compareValue(view->visibleWidth(), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style), op); + + return view->visibleWidth() != 0; +} + +// rest of the functions are trampolines which set the prefix according to the media feature expression used + +static bool min_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return colorMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return colorMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return monochromeMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return monochromeMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_pixel_ratioMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_pixel_ratioMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return heightMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return heightMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return widthMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return widthMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_heightMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_heightMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static bool min_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_widthMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix /*op*/) +{ + return device_widthMediaFeatureEval(value, style, frame, MaxPrefix); +} + +static void createFunctionMap() +{ + // Create the table. + gFunctionMap = new FunctionMap; +#define ADD_TO_FUNCTIONMAP(name, str) \ + gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval); + CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP); +#undef ADD_TO_FUNCTIONMAP +} + +bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const +{ + if (!m_frame || !m_style) + return m_expResult; + + if (!gFunctionMap) + createFunctionMap(); + + // call the media feature evaluation function. Assume no prefix + // and let trampoline functions override the prefix if prefix is + // used + EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl()); + if (func) + return func(expr->value(), m_style, m_frame, NoPrefix); + + return false; +} + +} // namespace diff --git a/WebCore/css/MediaQueryEvaluator.h b/WebCore/css/MediaQueryEvaluator.h new file mode 100644 index 0000000..5ae8fec --- /dev/null +++ b/WebCore/css/MediaQueryEvaluator.h @@ -0,0 +1,91 @@ +/* + * CSS Media Query Evaluator + * + * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaQueryEvaluator_h +#define MediaQueryEvaluator_h + +#include "PlatformString.h" + +namespace WebCore { +class CSSStyleSelector; +class Frame; +class RenderStyle; +class MediaList; +class MediaQueryExp; + +/** + * Class that evaluates css media queries as defined in + * CSS3 Module "Media Queries" (http://www.w3.org/TR/css3-mediaqueries/) + * Special constructors are needed, if simple media queries are to be + * evaluated without knowledge of the medium features. This can happen + * for example when parsing UA stylesheets, if evaluation is done + * right after parsing. + * + * the boolean parameter is used to approximate results of evaluation, if + * the device characteristics are not known. This can be used to prune the loading + * of stylesheets to only those which are probable to match. + */ +class MediaQueryEvaluator +{ +public: + /** Creates evaluator which evaluates only simple media queries + * Evaluator returns true for "all", and returns value of \mediaFeatureResult + * for any media features + */ + MediaQueryEvaluator(bool mediaFeatureResult = false); + + /** Creates evaluator which evaluates only simple media queries + * Evaluator returns true for acceptedMediaType and returns value of \mediafeatureResult + * for any media features + */ + MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult = false); + MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult = false); + + /** Creates evaluator which evaluates full media queries + */ + MediaQueryEvaluator(const String& acceptedMediaType, Frame*, RenderStyle*); + + ~MediaQueryEvaluator(); + + bool mediaTypeMatch(const String& mediaTypeToMatch) const; + bool mediaTypeMatchSpecific(const char* mediaTypeToMatch) const; + + /** Evaluates a list of media queries */ + bool eval(const MediaList*, CSSStyleSelector* = 0) const; + + /** Evaluates media query subexpression, ie "and (media-feature: value)" part */ + bool eval(const MediaQueryExp*) const; + +private: + String m_mediaType; + Frame* m_frame; // not owned + RenderStyle* m_style; // not owned + bool m_expResult; +}; + +} // namespace +#endif diff --git a/WebCore/css/MediaQueryExp.cpp b/WebCore/css/MediaQueryExp.cpp new file mode 100644 index 0000000..e6f9ff0 --- /dev/null +++ b/WebCore/css/MediaQueryExp.cpp @@ -0,0 +1,85 @@ +/* + * CSS Media Query + * + * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MediaQueryExp.h" + +#include "CSSParser.h" +#include "CSSPrimitiveValue.h" +#include "CSSValueList.h" + +namespace WebCore { + +MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, ValueList* valueList) + : m_mediaFeature(mediaFeature) + , m_value(0) +{ + if (valueList) { + if (valueList->size() == 1) { + Value* value = valueList->current(); + + if (value->id != 0) + m_value = new CSSPrimitiveValue(value->id); + else if (value->unit == CSSPrimitiveValue::CSS_STRING) + m_value = new CSSPrimitiveValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && + value->unit <= CSSPrimitiveValue::CSS_KHZ) + m_value = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + + valueList->next(); + } else if (valueList->size() > 1) { + // create list of values + // currently accepts only <integer>/<integer> + + CSSValueList* list = new CSSValueList(); + Value* value = 0; + bool isValid = true; + + while ((value = valueList->current()) && isValid) { + if (value->unit == Value::Operator && value->iValue == '/') + list->append(new CSSPrimitiveValue("/", CSSPrimitiveValue::CSS_STRING)); + else if (value->unit == CSSPrimitiveValue::CSS_NUMBER) + list->append(new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_NUMBER)); + else + isValid = false; + + value = valueList->next(); + } + + if (isValid) + m_value = list; + else + delete list; + } + } +} + +MediaQueryExp::~MediaQueryExp() +{ +} + +} // namespace diff --git a/WebCore/css/MediaQueryExp.h b/WebCore/css/MediaQueryExp.h new file mode 100644 index 0000000..14cb123 --- /dev/null +++ b/WebCore/css/MediaQueryExp.h @@ -0,0 +1,68 @@ +/* + * CSS Media Query + * + * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MediaQueryExp_h +#define MediaQueryExp_h + +#include "AtomicString.h" +#include "CSSValue.h" +#include "MediaFeatureNames.h" +#include <wtf/RefPtr.h> + +namespace WebCore { +class ValueList; + +class MediaQueryExp +{ +public: + MediaQueryExp(const AtomicString& mediaFeature, ValueList* values); + ~MediaQueryExp(); + + AtomicString mediaFeature() const { return m_mediaFeature; } + + CSSValue* value() const { return m_value.get(); } + + bool operator==(const MediaQueryExp& other) const { + return (other.m_mediaFeature == m_mediaFeature) + && ((!other.m_value && !m_value) + || (other.m_value && m_value && other.m_value->cssText() == m_value->cssText())); + } + + bool isViewportDependent() const { return m_mediaFeature == MediaFeatureNames::widthMediaFeature || + m_mediaFeature == MediaFeatureNames::heightMediaFeature || + m_mediaFeature == MediaFeatureNames::min_widthMediaFeature || + m_mediaFeature == MediaFeatureNames::min_heightMediaFeature || + m_mediaFeature == MediaFeatureNames::max_widthMediaFeature || + m_mediaFeature == MediaFeatureNames::max_heightMediaFeature; } +private: + AtomicString m_mediaFeature; + RefPtr<CSSValue> m_value; +}; + +} // namespace + +#endif diff --git a/WebCore/css/Pair.h b/WebCore/css/Pair.h new file mode 100644 index 0000000..df4f84b --- /dev/null +++ b/WebCore/css/Pair.h @@ -0,0 +1,56 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef Pair_h +#define Pair_h + +#include <wtf/RefCounted.h> +#include "CSSPrimitiveValue.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +// A primitive value representing a pair. This is useful for properties like border-radius, background-size/position, +// and border-spacing (all of which are space-separated sets of two values). At the moment we are only using it for +// border-radius and background-size, but (FIXME) border-spacing and background-position could be converted over to use +// it (eliminating some extra -webkit- internal properties). +class Pair : public RefCounted<Pair> { +public: + Pair() : RefCounted<Pair>(0), m_first(0), m_second(0) { } + Pair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second) + : RefCounted<Pair>(0), m_first(first), m_second(second) { } + virtual ~Pair() { } + + CSSPrimitiveValue* first() const { return m_first.get(); } + CSSPrimitiveValue* second() const { return m_second.get(); } + + void setFirst(PassRefPtr<CSSPrimitiveValue> first) { m_first = first; } + void setSecond(PassRefPtr<CSSPrimitiveValue> second) { m_second = second; } + +protected: + RefPtr<CSSPrimitiveValue> m_first; + RefPtr<CSSPrimitiveValue> m_second; +}; + +} // namespace + +#endif diff --git a/WebCore/css/RGBColor.idl b/WebCore/css/RGBColor.idl new file mode 100644 index 0000000..d16c0c6 --- /dev/null +++ b/WebCore/css/RGBColor.idl @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module css { + + // Introduced in DOM Level 2: + interface [ + ObjCCustomImplementation, + InterfaceUUID=2e3b1501-2cf7-4a4a-bbf7-d8843d1c3be7, + ImplementationUUID=cf779953-4898-4800-aa31-6c9e3f4711be + ] RGBColor { + readonly attribute CSSPrimitiveValue red; + readonly attribute CSSPrimitiveValue green; + readonly attribute CSSPrimitiveValue blue; + + // WebKit extensions +#if !defined(LANGUAGE_JAVASCRIPT) + readonly attribute CSSPrimitiveValue alpha; +#endif +#if defined(LANGUAGE_OBJECTIVE_C) + readonly attribute Color color; +#endif + }; + +} diff --git a/WebCore/css/Rect.h b/WebCore/css/Rect.h new file mode 100644 index 0000000..e0cc024 --- /dev/null +++ b/WebCore/css/Rect.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef Rect_h +#define Rect_h + +#include "CSSPrimitiveValue.h" +#include <wtf/RefCounted.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + + class Rect : public RefCounted<Rect> { + public: + Rect() : RefCounted<Rect>(0) { } + virtual ~Rect() { } + + CSSPrimitiveValue* top() const { return m_top.get(); } + CSSPrimitiveValue* right() const { return m_right.get(); } + CSSPrimitiveValue* bottom() const { return m_bottom.get(); } + CSSPrimitiveValue* left() const { return m_left.get(); } + + void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; } + void setRight(PassRefPtr<CSSPrimitiveValue> right) { m_right = right; } + void setBottom(PassRefPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; } + void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; } + + private: + RefPtr<CSSPrimitiveValue> m_top; + RefPtr<CSSPrimitiveValue> m_right; + RefPtr<CSSPrimitiveValue> m_bottom; + RefPtr<CSSPrimitiveValue> m_left; + }; + +} // namespace WebCore + +#endif // Rect_h diff --git a/WebCore/css/Rect.idl b/WebCore/css/Rect.idl new file mode 100644 index 0000000..3c31dc6 --- /dev/null +++ b/WebCore/css/Rect.idl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +module css { + + interface [ + GenerateConstructor, + InterfaceUUID=696bc4d9-c1d3-4225-a5b3-2cef28967705, + ImplementationUUID=ae83743f-4dc4-4785-869b-8c3010c7d006 + ] Rect { + readonly attribute CSSPrimitiveValue top; + readonly attribute CSSPrimitiveValue right; + readonly attribute CSSPrimitiveValue bottom; + readonly attribute CSSPrimitiveValue left; + }; + +} diff --git a/WebCore/css/SVGCSSComputedStyleDeclaration.cpp b/WebCore/css/SVGCSSComputedStyleDeclaration.cpp new file mode 100644 index 0000000..7168e5d --- /dev/null +++ b/WebCore/css/SVGCSSComputedStyleDeclaration.cpp @@ -0,0 +1,190 @@ +/* + Copyright (C) 2007 Eric Seidel <eric@webkit.org> + Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> + + 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 "config.h" + +#if ENABLE(SVG) +#include "CSSComputedStyleDeclaration.h" + +#include "CSSPrimitiveValueMappings.h" +#include "CSSPropertyNames.h" +#include "Document.h" + +namespace WebCore { + +static CSSPrimitiveValue* glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation) +{ + switch (orientation) { + case GO_0DEG: + return new CSSPrimitiveValue(0.0f, CSSPrimitiveValue::CSS_DEG); + case GO_90DEG: + return new CSSPrimitiveValue(90.0f, CSSPrimitiveValue::CSS_DEG); + case GO_180DEG: + return new CSSPrimitiveValue(180.0f, CSSPrimitiveValue::CSS_DEG); + case GO_270DEG: + return new CSSPrimitiveValue(270.0f, CSSPrimitiveValue::CSS_DEG); + default: + return 0; + } +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const +{ + Node* node = m_node.get(); + if (!node) + return 0; + + // Make sure our layout is up to date before we allow a query on these attributes. + if (updateLayout) + node->document()->updateLayout(); + + RenderStyle* style = node->computedStyle(); + if (!style) + return 0; + + const SVGRenderStyle* svgStyle = style->svgStyle(); + if (!svgStyle) + return 0; + + switch (static_cast<CSSPropertyID>(propertyID)) { + case CSS_PROP_CLIP_RULE: + return new CSSPrimitiveValue(svgStyle->clipRule()); + case CSS_PROP_FLOOD_OPACITY: + return new CSSPrimitiveValue(svgStyle->floodOpacity(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_STOP_OPACITY: + return new CSSPrimitiveValue(svgStyle->stopOpacity(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_POINTER_EVENTS: + return new CSSPrimitiveValue(svgStyle->pointerEvents()); + case CSS_PROP_COLOR_INTERPOLATION: + return new CSSPrimitiveValue(svgStyle->colorInterpolation()); + case CSS_PROP_COLOR_INTERPOLATION_FILTERS: + return new CSSPrimitiveValue(svgStyle->colorInterpolationFilters()); + case CSS_PROP_FILL_OPACITY: + return new CSSPrimitiveValue(svgStyle->fillOpacity(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_FILL_RULE: + return new CSSPrimitiveValue(svgStyle->fillRule()); + case CSS_PROP_COLOR_RENDERING: + return new CSSPrimitiveValue(svgStyle->colorRendering()); + case CSS_PROP_IMAGE_RENDERING: + return new CSSPrimitiveValue(svgStyle->imageRendering()); + case CSS_PROP_SHAPE_RENDERING: + return new CSSPrimitiveValue(svgStyle->shapeRendering()); + case CSS_PROP_STROKE_LINECAP: + return new CSSPrimitiveValue(svgStyle->capStyle()); + case CSS_PROP_STROKE_LINEJOIN: + return new CSSPrimitiveValue(svgStyle->joinStyle()); + case CSS_PROP_STROKE_MITERLIMIT: + return new CSSPrimitiveValue(svgStyle->strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_STROKE_OPACITY: + return new CSSPrimitiveValue(svgStyle->strokeOpacity(), CSSPrimitiveValue::CSS_NUMBER); + case CSS_PROP_TEXT_RENDERING: + return new CSSPrimitiveValue(svgStyle->textRendering()); + case CSS_PROP_ALIGNMENT_BASELINE: + return new CSSPrimitiveValue(svgStyle->alignmentBaseline()); + case CSS_PROP_DOMINANT_BASELINE: + return new CSSPrimitiveValue(svgStyle->dominantBaseline()); + case CSS_PROP_TEXT_ANCHOR: + return new CSSPrimitiveValue(svgStyle->textAnchor()); + case CSS_PROP_WRITING_MODE: + return new CSSPrimitiveValue(svgStyle->writingMode()); + case CSS_PROP_CLIP_PATH: + if (!svgStyle->clipPath().isEmpty()) + return new CSSPrimitiveValue(svgStyle->clipPath(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_MASK: + if (!svgStyle->maskElement().isEmpty()) + return new CSSPrimitiveValue(svgStyle->maskElement(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_FILTER: + if (!svgStyle->filter().isEmpty()) + return new CSSPrimitiveValue(svgStyle->filter(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_FLOOD_COLOR: + return new CSSPrimitiveValue(svgStyle->floodColor().rgb()); + case CSS_PROP_LIGHTING_COLOR: + return new CSSPrimitiveValue(svgStyle->lightingColor().rgb()); + case CSS_PROP_STOP_COLOR: + return new CSSPrimitiveValue(svgStyle->stopColor().rgb()); + case CSS_PROP_FILL: + return svgStyle->fillPaint(); + case CSS_PROP_KERNING: + return svgStyle->kerning(); + case CSS_PROP_MARKER_END: + if (!svgStyle->endMarker().isEmpty()) + return new CSSPrimitiveValue(svgStyle->endMarker(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_MARKER_MID: + if (!svgStyle->midMarker().isEmpty()) + return new CSSPrimitiveValue(svgStyle->midMarker(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_MARKER_START: + if (!svgStyle->startMarker().isEmpty()) + return new CSSPrimitiveValue(svgStyle->startMarker(), CSSPrimitiveValue::CSS_URI); + return new CSSPrimitiveValue(CSS_VAL_NONE); + case CSS_PROP_STROKE: + return svgStyle->strokePaint(); + case CSS_PROP_STROKE_DASHARRAY: + return svgStyle->strokeDashArray(); + case CSS_PROP_STROKE_DASHOFFSET: + return svgStyle->strokeDashOffset(); + case CSS_PROP_STROKE_WIDTH: + return svgStyle->strokeWidth(); + case CSS_PROP_BASELINE_SHIFT: { + switch (svgStyle->baselineShift()) { + case BS_BASELINE: + return new CSSPrimitiveValue(CSS_VAL_BASELINE); + case BS_SUPER: + return new CSSPrimitiveValue(CSS_VAL_SUPER); + case BS_SUB: + return new CSSPrimitiveValue(CSS_VAL_SUB); + case BS_LENGTH: + return svgStyle->baselineShiftValue(); + } + } + case CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: + return glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationHorizontal()); + case CSS_PROP_GLYPH_ORIENTATION_VERTICAL: { + if (CSSPrimitiveValue* value = glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationVertical())) + return value; + + if (svgStyle->glyphOrientationVertical() == GO_AUTO) + return new CSSPrimitiveValue(CSS_VAL_AUTO); + + return 0; + } + case CSS_PROP_MARKER: + case CSS_PROP_ENABLE_BACKGROUND: + case CSS_PROP_COLOR_PROFILE: + // the above properties are not yet implemented in the engine + break; + default: + // If you crash here, it's because you added a css property and are not handling it + // in either this switch statement or the one in CSSComputedStyleDelcaration::getPropertyCSSValue + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID); + } + LOG_ERROR("unimplemented propertyID: %d", propertyID); + return 0; +} + +} + +#endif // ENABLE(SVG) + +// vim:ts=4:noet diff --git a/WebCore/css/SVGCSSParser.cpp b/WebCore/css/SVGCSSParser.cpp new file mode 100644 index 0000000..4aca97d --- /dev/null +++ b/WebCore/css/SVGCSSParser.cpp @@ -0,0 +1,358 @@ +/* + Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> + 2004, 2005, 2007 Rob Buis <buis@kde.org> + Copyright (C) 2005, 2006 Apple Computer, Inc. + + This file is part of the KDE project + + 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 "config.h" + +#if ENABLE(SVG) +#include "CSSInheritedValue.h" +#include "CSSInitialValue.h" +#include "CSSParser.h" +#include "CSSProperty.h" +#include "CSSPropertyNames.h" +#include "CSSQuirkPrimitiveValue.h" +#include "CSSValueKeywords.h" +#include "CSSValueList.h" +#include "SVGPaint.h" + +using namespace std; + +namespace WebCore { + +bool CSSParser::parseSVGValue(int propId, bool important) +{ + Value* value = valueList->current(); + if (!value) + return false; + + int id = value->id; + + bool valid_primitive = false; + RefPtr<CSSValue> parsedValue; + + switch (propId) { + /* The comment to the right defines all valid value of these + * properties as defined in SVG 1.1, Appendix N. Property index */ + case CSS_PROP_ALIGNMENT_BASELINE: + // auto | baseline | before-edge | text-before-edge | middle | + // central | after-edge | text-after-edge | ideographic | alphabetic | + // hanging | mathematical | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_BASELINE || id == CSS_VAL_MIDDLE || + (id >= CSS_VAL_BEFORE_EDGE && id <= CSS_VAL_MATHEMATICAL)) + valid_primitive = true; + break; + + case CSS_PROP_BASELINE_SHIFT: + // baseline | super | sub | <percentage> | <length> | inherit + if (id == CSS_VAL_BASELINE || id == CSS_VAL_SUB || + id >= CSS_VAL_SUPER) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength|FPercent, false); + break; + + case CSS_PROP_DOMINANT_BASELINE: + // auto | use-script | no-change | reset-size | ideographic | + // alphabetic | hanging | mathematical | central | middle | + // text-after-edge | text-before-edge | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_MIDDLE || + (id >= CSS_VAL_USE_SCRIPT && id <= CSS_VAL_RESET_SIZE) || + (id >= CSS_VAL_CENTRAL && id <= CSS_VAL_MATHEMATICAL)) + valid_primitive = true; + break; + + case CSS_PROP_ENABLE_BACKGROUND: + // accumulate | new [x] [y] [width] [height] | inherit + if (id == CSS_VAL_ACCUMULATE) // TODO : new + valid_primitive = true; + break; + + case CSS_PROP_MARKER_START: + case CSS_PROP_MARKER_MID: + case CSS_PROP_MARKER_END: + case CSS_PROP_MASK: + if (id == CSS_VAL_NONE) + valid_primitive = true; + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + parsedValue = new CSSPrimitiveValue(value->string, CSSPrimitiveValue::CSS_URI); + if (parsedValue) + valueList->next(); + } + break; + + case CSS_PROP_CLIP_RULE: // nonzero | evenodd | inherit + case CSS_PROP_FILL_RULE: + if (id == CSS_VAL_NONZERO || id == CSS_VAL_EVENODD) + valid_primitive = true; + break; + + case CSS_PROP_STROKE_MITERLIMIT: // <miterlimit> | inherit + valid_primitive = validUnit(value, FNumber|FNonNeg, false); + break; + + case CSS_PROP_STROKE_LINEJOIN: // miter | round | bevel | inherit + if (id == CSS_VAL_MITER || id == CSS_VAL_ROUND || id == CSS_VAL_BEVEL) + valid_primitive = true; + break; + + case CSS_PROP_STROKE_LINECAP: // butt | round | square | inherit + if (id == CSS_VAL_BUTT || id == CSS_VAL_ROUND || id == CSS_VAL_SQUARE) + valid_primitive = true; + break; + + case CSS_PROP_STROKE_OPACITY: // <opacity-value> | inherit + case CSS_PROP_FILL_OPACITY: + case CSS_PROP_STOP_OPACITY: + case CSS_PROP_FLOOD_OPACITY: + valid_primitive = (!id && validUnit(value, FNumber|FPercent, false)); + break; + + case CSS_PROP_SHAPE_RENDERING: + // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || + id == CSS_VAL_CRISPEDGES || id == CSS_VAL_GEOMETRICPRECISION) + valid_primitive = true; + break; + + case CSS_PROP_TEXT_RENDERING: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || id == CSS_VAL_OPTIMIZELEGIBILITY || + id == CSS_VAL_GEOMETRICPRECISION) + valid_primitive = true; + break; + + case CSS_PROP_IMAGE_RENDERING: // auto | optimizeSpeed | + case CSS_PROP_COLOR_RENDERING: // optimizeQuality | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_OPTIMIZESPEED || + id == CSS_VAL_OPTIMIZEQUALITY) + valid_primitive = true; + break; + + case CSS_PROP_COLOR_PROFILE: // auto | sRGB | <name> | <uri> inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB) + valid_primitive = true; + break; + + case CSS_PROP_COLOR_INTERPOLATION: // auto | sRGB | linearRGB | inherit + case CSS_PROP_COLOR_INTERPOLATION_FILTERS: + if (id == CSS_VAL_AUTO || id == CSS_VAL_SRGB || id == CSS_VAL_LINEARRGB) + valid_primitive = true; + break; + + /* Start of supported CSS properties with validation. This is needed for parseShortHand to work + * correctly and allows optimization in applyRule(..) + */ + + case CSS_PROP_POINTER_EVENTS: + // none | visiblePainted | visibleFill | visibleStroke | visible | + // painted | fill | stroke | none | all | inherit + if (id == CSS_VAL_VISIBLE || id == CSS_VAL_NONE || + (id >= CSS_VAL_VISIBLEPAINTED && id <= CSS_VAL_ALL)) + valid_primitive = true; + break; + + case CSS_PROP_TEXT_ANCHOR: // start | middle | end | inherit + if (id == CSS_VAL_START || id == CSS_VAL_MIDDLE || id == CSS_VAL_END) + valid_primitive = true; + break; + + case CSS_PROP_GLYPH_ORIENTATION_VERTICAL: // auto | <angle> | inherit + if (id == CSS_VAL_AUTO) { + valid_primitive = true; + break; + } + /* fallthrough intentional */ + case CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit + if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) { + parsedValue = new CSSPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_DEG); + + if (parsedValue) + valueList->next(); + } + break; + + case CSS_PROP_FILL: // <paint> | inherit + case CSS_PROP_STROKE: // <paint> | inherit + { + if (id == CSS_VAL_NONE) + parsedValue = new SVGPaint(SVGPaint::SVG_PAINTTYPE_NONE); + else if (id == CSS_VAL_CURRENTCOLOR) + parsedValue = new SVGPaint(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR); + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + RGBA32 c = Color::transparent; + if (valueList->next() && parseColorFromValue(valueList->current(), c, true)) { + parsedValue = new SVGPaint(value->string, c); + } else + parsedValue = new SVGPaint(SVGPaint::SVG_PAINTTYPE_URI, value->string); + } else + parsedValue = parseSVGPaint(); + + if (parsedValue) + valueList->next(); + } + break; + + case CSS_PROP_COLOR: // <color> | inherit + if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || + (id >= CSS_VAL_ALICEBLUE && id <= CSS_VAL_YELLOWGREEN)) + parsedValue = new SVGColor(value->string); + else + parsedValue = parseSVGColor(); + + if (parsedValue) + valueList->next(); + break; + + case CSS_PROP_STOP_COLOR: // TODO : icccolor + case CSS_PROP_FLOOD_COLOR: + case CSS_PROP_LIGHTING_COLOR: + if ((id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || + (id >= CSS_VAL_ALICEBLUE && id <= CSS_VAL_YELLOWGREEN)) + parsedValue = new SVGColor(value->string); + else if (id == CSS_VAL_CURRENTCOLOR) + parsedValue = new SVGColor(SVGColor::SVG_COLORTYPE_CURRENTCOLOR); + else // TODO : svgcolor (iccColor) + parsedValue = parseSVGColor(); + + if (parsedValue) + valueList->next(); + + break; + + case CSS_PROP_WRITING_MODE: + // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit + if (id >= CSS_VAL_LR_TB && id <= CSS_VAL_TB) + valid_primitive = true; + break; + + case CSS_PROP_STROKE_WIDTH: // <length> | inherit + case CSS_PROP_STROKE_DASHOFFSET: + valid_primitive = validUnit(value, FLength | FPercent, false); + break; + case CSS_PROP_STROKE_DASHARRAY: // none | <dasharray> | inherit + if (id == CSS_VAL_NONE) + valid_primitive = true; + else + parsedValue = parseSVGStrokeDasharray(); + + break; + + case CSS_PROP_KERNING: // auto | normal | <length> | inherit + if (id == CSS_VAL_AUTO || id == CSS_VAL_NORMAL) + valid_primitive = true; + else + valid_primitive = validUnit(value, FLength, false); + break; + + case CSS_PROP_CLIP_PATH: // <uri> | none | inherit + case CSS_PROP_FILTER: + if (id == CSS_VAL_NONE) + valid_primitive = true; + else if (value->unit == CSSPrimitiveValue::CSS_URI) { + parsedValue = new CSSPrimitiveValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + if (parsedValue) + valueList->next(); + } + break; + + /* shorthand properties */ + case CSS_PROP_MARKER: + { + if (!parseValue(CSS_PROP_MARKER_START, important)) + return false; + CSSValue *value = parsedProperties[numParsedProperties - 1]->value(); + m_implicitShorthand = true; + addProperty(CSS_PROP_MARKER_MID, value, important); + addProperty(CSS_PROP_MARKER_END, value, important); + m_implicitShorthand = false; + return true; + } + default: + // If you crash here, it's because you added a css property and are not handling it + // in either this switch statement or the one in CSSParser::parseValue + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); + return false; + } + + if (valid_primitive) { + if (id != 0) + parsedValue = new CSSPrimitiveValue(id); + else if (value->unit == CSSPrimitiveValue::CSS_STRING) + parsedValue = new CSSPrimitiveValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + parsedValue = new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + else if (value->unit >= Value::Q_EMS) + parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS); + valueList->next(); + } + if (!parsedValue || (valueList->current() && !inShorthand())) + return false; + + addProperty(propId, parsedValue.release(), important); + return true; +} + +PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray() +{ + CSSValueList* ret = new CSSValueList; + Value* value = valueList->current(); + bool valid_primitive = true; + while (value) { + valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false); + if (!valid_primitive) + break; + if (value->id != 0) + ret->append(new CSSPrimitiveValue(value->id)); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + ret->append(new CSSPrimitiveValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit)); + value = valueList->next(); + if (value && value->unit == Value::Operator && value->iValue == ',') + value = valueList->next(); + } + if (!valid_primitive) { + delete ret; + ret = 0; + } + + return ret; +} + +PassRefPtr<CSSValue> CSSParser::parseSVGPaint() +{ + RGBA32 c = Color::transparent; + if (!parseColorFromValue(valueList->current(), c, true)) + return new SVGPaint(); + return new SVGPaint(Color(c)); +} + +PassRefPtr<CSSValue> CSSParser::parseSVGColor() +{ + RGBA32 c = Color::transparent; + if (!parseColorFromValue(valueList->current(), c, true)) + return 0; + return new SVGColor(Color(c)); +} + +} + +#endif // ENABLE(SVG) + +// vim:ts=4:noet diff --git a/WebCore/css/SVGCSSPropertyNames.in b/WebCore/css/SVGCSSPropertyNames.in new file mode 100644 index 0000000..e1ca112 --- /dev/null +++ b/WebCore/css/SVGCSSPropertyNames.in @@ -0,0 +1,48 @@ +# +# all valid SVG CSS2 properties. +# + +# SVG style props +clip-path +clip-rule +mask +# opacity +enable-background +filter +flood-color +flood-opacity +lighting-color +stop-color +stop-opacity +pointer-events +color-interpolation +color-interpolation-filters +color-profile +color-rendering +fill +fill-opacity +fill-rule +#font-size-adjust +image-rendering +marker +marker-end +marker-mid +marker-start +shape-rendering +stroke +stroke-dasharray +stroke-dashoffset +stroke-linecap +stroke-linejoin +stroke-miterlimit +stroke-opacity +stroke-width +text-rendering +alignment-baseline +baseline-shift +dominant-baseline +glyph-orientation-horizontal +glyph-orientation-vertical +kerning +text-anchor +writing-mode diff --git a/WebCore/css/SVGCSSStyleSelector.cpp b/WebCore/css/SVGCSSStyleSelector.cpp new file mode 100644 index 0000000..e3831df --- /dev/null +++ b/WebCore/css/SVGCSSStyleSelector.cpp @@ -0,0 +1,615 @@ +/* + Copyright (C) 2005 Apple Computer, Inc. + Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> + 2004, 2005 Rob Buis <buis@kde.org> + Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> + + Based on khtml css code by: + Copyright(C) 1999-2003 Lars Knoll(knoll@kde.org) + (C) 2003 Apple Computer, Inc. + (C) 2004 Allan Sandfeld Jensen(kde@carewolf.com) + (C) 2004 Germain Garand(germain@ebooksfrance.org) + + This file is part of the KDE project + + 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 "config.h" + +#if ENABLE(SVG) +#include "CSSStyleSelector.h" + +#include "CSSPrimitiveValueMappings.h" +#include "CSSPropertyNames.h" +#include "CSSValueList.h" +#include "SVGColor.h" +#include "SVGNames.h" +#include "SVGPaint.h" +#include "SVGRenderStyle.h" +#include "SVGRenderStyleDefs.h" +#include "SVGStyledElement.h" +#include <stdlib.h> +#include <wtf/MathExtras.h> + +#define HANDLE_INHERIT(prop, Prop) \ +if (isInherit) \ +{\ + svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\ + return;\ +} + +#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ +HANDLE_INHERIT(prop, Prop) \ +else if (isInitial) \ + svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); + +#define HANDLE_INHERIT_COND(propID, prop, Prop) \ +if (id == propID) \ +{\ + svgstyle->set##Prop(m_parentStyle->svgStyle()->prop());\ + return;\ +} + +#define HANDLE_INITIAL_COND(propID, Prop) \ +if (id == propID) \ +{\ + svgstyle->set##Prop(SVGRenderStyle::initial##Prop());\ + return;\ +} + +#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ +if (id == propID) { \ + svgstyle->set##Prop(SVGRenderStyle::initial##Value()); \ + return; \ +} + +namespace WebCore { + +static float roundToNearestGlyphOrientationAngle(float angle) +{ + angle = fabsf(fmodf(angle, 360.0f)); + + if (angle <= 45.0f || angle > 315.0f) + return 0.0f; + else if (angle > 45.0f && angle <= 135.0f) + return 90.0f; + else if (angle > 135.0f && angle <= 225.0f) + return 180.0f; + + return 270.0f; +} + +static int angleToGlyphOrientation(float angle) +{ + angle = roundToNearestGlyphOrientationAngle(angle); + + if (angle == 0.0f) + return GO_0DEG; + else if (angle == 90.0f) + return GO_90DEG; + else if (angle == 180.0f) + return GO_180DEG; + else if (angle == 270.0f) + return GO_270DEG; + + return -1; +} + +void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) +{ + CSSPrimitiveValue* primitiveValue = 0; + if (value->isPrimitiveValue()) + primitiveValue = static_cast<CSSPrimitiveValue*>(value); + + SVGRenderStyle* svgstyle = m_style->accessSVGStyle(); + unsigned short valueType = value->cssValueType(); + + bool isInherit = m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT; + bool isInitial = valueType == CSSPrimitiveValue::CSS_INITIAL || (!m_parentNode && valueType == CSSPrimitiveValue::CSS_INHERIT); + + // What follows is a list that maps the CSS properties into their + // corresponding front-end RenderStyle values. Shorthands(e.g. border, + // background) occur in this list as well and are only hit when mapping + // "inherit" or "initial" into front-end values. + switch (id) + { + // ident only properties + case CSS_PROP_ALIGNMENT_BASELINE: + { + HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline) + if (!primitiveValue) + break; + + svgstyle->setAlignmentBaseline(*primitiveValue); + break; + } + case CSS_PROP_BASELINE_SHIFT: + { + HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift); + if (!primitiveValue) + break; + + if (primitiveValue->getIdent()) { + switch (primitiveValue->getIdent()) { + case CSS_VAL_BASELINE: + svgstyle->setBaselineShift(BS_BASELINE); + break; + case CSS_VAL_SUB: + svgstyle->setBaselineShift(BS_SUB); + break; + case CSS_VAL_SUPER: + svgstyle->setBaselineShift(BS_SUPER); + break; + default: + break; + } + } else { + svgstyle->setBaselineShift(BS_LENGTH); + svgstyle->setBaselineShiftValue(primitiveValue); + } + + break; + } + case CSS_PROP_KERNING: + { + if (isInherit) { + HANDLE_INHERIT_COND(CSS_PROP_KERNING, kerning, Kerning) + return; + } + else if (isInitial) { + HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_KERNING, Kerning, Kerning) + return; + } + + svgstyle->setKerning(primitiveValue); + break; + } + case CSS_PROP_POINTER_EVENTS: + { + HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents) + if (!primitiveValue) + break; + + svgstyle->setPointerEvents(*primitiveValue); + break; + } + case CSS_PROP_DOMINANT_BASELINE: + { + HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline) + if (primitiveValue) + svgstyle->setDominantBaseline(*primitiveValue); + break; + } + case CSS_PROP_COLOR_INTERPOLATION: + { + HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation) + if (primitiveValue) + svgstyle->setColorInterpolation(*primitiveValue); + break; + } + case CSS_PROP_COLOR_INTERPOLATION_FILTERS: + { + HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters) + if (primitiveValue) + svgstyle->setColorInterpolationFilters(*primitiveValue); + break; + } + case CSS_PROP_COLOR_RENDERING: + { + HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering) + if (primitiveValue) + svgstyle->setColorRendering(*primitiveValue); + break; + } + case CSS_PROP_CLIP_RULE: + { + HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule) + if (primitiveValue) + svgstyle->setClipRule(*primitiveValue); + break; + } + case CSS_PROP_FILL_RULE: + { + HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule) + if (primitiveValue) + svgstyle->setFillRule(*primitiveValue); + break; + } + case CSS_PROP_STROKE_LINEJOIN: + { + HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle) + if (primitiveValue) + svgstyle->setJoinStyle(*primitiveValue); + break; + } + case CSS_PROP_IMAGE_RENDERING: + { + HANDLE_INHERIT_AND_INITIAL(imageRendering, ImageRendering) + if (primitiveValue) + svgstyle->setImageRendering(*primitiveValue); + break; + } + case CSS_PROP_SHAPE_RENDERING: + { + HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering) + if (primitiveValue) + svgstyle->setShapeRendering(*primitiveValue); + break; + } + case CSS_PROP_TEXT_RENDERING: + { + HANDLE_INHERIT_AND_INITIAL(textRendering, TextRendering) + if (primitiveValue) + svgstyle->setTextRendering(*primitiveValue); + break; + } + // end of ident only properties + case CSS_PROP_FILL: + { + HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint) + if (!primitiveValue && value) { + SVGPaint *paint = static_cast<SVGPaint*>(value); + if (paint) + svgstyle->setFillPaint(paint); + } + + break; + } + case CSS_PROP_STROKE: + { + HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint) + if (!primitiveValue && value) { + SVGPaint *paint = static_cast<SVGPaint*>(value); + if (paint) + svgstyle->setStrokePaint(paint); + } + + break; + } + case CSS_PROP_STROKE_WIDTH: + { + HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth) + if (!primitiveValue) + return; + + svgstyle->setStrokeWidth(primitiveValue); + break; + } + case CSS_PROP_STROKE_DASHARRAY: + { + HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray) + if (!primitiveValue && value) { + CSSValueList* dashes = static_cast<CSSValueList*>(value); + if (dashes) + svgstyle->setStrokeDashArray(dashes); + } + + break; + } + case CSS_PROP_STROKE_DASHOFFSET: + { + HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset) + if (!primitiveValue) + return; + + svgstyle->setStrokeDashOffset(primitiveValue); + break; + } + case CSS_PROP_FILL_OPACITY: + { + HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity) + if (!primitiveValue) + return; + + float f = 0.0f; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + f = primitiveValue->getFloatValue() / 100.0f; + else if (type == CSSPrimitiveValue::CSS_NUMBER) + f = primitiveValue->getFloatValue(); + else + return; + + svgstyle->setFillOpacity(f); + break; + } + case CSS_PROP_STROKE_OPACITY: + { + HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity) + if (!primitiveValue) + return; + + float f = 0.0f; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + f = primitiveValue->getFloatValue() / 100.0f; + else if (type == CSSPrimitiveValue::CSS_NUMBER) + f = primitiveValue->getFloatValue(); + else + return; + + svgstyle->setStrokeOpacity(f); + break; + } + case CSS_PROP_STOP_OPACITY: + { + HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity) + if (!primitiveValue) + return; + + float f = 0.0f; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + f = primitiveValue->getFloatValue() / 100.0f; + else if (type == CSSPrimitiveValue::CSS_NUMBER) + f = primitiveValue->getFloatValue(); + else + return; + + svgstyle->setStopOpacity(f); + break; + } + case CSS_PROP_MARKER_START: + { + HANDLE_INHERIT_AND_INITIAL(startMarker, StartMarker) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + + svgstyle->setStartMarker(s); + break; + } + case CSS_PROP_MARKER_MID: + { + HANDLE_INHERIT_AND_INITIAL(midMarker, MidMarker) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + + svgstyle->setMidMarker(s); + break; + } + case CSS_PROP_MARKER_END: + { + HANDLE_INHERIT_AND_INITIAL(endMarker, EndMarker) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + + svgstyle->setEndMarker(s); + break; + } + case CSS_PROP_STROKE_LINECAP: + { + HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle) + if (primitiveValue) + svgstyle->setCapStyle(*primitiveValue); + break; + } + case CSS_PROP_STROKE_MITERLIMIT: + { + HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit) + if (!primitiveValue) + return; + + float f = 0.0f; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_NUMBER) + f = primitiveValue->getFloatValue(); + else + return; + + svgstyle->setStrokeMiterLimit(f); + break; + } + case CSS_PROP_FILTER: + { + HANDLE_INHERIT_AND_INITIAL(filter, Filter) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + svgstyle->setFilter(s); + break; + } + case CSS_PROP_MASK: + { + HANDLE_INHERIT_AND_INITIAL(maskElement, MaskElement) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + + svgstyle->setMaskElement(s); + break; + } + case CSS_PROP_CLIP_PATH: + { + HANDLE_INHERIT_AND_INITIAL(clipPath, ClipPath) + if (!primitiveValue) + return; + + String s; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_URI) + s = primitiveValue->getStringValue(); + else + return; + + svgstyle->setClipPath(s); + break; + } + case CSS_PROP_TEXT_ANCHOR: + { + HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor) + if (primitiveValue) + svgstyle->setTextAnchor(*primitiveValue); + break; + } + case CSS_PROP_WRITING_MODE: + { + HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode) + if (primitiveValue) + svgstyle->setWritingMode(*primitiveValue); + break; + } + case CSS_PROP_STOP_COLOR: + { + HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor); + + SVGColor* c = static_cast<SVGColor*>(value); + if (!c) + return CSSStyleSelector::applyProperty(id, value); + + Color col; + if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR) + col = m_style->color(); + else + col = c->color(); + + svgstyle->setStopColor(col); + break; + } + case CSS_PROP_LIGHTING_COLOR: + { + HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor); + + SVGColor* c = static_cast<SVGColor*>(value); + if (!c) + return CSSStyleSelector::applyProperty(id, value); + + Color col; + if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR) + col = m_style->color(); + else + col = c->color(); + + svgstyle->setLightingColor(col); + break; + } + case CSS_PROP_FLOOD_OPACITY: + { + HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity) + if (!primitiveValue) + return; + + float f = 0.0f; + int type = primitiveValue->primitiveType(); + if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + f = primitiveValue->getFloatValue() / 100.0f; + else if (type == CSSPrimitiveValue::CSS_NUMBER) + f = primitiveValue->getFloatValue(); + else + return; + + svgstyle->setFloodOpacity(f); + break; + } + case CSS_PROP_FLOOD_COLOR: + { + Color col; + if (isInitial) + col = SVGRenderStyle::initialFloodColor(); + else { + SVGColor *c = static_cast<SVGColor*>(value); + if (!c) + return CSSStyleSelector::applyProperty(id, value); + + if (c->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR) + col = m_style->color(); + else + col = c->color(); + } + + svgstyle->setFloodColor(col); + break; + } + case CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL: + { + HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal) + if (!primitiveValue) + return; + + if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) { + int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue()); + ASSERT(orientation != -1); + + svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation); + } + + break; + } + case CSS_PROP_GLYPH_ORIENTATION_VERTICAL: + { + HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical) + if (!primitiveValue) + return; + + if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) { + int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue()); + ASSERT(orientation != -1); + + svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation); + } else if (primitiveValue->getIdent() == CSS_VAL_AUTO) + svgstyle->setGlyphOrientationVertical(GO_AUTO); + + break; + } + case CSS_PROP_ENABLE_BACKGROUND: + // Silently ignoring this property for now + // http://bugs.webkit.org/show_bug.cgi?id=6022 + break; + default: + // If you crash here, it's because you added a css property and are not handling it + // in either this switch statement or the one in CSSStyleSelector::applyProperty + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id); + return; + } +} + +} + +// vim:ts=4:noet +#endif // ENABLE(SVG) diff --git a/WebCore/css/SVGCSSValueKeywords.in b/WebCore/css/SVGCSSValueKeywords.in new file mode 100644 index 0000000..e655378 --- /dev/null +++ b/WebCore/css/SVGCSSValueKeywords.in @@ -0,0 +1,298 @@ +# These are all values accepted for CSS2. +# +# WARNING: +# -------- +# +# The Values are sorted according to the properties they belong to, +# and have to be in the same order as the enums in RenderStyle.h. +# +# If not, the optimizations in the cssparser and style selector will fail, +# and produce incorrect results. +# +# +# CSS_PROP_*_COLOR +# +aliceblue +antiquewhite +# aqua +aquamarine +azure +beige +bisque +# black +blanchedalmond +# blue +blueviolet +brown +burlywood +cadetblue +chartreuse +chocolate +coral +cornflowerblue +cornsilk +crimson +cyan +darkblue +darkcyan +darkgoldenrod +darkgray +darkgreen +darkgrey +darkkhaki +darkmagenta +darkolivegreen +darkorange +darkorchid +darkred +darksalmon +darkseagreen +darkslateblue +darkslategray +darkslategrey +darkturquoise +darkviolet +deeppink +deepskyblue +dimgray +dimgrey +dodgerblue +firebrick +floralwhite +forestgreen +# fuchsia +gainsboro +ghostwhite +gold +goldenrod +# gray +# grey +# green +greenyellow +honeydew +hotpink +indianred +indigo +ivory +khaki +lavender +lavenderblush +lawngreen +lemonchiffon +lightblue +lightcoral +lightcyan +lightgoldenrodyellow +lightgray +lightgreen +lightgrey +lightpink +lightsalmon +lightseagreen +lightskyblue +lightslategray +lightslategrey +lightsteelblue +lightyellow +# lime +limegreen +linen +magenta +# maroon +mediumaquamarine +mediumblue +mediumorchid +mediumpurple +mediumseagreen +mediumslateblue +mediumspringgreen +mediumturquoise +mediumvioletred +midnightblue +mintcream +mistyrose +moccasin +navajowhite +# navy +oldlace +# olive +olivedrab +# orange +orangered +orchid +palegoldenrod +palegreen +paleturquoise +palevioletred +papayawhip +peachpuff +peru +pink +plum +powderblue +# purple +# red +rosybrown +royalblue +saddlebrown +salmon +sandybrown +seagreen +seashell +sienna +# silver +skyblue +slateblue +slategray +slategrey +snow +springgreen +steelblue +tan +# teal +thistle +tomato +turquoise +violet +wheat +# white +whitesmoke +# yellow +yellowgreen + +# CSS_PROP_CLIP_PATH +# CSS_PROP_CLIP_RULE +nonzero +evenodd + +# CSS_PROP_MASK +# CSS_PROP_OPACITY +# CSS_PROP_ENABLE_BACKGROUND +accumulate +new + +# CSS_PROP_FILTER +# CSS_PROP_FLOOD_COLOR +currentColor + +# CSS_PROP_FLOOD_OPACITY +# CSS_PROP_LIGHTING_COLOR +#currentColor + +# CSS_PROP_STOP_COLOR +# CSS_PROP_STOP_OPACITY +# CSS_PROP_POINTER_EVENTS +visiblePainted +visibleFill +visibleStroke +#visible +painted +fill +stroke +all +#none + +# CSS_PROP_COLOR_INTERPOLATION +#auto +sRGB +linearRGB + +# CSS_PROP_COLOR_INTERPOLATION_FILTERS +#auto +#sRGB +#linearRGB + +# CSS_PROP_COLOR_PROFILE +#sRGB + +# CSS_PROP_COLOR_RENDERING +#auto +optimizeSpeed +optimizeQuality + +## CSS_PROP_FILL +#currentColor + +# CSS_PROP_FILL_OPACITY +# CSS_PROP_FILL_RULE +#nonzero +#evenodd + +# CSS_PROP_IMAGE_RENDERING +#auto +#optimizeSpeed +#optimizeQuality + +# CSS_PROP_MARKER +# CSS_PROP_MARKER_END +# CSS_PROP_MARKER_MID +# CSS_PROP_MARKER_START +# CSS_PROP_SHAPE_RENDERING +#auto +#optimizeSpeed +crispEdges +geometricPrecision + +# CSS_PROP_STROKE +# CSS_PROP_STROKE_DASHARRAY +# CSS_PROP_STROKE_DASHOFFSET +# CSS_PROP_STROKE_LINECAP +butt +# round +# square + +# CSS_PROP_STROKE_LINEJOIN +miter +# round +bevel + +# CSS_PROP_STROKE_MITERLIMIT +# CSS_PROP_STROKE_OPACITY +# CSS_PROP_STROKE_WIDTH +# CSS_PROP_TEXT_RENDERING +#auto +#optimizeSpeed +optimizeLegibility +#geometricPrecision + +# CSS_PROP_ALIGNMENT_BASELINE +#auto +# baseline +before-edge +after-edge +#middle +central +text-before-edge +text-after-edge +ideographic +alphabetic +hanging +mathematical + +# CSS_PROP_BASELINE_SHIFT +#baseline +# sub +# super + +# CSS_PROP_DOMINANT_BASELINE +#auto +use-script +no-change +reset-size + +# CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL + +# CSS_PROP_GLYPH_ORIENTATION_VERTICAL +# CSS_PROP_KERNING +# CSS_PROP_TEXT_ANCHOR +# start +# middle +# end + +# CSS_PROP_WRITING_MODE +lr-tb +rl-tb +tb-rl +lr +rl +tb diff --git a/WebCore/css/ShadowValue.cpp b/WebCore/css/ShadowValue.cpp new file mode 100644 index 0000000..5794405 --- /dev/null +++ b/WebCore/css/ShadowValue.cpp @@ -0,0 +1,67 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "ShadowValue.h" + +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" + +namespace WebCore { + +// Used for text-shadow and box-shadow +ShadowValue::ShadowValue(PassRefPtr<CSSPrimitiveValue> _x, + PassRefPtr<CSSPrimitiveValue> _y, + PassRefPtr<CSSPrimitiveValue> _blur, + PassRefPtr<CSSPrimitiveValue> _color) + : x(_x) + , y(_y) + , blur(_blur) + , color(_color) +{ +} + +String ShadowValue::cssText() const +{ + String text(""); + + if (color) + text += color->cssText(); + if (x) { + if (!text.isEmpty()) + text += " "; + text += x->cssText(); + } + if (y) { + if (!text.isEmpty()) + text += " "; + text += y->cssText(); + } + if (blur) { + if (!text.isEmpty()) + text += " "; + text += blur->cssText(); + } + + return text; +} + +} diff --git a/WebCore/css/ShadowValue.h b/WebCore/css/ShadowValue.h new file mode 100644 index 0000000..2f94b94 --- /dev/null +++ b/WebCore/css/ShadowValue.h @@ -0,0 +1,53 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef ShadowValue_h +#define ShadowValue_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSPrimitiveValue; + +// Used for text-shadow and box-shadow +class ShadowValue : public CSSValue +{ +public: + ShadowValue(PassRefPtr<CSSPrimitiveValue> x, + PassRefPtr<CSSPrimitiveValue> y, + PassRefPtr<CSSPrimitiveValue> blur, + PassRefPtr<CSSPrimitiveValue> color); + + virtual String cssText() const; + + RefPtr<CSSPrimitiveValue> x; + RefPtr<CSSPrimitiveValue> y; + RefPtr<CSSPrimitiveValue> blur; + RefPtr<CSSPrimitiveValue> color; +}; + +} // namespace + +#endif diff --git a/WebCore/css/StyleBase.cpp b/WebCore/css/StyleBase.cpp new file mode 100644 index 0000000..f608c63 --- /dev/null +++ b/WebCore/css/StyleBase.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) + * 2001-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006, 2008 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "StyleBase.h" + +#include "Document.h" +#include "Node.h" +#include "StyleSheet.h" + +namespace WebCore { + +void StyleBase::checkLoaded() +{ + if (parent()) + parent()->checkLoaded(); +} + +StyleSheet* StyleBase::stylesheet() +{ + StyleBase *b = this; + while (b && !b->isStyleSheet()) + b = b->parent(); + return static_cast<StyleSheet*>(b); +} + +KURL StyleBase::baseURL() const +{ + // Try to find the style sheet. If found look for its URL. + // If it has none, get the URL from the parent sheet or the parent node. + + StyleSheet* sheet = const_cast<StyleBase*>(this)->stylesheet(); + if (!sheet) + return KURL(); + if (!sheet->href().isNull()) + return KURL(sheet->href()); + if (sheet->parent()) + return sheet->parent()->baseURL(); + if (!sheet->ownerNode()) + return KURL(); + return sheet->ownerNode()->document()->baseURL(); +} + +} diff --git a/WebCore/css/StyleBase.h b/WebCore/css/StyleBase.h new file mode 100644 index 0000000..020dbd3 --- /dev/null +++ b/WebCore/css/StyleBase.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 1999 Waldo Bastian (bastian@kde.org) + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmial.com) + * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef StyleBase_h +#define StyleBase_h + +#include <wtf/RefCounted.h> + +namespace WebCore { + + class String; + class StyleSheet; + class KURL; + + // a style class which has a parent (almost all have) + class StyleBase : public RefCounted<StyleBase> { + public: + StyleBase(StyleBase* parent) + : RefCounted<StyleBase>(0) + , m_parent(parent) + , m_strictParsing(!parent || parent->useStrictParsing()) + { + } + virtual ~StyleBase() { } + + StyleBase* parent() const { return m_parent; } + void setParent(StyleBase* parent) { m_parent = parent; } + + // returns the url of the style sheet this object belongs to + KURL baseURL() const; + + virtual bool isStyleSheet() const { return false; } + virtual bool isCSSStyleSheet() const { return false; } + virtual bool isXSLStyleSheet() const { return false; } + virtual bool isStyleSheetList() const { return false; } + virtual bool isMediaList() { return false; } + virtual bool isRuleList() { return false; } + virtual bool isRule() { return false; } + virtual bool isStyleRule() { return false; } + virtual bool isCharsetRule() { return false; } + virtual bool isImportRule() { return false; } + virtual bool isMediaRule() { return false; } + virtual bool isFontFaceRule() { return false; } + virtual bool isPageRule() { return false; } + virtual bool isUnknownRule() { return false; } + virtual bool isStyleDeclaration() { return false; } + virtual bool isValue() { return false; } + virtual bool isPrimitiveValue() const { return false; } + virtual bool isValueList() { return false; } + virtual bool isValueCustom() { return false; } +#if ENABLE(SVG) + virtual bool isSVGColor() const { return false; } + virtual bool isSVGPaint() const { return false; } +#endif + + virtual bool parseString(const String&, bool /*strict*/ = false) { return false; } + virtual void checkLoaded(); + + void setStrictParsing(bool b) { m_strictParsing = b; } + bool useStrictParsing() const { return m_strictParsing; } + + virtual void insertedIntoParent() { } + + StyleSheet* stylesheet(); + + private: + StyleBase* m_parent; + bool m_strictParsing; + }; +} + +#endif diff --git a/WebCore/css/StyleList.cpp b/WebCore/css/StyleList.cpp new file mode 100644 index 0000000..412509e --- /dev/null +++ b/WebCore/css/StyleList.cpp @@ -0,0 +1,54 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) + * 2001-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "StyleList.h" + +namespace WebCore { + +void StyleList::append(PassRefPtr<StyleBase> child) +{ + StyleBase* c = child.get(); + m_children.append(child); + c->insertedIntoParent(); +} + +void StyleList::insert(unsigned position, PassRefPtr<StyleBase> child) +{ + StyleBase* c = child.get(); + if (position >= length()) + m_children.append(child); + else + m_children.insert(position, child); + c->insertedIntoParent(); +} + +void StyleList::remove(unsigned position) +{ + if (position >= length()) + return; + m_children.remove(position); +} + +} diff --git a/WebCore/css/StyleList.h b/WebCore/css/StyleList.h new file mode 100644 index 0000000..2a4e112 --- /dev/null +++ b/WebCore/css/StyleList.h @@ -0,0 +1,50 @@ +/* + * This file is part of the CSS implementation for KDE. + * + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef StyleList_h +#define StyleList_h + +#include "StyleBase.h" +#include <wtf/PassRefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + + // a style class which has a list of children (StyleSheets for example) + class StyleList : public StyleBase { + public: + StyleList(StyleBase* parent) : StyleBase(parent) { } + + unsigned length() { return m_children.size(); } + StyleBase* item(unsigned num) { return num < length() ? m_children[num].get() : 0; } + + void append(PassRefPtr<StyleBase>); + void insert(unsigned position, PassRefPtr<StyleBase>); + void remove(unsigned position); + + protected: + Vector<RefPtr<StyleBase> > m_children; + }; +} + +#endif diff --git a/WebCore/css/StyleSheet.cpp b/WebCore/css/StyleSheet.cpp new file mode 100644 index 0000000..7941d70 --- /dev/null +++ b/WebCore/css/StyleSheet.cpp @@ -0,0 +1,74 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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 "config.h" +#include "StyleSheet.h" + +#include "MediaList.h" + +namespace WebCore { + +StyleSheet::StyleSheet(StyleSheet* parentSheet, const String& href) + : StyleList(parentSheet) + , m_parentNode(0) + , m_strHref(href) + , m_disabled(false) +{ +} + + +StyleSheet::StyleSheet(Node* parentNode, const String& href) + : StyleList(0) + , m_parentNode(parentNode) + , m_strHref(href) + , m_disabled(false) +{ +} + +StyleSheet::StyleSheet(StyleBase* owner, const String& href) + : StyleList(owner) + , m_parentNode(0) + , m_strHref(href) + , m_disabled(false) +{ +} + +StyleSheet::~StyleSheet() +{ + if (m_media) + m_media->setParent(0); +} + +StyleSheet* StyleSheet::parentStyleSheet() const +{ + return (parent() && parent()->isStyleSheet()) ? static_cast<StyleSheet*>(parent()) : 0; +} + +void StyleSheet::setMedia(MediaList* media) +{ + if (m_media) + m_media->setParent(0); + + m_media = media; + m_media->setParent(this); +} + +} diff --git a/WebCore/css/StyleSheet.h b/WebCore/css/StyleSheet.h new file mode 100644 index 0000000..c00faa2 --- /dev/null +++ b/WebCore/css/StyleSheet.h @@ -0,0 +1,72 @@ +/* + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006 Apple Computer, Inc. + * + * 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. + */ + +#ifndef StyleSheet_h +#define StyleSheet_h + +#include "StyleList.h" +#include "PlatformString.h" + +namespace WebCore { + +class Node; +class CachedCSSStyleSheet; +class MediaList; + +class StyleSheet : public StyleList { +public: + StyleSheet(Node* ownerNode, const String& href = String()); + StyleSheet(StyleSheet* parentSheet, const String& href = String()); + StyleSheet(StyleBase* owner, const String& href = String()); + virtual ~StyleSheet(); + + virtual bool isStyleSheet() const { return true; } + + virtual String type() const { return String(); } + + bool disabled() const { return m_disabled; } + void setDisabled(bool disabled) { m_disabled = disabled; styleSheetChanged(); } + + Node* ownerNode() const { return m_parentNode; } + StyleSheet *parentStyleSheet() const; + String href() const { return m_strHref; } + void setHref(const String& href) { m_strHref = href; } + String title() const { return m_strTitle; } + void setTitle(const String& s) { m_strTitle = s; } + MediaList* media() const { return m_media.get(); } + void setMedia(MediaList*); + + virtual bool isLoading() { return false; } + + virtual void styleSheetChanged() { } + +protected: + Node* m_parentNode; + String m_strHref; + String m_strTitle; + RefPtr<MediaList> m_media; + bool m_disabled; +}; + +} // namespace + +#endif diff --git a/WebCore/css/StyleSheet.idl b/WebCore/css/StyleSheet.idl new file mode 100644 index 0000000..2c17248 --- /dev/null +++ b/WebCore/css/StyleSheet.idl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module stylesheets { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + ObjCCustomInternalImpl, + InterfaceUUID=2bd2db5f-aaab-4422-96a0-e05455313f35, + ImplementationUUID=a8ca694d-71f2-4479-8c76-ee9c1c729b49 + ] StyleSheet { + readonly attribute [ConvertNullStringTo=Null] DOMString type; + attribute boolean disabled; + readonly attribute Node ownerNode; + readonly attribute StyleSheet parentStyleSheet; + readonly attribute [ConvertNullStringTo=Null] DOMString href; + readonly attribute [ConvertNullStringTo=Null] DOMString title; + readonly attribute MediaList media; + }; + +} diff --git a/WebCore/css/StyleSheetList.cpp b/WebCore/css/StyleSheetList.cpp new file mode 100644 index 0000000..d9d678d --- /dev/null +++ b/WebCore/css/StyleSheetList.cpp @@ -0,0 +1,94 @@ +/** + * This file is part of the DOM implementation for KDE. + * + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * + * 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 "config.h" +#include "StyleSheetList.h" + +#include "CSSStyleSheet.h" +#include "Document.h" +#include "HTMLNames.h" +#include "HTMLStyleElement.h" +#include "PlatformString.h" + +namespace WebCore { + +using namespace HTMLNames; + +StyleSheetList::StyleSheetList(Document* doc) + : RefCounted<StyleSheetList>(0) + , m_doc(doc) +{ +} + +StyleSheetList::~StyleSheetList() +{ + for (DeprecatedPtrListIterator<StyleSheet> it (styleSheets); it.current(); ++it) + it.current()->deref(); +} + +void StyleSheetList::documentDestroyed() +{ + m_doc = 0; +} + +void StyleSheetList::add(StyleSheet* s) +{ + if (!styleSheets.containsRef(s)) { + s->ref(); + styleSheets.append(s); + } +} + +void StyleSheetList::remove(StyleSheet* s) +{ + if (styleSheets.removeRef(s)) + s->deref(); +} + +unsigned StyleSheetList::length() const +{ + return styleSheets.count(); +} + +StyleSheet* StyleSheetList::item(unsigned index) +{ + return index < length() ? styleSheets.at(index) : 0; +} + +HTMLStyleElement* StyleSheetList::getNamedItem(const String& name) const +{ + if (!m_doc) + return 0; + + // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag + // (this is consistent with all the other collections) + // ### Bad implementation because returns a single element (are IDs always unique?) + // and doesn't look for name attribute. + // But unicity of stylesheet ids is good practice anyway ;) + + Element* element = m_doc->getElementById(name); + if (element && element->hasTagName(styleTag)) + return static_cast<HTMLStyleElement*>(element); + return 0; +} + +} // namespace WebCore diff --git a/WebCore/css/StyleSheetList.h b/WebCore/css/StyleSheetList.h new file mode 100644 index 0000000..cfc1b81 --- /dev/null +++ b/WebCore/css/StyleSheetList.h @@ -0,0 +1,57 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + */ + +#ifndef StyleSheetList_h +#define StyleSheetList_h + +#include <wtf/RefCounted.h> +#include "DeprecatedPtrList.h" + +namespace WebCore { + +class Document; +class HTMLStyleElement; +class StyleSheet; +class String; + +class StyleSheetList : public RefCounted<StyleSheetList> { +public: + StyleSheetList(Document*); + ~StyleSheetList(); + + void documentDestroyed(); + + unsigned length() const; + StyleSheet* item(unsigned index); + + void add(StyleSheet*); + void remove(StyleSheet*); + + HTMLStyleElement* getNamedItem(const String&) const; + + DeprecatedPtrList<StyleSheet> styleSheets; + +private: + Document* m_doc; +}; + +} // namespace WebCore + +#endif // StyleSheetList_h diff --git a/WebCore/css/StyleSheetList.idl b/WebCore/css/StyleSheetList.idl new file mode 100644 index 0000000..2abd22f --- /dev/null +++ b/WebCore/css/StyleSheetList.idl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.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. + */ + +module stylesheets { + + // Introduced in DOM Level 2: + interface [ + GenerateConstructor, + HasIndexGetter, + HasNameGetter, + InterfaceUUID=707da1d7-7c8f-42b1-bbbf-c009e429663f, + ImplementationUUID=5991ebaf-ce6c-42db-b1c8-fb34af8d5c76 + ] StyleSheetList { + readonly attribute unsigned long length; + StyleSheet item(in unsigned long index); + }; + +} diff --git a/WebCore/css/html4.css b/WebCore/css/html4.css new file mode 100644 index 0000000..65ec4e5 --- /dev/null +++ b/WebCore/css/html4.css @@ -0,0 +1,658 @@ +/* + * The default style sheet used to render HTML. + * + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * 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. + * + */ + +@namespace "http://www.w3.org/1999/xhtml"; + +html { + display: block +} + +/* children of the <head> element all have display:none */ +head { + display: none +} + +meta { + display: none +} + +title { + display: none +} + +link { + display: none +} + +style { + display: none +} + +script { + display: none +} + +/* generic block-level elements */ + +body { + display: block; + margin: 8px +} + +p { + display: block; + margin: 1.0__qem 0px +} + +div { + display: block +} + +layer { + display: block +} + +marquee { + display: inline-block; + overflow: -webkit-marquee +} + +address { + display: block +} + +blockquote { + display: block; + margin: 1__qem 40px 1em 40px +} + +q { + display: inline +} + +q:before { + content: '"' + /* FIXME: content: open-quote; */ +} + +q:after { + content: '"' + /* FIXME: content: close-quote; */ +} + +center { + display: block; + /* special centering to be able to emulate the html4/netscape behaviour */ + text-align: -webkit-center +} + +hr { + display: block; + margin: 0.5em auto; + border-style: inset; + border-width: 1px +} + +map { + display: inline +} + +/* heading elements */ + +h1 { + display: block; + font-size: 2em; + margin: .67__qem 0 .67em 0; + font-weight: bold +} + +h2 { + display: block; + font-size: 1.5em; + margin: .83__qem 0 .83em 0; + font-weight: bold +} + +h3 { + display: block; + font-size: 1.17em; + margin: 1__qem 0 1em 0; + font-weight: bold +} + +h4 { + display: block; + margin: 1.33__qem 0 1.33em 0; + font-weight: bold +} + +h5 { + display: block; + font-size: .83em; + margin: 1.67__qem 0 1.67em 0; + font-weight: bold +} + +h6 { + display: block; + font-size: .67em; + margin: 2.33__qem 0 2.33em 0; + font-weight: bold +} + +/* tables */ + +table { + display: table; + border-collapse: separate; + border-spacing: 2px; + border-color: gray +} + +thead { + display: table-header-group; + vertical-align: middle; + border-color: inherit +} + +tbody { + display: table-row-group; + vertical-align: middle; + border-color: inherit +} + +tfoot { + display: table-footer-group; + vertical-align: middle; + border-color: inherit +} + +/* for tables without table section elements (can happen with XHTML or dynamically created tables) */ +table > tr { + vertical-align: middle; +} + +col { + display: table-column +} + +colgroup { + display: table-column-group +} + +tr { + display: table-row; + vertical-align: inherit; + border-color: inherit +} + +td, th { + display: table-cell; + vertical-align: inherit +} + +th { + font-weight: bold +} + +caption { + display: table-caption; + text-align: -webkit-center +} + +/* lists */ + +ul, menu, dir { + display: block; + list-style-type: disc; + margin: 1__qem 0 1em 0; + -webkit-padding-start: 40px +} + +ol { + display: block; + list-style-type: decimal; + margin: 1__qem 0 1em 0; + -webkit-padding-start: 40px +} + +li { + display: list-item +} + +ul ul, ol ul { + list-style-type: circle +} + +ol ol ul, ol ul ul, ul ol ul, ul ul ul { + list-style-type: square +} + +dd { + display: block; + -webkit-margin-start: 40px +} + +dl { + display: block; + margin: 1__qem 0 1em 0 +} + +dt { + display: block +} + +ol ul, ul ol, ul ul, ol ol { + margin-top: 0; + margin-bottom: 0 +} + +/* form elements */ + +form { + display: block; + margin: 0__qem 0 1em 0 +} + +label { + cursor: default; +} + +legend { + display: block; + padding-left: 2px; + padding-right: 2px; + border: none +} + +fieldset { + display: block; + margin-left: 2px; + margin-right: 2px; + padding: 0.35em 0.75em 0.625em; + border: 2px groove ThreeDFace +} + +button { + -webkit-appearance: button; +} + +input, textarea, keygen, select, button, isindex { + margin: 0__qem; + font: -webkit-small-control; + color: initial; + letter-spacing: normal; + word-spacing: normal; + line-height: normal; + text-transform: none; + text-indent: 0; + text-shadow: none; + display: inline-block; + text-align: -webkit-auto; +} + +input[type="hidden"] { + display: none +} + +input, input[type="password"], input[type="search"], isindex { + -webkit-appearance: textfield; + padding: 1px; + background-color: white; + border: 2px inset; + -webkit-rtl-ordering: logical; + -webkit-user-select: text; + cursor: auto; +} + +input[type="search"] { + -webkit-appearance: searchfield; + -webkit-box-sizing: border-box; +} + +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: searchfield-cancel-button; +} + +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: searchfield-decoration; +} + +input[type="search"]::-webkit-search-results-decoration { + -webkit-appearance: searchfield-results-decoration; +} + +input[type="search"]::-webkit-search-results-button { + -webkit-appearance: searchfield-results-button; +} + +textarea { + -webkit-appearance: textarea; + background-color: white; + border: 1px solid; + -webkit-rtl-ordering: logical; + -webkit-user-select: text; + -webkit-box-orient: vertical; + resize: auto; + cursor: auto; +} + +input[type="password"] { + -webkit-text-security: disc !important; +} + +input[type="hidden"], input[type="image"], input[type="file"] { + -webkit-appearance: initial; + padding: initial; + background-color: initial; + border: initial; +} + +input[type="file"] { + -webkit-box-align: baseline; +} + +input:-webkit-autofill { + background-color: #FAFFBD !important; + background-image:none !important; +} + +input[type="radio"], input[type="checkbox"] { + margin: 3px 0.5ex; + padding: initial; + background-color: initial; + border: initial; +} + +input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button { + -webkit-appearance: push-button; + white-space: pre +} + +input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button, button { + -webkit-box-align: center; + text-align: center; + cursor: default; + color: ButtonText; + padding: 2px 6px 3px 6px; + border: 2px outset ButtonFace; + background-color: ButtonFace; + -webkit-box-sizing: border-box +} + +input[type="range"] { + -webkit-appearance: slider-horizontal; + padding: initial; + border: initial; + margin: 2px; +} + +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: sliderthumb-horizontal; +} + +input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled, input[type="file"]:disabled::-webkit-file-upload-button, button:disabled, select:disabled, keygen:disabled, optgroup:disabled, option:disabled { + color: GrayText +} + +input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active, input[type="file"]:active::-webkit-file-upload-button, button:active { + border-style: inset +} + +input[type="button"]:active:disabled, input[type="submit"]:active:disabled, input[type="reset"]:active:disabled, input[type="file"]:active:disabled::-webkit-file-upload-button, button:active:disabled { + border-style: outset +} + +area, param { + display: none +} + +input[type="checkbox"] { + -webkit-appearance: checkbox; + -webkit-box-sizing: border-box; +} + +input[type="radio"] { + -webkit-appearance: radio; + -webkit-box-sizing: border-box; +} + +keygen, select { + -webkit-appearance: menulist; + -webkit-box-sizing: border-box; + -webkit-box-align: center; + border: 1px solid; + -webkit-border-radius: 5px; + white-space: pre; + -webkit-rtl-ordering: logical; + color: black; + background-color: white; + cursor: default; +} + +select[size], +select[multiple], +select[size][multiple] { + -webkit-appearance: listbox; + -webkit-box-align: start; + border: 1px inset gray; + -webkit-border-radius: initial; + white-space: initial; +} + +select[size="0"], +select[size="1"] { + -webkit-appearance: menulist; + -webkit-box-align: center; + border: 1px solid; + -webkit-border-radius: 5px; + white-space: pre; +} + +optgroup { + font-weight: bolder; +} + +option { + font-weight: normal; +} + +/* inline elements */ + +u, ins { + text-decoration: underline +} + +strong, b { + font-weight: bolder +} + +i, cite, em, var, address { + font-style: italic +} + +tt, code, kbd, samp { + font-family: monospace +} + +pre, xmp, plaintext, listing { + display: block; + font-family: monospace; + white-space: pre; + margin: 1__qem 0 +} + +big { + font-size: larger +} + +small { + font-size: smaller +} + +s, strike, del { + text-decoration: line-through +} + +sub { + vertical-align: sub; + font-size: smaller +} + +sup { + vertical-align: super; + font-size: smaller +} + +nobr { + white-space: nowrap +} + +/* states */ + +:focus { + outline: auto 5px -webkit-focus-ring-color +} + +/* Read-only text fields do not show a focus ring but do still receive focus */ +html:focus, body:focus, input[readonly]:focus { + outline: none +} + +input:focus, textarea:focus, isindex:focus, keygen:focus, select:focus { + outline-offset: -2px +} + +input[type="button"]:focus, +input[type="checkbox"]:focus, +input[type="file"]:focus, +input[type="hidden"]:focus, +input[type="image"]:focus, +input[type="radio"]:focus, +input[type="reset"]:focus, +input[type="search"]:focus, +input[type="submit"]:focus, +input[type="file"]:focus::-webkit-file-upload-button { + outline-offset: 0 +} + +a:-webkit-any-link { + color: -webkit-link; + text-decoration: underline; + cursor: auto; +} + +a:-webkit-any-link:active { + color: -webkit-activelink +} + +/* other elements */ + +noframes { + display: none +} + +frameset, frame { + display: block +} + +frameset { + border-color: inherit +} + +iframe { + border: 2px inset +} + +/* media controls */ +/* FIXME this is not the final styling */ + +audio { + width: 200px; + height: 16px; +} + +audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { + position: absolute; + bottom: 0; + width: 100%; + height: 16px; + -webkit-user-select: none; +} + +audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { + -webkit-appearance: media-mute-button; + position: absolute; + top: 0; + left: 0; + width: 17px; + height: 16px; +} + +audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { + -webkit-appearance: media-play-button; + position: absolute; + top: 0; + left: 16px; + width: 17px; + height: 16px; +} + +audio::-webkit-media-controls-time-display, video::-webkit-media-controls-time-display { + display: none; +} + +audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { + -webkit-appearance: media-slider; + position: absolute; + top: 0; + left: 32px; + right: 32px; + height: 16px; + padding: 0px 2px; +} + +audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button { + -webkit-appearance: media-seek-back-button; + position: absolute; + top: 0; + right: 16px; + width: 17px; + height: 16px; +} + + +audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button { + -webkit-appearance: media-seek-forward-button; + position: absolute; + top: 0; + right: 0; + width: 17px; + height: 16px; +} + +audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button { + display: none; +} + +/* noscript is handled internally, as it depends on settings */ diff --git a/WebCore/css/make-css-file-arrays.pl b/WebCore/css/make-css-file-arrays.pl new file mode 100755 index 0000000..05c8fd1 --- /dev/null +++ b/WebCore/css/make-css-file-arrays.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2006 Apple Computer, Inc. +# +# 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. +# + +# Usage: make-css-file-arrays.pl <header> <output> <input> ... + +use strict; +use Getopt::Long; + +my $preprocessor; + +GetOptions('preprocessor=s' => \$preprocessor); + +if (!$preprocessor) { + $preprocessor = "/usr/bin/gcc -E -P -x c++"; +} + +my $header = $ARGV[0]; +shift; + +my $out = $ARGV[0]; +shift; + +open HEADER, ">", $header or die; +open OUT, ">", $out or die; + +print HEADER "namespace WebCore {\n"; +print OUT "namespace WebCore {\n"; + +for my $in (@ARGV) { + $in =~ /(\w+)\.css$/ or die; + my $name = $1; + + # Slurp in the CSS file. + open IN, $preprocessor . " " . $in . "|" or die; + my $text; { local $/; $text = <IN>; } + close IN; + + # Remove comments in a simple-minded way that will work fine for our files. + # Could do this a fancier way if we were worried about arbitrary CSS source. + $text =~ s|/\*.*?\*/||gs; + + # Crunch whitespace just to make it a little smaller. + # Could do work to avoid doing this inside quote marks but our files don't have runs of spaces in quotes. + # Could crunch further based on places where whitespace is optional. + $text =~ s|\s+| |gs; + $text =~ s|^ ||; + $text =~ s| $||; + + # Write out a C array of the characters. + my $length = length $text; + print HEADER "extern const char ${name}UserAgentStyleSheet[${length}];\n"; + print OUT "extern const char ${name}UserAgentStyleSheet[${length}] = {\n"; + my $i = 0; + while ($i < $length) { + print OUT " "; + my $j = 0; + while ($j < 16 && $i < $length) { + print OUT ", " unless $j == 0; + print OUT ord substr $text, $i, 1; + ++$i; + ++$j; + } + print OUT "," unless $i == $length; + print OUT "\n"; + } + print OUT "};\n"; + +} + +print HEADER "}\n"; +print OUT "}\n"; diff --git a/WebCore/css/makegrammar.pl b/WebCore/css/makegrammar.pl new file mode 100644 index 0000000..fc19e10 --- /dev/null +++ b/WebCore/css/makegrammar.pl @@ -0,0 +1,55 @@ +#! /usr/bin/perl +# +# This file is part of the WebKit project +# +# Copyright (C) 2007 Trolltech ASA +# +# 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. +use strict; +use warnings; + +my $grammar = $ARGV[0]; +my $fileBase = $ARGV[1]; + +system("bison -d -p cssyy " . $grammar . " -o " . $fileBase . ".tab.c"); + +open HEADER, ">" . $fileBase . ".h" or die; +print HEADER << "EOF"; +#ifndef CSSGRAMMAR_H +#define CSSGRAMMAR_H +EOF + +open HPP, "<" . $fileBase . ".tab.h" or die; +while (<HPP>) { + print HEADER; +} +close HPP; + +print HEADER "#endif\n"; + +close HEADER; + +unlink($fileBase . ".tab.h"); + +open CPP, ">" . $fileBase . ".cpp" or die; +open GENSRC, "<" . $fileBase . ".tab.c" or die; +while (<GENSRC>) { + print CPP; +} +close GENSRC; +close CPP; + +unlink($fileBase . ".tab.c"); diff --git a/WebCore/css/makeprop.pl b/WebCore/css/makeprop.pl new file mode 100644 index 0000000..1600c1b --- /dev/null +++ b/WebCore/css/makeprop.pl @@ -0,0 +1,114 @@ +#! /usr/bin/perl +# +# This file is part of the WebKit project +# +# Copyright (C) 1999 Waldo Bastian (bastian@kde.org) +# Copyright (C) 2007 Apple Inc. All rights reserved. +# Copyright (C) 2007 Trolltech ASA +# +# 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. +use strict; +use warnings; + +open NAMES, "<CSSPropertyNames.in" || die "Could not find CSSPropertyNames.in"; +my @names = (); +while (<NAMES>) { + next if (m/#/); + chomp $_; + next if ($_ eq ""); + push @names, $_; +} +close(NAMES); + +open GPERF, ">CSSPropertyNames.gperf" || die "Could not open CSSPropertyNames.gperf for writing"; +print GPERF << "EOF"; +%{ +/* This file is automatically generated from CSSPropertyNames.in by makeprop, do not edit */ +#include \"CSSPropertyNames.h\" +%} +struct props { + const char* name; + int id; +}; +%% +EOF + +foreach my $name (@names) { + my $id = $name; + $id =~ s/-/_/g; + print GPERF $name . ", CSS_PROP_" . uc($id) . "\n"; +} +print GPERF "%%\n"; +close GPERF; + +open HEADER, ">CSSPropertyNames.h" || die "Could not open CSSPropertyNames.h for writing"; +print HEADER << "EOF"; +/* This file is automatically generated from CSSPropertyNames.in by makeprop, do not edit */ + +#ifndef CSSPropertyNames_h +#define CSSPropertyNames_h + +enum CSSPropertyID { + CSS_PROP_INVALID = 0, +EOF + +my $i = 1; +my $maxLen = 0; +foreach my $name (@names) { + my $id = $name; + $id =~ s/-/_/g; + print HEADER " CSS_PROP_" . uc($id) . " = " . $i . ",\n"; + $i = $i + 1; + if (length($name) > $maxLen) { + $maxLen = length($name); + } +} +print HEADER "};\n\n"; +print HEADER "const int numCSSProperties = " . $i . ";\n"; +print HEADER "const size_t maxCSSPropertyNameLength = " . $maxLen . ";\n"; + +print HEADER << "EOF"; + +const char* getPropertyName(CSSPropertyID); + +#endif +EOF + +close HEADER; + +system("gperf -a -L ANSI-C -E -C -c -o -t --key-positions=\"*\" -NfindProp -Hhash_prop -Wwordlist_prop -D -s 2 CSSPropertyNames.gperf > CSSPropertyNames.c"); + +open C, ">>CSSPropertyNames.c" || die "Could not open CSSPropertyNames.c for writing"; +print C "static const char * const propertyList[] = {\n"; +print C "\"\",\n"; + +foreach my $name (@names) { + print C "\"" . $name . "\", \n"; +} + +print C << "EOF"; + 0 +}; +const char* getPropertyName(CSSPropertyID id) +{ + if (id >= numCSSProperties || id <= 0) + return 0; + return propertyList[id]; +} +EOF + +close C; + diff --git a/WebCore/css/maketokenizer b/WebCore/css/maketokenizer new file mode 100644 index 0000000..7cd3a9c --- /dev/null +++ b/WebCore/css/maketokenizer @@ -0,0 +1,127 @@ +print <<END; +/* + * This file is part of the DOM implementation for KDE. + * + * Copyright (C) 2003 Lars Knoll (knoll\@kde.org) + * + * + * 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. + */ + +/* This file is mostly data generated by flex. Unfortunately flex + can't handle 16bit strings directly, so we just copy the part of + the code we need and modify it to our needs. + + Most of the defines below are to make sure we can easily use the + flex generated code, using as little editing as possible. + + The flex syntax to generate the lexer are more or less directly + copied from the CSS2.1 specs, with some fixes for comments and + the important symbol. + + To regenerate, run flex on tokenizer.flex. After this, copy the + data tables and the YY_DECL method over to this file. Remove the + init code from YY_DECL and change the YY_END_OF_BUFFER to only call + yyterminate(). + +*/ + +// --------- begin generated code ------------------- + +END + +{ +print<<END + +#include "CSSGrammar.h" + +#define INITIAL 0 +#define mediaquery 1 + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ +END +} + + +while (<>) { + last if /YY_NUM_RULES/; +} + +print; +while (<>) { + last if /yy_last_accepting/; + print; +} + +# media query, tokenizer state support +while (<>) { + last if /yytext/; +} +while (<>) { + last if not (/define/ || /line/) ; + print; +} + +while (<>) { + last if /^YY_DECL/; +} + +print; +while (<>) { + s/char/UChar/; + print; + last if /yy_act/; +} + +while (<>) { + last if /while \( 1 \)/; +} + +print; +while (<>) { + next if /^yy_match:/; + next if /^do_action:/; + last if /YY_END_OF_BUFFER/; + print; + print "case YY_END_OF_BUFFER:\n" if /^case YY_STATE_EOF\(INITIAL\):/; +} + +while (<>) { + last if /default:/; +} + +print; +while (<>) { + print; + last if /end of yylex/; +} diff --git a/WebCore/css/makevalues.pl b/WebCore/css/makevalues.pl new file mode 100644 index 0000000..97f73ae --- /dev/null +++ b/WebCore/css/makevalues.pl @@ -0,0 +1,108 @@ +#! /usr/bin/perl +# +# This file is part of the WebKit project +# +# Copyright (C) 1999 Waldo Bastian (bastian@kde.org) +# Copyright (C) 2007 Apple Inc. All rights reserved. +# Copyright (C) 2007 Trolltech ASA +# +# 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. +use strict; +use warnings; + +open NAMES, "<CSSValueKeywords.in" || die "Could not open CSSValueKeywords.in"; +my @names = (); +while (<NAMES>) { + next if (m/#/); + chomp $_; + next if ($_ eq ""); + push @names, $_; +} +close(NAMES); + +open GPERF, ">CSSValueKeywords.gperf" || die "Could not open CSSValueKeywords.gperf for writing"; +print GPERF << "EOF"; +%{ +/* This file is automatically generated from CSSValueKeywords.in by makevalues, do not edit */ + +#include \"CSSValueKeywords.h\" +%} +struct css_value { + const char* name; + int id; +}; +%% +EOF + +foreach my $name (@names) { + my $id = $name; + $id =~ s/-/_/g; + print GPERF $name . ", CSS_VAL_" . uc($id) . "\n"; +} +print GPERF "%%\n"; +close GPERF; + +open HEADER, ">CSSValueKeywords.h" || die "Could not open CSSValueKeywords.h for writing"; +print HEADER << "EOF"; +/* This file is automatically generated from CSSValueKeywords.in by makevalues, do not edit */ + +#ifndef CSSValues_h +#define CSSValues_h + +const int CSS_VAL_INVALID = 0; +EOF + +my $i = 1; +my $maxLen = 0; +foreach my $name (@names) { + my $id = $name; + $id =~ s/-/_/g; + print HEADER "const int CSS_VAL_" . uc($id) . " = " . $i . ";\n"; + $i = $i + 1; + if (length($name) > $maxLen) { + $maxLen = length($name); + } +} +print HEADER "const int numCSSValueKeywords = " . $i . ";\n"; +print HEADER "const size_t maxCSSValueKeywordLength = " . $maxLen . ";\n"; +print HEADER << "EOF"; + +const char* getValueName(unsigned short id); + +#endif +EOF +close HEADER; + +system("gperf -L ANSI-C -E -C -n -o -t --key-positions=\"*\" -NfindValue -Hhash_val -Wwordlist_value -D CSSValueKeywords.gperf > CSSValueKeywords.c"); + +open C, ">>CSSValueKeywords.c" || die "Could not open CSSValueKeywords.c for writing"; +print C "static const char * const valueList[] = {\n"; +print C "\"\",\n"; +foreach my $name (@names) { + print C "\"" . $name . "\", \n"; +} +print C << "EOF"; + 0 +}; +const char* getValueName(unsigned short id) +{ + if (id >= numCSSValueKeywords || id <= 0) + return 0; + return valueList[id]; +} +EOF + +close C; diff --git a/WebCore/css/quirks.css b/WebCore/css/quirks.css new file mode 100644 index 0000000..1b79582 --- /dev/null +++ b/WebCore/css/quirks.css @@ -0,0 +1,48 @@ +/* + * Additonal style sheet used to render HTML pages in quirks mode. + * + * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * + * 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. + * + */ + +/* Give floated images margins of 3px */ +img[align="left"] { + margin-right: 3px; +} +img[align="right"] { + margin-left: 3px; +} + +/* Tables reset both line-height and white-space in quirks mode. */ +/* Compatible with WinIE. Note that font-family is *not* reset. */ +table { + white-space: normal; + line-height: normal; + font-weight: normal; + font-size: medium; + font-variant: normal; + font-style: normal; + color: -webkit-text; + text-align: -webkit-auto +} + +/* This will apply only to text fields, since all other inputs already use border box sizing */ +input:not([type=image]), textarea { + -webkit-box-sizing: border-box; +} diff --git a/WebCore/css/svg.css b/WebCore/css/svg.css new file mode 100644 index 0000000..322eda8 --- /dev/null +++ b/WebCore/css/svg.css @@ -0,0 +1,65 @@ +/* + * The default style sheet used to render SVG. + * + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@namespace "http://www.w3.org/2000/svg"; + +/* + When an outermost SVG 'svg' element is stand-alone or embedded inline within a parent XML grammar + which does not use CSS layout [CSS2-LAYOUT] or XSL formatting [XSL], the 'overflow' property on the + outermost 'svg' element is ignored for the purposes of visual rendering and the initial clipping path is set + to the bounds of the initial viewport. +*/ +svg:root { + overflow: hidden !important +} + +svg { + width: 100%; + height: 100%; +} + +svg, symbol, marker, pattern { + overflow: hidden +} + +text, foreignObject { + display: block +} + +text, tspan, textPath { + white-space: nowrap +} + +text, tspan, tref { + -webkit-text-size-adjust: none; +} + +/* states */ + +:focus { + outline: auto 5px -webkit-focus-ring-color +} diff --git a/WebCore/css/tokenizer.flex b/WebCore/css/tokenizer.flex new file mode 100644 index 0000000..214b5bf --- /dev/null +++ b/WebCore/css/tokenizer.flex @@ -0,0 +1,98 @@ +%option case-insensitive +%option noyywrap +%option 8bit +%option stack +%s mediaquery + +h [0-9a-fA-F] +nonascii [\200-\377] +unicode \\{h}{1,6}[ \t\r\n\f]? +escape {unicode}|\\[ -~\200-\377] +nmstart [_a-zA-Z]|{nonascii}|{escape} +nmchar [_a-zA-Z0-9-]|{nonascii}|{escape} +string1 \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\" +string2 \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\' +hexcolor {h}{3}|{h}{6} + +ident -?{nmstart}{nmchar}* +name {nmchar}+ +num [0-9]+|[0-9]*"."[0-9]+ +intnum [0-9]+ +string {string1}|{string2} +url ([!#$%&*-~]|{nonascii}|{escape})* +w [ \t\r\n\f]* +nl \n|\r\n|\r|\f +range \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h}))))) +nth (-?[0-9]*n[\+-][0-9]+)|(-?[0-9]*n) + +%% + +\/\*[^*]*\*+([^/*][^*]*\*+)*\/ /* ignore comments */ + +[ \t\r\n\f]+ {yyTok = WHITESPACE; return yyTok;} + +"<!--" {yyTok = SGML_CD; return yyTok;} +"-->" {yyTok = SGML_CD; return yyTok;} +"~=" {yyTok = INCLUDES; return yyTok;} +"|=" {yyTok = DASHMATCH; return yyTok;} +"^=" {yyTok = BEGINSWITH; return yyTok;} +"$=" {yyTok = ENDSWITH; return yyTok;} +"*=" {yyTok = CONTAINS; return yyTok;} +<mediaquery>"not" {yyTok = MEDIA_NOT; return yyTok;} +<mediaquery>"only" {yyTok = MEDIA_ONLY; return yyTok;} +<mediaquery>"and" {yyTok = MEDIA_AND; return yyTok;} + +{string} {yyTok = STRING; return yyTok;} +{ident} {yyTok = IDENT; return yyTok;} +{nth} {yyTok = NTH; return yyTok;} + +"#"{hexcolor} {yyTok = HEX; return yyTok;} +"#"{ident} {yyTok = IDSEL; return yyTok;} + +"@import" {BEGIN(mediaquery); yyTok = IMPORT_SYM; return yyTok;} +"@page" {yyTok = PAGE_SYM; return yyTok;} +"@media" {BEGIN(mediaquery); yyTok = MEDIA_SYM; return yyTok;} +"@font-face" {yyTok = FONT_FACE_SYM; return yyTok;} +"@charset" {yyTok = CHARSET_SYM; return yyTok;} +"@namespace" {yyTok = NAMESPACE_SYM; return yyTok; } +"@-webkit-rule" {yyTok = WEBKIT_RULE_SYM; return yyTok; } +"@-webkit-decls" {yyTok = WEBKIT_DECLS_SYM; return yyTok; } +"@-webkit-value" {yyTok = WEBKIT_VALUE_SYM; return yyTok; } +"@-webkit-mediaquery" {BEGIN(mediaquery); yyTok = WEBKIT_MEDIAQUERY_SYM; return yyTok; } + +"!"{w}"important" {yyTok = IMPORTANT_SYM; return yyTok;} + +{num}em {yyTok = EMS; return yyTok;} +{num}__qem {yyTok = QEMS; return yyTok;} /* quirky ems */ +{num}ex {yyTok = EXS; return yyTok;} +{num}px {yyTok = PXS; return yyTok;} +{num}cm {yyTok = CMS; return yyTok;} +{num}mm {yyTok = MMS; return yyTok;} +{num}in {yyTok = INS; return yyTok;} +{num}pt {yyTok = PTS; return yyTok;} +{num}pc {yyTok = PCS; return yyTok;} +{num}deg {yyTok = DEGS; return yyTok;} +{num}rad {yyTok = RADS; return yyTok;} +{num}grad {yyTok = GRADS; return yyTok;} +{num}ms {yyTok = MSECS; return yyTok;} +{num}s {yyTok = SECS; return yyTok;} +{num}Hz {yyTok = HERZ; return yyTok;} +{num}kHz {yyTok = KHERZ; return yyTok;} +{num}{ident} {yyTok = DIMEN; return yyTok;} +{num}%+ {yyTok = PERCENTAGE; return yyTok;} +{intnum} {yyTok = INTEGER; return yyTok;} +{num} {yyTok = FLOATTOKEN; return yyTok;} + +"not(" {yyTok = NOTFUNCTION; return yyTok;} +"url("{w}{string}{w}")" {yyTok = URI; return yyTok;} +"url("{w}{url}{w}")" {yyTok = URI; return yyTok;} +{ident}"(" {yyTok = FUNCTION; return yyTok;} + +U\+{range} {yyTok = UNICODERANGE; return yyTok;} +U\+{h}{1,6}-{h}{1,6} {yyTok = UNICODERANGE; return yyTok;} + +<mediaquery>"{" | +<mediaquery>";" {BEGIN(INITIAL); yyTok = *yytext; return yyTok; } +. {yyTok = *yytext; return yyTok;} + +%% diff --git a/WebCore/css/view-source.css b/WebCore/css/view-source.css new file mode 100644 index 0000000..8d34211 --- /dev/null +++ b/WebCore/css/view-source.css @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +body { + margin: 0 +} + +table { + border-spacing: 0; + counter-reset: lines; + white-space: pre-wrap !important; + margin: 0; + word-break: break-word; + font-family: monospace; +} + +td { + padding: 0 !important; + vertical-align: baseline +} + +.webkit-line-gutter-backdrop, .webkit-line-number { + padding: 0 2px !important; + min-width: 21px; + background-color: rgb(240, 240, 240); + border-right: 1px solid rgb(128, 128, 128) !important; + -webkit-user-select: none; +} + +.webkit-line-gutter-backdrop { + position: absolute; + z-index: -1; + left: 0; + top: 0; + height: 100% +} + +.webkit-line-number { + text-align: right; + color: rgb(128, 128, 128); + word-break: normal; + white-space: nowrap; + font-size: 9px; + font-family: Helvetica +} + +.webkit-line-number::before { + content: counter(lines); + counter-increment: lines; + -webkit-user-select: none +} + +.webkit-line-content { + padding: 0 5px !important; +} + +.webkit-html-tag { + /* Keep this in sync with inspector.css (.webkit-html-tag) */ + color: rgb(136, 18, 128); +} + +.webkit-html-attribute-name { + /* Keep this in sync with inspector.css (.webkit-html-attribute-name) */ + color: rgb(153, 69, 0); +} + +.webkit-html-attribute-value { + /* Keep this in sync with inspector.css (.webkit-html-attribute-value) */ + color: rgb(26, 26, 166); +} + +.webkit-html-external-link, .webkit-html-resource-link { + /* Keep this in sync with inspector.css (.webkit-html-external-link, .webkit-html-resource-link) */ + color: #00e; +} + +.webkit-html-external-link { + /* Keep this in sync with inspector.css (.webkit-html-external-link) */ + text-decoration: none; +} + +.webkit-html-external-link:hover { + /* Keep this in sync with inspector.css (.webkit-html-external-link:hover) */ + text-decoration: underline; +} + +.webkit-html-comment { + /* Keep this in sync with inspector.css (.comment) */ + color: rgb(35, 110, 37); +} + +.webkit-html-doctype { + color: rgb(192, 192, 192); +} + +.webkit-html-entity { + rgb(136, 18, 128); +} + +.webkit-html-message-bubble { + -webkit-box-shadow: black 0px 2px 5px; + -webkit-border-radius: 9px; + -webkit-border-fit: lines; + font-size: 9px; + font-family: Lucida Grande; + font-weight: bold; + margin: 6px 25px; + padding: 0 7px 1px; +} + +.webkit-html-warning-message { + background-color: rgb(100%, 62%, 42%); + border: 2px solid rgb(100%, 52%, 21%); +} + +.webkit-html-error-message { + background-color: rgb(100%, 42%, 42%); + border: 2px solid rgb(100%, 31%, 31%); +} + +.webkit-html-message-line { + padding-left: 23px; + text-indent: -20px; +} + +.webkit-html-message-icon { + position: relative; + top: 2px; + margin: 0 4px; +} |