Changeset 173217 in webkit


Ignore:
Timestamp:
Sep 3, 2014 12:26:38 PM (10 years ago)
Author:
hyatt@apple.com
Message:

Add support for the initial-letter CSS property to first-letter
https://bugs.webkit.org/show_bug.cgi?id=136484

Reviewed by Dean Jackson.
Source/WebCore:


New tests in fast/css-generated-content/initial-letter-*.html

This patch add support for the CSS initial-letter property, enabling
better drop caps support in WebKit. Letters size to a specified number of
paragraph lines, and align to the cap-height of the first line and the baseline
of the last line.

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::propertyValue):
Add -webkit-initial-letter to the list.

  • css/CSSLineBoxContainValue.cpp:

(WebCore::CSSLineBoxContainValue::customCSSText):

  • css/CSSLineBoxContainValue.h:

Add support for a new value of line-box-contain, initial-letter, that causes
lines to use cap-height above the baseline and the glyph bounds below the
baseline.

  • css/CSSParser.cpp:

(WebCore::CSSParser::parseValue):
Add support for parsing of initial-letter.

(WebCore::CSSParser::parseLineBoxContain):
Add the new line-box-contain value for first-letters with initial-letter set.

  • css/CSSPropertyNames.in:

Add the new initial-letter property.

  • css/CSSValueKeywords.in:

Add the new initial-letter line-box-contain value.

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::applyProperty):
Map initial-letter into the RenderStyle.

  • platform/graphics/FontMetrics.h:

(WebCore::FontMetrics::hasCapHeight):
(WebCore::FontMetrics::floatCapHeight):
(WebCore::FontMetrics::setCapHeight):
(WebCore::FontMetrics::capHeight):

  • platform/graphics/ios/SimpleFontDataIOS.mm:

(WebCore::SimpleFontData::platformInit):

  • platform/graphics/mac/SimpleFontDataMac.mm:

(WebCore::SimpleFontData::platformInit):
Add support for cap-height to the font system. iOS and Mac have been patched.
Other platforms will need to add support for cap-height to get this feature.
hasCapHeight() will return false for unsupported platforms for graceful
degradation.

  • rendering/RenderBlock.cpp:

(WebCore::styleForFirstLetter):
Modified to check for initialLetterDrop/Height and to adjust the style
accordingly (e.g., to apply float when needed).

  • rendering/RenderBlockFlow.cpp:

(WebCore::RenderBlockFlow::computeLogicalLocationForFloat):
Code to adjust the float's position and margin to do cap-height alignment
and sunken letters.

  • rendering/RenderBlockFlow.h:

Remove the const from computeLogicalLocationForFloat, since the margin of the
float can now be modified dynamically for sunken first-letters.

  • rendering/RootInlineBox.cpp:

(WebCore::RootInlineBox::ascentAndDescentForBox):
Add support for initial-letter line-box-contain value.

  • rendering/RootInlineBox.h:

Add the includeInitialLetterForBox method to support the new line-box-contain value.

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::changeRequiresLayout):

  • rendering/style/RenderStyle.h:
  • rendering/style/StyleRareNonInheritedData.cpp:

(WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
(WebCore::StyleRareNonInheritedData::operator==):

  • rendering/style/StyleRareNonInheritedData.h:

Normal maintenance stuff for addition of a new CSS property (making sure it is diffed
properly for layout changes and copied on assignment, etc.)

LayoutTests:

  • fast/css-generated-content/initial-letter-basic.html: Added.
  • fast/css-generated-content/initial-letter-border-padding.html: Added.
  • fast/css-generated-content/initial-letter-descender.html: Added.
  • fast/css-generated-content/initial-letter-raised.html: Added.
  • fast/css-generated-content/initial-letter-sunken.html: Added.
  • platform/mac/fast/css-generated-content/initial-letter-basic-expected.png: Added.
  • platform/mac/fast/css-generated-content/initial-letter-basic-expected.txt: Added.
  • platform/mac/fast/css-generated-content/initial-letter-border-padding-expected.png: Added.
  • platform/mac/fast/css-generated-content/initial-letter-border-padding-expected.txt: Added.
  • platform/mac/fast/css-generated-content/initial-letter-descender-expected.png: Added.
  • platform/mac/fast/css-generated-content/initial-letter-descender-expected.txt: Added.
  • platform/mac/fast/css-generated-content/initial-letter-raised-expected.png: Added.
  • platform/mac/fast/css-generated-content/initial-letter-raised-expected.txt: Added.
  • platform/mac/fast/css-generated-content/initial-letter-sunken-expected.png: Added.
  • platform/mac/fast/css-generated-content/initial-letter-sunken-expected.txt: Added.
Location:
trunk
Files:
15 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r173210 r173217  
     12014-09-03  David Hyatt  <hyatt@apple.com>
     2
     3        Add support for the initial-letter CSS property to first-letter
     4        https://bugs.webkit.org/show_bug.cgi?id=136484
     5
     6        Reviewed by Dean Jackson.
     7
     8        * fast/css-generated-content/initial-letter-basic.html: Added.
     9        * fast/css-generated-content/initial-letter-border-padding.html: Added.
     10        * fast/css-generated-content/initial-letter-descender.html: Added.
     11        * fast/css-generated-content/initial-letter-raised.html: Added.
     12        * fast/css-generated-content/initial-letter-sunken.html: Added.
     13        * platform/mac/fast/css-generated-content/initial-letter-basic-expected.png: Added.
     14        * platform/mac/fast/css-generated-content/initial-letter-basic-expected.txt: Added.
     15        * platform/mac/fast/css-generated-content/initial-letter-border-padding-expected.png: Added.
     16        * platform/mac/fast/css-generated-content/initial-letter-border-padding-expected.txt: Added.
     17        * platform/mac/fast/css-generated-content/initial-letter-descender-expected.png: Added.
     18        * platform/mac/fast/css-generated-content/initial-letter-descender-expected.txt: Added.
     19        * platform/mac/fast/css-generated-content/initial-letter-raised-expected.png: Added.
     20        * platform/mac/fast/css-generated-content/initial-letter-raised-expected.txt: Added.
     21        * platform/mac/fast/css-generated-content/initial-letter-sunken-expected.png: Added.
     22        * platform/mac/fast/css-generated-content/initial-letter-sunken-expected.txt: Added.
     23
    1242014-09-03  Brent Fulgham  <bfulgham@apple.com>
    225
  • trunk/Source/WebCore/ChangeLog

    r173216 r173217  
     12014-09-03  David Hyatt  <hyatt@apple.com>
     2
     3        Add support for the initial-letter CSS property to first-letter
     4        https://bugs.webkit.org/show_bug.cgi?id=136484
     5
     6        Reviewed by Dean Jackson.
     7       
     8        New tests in fast/css-generated-content/initial-letter-*.html
     9
     10        This patch add support for the CSS initial-letter property, enabling
     11        better drop caps support in WebKit. Letters size to a specified number of
     12        paragraph lines, and align to the cap-height of the first line and the baseline
     13        of the last line.
     14
     15        * css/CSSComputedStyleDeclaration.cpp:
     16        (WebCore::ComputedStyleExtractor::propertyValue):
     17        Add -webkit-initial-letter to the list.
     18
     19        * css/CSSLineBoxContainValue.cpp:
     20        (WebCore::CSSLineBoxContainValue::customCSSText):
     21        * css/CSSLineBoxContainValue.h:
     22        Add support for a new value of line-box-contain, initial-letter, that causes
     23        lines to use cap-height above the baseline and the glyph bounds below the
     24        baseline.
     25
     26        * css/CSSParser.cpp:
     27        (WebCore::CSSParser::parseValue):
     28        Add support for parsing of initial-letter.
     29
     30        (WebCore::CSSParser::parseLineBoxContain):
     31        Add the new line-box-contain value for first-letters with initial-letter set.
     32
     33        * css/CSSPropertyNames.in:
     34        Add the new initial-letter property.
     35
     36        * css/CSSValueKeywords.in:
     37        Add the new initial-letter line-box-contain value.
     38
     39        * css/StyleResolver.cpp:
     40        (WebCore::StyleResolver::applyProperty):
     41        Map initial-letter into the RenderStyle.
     42
     43        * platform/graphics/FontMetrics.h:
     44        (WebCore::FontMetrics::hasCapHeight):
     45        (WebCore::FontMetrics::floatCapHeight):
     46        (WebCore::FontMetrics::setCapHeight):
     47        (WebCore::FontMetrics::capHeight):
     48        * platform/graphics/ios/SimpleFontDataIOS.mm:
     49        (WebCore::SimpleFontData::platformInit):
     50        * platform/graphics/mac/SimpleFontDataMac.mm:
     51        (WebCore::SimpleFontData::platformInit):
     52        Add support for cap-height to the font system. iOS and Mac have been patched.
     53        Other platforms will need to add support for cap-height to get this feature.
     54        hasCapHeight() will return false for unsupported platforms for graceful
     55        degradation.
     56
     57        * rendering/RenderBlock.cpp:
     58        (WebCore::styleForFirstLetter):
     59        Modified to check for initialLetterDrop/Height and to adjust the style
     60        accordingly (e.g., to apply float when needed).
     61
     62        * rendering/RenderBlockFlow.cpp:
     63        (WebCore::RenderBlockFlow::computeLogicalLocationForFloat):
     64        Code to adjust the float's position and margin to do cap-height alignment
     65        and sunken letters.
     66
     67        * rendering/RenderBlockFlow.h:
     68        Remove the const from computeLogicalLocationForFloat, since the margin of the
     69        float can now be modified dynamically for sunken first-letters.
     70
     71        * rendering/RootInlineBox.cpp:
     72        (WebCore::RootInlineBox::ascentAndDescentForBox):
     73        Add support for initial-letter line-box-contain value.
     74
     75        * rendering/RootInlineBox.h:
     76        Add the includeInitialLetterForBox method to support the new line-box-contain value.
     77
     78        * rendering/style/RenderStyle.cpp:
     79        (WebCore::RenderStyle::changeRequiresLayout):
     80        * rendering/style/RenderStyle.h:
     81        * rendering/style/StyleRareNonInheritedData.cpp:
     82        (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
     83        (WebCore::StyleRareNonInheritedData::operator==):
     84        * rendering/style/StyleRareNonInheritedData.h:
     85        Normal maintenance stuff for addition of a new CSS property (making sure it is diffed
     86        properly for layout changes and copied on assignment, etc.)
     87
    1882014-09-03  Brent Fulgham  <bfulgham@apple.com>
    289
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r173212 r173217  
    317317    CSSPropertyWebkitHyphenateLimitLines,
    318318    CSSPropertyWebkitHyphens,
     319    CSSPropertyWebkitInitialLetter,
    319320    CSSPropertyWebkitLineAlign,
    320321    CSSPropertyWebkitLineBoxContain,
     
    27102711            // Not a real style property -- used by the editing engine -- so has no computed value.
    27112712            break;
     2713        case CSSPropertyWebkitInitialLetter: {
     2714            RefPtr<CSSPrimitiveValue> drop = !style->initialLetterDrop() ? cssValuePool().createIdentifierValue(CSSValueNormal) : cssValuePool().createValue(style->initialLetterDrop(), CSSPrimitiveValue::CSS_NUMBER);
     2715            RefPtr<CSSPrimitiveValue> size = !style->initialLetterHeight() ? cssValuePool().createIdentifierValue(CSSValueNormal) : cssValuePool().createValue(style->initialLetterHeight(), CSSPrimitiveValue::CSS_NUMBER);
     2716            return cssValuePool().createValue(Pair::create(drop.release(), size.release()));
     2717        }
    27122718        case CSSPropertyWebkitMarginBottomCollapse:
    27132719        case CSSPropertyWebkitMarginAfterCollapse:
  • trunk/Source/WebCore/css/CSSLineBoxContainValue.cpp

    r158543 r173217  
    6868        text.appendLiteral("inline-box");
    6969    }
     70    if (m_value & LineBoxContainInitialLetter) {
     71        if (!text.isEmpty())
     72            text.append(' ');
     73        text.appendLiteral("initial-letter");
     74    }
    7075
    7176    return text.toString();
  • trunk/Source/WebCore/css/CSSLineBoxContainValue.h

    r158543 r173217  
    3636
    3737enum LineBoxContainFlags { LineBoxContainNone = 0x0, LineBoxContainBlock = 0x1, LineBoxContainInline = 0x2, LineBoxContainFont = 0x4, LineBoxContainGlyphs = 0x8,
    38                            LineBoxContainReplaced = 0x10, LineBoxContainInlineBox = 0x20 };
     38                           LineBoxContainReplaced = 0x10, LineBoxContainInlineBox = 0x20, LineBoxContainInitialLetter = 0x40 };
    3939typedef unsigned LineBoxContain;
    4040
  • trunk/Source/WebCore/css/CSSParser.cpp

    r172904 r173217  
    24152415        }
    24162416        break;
     2417    case CSSPropertyWebkitInitialLetter: {
     2418        if (id == CSSValueNormal)
     2419            validPrimitive = true;
     2420        else {
     2421            if (num != 1 && num != 2)
     2422                return false;
     2423            validPrimitive = validUnit(value, FPositiveInteger);
     2424            if (!validPrimitive)
     2425                return false;
     2426            RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
     2427            RefPtr<CSSPrimitiveValue> parsedValue2;
     2428            if (num == 2) {
     2429                value = m_valueList->next();
     2430                validPrimitive = validUnit(value, FPositiveInteger);
     2431                if (!validPrimitive)
     2432                    return false;
     2433                parsedValue2 = createPrimitiveNumericValue(value);
     2434            } else
     2435                parsedValue2 = parsedValue1;
     2436            addProperty(propId, createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release()), important);
     2437            return true;
     2438        }
     2439        break;
     2440    }
    24172441    case CSSPropertyWebkitBoxReflect:
    24182442        if (id == CSSValueNone)
     
    98379861                return false;
    98389862            lineBoxContain |= LineBoxContainInlineBox;
     9863        } else if (value->id == CSSValueInitialLetter) {
     9864            if (lineBoxContain & LineBoxContainInitialLetter)
     9865                return false;
     9866            lineBoxContain |= LineBoxContainInitialLetter;
    98399867        } else
    98409868            return false;
  • trunk/Source/WebCore/css/CSSPropertyNames.in

    r172861 r173217  
    332332-webkit-hyphens [Inherited]
    333333-epub-hyphens = -webkit-hyphens
     334-webkit-initial-letter
    334335-webkit-line-box-contain [Inherited]
    335336-webkit-line-align [Inherited]
  • trunk/Source/WebCore/css/CSSValueKeywords.in

    r172861 r173217  
    972972glyphs
    973973inline-box
     974initial-letter
    974975replaced
    975976
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r173012 r173217  
    29452945        return;
    29462946    }
     2947    case CSSPropertyWebkitInitialLetter: {
     2948        HANDLE_INHERIT_AND_INITIAL(initialLetter, InitialLetter)
     2949        if (!value->isPrimitiveValue())
     2950            return;
     2951       
     2952        if (primitiveValue->getValueID() == CSSValueNormal) {
     2953            state.style()->setInitialLetter(IntSize());
     2954            return;
     2955        }
     2956           
     2957        CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
     2958        Pair* pair = primitiveValue->getPairValue();
     2959        if (!pair || !pair->first() || !pair->second())
     2960            return;
     2961
     2962        state.style()->setInitialLetter(IntSize(pair->first()->getIntValue(), pair->second()->getIntValue()));
     2963        return;
     2964    }
     2965   
    29472966#endif
    29482967    // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version.
  • trunk/Source/WebCore/platform/graphics/FontMetrics.h

    r142904 r173217  
    8484    bool hasXHeight() const { return m_hasXHeight && m_xHeight > 0; }
    8585    void setHasXHeight(bool hasXHeight) { m_hasXHeight = hasXHeight; }
    86 
     86   
     87    bool hasCapHeight() const { return m_hasCapHeight && m_capHeight > 0; }
     88    float floatCapHeight() const { return m_capHeight; }
     89    void setCapHeight(float capHeight)
     90    {
     91        m_capHeight = capHeight;
     92        m_hasCapHeight = true;
     93    }
     94   
    8795    // Integer variants of certain metrics, used for HTML rendering.
    8896    int ascent(FontBaseline baselineType = AlphabeticBaseline) const
     
    92100        return height() - height() / 2;
    93101    }
    94 
     102   
    95103    int descent(FontBaseline baselineType = AlphabeticBaseline) const
    96104    {
     
    107115    int lineGap() const { return lroundf(m_lineGap); }
    108116    int lineSpacing() const { return lroundf(m_lineSpacing); }
    109 
     117   
     118    int capHeight() const { return lroundf(m_capHeight); }
     119   
    110120    bool hasIdenticalAscentDescentAndLineGap(const FontMetrics& other) const
    111121    {
     
    143153    float m_lineSpacing;
    144154    float m_xHeight;
     155    float m_capHeight;
    145156    float m_zeroWidth;
    146157    bool m_hasXHeight;
     158    bool m_hasCapHeight;
    147159    bool m_hasZeroWidth;
    148160};
  • trunk/Source/WebCore/platform/graphics/ios/SimpleFontDataIOS.mm

    r167773 r173217  
    7676    float ascent;
    7777    float descent;
     78    float capHeight;
    7879    float lineGap;
    7980    float lineSpacing;
     
    8788        lineGap = fontService.lineGap();
    8889        xHeight = fontService.xHeight();
     90        capHeight = fontService.capHeight();
    8991        unitsPerEm = fontService.unitsPerEm();
    9092        familyName = adoptCF(CTFontCopyFamilyName(ctFont));
     
    99101        lineGap = lroundf(scaleEmToUnits(CGFontGetLeading(cgFont), unitsPerEm) * pointSize);
    100102        xHeight = scaleEmToUnits(CGFontGetXHeight(cgFont), unitsPerEm) * pointSize;
     103        capHeight = scaleEmToUnits(CGFontGetCapHeight(cgFont), unitsPerEm) * pointSize;
    101104
    102105        lineSpacing = ascent + descent + lineGap;
     
    110113    m_fontMetrics.setLineSpacing(lineSpacing);
    111114    m_fontMetrics.setXHeight(xHeight);
     115    m_fontMetrics.setCapHeight(capHeight);
    112116    m_shouldNotBeUsedForArabic = fontFamilyShouldNotBeUsedForArabic(familyName.get());
    113117
  • trunk/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm

    r167773 r173217  
    187187    int iAscent;
    188188    int iDescent;
     189    int iCapHeight;
    189190    int iLineGap;
    190191    unsigned unitsPerEm;
     
    193194    // such fonts meant the same distance, but in the reverse direction.
    194195    iDescent = -abs(CGFontGetDescent(m_platformData.cgFont()));
     196    iCapHeight = CGFontGetCapHeight(m_platformData.cgFont());
    195197    iLineGap = CGFontGetLeading(m_platformData.cgFont());
    196198    unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
     
    199201    float ascent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
    200202    float descent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
     203    float capHeight = scaleEmToUnits(iCapHeight, unitsPerEm) * pointSize;
     204   
    201205    float lineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
    202206
     
    240244    m_fontMetrics.setAscent(ascent);
    241245    m_fontMetrics.setDescent(descent);
     246    m_fontMetrics.setCapHeight(capHeight);
    242247    m_fontMetrics.setLineGap(lineGap);
    243248    m_fontMetrics.setXHeight(xHeight);
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r173134 r173217  
    34543454{
    34553455    RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, &firstLetterContainer->firstLineStyle());
     3456   
     3457    // If we have an initial letter drop that is >= 1, then we need to force floating to be on.
     3458    if (pseudoStyle->initialLetterDrop() >= 1 && !pseudoStyle->isFloating())
     3459        pseudoStyle->setFloating(pseudoStyle->isLeftToRightDirection() ? LeftFloat : RightFloat);
     3460
     3461    // We have to compute the correct font-size for the first-letter if it has an initial letter height set.
     3462    RenderObject* paragraph = firstLetterContainer->isRenderBlockFlow() ? firstLetterContainer : firstLetterContainer->containingBlock();
     3463    if (pseudoStyle->initialLetterHeight() >= 1 && pseudoStyle->fontMetrics().hasCapHeight() && paragraph->style().fontMetrics().hasCapHeight()) {
     3464        // FIXME: For ideographic baselines, we want to go from line edge to line edge. This is equivalent to (N-1)*line-height + the font height.
     3465        // We don't yet support ideographic baselines.
     3466        // For an N-line first-letter and for alphabetic baselines, the cap-height of the first letter needs to equal (N-1)*line-height of paragraph lines + cap-height of the paragraph
     3467        // Mathematically we can't rely on font-size, since font().height() doesn't necessarily match. For reliability, the best approach is simply to
     3468        // compare the final measured cap-heights of the two fonts in order to get to the closest possible value.
     3469        pseudoStyle->setLineBoxContain(LineBoxContainInitialLetter);
     3470        int lineHeight = paragraph->style().computedLineHeight();
     3471       
     3472        // Set the font to be one line too big and then ratchet back to get to a precise fit. We can't just set the desired font size based off font height metrics
     3473        // because many fonts bake ascent into the font metrics. Therefore we have to look at actual measured cap height values in order to know when we have a good fit.
     3474        FontDescription newFontDescription = pseudoStyle->fontDescription();
     3475        float capRatio = pseudoStyle->fontMetrics().floatCapHeight() / pseudoStyle->fontSize();
     3476        float startingFontSize = ((pseudoStyle->initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight()) / capRatio;
     3477        newFontDescription.setSpecifiedSize(startingFontSize);
     3478        newFontDescription.setComputedSize(startingFontSize);
     3479        pseudoStyle->setFontDescription(newFontDescription);
     3480        pseudoStyle->font().update(pseudoStyle->font().fontSelector());
     3481       
     3482        int desiredCapHeight = (pseudoStyle->initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight();
     3483        int actualCapHeight = pseudoStyle->fontMetrics().capHeight();
     3484        while (actualCapHeight > desiredCapHeight) {
     3485            FontDescription newFontDescription = pseudoStyle->fontDescription();
     3486            newFontDescription.setSpecifiedSize(newFontDescription.specifiedSize() - 1);
     3487            newFontDescription.setComputedSize(newFontDescription.computedSize() -1);
     3488            pseudoStyle->setFontDescription(newFontDescription);
     3489            pseudoStyle->font().update(pseudoStyle->font().fontSelector());
     3490            actualCapHeight = pseudoStyle->fontMetrics().capHeight();
     3491        }
     3492    }
     3493   
    34563494    // Force inline display (except for floating first-letters).
    34573495    pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
  • trunk/Source/WebCore/rendering/RenderBlockFlow.cpp

    r173114 r173217  
    22912291}
    22922292
    2293 LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
     2293LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset)
    22942294{
    22952295    RenderBox& childBox = floatingObject->renderer();
     
    23362336        // fast/block/float/clamped-right-float.html.
    23372337        floatLogicalLeft -= logicalWidthForFloat(floatingObject);
     2338    }
     2339   
     2340    if (childBox.style().styleType() == FIRST_LETTER && childBox.style().initialLetterDrop() > 0) {
     2341        const RenderStyle& style = firstLineStyle();
     2342        const FontMetrics& fontMetrics = style.fontMetrics();
     2343        if (fontMetrics.hasCapHeight()) {
     2344            LayoutUnit heightOfLine = lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
     2345            LayoutUnit beforeMarginBorderPadding = childBox.borderAndPaddingBefore() + childBox.marginBefore();
     2346           
     2347            // Make an adjustment to align with the cap height of a theoretical block line.
     2348            LayoutUnit adjustment = fontMetrics.ascent() + (heightOfLine - fontMetrics.height()) / 2 - fontMetrics.capHeight() - beforeMarginBorderPadding;
     2349            logicalTopOffset += adjustment;
     2350           
     2351            // For sunken and raised caps, we have to make some adjustments. Test if we're sunken or raised (dropHeightDelta will be
     2352            // positive for raised and negative for sunken).
     2353            int dropHeightDelta = childBox.style().initialLetterHeight() - childBox.style().initialLetterDrop();
     2354           
     2355            // If we're sunken, the float needs to shift down but lines still need to avoid it. In order to do that we increase the float's margin.
     2356            if (dropHeightDelta < 0) {
     2357                LayoutUnit marginTopIncrease = -dropHeightDelta * heightOfLine;
     2358                childBox.setMarginBefore(childBox.marginTop() + marginTopIncrease);
     2359            }
     2360           
     2361            // If we're raised, then we actually have to grow the height of the block, since the lines have to be pushed down as though we're placing
     2362            // empty lines beside the first letter.
     2363            if (dropHeightDelta > 0)
     2364                setLogicalHeight(logicalHeight() + dropHeightDelta * heightOfLine);
     2365        }
    23382366    }
    23392367   
  • trunk/Source/WebCore/rendering/RenderBlockFlow.h

    r173114 r173217  
    479479    void removeFloatingObject(RenderBox&);
    480480    void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
    481     LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
     481    LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset);
    482482
    483483    // Called from lineWidth, to position the floats added in the last line.
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r172607 r173217  
    14911491            return;
    14921492        }
    1493 
    1494         if (floats[floatIndex].rect.size() != newSize) {
     1493   
     1494        // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats
     1495        // as dirty.
     1496        if (floats[floatIndex].rect.size() != newSize || (floatingBox->style().styleType() == FIRST_LETTER && floatingBox->style().initialLetterDrop() > 0)) {
    14951497            LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
    14961498            LayoutUnit floatHeight = isHorizontalWritingMode() ? std::max(floats[floatIndex].rect.height(), newSize.height()) : std::max(floats[floatIndex].rect.width(), newSize.width());
  • trunk/Source/WebCore/rendering/RootInlineBox.cpp

    r172317 r173217  
    901901        glyphOverflow->bottom = std::min(glyphOverflow->bottom, std::max(0, glyphOverflow->bottom - boxLineStyle.fontMetrics().descent(baselineType())));
    902902    }
     903   
     904    if (includeInitialLetterForBox(box)) {
     905        // FIXME: Can't use glyph bounds in vertical writing mode because they are garbage.
     906        bool canUseGlyphs = isHorizontal() && glyphOverflow && glyphOverflow->computeBounds;
     907        int letterAscent = baselineType() == AlphabeticBaseline ? boxLineStyle.fontMetrics().capHeight() : (canUseGlyphs ? glyphOverflow->top : boxLineStyle.fontMetrics().ascent(baselineType()));
     908        int letterDescent = canUseGlyphs ? glyphOverflow->bottom : (box.isRootInlineBox() ? 0 : boxLineStyle.fontMetrics().descent(baselineType()));
     909        setAscentAndDescent(ascent, descent, letterAscent, letterDescent, ascentDescentSet);
     910        affectsAscent = letterAscent - box.logicalTop() > 0;
     911        affectsDescent = letterDescent + box.logicalTop() > 0;
     912        if (canUseGlyphs) {
     913            glyphOverflow->top = std::min(glyphOverflow->top, std::max(0, glyphOverflow->top - boxLineStyle.fontMetrics().ascent(baselineType())));
     914            glyphOverflow->bottom = std::min(glyphOverflow->bottom, std::max(0, glyphOverflow->bottom - boxLineStyle.fontMetrics().descent(baselineType())));
     915        }
     916    }
    903917
    904918    if (includeMarginForBox(box)) {
     
    10251039}
    10261040
    1027 bool RootInlineBox::includeMarginForBox(InlineBox& box) const
     1041bool RootInlineBox::includeInitialLetterForBox(InlineBox& box) const
    10281042{
    10291043    if (box.renderer().isReplaced() || (box.renderer().isTextOrLineBreak() && !box.behavesLikeText()))
    10301044        return false;
     1045   
     1046    if (!box.behavesLikeText() && box.isInlineFlowBox() && !toInlineFlowBox(&box)->hasTextChildren())
     1047        return false;
     1048
     1049    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
     1050    return (lineBoxContain & LineBoxContainInitialLetter);
     1051}
     1052
     1053bool RootInlineBox::includeMarginForBox(InlineBox& box) const
     1054{
     1055    if (box.renderer().isReplaced() || (box.renderer().isTextOrLineBreak() && !box.behavesLikeText()))
     1056        return false;
    10311057
    10321058    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
     
    10391065    // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
    10401066    LineBoxContain lineBoxContain = renderer().style().lineBoxContain();
    1041     return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
     1067    return isHorizontal() && ((lineBoxContain & LineBoxContainGlyphs) || (lineBoxContain & LineBoxContainInitialLetter));
    10421068}
    10431069
  • trunk/Source/WebCore/rendering/RootInlineBox.h

    r173114 r173217  
    196196    bool includeFontForBox(InlineBox&) const;
    197197    bool includeGlyphsForBox(InlineBox&) const;
     198    bool includeInitialLetterForBox(InlineBox&) const;
    198199    bool includeMarginForBox(InlineBox&) const;
    199200
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r172656 r173217  
    435435            || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
    436436            || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
     437            || rareNonInheritedData->m_initialLetter != other->rareNonInheritedData->m_initialLetter
    437438            || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
    438439            return true;
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r172849 r173217  
    10831083    LineBoxContain lineBoxContain() const { return rareInheritedData->m_lineBoxContain; }
    10841084    const LineClampValue& lineClamp() const { return rareNonInheritedData->lineClamp; }
     1085    const IntSize& initialLetter() const { return rareNonInheritedData->m_initialLetter; }
     1086    int initialLetterDrop() const { return initialLetter().width(); }
     1087    int initialLetterHeight() const { return initialLetter().height(); }
     1088
    10851089#if ENABLE(CSS_SCROLL_SNAP)
    10861090    ScrollSnapType scrollSnapType() const { return static_cast<ScrollSnapType>(rareNonInheritedData->m_scrollSnapType); }
     
    16131617    void setLineBoxContain(LineBoxContain c) { SET_VAR(rareInheritedData, m_lineBoxContain, c); }
    16141618    void setLineClamp(LineClampValue c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
     1619   
     1620    void setInitialLetter(const IntSize& size) { SET_VAR(rareNonInheritedData, m_initialLetter, size); }
     1621   
    16151622#if ENABLE(CSS_SCROLL_SNAP)
    16161623    void setScrollSnapType(ScrollSnapType type) { SET_VAR(rareNonInheritedData, m_scrollSnapType, type); }
     
    19831990
    19841991    // Keep these at the end.
     1992    static IntSize initialInitialLetter() { return IntSize(); }
    19851993    static LineClampValue initialLineClamp() { return LineClampValue(); }
    19861994    static ETextSecurity initialTextSecurity() { return TSNONE; }
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp

    r172192 r173217  
    4242    , m_perspectiveOriginY(RenderStyle::initialPerspectiveOriginY())
    4343    , lineClamp(RenderStyle::initialLineClamp())
     44    , m_initialLetter(RenderStyle::initialInitialLetter())
    4445    , m_deprecatedFlexibleBox(StyleDeprecatedFlexibleBoxData::create())
    4546    , m_flexibleBox(StyleFlexibleBoxData::create())
     
    113114    , m_perspectiveOriginY(o.m_perspectiveOriginY)
    114115    , lineClamp(o.lineClamp)
     116    , m_initialLetter(o.m_initialLetter)
    115117    , m_deprecatedFlexibleBox(o.m_deprecatedFlexibleBox)
    116118    , m_flexibleBox(o.m_flexibleBox)
     
    206208        && m_perspectiveOriginY == o.m_perspectiveOriginY
    207209        && lineClamp == o.lineClamp
     210        && m_initialLetter == o.m_initialLetter
    208211#if ENABLE(DASHBOARD_SUPPORT)
    209212        && m_dashboardRegions == o.m_dashboardRegions
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h

    r172192 r173217  
    109109
    110110    LineClampValue lineClamp; // An Apple extension.
     111   
     112    IntSize m_initialLetter;
     113
    111114#if ENABLE(DASHBOARD_SUPPORT)
    112115    Vector<StyleDashboardRegion> m_dashboardRegions;
Note: See TracChangeset for help on using the changeset viewer.