Changeset 83618 in webkit


Ignore:
Timestamp:
Apr 12, 2011 12:02:11 PM (13 years ago)
Author:
rniwa@webkit.org
Message:

2011-04-12 Ryosuke Niwa <rniwa@webkit.org>

Reviewed by Eric Seidel.

Move StyleChange and other global functions from ApplyStyleCommand to EditingStyle
https://bugs.webkit.org/show_bug.cgi?id=55974

Moved StyleChange, getIdentifierValue, and legacyFontSizeFromCSSValue from ApplyStyleCommand
to EditingStyle. Also moved reconcileTextDecorationProperties, getIdentifierValue,
setTextDecorationProperty, isCSSValueLength, legacyFontSizeFromCSSValue, extractTextStyles,
diffTextDecorations, fontWeightIsBold, getTextAlignment, and getPropertiesNotIn.

Because of this move, getPropertiesNotIn is no longer visible outside of EditingStyle.cpp

  • editing/ApplyStyleCommand.cpp:
  • editing/ApplyStyleCommand.h:
  • editing/EditingStyle.cpp: (WebCore::reconcileTextDecorationProperties): (WebCore::StyleChange::StyleChange): (WebCore::setTextDecorationProperty): (WebCore::getRGBAFontColor): (WebCore::StyleChange::extractTextStyles): (WebCore::diffTextDecorations): (WebCore::fontWeightIsBold): (WebCore::getTextAlignment): (WebCore::getPropertiesNotIn): (WebCore::getIdentifierValue): (WebCore::isCSSValueLength): (WebCore::legacyFontSizeFromCSSValue):
  • editing/EditingStyle.h: (WebCore::StyleChange::cssStyle): (WebCore::StyleChange::applyBold): (WebCore::StyleChange::applyItalic): (WebCore::StyleChange::applyUnderline): (WebCore::StyleChange::applyLineThrough): (WebCore::StyleChange::applySubscript): (WebCore::StyleChange::applySuperscript): (WebCore::StyleChange::applyFontColor): (WebCore::StyleChange::applyFontFace): (WebCore::StyleChange::applyFontSize): (WebCore::StyleChange::fontColor): (WebCore::StyleChange::fontFace): (WebCore::StyleChange::fontSize): (WebCore::StyleChange::operator==): (WebCore::StyleChange::operator!=):
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r83615 r83618  
     12011-04-12  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Move StyleChange and other global functions from ApplyStyleCommand to EditingStyle
     6        https://bugs.webkit.org/show_bug.cgi?id=55974
     7
     8        Moved StyleChange, getIdentifierValue, and legacyFontSizeFromCSSValue from ApplyStyleCommand
     9        to EditingStyle. Also moved reconcileTextDecorationProperties, getIdentifierValue,
     10        setTextDecorationProperty, isCSSValueLength, legacyFontSizeFromCSSValue, extractTextStyles,
     11        diffTextDecorations, fontWeightIsBold, getTextAlignment, and getPropertiesNotIn.
     12
     13        Because of this move, getPropertiesNotIn is no longer visible outside of EditingStyle.cpp
     14
     15        * editing/ApplyStyleCommand.cpp:
     16        * editing/ApplyStyleCommand.h:
     17        * editing/EditingStyle.cpp:
     18        (WebCore::reconcileTextDecorationProperties):
     19        (WebCore::StyleChange::StyleChange):
     20        (WebCore::setTextDecorationProperty):
     21        (WebCore::getRGBAFontColor):
     22        (WebCore::StyleChange::extractTextStyles):
     23        (WebCore::diffTextDecorations):
     24        (WebCore::fontWeightIsBold):
     25        (WebCore::getTextAlignment):
     26        (WebCore::getPropertiesNotIn):
     27        (WebCore::getIdentifierValue):
     28        (WebCore::isCSSValueLength):
     29        (WebCore::legacyFontSizeFromCSSValue):
     30        * editing/EditingStyle.h:
     31        (WebCore::StyleChange::cssStyle):
     32        (WebCore::StyleChange::applyBold):
     33        (WebCore::StyleChange::applyItalic):
     34        (WebCore::StyleChange::applyUnderline):
     35        (WebCore::StyleChange::applyLineThrough):
     36        (WebCore::StyleChange::applySubscript):
     37        (WebCore::StyleChange::applySuperscript):
     38        (WebCore::StyleChange::applyFontColor):
     39        (WebCore::StyleChange::applyFontFace):
     40        (WebCore::StyleChange::applyFontSize):
     41        (WebCore::StyleChange::fontColor):
     42        (WebCore::StyleChange::fontFace):
     43        (WebCore::StyleChange::fontSize):
     44        (WebCore::StyleChange::operator==):
     45        (WebCore::StyleChange::operator!=):
     46
    1472011-04-12  Diego Gonzalez  <diegohcg@webkit.org>
    248
  • trunk/Source/WebCore/editing/ApplyStyleCommand.cpp

    r82503 r83618  
    5555using namespace HTMLNames;
    5656
    57 static RGBA32 getRGBAFontColor(CSSStyleDeclaration* style)
    58 {
    59     RefPtr<CSSValue> colorValue = style->getPropertyCSSValue(CSSPropertyColor);
    60     if (!colorValue || !colorValue->isPrimitiveValue())
    61         return Color::transparent;
    62 
    63     CSSPrimitiveValue* primitiveColor = static_cast<CSSPrimitiveValue*>(colorValue.get());
    64     RGBA32 rgba = 0;
    65     if (primitiveColor->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR) {
    66         CSSParser::parseColor(rgba, colorValue->cssText());
    67         // Need to take care of named color such as green and black
    68         // This code should be removed after https://bugs.webkit.org/show_bug.cgi?id=28282 is fixed.
    69     } else
    70         rgba = primitiveColor->getRGBA32Value();
    71 
    72     return rgba;
    73 }
    74 
    75 class StyleChange {
    76 public:
    77     StyleChange(EditingStyle*, const Position&);
    78 
    79     String cssStyle() const { return m_cssStyle; }
    80     bool applyBold() const { return m_applyBold; }
    81     bool applyItalic() const { return m_applyItalic; }
    82     bool applyUnderline() const { return m_applyUnderline; }
    83     bool applyLineThrough() const { return m_applyLineThrough; }
    84     bool applySubscript() const { return m_applySubscript; }
    85     bool applySuperscript() const { return m_applySuperscript; }
    86     bool applyFontColor() const { return m_applyFontColor.length() > 0; }
    87     bool applyFontFace() const { return m_applyFontFace.length() > 0; }
    88     bool applyFontSize() const { return m_applyFontSize.length() > 0; }
    89 
    90     String fontColor() { return m_applyFontColor; }
    91     String fontFace() { return m_applyFontFace; }
    92     String fontSize() { return m_applyFontSize; }
    93 
    94     bool operator==(const StyleChange& other)
    95     {
    96         return m_cssStyle == other.m_cssStyle
    97             && m_applyBold == other.m_applyBold
    98             && m_applyItalic == other.m_applyItalic
    99             && m_applyUnderline == other.m_applyUnderline
    100             && m_applyLineThrough == other.m_applyLineThrough
    101             && m_applySubscript == other.m_applySubscript
    102             && m_applySuperscript == other.m_applySuperscript
    103             && m_applyFontColor == other.m_applyFontColor
    104             && m_applyFontFace == other.m_applyFontFace
    105             && m_applyFontSize == other.m_applyFontSize;
    106     }
    107     bool operator!=(const StyleChange& other)
    108     {
    109         return !(*this == other);
    110     }
    111 private:
    112     void init(EditingStyle*, const Position&);
    113     void reconcileTextDecorationProperties(CSSMutableStyleDeclaration*);
    114     void extractTextStyles(Document*, CSSMutableStyleDeclaration*, bool shouldUseFixedFontDefaultSize);
    115 
    116     String m_cssStyle;
    117     bool m_applyBold;
    118     bool m_applyItalic;
    119     bool m_applyUnderline;
    120     bool m_applyLineThrough;
    121     bool m_applySubscript;
    122     bool m_applySuperscript;
    123     String m_applyFontColor;
    124     String m_applyFontFace;
    125     String m_applyFontSize;
    126 };
    127 
    128 
    129 StyleChange::StyleChange(EditingStyle* style, const Position& position)
    130     : m_applyBold(false)
    131     , m_applyItalic(false)
    132     , m_applyUnderline(false)
    133     , m_applyLineThrough(false)
    134     , m_applySubscript(false)
    135     , m_applySuperscript(false)
    136 {
    137     init(style, position);
    138 }
    139 
    140 void StyleChange::init(EditingStyle* style, const Position& position)
    141 {
    142     Document* document = position.anchorNode() ? position.anchorNode()->document() : 0;
    143     if (!style || !style->style() || !document || !document->frame())
    144         return;
    145 
    146     RefPtr<CSSComputedStyleDeclaration> computedStyle = position.computedStyle();
    147     RefPtr<CSSMutableStyleDeclaration> mutableStyle = getPropertiesNotIn(style->style(), computedStyle.get());
    148 
    149     reconcileTextDecorationProperties(mutableStyle.get());
    150     if (!document->frame()->editor()->shouldStyleWithCSS())
    151         extractTextStyles(document, mutableStyle.get(), computedStyle->useFixedFontDefaultSize());
    152 
    153     // Changing the whitespace style in a tab span would collapse the tab into a space.
    154     if (isTabSpanTextNode(position.deprecatedNode()) || isTabSpanNode((position.deprecatedNode())))
    155         mutableStyle->removeProperty(CSSPropertyWhiteSpace);
    156 
    157     // If unicode-bidi is present in mutableStyle and direction is not, then add direction to mutableStyle.
    158     // FIXME: Shouldn't this be done in getPropertiesNotIn?
    159     if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->style()->getPropertyCSSValue(CSSPropertyDirection))
    160         mutableStyle->setProperty(CSSPropertyDirection, style->style()->getPropertyValue(CSSPropertyDirection));
    161 
    162     // Save the result for later
    163     m_cssStyle = mutableStyle->cssText().stripWhiteSpace();
    164 }
    165 
    166 void StyleChange::reconcileTextDecorationProperties(CSSMutableStyleDeclaration* style)
    167 {   
    168     RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
    169     RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
    170     // We shouldn't have both text-decoration and -webkit-text-decorations-in-effect because that wouldn't make sense.
    171     ASSERT(!textDecorationsInEffect || !textDecoration);
    172     if (textDecorationsInEffect) {
    173         style->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText());
    174         style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
    175         textDecoration = textDecorationsInEffect;
    176     }
    177 
    178     // If text-decoration is set to "none", remove the property because we don't want to add redundant "text-decoration: none".
    179     if (textDecoration && !textDecoration->isValueList())
    180         style->removeProperty(CSSPropertyTextDecoration);
    181 }
    182 
    183 static int getIdentifierValue(CSSStyleDeclaration* style, int propertyID)
    184 {
    185     if (!style)
    186         return 0;
    187 
    188     RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
    189     if (!value || !value->isPrimitiveValue())
    190         return 0;
    191 
    192     return static_cast<CSSPrimitiveValue*>(value.get())->getIdent();
    193 }
    194 
    195 static void setTextDecorationProperty(CSSMutableStyleDeclaration* style, const CSSValueList* newTextDecoration, int propertyID)
    196 {
    197     if (newTextDecoration->length())
    198         style->setProperty(propertyID, newTextDecoration->cssText(), style->getPropertyPriority(propertyID));
    199     else {
    200         // text-decoration: none is redundant since it does not remove any text decorations.
    201         ASSERT(!style->getPropertyPriority(propertyID));
    202         style->removeProperty(propertyID);
    203     }
    204 }
    205 
    206 static bool isCSSValueLength(CSSPrimitiveValue* value)
    207 {
    208     return value->primitiveType() >= CSSPrimitiveValue::CSS_PX && value->primitiveType() <= CSSPrimitiveValue::CSS_PC;
    209 }
    210 
    211 int legacyFontSizeFromCSSValue(Document* document, CSSPrimitiveValue* value, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode mode)
    212 {
    213     if (isCSSValueLength(value)) {
    214         int pixelFontSize = value->getIntValue(CSSPrimitiveValue::CSS_PX);
    215         int legacyFontSize = CSSStyleSelector::legacyFontSize(document, pixelFontSize, shouldUseFixedFontDefaultSize);
    216         // Use legacy font size only if pixel value matches exactly to that of legacy font size.
    217         int cssPrimitiveEquivalent = legacyFontSize - 1 + CSSValueXSmall;
    218         if (mode == AlwaysUseLegacyFontSize || CSSStyleSelector::fontSizeForKeyword(document, cssPrimitiveEquivalent, shouldUseFixedFontDefaultSize) == pixelFontSize)
    219             return legacyFontSize;
    220 
    221         return 0;
    222     }
    223 
    224     if (CSSValueXSmall <= value->getIdent() && value->getIdent() <= CSSValueWebkitXxxLarge)
    225         return value->getIdent() - CSSValueXSmall + 1;
    226 
    227     return 0;
    228 }
    229 
    230 void StyleChange::extractTextStyles(Document* document, CSSMutableStyleDeclaration* style, bool shouldUseFixedFontDefaultSize)
    231 {
    232     ASSERT(style);
    233 
    234     if (getIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
    235         style->removeProperty(CSSPropertyFontWeight);
    236         m_applyBold = true;
    237     }
    238 
    239     int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle);
    240     if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) {
    241         style->removeProperty(CSSPropertyFontStyle);
    242         m_applyItalic = true;
    243     }
    244 
    245     // Assuming reconcileTextDecorationProperties has been called, there should not be -webkit-text-decorations-in-effect
    246     // Furthermore, text-decoration: none has been trimmed so that text-decoration property is always a CSSValueList.
    247     RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
    248     if (textDecoration && textDecoration->isValueList()) {
    249         DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline)));
    250         DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)));
    251 
    252         RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
    253         if (newTextDecoration->removeAll(underline.get()))
    254             m_applyUnderline = true;
    255         if (newTextDecoration->removeAll(lineThrough.get()))
    256             m_applyLineThrough = true;
    257 
    258         // If trimTextDecorations, delete underline and line-through
    259         setTextDecorationProperty(style, newTextDecoration.get(), CSSPropertyTextDecoration);
    260     }
    261 
    262     int verticalAlign = getIdentifierValue(style, CSSPropertyVerticalAlign);
    263     switch (verticalAlign) {
    264     case CSSValueSub:
    265         style->removeProperty(CSSPropertyVerticalAlign);
    266         m_applySubscript = true;
    267         break;
    268     case CSSValueSuper:
    269         style->removeProperty(CSSPropertyVerticalAlign);
    270         m_applySuperscript = true;
    271         break;
    272     }
    273 
    274     if (style->getPropertyCSSValue(CSSPropertyColor)) {
    275         m_applyFontColor = Color(getRGBAFontColor(style)).serialized();
    276         style->removeProperty(CSSPropertyColor);
    277     }
    278 
    279     m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily);
    280     style->removeProperty(CSSPropertyFontFamily);
    281 
    282     if (RefPtr<CSSValue> fontSize = style->getPropertyCSSValue(CSSPropertyFontSize)) {
    283         if (!fontSize->isPrimitiveValue())
    284             style->removeProperty(CSSPropertyFontSize); // Can't make sense of the number. Put no font size.
    285         else if (int legacyFontSize = legacyFontSizeFromCSSValue(document, static_cast<CSSPrimitiveValue*>(fontSize.get()),
    286                 shouldUseFixedFontDefaultSize, UseLegacyFontSizeOnlyIfPixelValuesMatch)) {
    287             m_applyFontSize = String::number(legacyFontSize);
    288             style->removeProperty(CSSPropertyFontSize);
    289         }
    290     }
    291 }
    292 
    29357static String& styleSpanClassString()
    29458{
     
    353117    styleElement->setAttribute(classAttr, styleSpanClassString());
    354118    return styleElement.release();
    355 }
    356 
    357 static void diffTextDecorations(CSSMutableStyleDeclaration* style, int propertID, CSSValue* refTextDecoration)
    358 {
    359     RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(propertID);
    360     if (!textDecoration || !textDecoration->isValueList() || !refTextDecoration || !refTextDecoration->isValueList())
    361         return;
    362 
    363     RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
    364     CSSValueList* valuesInRefTextDecoration = static_cast<CSSValueList*>(refTextDecoration);
    365 
    366     for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++)
    367         newTextDecoration->removeAll(valuesInRefTextDecoration->item(i));
    368 
    369     setTextDecorationProperty(style, newTextDecoration.get(), propertID);
    370 }
    371 
    372 static bool fontWeightIsBold(CSSStyleDeclaration* style)
    373 {
    374     ASSERT(style);
    375     RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight);
    376 
    377     if (!fontWeight)
    378         return false;
    379     if (!fontWeight->isPrimitiveValue())
    380         return false;
    381 
    382     // Because b tag can only bold text, there are only two states in plain html: bold and not bold.
    383     // Collapse all other values to either one of these two states for editing purposes.
    384     switch (static_cast<CSSPrimitiveValue*>(fontWeight.get())->getIdent()) {
    385         case CSSValue100:
    386         case CSSValue200:
    387         case CSSValue300:
    388         case CSSValue400:
    389         case CSSValue500:
    390         case CSSValueNormal:
    391             return false;
    392         case CSSValueBold:
    393         case CSSValue600:
    394         case CSSValue700:
    395         case CSSValue800:
    396         case CSSValue900:
    397             return true;
    398     }
    399 
    400     ASSERT_NOT_REACHED(); // For CSSValueBolder and CSSValueLighter
    401     return false; // Make compiler happy
    402 }
    403 
    404 static int getTextAlignment(CSSStyleDeclaration* style)
    405 {
    406     int textAlign = getIdentifierValue(style, CSSPropertyTextAlign);
    407     switch (textAlign) {
    408     case CSSValueCenter:
    409     case CSSValueWebkitCenter:
    410         return CSSValueCenter;
    411     case CSSValueJustify:
    412         return CSSValueJustify;
    413     case CSSValueLeft:
    414     case CSSValueWebkitLeft:
    415         return CSSValueLeft;
    416     case CSSValueRight:
    417     case CSSValueWebkitRight:
    418         return CSSValueRight;
    419     }
    420     return CSSValueInvalid;
    421 }
    422 
    423 RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle)
    424 {
    425     ASSERT(styleWithRedundantProperties);
    426     ASSERT(baseStyle);
    427     RefPtr<CSSMutableStyleDeclaration> result = styleWithRedundantProperties->copy();
    428     baseStyle->diff(result.get());
    429 
    430     RefPtr<CSSValue> baseTextDecorationsInEffect = baseStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
    431     diffTextDecorations(result.get(), CSSPropertyTextDecoration, baseTextDecorationsInEffect.get());
    432     diffTextDecorations(result.get(), CSSPropertyWebkitTextDecorationsInEffect, baseTextDecorationsInEffect.get());
    433 
    434     if (fontWeightIsBold(result.get()) == fontWeightIsBold(baseStyle))
    435         result->removeProperty(CSSPropertyFontWeight);
    436 
    437     if (getRGBAFontColor(result.get()) == getRGBAFontColor(baseStyle))
    438         result->removeProperty(CSSPropertyColor);
    439 
    440     if (getTextAlignment(result.get()) == getTextAlignment(baseStyle))
    441         result->removeProperty(CSSPropertyTextAlign);       
    442 
    443     return result;
    444119}
    445120
  • trunk/Source/WebCore/editing/ApplyStyleCommand.h

    r80580 r83618  
    3535class CSSPrimitiveValue;
    3636class EditingStyle;
    37 class HTMLElement;
    3837class StyleChange;
    3938
     
    131130};
    132131
    133 enum LegacyFontSizeMode { AlwaysUseLegacyFontSize, UseLegacyFontSizeOnlyIfPixelValuesMatch };
    134 int legacyFontSizeFromCSSValue(Document*, CSSPrimitiveValue*, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode);
    135132bool isStyleSpan(const Node*);
    136133PassRefPtr<HTMLElement> createStyleSpanElement(Document*);
    137 RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle);
    138134
    139135} // namespace WebCore
  • trunk/Source/WebCore/editing/EditingStyle.cpp

    r83247 r83618  
    3131#include "CSSComputedStyleDeclaration.h"
    3232#include "CSSMutableStyleDeclaration.h"
     33#include "CSSParser.h"
     34#include "CSSStyleSelector.h"
    3335#include "CSSValueKeywords.h"
    3436#include "CSSValueList.h"
     
    8890}
    8991
     92static RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle);
     93
    9094class HTMLElementEquivalent {
    9195public:
     
    774778}
    775779
    776 }
     780static void reconcileTextDecorationProperties(CSSMutableStyleDeclaration* style)
     781{   
     782    RefPtr<CSSValue> textDecorationsInEffect = style->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
     783    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
     784    // We shouldn't have both text-decoration and -webkit-text-decorations-in-effect because that wouldn't make sense.
     785    ASSERT(!textDecorationsInEffect || !textDecoration);
     786    if (textDecorationsInEffect) {
     787        style->setProperty(CSSPropertyTextDecoration, textDecorationsInEffect->cssText());
     788        style->removeProperty(CSSPropertyWebkitTextDecorationsInEffect);
     789        textDecoration = textDecorationsInEffect;
     790    }
     791
     792    // If text-decoration is set to "none", remove the property because we don't want to add redundant "text-decoration: none".
     793    if (textDecoration && !textDecoration->isValueList())
     794        style->removeProperty(CSSPropertyTextDecoration);
     795}
     796
     797StyleChange::StyleChange(EditingStyle* style, const Position& position)
     798    : m_applyBold(false)
     799    , m_applyItalic(false)
     800    , m_applyUnderline(false)
     801    , m_applyLineThrough(false)
     802    , m_applySubscript(false)
     803    , m_applySuperscript(false)
     804{
     805    Document* document = position.anchorNode() ? position.anchorNode()->document() : 0;
     806    if (!style || !style->style() || !document || !document->frame())
     807        return;
     808
     809    RefPtr<CSSComputedStyleDeclaration> computedStyle = position.computedStyle();
     810    RefPtr<CSSMutableStyleDeclaration> mutableStyle = getPropertiesNotIn(style->style(), computedStyle.get());
     811
     812    reconcileTextDecorationProperties(mutableStyle.get());
     813    if (!document->frame()->editor()->shouldStyleWithCSS())
     814        extractTextStyles(document, mutableStyle.get(), computedStyle->useFixedFontDefaultSize());
     815
     816    // Changing the whitespace style in a tab span would collapse the tab into a space.
     817    if (isTabSpanTextNode(position.deprecatedNode()) || isTabSpanNode((position.deprecatedNode())))
     818        mutableStyle->removeProperty(CSSPropertyWhiteSpace);
     819
     820    // If unicode-bidi is present in mutableStyle and direction is not, then add direction to mutableStyle.
     821    // FIXME: Shouldn't this be done in getPropertiesNotIn?
     822    if (mutableStyle->getPropertyCSSValue(CSSPropertyUnicodeBidi) && !style->style()->getPropertyCSSValue(CSSPropertyDirection))
     823        mutableStyle->setProperty(CSSPropertyDirection, style->style()->getPropertyValue(CSSPropertyDirection));
     824
     825    // Save the result for later
     826    m_cssStyle = mutableStyle->cssText().stripWhiteSpace();
     827}
     828
     829static void setTextDecorationProperty(CSSMutableStyleDeclaration* style, const CSSValueList* newTextDecoration, int propertyID)
     830{
     831    if (newTextDecoration->length())
     832        style->setProperty(propertyID, newTextDecoration->cssText(), style->getPropertyPriority(propertyID));
     833    else {
     834        // text-decoration: none is redundant since it does not remove any text decorations.
     835        ASSERT(!style->getPropertyPriority(propertyID));
     836        style->removeProperty(propertyID);
     837    }
     838}
     839
     840static RGBA32 getRGBAFontColor(CSSStyleDeclaration* style)
     841{
     842    RefPtr<CSSValue> colorValue = style->getPropertyCSSValue(CSSPropertyColor);
     843    if (!colorValue || !colorValue->isPrimitiveValue())
     844        return Color::transparent;
     845
     846    CSSPrimitiveValue* primitiveColor = static_cast<CSSPrimitiveValue*>(colorValue.get());
     847    if (primitiveColor->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
     848        return primitiveColor->getRGBA32Value();
     849
     850    // Need to take care of named color such as green and black
     851    // This code should be removed after https://bugs.webkit.org/show_bug.cgi?id=28282 is fixed.
     852    RGBA32 rgba = 0;
     853    CSSParser::parseColor(rgba, colorValue->cssText());
     854    return rgba;
     855}
     856
     857void StyleChange::extractTextStyles(Document* document, CSSMutableStyleDeclaration* style, bool shouldUseFixedFontDefaultSize)
     858{
     859    ASSERT(style);
     860
     861    if (getIdentifierValue(style, CSSPropertyFontWeight) == CSSValueBold) {
     862        style->removeProperty(CSSPropertyFontWeight);
     863        m_applyBold = true;
     864    }
     865
     866    int fontStyle = getIdentifierValue(style, CSSPropertyFontStyle);
     867    if (fontStyle == CSSValueItalic || fontStyle == CSSValueOblique) {
     868        style->removeProperty(CSSPropertyFontStyle);
     869        m_applyItalic = true;
     870    }
     871
     872    // Assuming reconcileTextDecorationProperties has been called, there should not be -webkit-text-decorations-in-effect
     873    // Furthermore, text-decoration: none has been trimmed so that text-decoration property is always a CSSValueList.
     874    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(CSSPropertyTextDecoration);
     875    if (textDecoration && textDecoration->isValueList()) {
     876        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, underline, (CSSPrimitiveValue::createIdentifier(CSSValueUnderline)));
     877        DEFINE_STATIC_LOCAL(RefPtr<CSSPrimitiveValue>, lineThrough, (CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)));
     878
     879        RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
     880        if (newTextDecoration->removeAll(underline.get()))
     881            m_applyUnderline = true;
     882        if (newTextDecoration->removeAll(lineThrough.get()))
     883            m_applyLineThrough = true;
     884
     885        // If trimTextDecorations, delete underline and line-through
     886        setTextDecorationProperty(style, newTextDecoration.get(), CSSPropertyTextDecoration);
     887    }
     888
     889    int verticalAlign = getIdentifierValue(style, CSSPropertyVerticalAlign);
     890    switch (verticalAlign) {
     891    case CSSValueSub:
     892        style->removeProperty(CSSPropertyVerticalAlign);
     893        m_applySubscript = true;
     894        break;
     895    case CSSValueSuper:
     896        style->removeProperty(CSSPropertyVerticalAlign);
     897        m_applySuperscript = true;
     898        break;
     899    }
     900
     901    if (style->getPropertyCSSValue(CSSPropertyColor)) {
     902        m_applyFontColor = Color(getRGBAFontColor(style)).serialized();
     903        style->removeProperty(CSSPropertyColor);
     904    }
     905
     906    m_applyFontFace = style->getPropertyValue(CSSPropertyFontFamily);
     907    style->removeProperty(CSSPropertyFontFamily);
     908
     909    if (RefPtr<CSSValue> fontSize = style->getPropertyCSSValue(CSSPropertyFontSize)) {
     910        if (!fontSize->isPrimitiveValue())
     911            style->removeProperty(CSSPropertyFontSize); // Can't make sense of the number. Put no font size.
     912        else if (int legacyFontSize = legacyFontSizeFromCSSValue(document, static_cast<CSSPrimitiveValue*>(fontSize.get()),
     913                shouldUseFixedFontDefaultSize, UseLegacyFontSizeOnlyIfPixelValuesMatch)) {
     914            m_applyFontSize = String::number(legacyFontSize);
     915            style->removeProperty(CSSPropertyFontSize);
     916        }
     917    }
     918}
     919
     920static void diffTextDecorations(CSSMutableStyleDeclaration* style, int propertID, CSSValue* refTextDecoration)
     921{
     922    RefPtr<CSSValue> textDecoration = style->getPropertyCSSValue(propertID);
     923    if (!textDecoration || !textDecoration->isValueList() || !refTextDecoration || !refTextDecoration->isValueList())
     924        return;
     925
     926    RefPtr<CSSValueList> newTextDecoration = static_cast<CSSValueList*>(textDecoration.get())->copy();
     927    CSSValueList* valuesInRefTextDecoration = static_cast<CSSValueList*>(refTextDecoration);
     928
     929    for (size_t i = 0; i < valuesInRefTextDecoration->length(); i++)
     930        newTextDecoration->removeAll(valuesInRefTextDecoration->item(i));
     931
     932    setTextDecorationProperty(style, newTextDecoration.get(), propertID);
     933}
     934
     935static bool fontWeightIsBold(CSSStyleDeclaration* style)
     936{
     937    ASSERT(style);
     938    RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight);
     939
     940    if (!fontWeight)
     941        return false;
     942    if (!fontWeight->isPrimitiveValue())
     943        return false;
     944
     945    // Because b tag can only bold text, there are only two states in plain html: bold and not bold.
     946    // Collapse all other values to either one of these two states for editing purposes.
     947    switch (static_cast<CSSPrimitiveValue*>(fontWeight.get())->getIdent()) {
     948        case CSSValue100:
     949        case CSSValue200:
     950        case CSSValue300:
     951        case CSSValue400:
     952        case CSSValue500:
     953        case CSSValueNormal:
     954            return false;
     955        case CSSValueBold:
     956        case CSSValue600:
     957        case CSSValue700:
     958        case CSSValue800:
     959        case CSSValue900:
     960            return true;
     961    }
     962
     963    ASSERT_NOT_REACHED(); // For CSSValueBolder and CSSValueLighter
     964    return false; // Make compiler happy
     965}
     966
     967static int getTextAlignment(CSSStyleDeclaration* style)
     968{
     969    int textAlign = getIdentifierValue(style, CSSPropertyTextAlign);
     970    switch (textAlign) {
     971    case CSSValueCenter:
     972    case CSSValueWebkitCenter:
     973        return CSSValueCenter;
     974    case CSSValueJustify:
     975        return CSSValueJustify;
     976    case CSSValueLeft:
     977    case CSSValueWebkitLeft:
     978        return CSSValueLeft;
     979    case CSSValueRight:
     980    case CSSValueWebkitRight:
     981        return CSSValueRight;
     982    }
     983    return CSSValueInvalid;
     984}
     985
     986RefPtr<CSSMutableStyleDeclaration> getPropertiesNotIn(CSSStyleDeclaration* styleWithRedundantProperties, CSSStyleDeclaration* baseStyle)
     987{
     988    ASSERT(styleWithRedundantProperties);
     989    ASSERT(baseStyle);
     990    RefPtr<CSSMutableStyleDeclaration> result = styleWithRedundantProperties->copy();
     991    baseStyle->diff(result.get());
     992
     993    RefPtr<CSSValue> baseTextDecorationsInEffect = baseStyle->getPropertyCSSValue(CSSPropertyWebkitTextDecorationsInEffect);
     994    diffTextDecorations(result.get(), CSSPropertyTextDecoration, baseTextDecorationsInEffect.get());
     995    diffTextDecorations(result.get(), CSSPropertyWebkitTextDecorationsInEffect, baseTextDecorationsInEffect.get());
     996
     997    if (fontWeightIsBold(result.get()) == fontWeightIsBold(baseStyle))
     998        result->removeProperty(CSSPropertyFontWeight);
     999
     1000    if (getRGBAFontColor(result.get()) == getRGBAFontColor(baseStyle))
     1001        result->removeProperty(CSSPropertyColor);
     1002
     1003    if (getTextAlignment(result.get()) == getTextAlignment(baseStyle))
     1004        result->removeProperty(CSSPropertyTextAlign);       
     1005
     1006    return result;
     1007}
     1008
     1009
     1010int getIdentifierValue(CSSStyleDeclaration* style, int propertyID)
     1011{
     1012    if (!style)
     1013        return 0;
     1014
     1015    RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
     1016    if (!value || !value->isPrimitiveValue())
     1017        return 0;
     1018
     1019    return static_cast<CSSPrimitiveValue*>(value.get())->getIdent();
     1020}
     1021
     1022static bool isCSSValueLength(CSSPrimitiveValue* value)
     1023{
     1024    return value->primitiveType() >= CSSPrimitiveValue::CSS_PX && value->primitiveType() <= CSSPrimitiveValue::CSS_PC;
     1025}
     1026
     1027int legacyFontSizeFromCSSValue(Document* document, CSSPrimitiveValue* value, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode mode)
     1028{
     1029    if (isCSSValueLength(value)) {
     1030        int pixelFontSize = value->getIntValue(CSSPrimitiveValue::CSS_PX);
     1031        int legacyFontSize = CSSStyleSelector::legacyFontSize(document, pixelFontSize, shouldUseFixedFontDefaultSize);
     1032        // Use legacy font size only if pixel value matches exactly to that of legacy font size.
     1033        int cssPrimitiveEquivalent = legacyFontSize - 1 + CSSValueXSmall;
     1034        if (mode == AlwaysUseLegacyFontSize || CSSStyleSelector::fontSizeForKeyword(document, cssPrimitiveEquivalent, shouldUseFixedFontDefaultSize) == pixelFontSize)
     1035            return legacyFontSize;
     1036
     1037        return 0;
     1038    }
     1039
     1040    if (CSSValueXSmall <= value->getIdent() && value->getIdent() <= CSSValueWebkitXxxLarge)
     1041        return value->getIdent() - CSSValueXSmall + 1;
     1042
     1043    return 0;
     1044}
     1045
     1046}
  • trunk/Source/WebCore/editing/EditingStyle.h

    r80580 r83618  
    3333
    3434#include "CSSPropertyNames.h"
     35#include "PlatformString.h"
    3536#include "WritingDirection.h"
    3637#include <wtf/Forward.h>
     
    4445class CSSComputedStyleDeclaration;
    4546class CSSMutableStyleDeclaration;
     47class CSSPrimitiveValue;
    4648class Document;
    4749class HTMLElement;
     
    145147};
    146148
     149class StyleChange {
     150public:
     151    StyleChange(EditingStyle*, const Position&);
     152
     153    String cssStyle() const { return m_cssStyle; }
     154    bool applyBold() const { return m_applyBold; }
     155    bool applyItalic() const { return m_applyItalic; }
     156    bool applyUnderline() const { return m_applyUnderline; }
     157    bool applyLineThrough() const { return m_applyLineThrough; }
     158    bool applySubscript() const { return m_applySubscript; }
     159    bool applySuperscript() const { return m_applySuperscript; }
     160    bool applyFontColor() const { return m_applyFontColor.length() > 0; }
     161    bool applyFontFace() const { return m_applyFontFace.length() > 0; }
     162    bool applyFontSize() const { return m_applyFontSize.length() > 0; }
     163
     164    String fontColor() { return m_applyFontColor; }
     165    String fontFace() { return m_applyFontFace; }
     166    String fontSize() { return m_applyFontSize; }
     167
     168    bool operator==(const StyleChange& other)
     169    {
     170        return m_cssStyle == other.m_cssStyle
     171            && m_applyBold == other.m_applyBold
     172            && m_applyItalic == other.m_applyItalic
     173            && m_applyUnderline == other.m_applyUnderline
     174            && m_applyLineThrough == other.m_applyLineThrough
     175            && m_applySubscript == other.m_applySubscript
     176            && m_applySuperscript == other.m_applySuperscript
     177            && m_applyFontColor == other.m_applyFontColor
     178            && m_applyFontFace == other.m_applyFontFace
     179            && m_applyFontSize == other.m_applyFontSize;
     180    }
     181    bool operator!=(const StyleChange& other)
     182    {
     183        return !(*this == other);
     184    }
     185private:
     186    void extractTextStyles(Document*, CSSMutableStyleDeclaration*, bool shouldUseFixedFontDefaultSize);
     187
     188    String m_cssStyle;
     189    bool m_applyBold;
     190    bool m_applyItalic;
     191    bool m_applyUnderline;
     192    bool m_applyLineThrough;
     193    bool m_applySubscript;
     194    bool m_applySuperscript;
     195    String m_applyFontColor;
     196    String m_applyFontFace;
     197    String m_applyFontSize;
     198};
     199
     200// FIXME: Remove these functions or make them non-global to discourage using CSSStyleDeclaration directly.
     201int getIdentifierValue(CSSStyleDeclaration*, int propertyID);
     202enum LegacyFontSizeMode { AlwaysUseLegacyFontSize, UseLegacyFontSizeOnlyIfPixelValuesMatch };
     203int legacyFontSizeFromCSSValue(Document*, CSSPrimitiveValue*, bool shouldUseFixedFontDefaultSize, LegacyFontSizeMode);
     204
    147205} // namespace WebCore
    148206
Note: See TracChangeset for help on using the changeset viewer.