void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); Length lineHeight; if (primitiveValue->getValueID() == CSSValueNormal) { lineHeight = RenderStyle::initialLineHeight(); } else if (primitiveValue->isLength()) { lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData()); } else if (primitiveValue->isPercentage()) { lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed); } else if (primitiveValue->isNumber()) { lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); } else if (primitiveValue->isCalculated()) { Length length = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData())); lineHeight = Length(valueForLength(length, state.style()->fontSize()), Fixed); } else { return; } state.style()->setLineHeight(lineHeight); }
static void updateFromStyle(Vector<LayoutUnit>& snapOffsets, const RenderStyle& style, ScrollEventAxis axis, LayoutUnit viewSize, LayoutUnit scrollSize, Vector<LayoutUnit>& snapOffsetSubsequence) { std::sort(snapOffsetSubsequence.begin(), snapOffsetSubsequence.end()); if (snapOffsetSubsequence.isEmpty()) snapOffsetSubsequence.append(0); // Always put a snap point on the zero offset. snapOffsets.append(0); auto* points = (axis == ScrollEventAxis::Horizontal) ? style.scrollSnapPointsX() : style.scrollSnapPointsY(); bool hasRepeat = points ? points->hasRepeat : false; LayoutUnit repeatOffset = points ? valueForLength(points->repeatOffset, viewSize) : LayoutUnit(); LayoutUnit destinationOffset = destinationOffsetForViewSize(axis, style.scrollSnapDestination(), viewSize); LayoutUnit curSnapPositionShift = 0; LayoutUnit maxScrollOffset = scrollSize - viewSize; LayoutUnit lastSnapPosition = curSnapPositionShift; do { for (auto& snapPosition : snapOffsetSubsequence) { LayoutUnit potentialSnapPosition = curSnapPositionShift + snapPosition - destinationOffset; if (potentialSnapPosition < 0) continue; if (potentialSnapPosition >= maxScrollOffset) break; // Don't add another zero offset value. if (potentialSnapPosition) snapOffsets.append(potentialSnapPosition); lastSnapPosition = potentialSnapPosition + destinationOffset; } curSnapPositionShift = lastSnapPosition + repeatOffset; } while (hasRepeat && curSnapPositionShift < maxScrollOffset); // Always put a snap point on the maximum scroll offset. // Not a part of the spec, but necessary to prevent unreachable content when snapping. if (snapOffsets.last() != maxScrollOffset) snapOffsets.append(maxScrollOffset); }
float SVGLengthContext::valueForLength(const Length& length, const ComputedStyle& style, SVGLengthMode mode) const { return valueForLength(length, style.effectiveZoom(), mode); }
float SVGLengthContext::valueForLength(const UnzoomedLength& unzoomedLength, SVGLengthMode mode) const { return valueForLength(unzoomedLength.length(), 1, mode); }
int intValueForLength(const Length& length, LayoutUnit maximumValue) { return static_cast<int>(valueForLength(length, maximumValue)); }
static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize) { return valueForLength(length, maxSize) * (length.isFixed() ? scale : 1); }
static LayoutUnit destinationOffsetForViewSize(ScrollEventAxis axis, const LengthSize& destination, LayoutUnit viewSize) { const Length& dimension = (axis == ScrollEventAxis::Horizontal) ? destination.width() : destination.height(); return valueForLength(dimension, viewSize); }
void FixedTableLayout::layout() { int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection(); unsigned nEffCols = m_table->numEffCols(); // FIXME: It is possible to be called without having properly updated our internal representation. // This means that our preferred logical widths were not recomputed as expected. if (nEffCols != m_width.size()) { calcWidthArray(); // FIXME: Table layout shouldn't modify our table structure (but does due to columns and column-groups). nEffCols = m_table->numEffCols(); } Vector<int> calcWidth(nEffCols, 0); unsigned numAuto = 0; unsigned autoSpan = 0; int totalFixedWidth = 0; int totalPercentWidth = 0; float totalPercent = 0; // Compute requirements and try to satisfy fixed and percent widths. // Percentages are of the table's width, so for example // for a table width of 100px with columns (40px, 10%), the 10% compute // to 10px here, and will scale up to 20px in the final (80px, 20px). for (unsigned i = 0; i < nEffCols; i++) { if (m_width[i].isFixed()) { calcWidth[i] = m_width[i].value(); totalFixedWidth += calcWidth[i]; } else if (m_width[i].isPercentNotCalculated()) { calcWidth[i] = valueForLength(m_width[i], tableLogicalWidth); totalPercentWidth += calcWidth[i]; totalPercent += m_width[i].percent(); } else if (m_width[i].isAuto()) { numAuto++; autoSpan += m_table->spanOfEffCol(i); } } int hspacing = m_table->hBorderSpacing(); int totalWidth = totalFixedWidth + totalPercentWidth; if (!numAuto || totalWidth > tableLogicalWidth) { // If there are no auto columns, or if the total is too wide, take // what we have and scale it to fit as necessary. if (totalWidth != tableLogicalWidth) { // Fixed widths only scale up if (totalFixedWidth && totalWidth < tableLogicalWidth) { totalFixedWidth = 0; for (unsigned i = 0; i < nEffCols; i++) { if (m_width[i].isFixed()) { calcWidth[i] = calcWidth[i] * tableLogicalWidth / totalWidth; totalFixedWidth += calcWidth[i]; } } } if (totalPercent) { totalPercentWidth = 0; for (unsigned i = 0; i < nEffCols; i++) { if (m_width[i].isPercentNotCalculated()) { calcWidth[i] = m_width[i].percent() * (tableLogicalWidth - totalFixedWidth) / totalPercent; totalPercentWidth += calcWidth[i]; } } } totalWidth = totalFixedWidth + totalPercentWidth; } } else { // Divide the remaining width among the auto columns. ASSERT(autoSpan >= numAuto); int remainingWidth = tableLogicalWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto); int lastAuto = 0; for (unsigned i = 0; i < nEffCols; i++) { if (m_width[i].isAuto()) { unsigned span = m_table->spanOfEffCol(i); int w = remainingWidth * span / autoSpan; calcWidth[i] = w + hspacing * (span - 1); remainingWidth -= w; if (!remainingWidth) break; lastAuto = i; numAuto--; ASSERT(autoSpan >= span); autoSpan -= span; } } // Last one gets the remainder. if (remainingWidth) calcWidth[lastAuto] += remainingWidth; totalWidth = tableLogicalWidth; } if (totalWidth < tableLogicalWidth) { // Spread extra space over columns. int remainingWidth = tableLogicalWidth - totalWidth; int total = nEffCols; while (total) { int w = remainingWidth / total; remainingWidth -= w; calcWidth[--total] += w; } if (nEffCols > 0) calcWidth[nEffCols - 1] += remainingWidth; } int pos = 0; for (unsigned i = 0; i < nEffCols; i++) { m_table->setColumnPosition(i, pos); pos += calcWidth[i] + hspacing; } int colPositionsSize = m_table->columnPositions().size(); if (colPositionsSize > 0) m_table->setColumnPosition(colPositionsSize - 1, pos); }
int intValueForLength(const Length& length, LayoutUnit maximumValue, RenderView* renderView, bool roundPercentages) { return static_cast<int>(valueForLength(length, maximumValue, renderView, roundPercentages)); }
void updateSnapOffsetsForScrollableArea(ScrollableArea& scrollableArea, HTMLElement& scrollingElement, const RenderBox& scrollingElementBox, const RenderStyle& scrollingElementStyle) { if (scrollingElementStyle.scrollSnapType() == ScrollSnapType::None) { scrollableArea.clearHorizontalSnapOffsets(); scrollableArea.clearVerticalSnapOffsets(); return; } LayoutRect viewSize = scrollingElementBox.contentBoxRect(); LayoutUnit viewWidth = viewSize.width(); LayoutUnit viewHeight = viewSize.height(); LayoutUnit scrollWidth = scrollingElementBox.scrollWidth(); LayoutUnit scrollHeight = scrollingElementBox.scrollHeight(); bool canComputeHorizontalOffsets = scrollWidth > 0 && viewWidth > 0 && viewWidth < scrollWidth; bool canComputeVerticalOffsets = scrollHeight > 0 && viewHeight > 0 && viewHeight < scrollHeight; if (!canComputeHorizontalOffsets) scrollableArea.clearHorizontalSnapOffsets(); if (!canComputeVerticalOffsets) scrollableArea.clearVerticalSnapOffsets(); if (!canComputeHorizontalOffsets && !canComputeVerticalOffsets) return; Vector<LayoutUnit> horizontalSnapOffsetSubsequence; Vector<LayoutUnit> verticalSnapOffsetSubsequence; bool scrollSnapPointsXUsesElements = styleUsesElements(ScrollEventAxis::Horizontal, scrollingElementStyle); bool scrollSnapPointsYUsesElements = styleUsesElements(ScrollEventAxis::Vertical, scrollingElementStyle); if (scrollSnapPointsXUsesElements || scrollSnapPointsYUsesElements) { bool shouldAddHorizontalChildOffsets = scrollSnapPointsXUsesElements && canComputeHorizontalOffsets; bool shouldAddVerticalChildOffsets = scrollSnapPointsYUsesElements && canComputeVerticalOffsets; appendChildSnapOffsets(scrollingElement, shouldAddHorizontalChildOffsets, horizontalSnapOffsetSubsequence, shouldAddVerticalChildOffsets, verticalSnapOffsetSubsequence); } if (scrollingElementStyle.scrollSnapPointsX() && !scrollSnapPointsXUsesElements && canComputeHorizontalOffsets) { for (auto& snapLength : scrollingElementStyle.scrollSnapPointsX()->offsets) horizontalSnapOffsetSubsequence.append(valueForLength(snapLength, viewWidth)); } if (scrollingElementStyle.scrollSnapPointsY() && !scrollSnapPointsYUsesElements && canComputeVerticalOffsets) { for (auto& snapLength : scrollingElementStyle.scrollSnapPointsY()->offsets) verticalSnapOffsetSubsequence.append(valueForLength(snapLength, viewHeight)); } if (canComputeHorizontalOffsets) { auto horizontalSnapOffsets = std::make_unique<Vector<LayoutUnit>>(); updateFromStyle(*horizontalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Horizontal, viewWidth, scrollWidth, horizontalSnapOffsetSubsequence); if (horizontalSnapOffsets->isEmpty()) scrollableArea.clearHorizontalSnapOffsets(); else scrollableArea.setHorizontalSnapOffsets(WTF::move(horizontalSnapOffsets)); } if (canComputeVerticalOffsets) { auto verticalSnapOffsets = std::make_unique<Vector<LayoutUnit>>(); updateFromStyle(*verticalSnapOffsets, scrollingElementStyle, ScrollEventAxis::Vertical, viewHeight, scrollHeight, verticalSnapOffsetSubsequence); if (verticalSnapOffsets->isEmpty()) scrollableArea.clearVerticalSnapOffsets(); else scrollableArea.setVerticalSnapOffsets(WTF::move(verticalSnapOffsets)); } }
static int computeEdgeSlice(const Length& slice, LayoutUnit maximum) { return std::min<int>(maximum, valueForLength(slice, maximum)); }
void LayoutReplaced::computePositionedLogicalHeight( LogicalExtentComputedValues& computedValues) const { // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements" // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height> // (block-style-comments in this function correspond to text from the spec and // the numbers correspond to numbers in spec) // We don't use containingBlock(), since we may be positioned by an enclosing // relpositioned inline. const LayoutBoxModelObject* containerBlock = toLayoutBoxModelObject(container()); const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock); const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false); // Variables to solve. Length marginBefore = style()->marginBefore(); Length marginAfter = style()->marginAfter(); LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before; LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after; Length logicalTop = style()->logicalTop(); Length logicalBottom = style()->logicalBottom(); // --------------------------------------------------------------------------- // 1. The used value of 'height' is determined as for inline replaced // elements. // --------------------------------------------------------------------------- // NOTE: This value of height is final in that the min/max height calculations // are dealt with in computeReplacedHeight(). This means that the steps to // produce correct max/min in the non-replaced version, are not necessary. computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight(); const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent; // --------------------------------------------------------------------------- // 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' with the // element's static position. // --------------------------------------------------------------------------- // see FIXME 1 computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock); // --------------------------------------------------------------------------- // 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or // 'margin-bottom' with '0'. // --------------------------------------------------------------------------- // FIXME: The spec. says that this step should only be taken when bottom is // auto, but if only top is auto, this makes step 4 impossible. if (logicalTop.isAuto() || logicalBottom.isAuto()) { if (marginBefore.isAuto()) marginBefore.setValue(Fixed, 0); if (marginAfter.isAuto()) marginAfter.setValue(Fixed, 0); } // --------------------------------------------------------------------------- // 4. If at this point both 'margin-top' and 'margin-bottom' are still 'auto', // solve the equation under the extra constraint that the two margins must // get equal values. // --------------------------------------------------------------------------- LayoutUnit logicalTopValue; LayoutUnit logicalBottomValue; if (marginBefore.isAuto() && marginAfter.isAuto()) { // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined. ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto())); logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue); // NOTE: This may result in negative values. marginBeforeAlias = difference / 2; // split the difference marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences // ------------------------------------------------------------------------- // 5. If at this point there is only one 'auto' left, solve the equation // for that value. // ------------------------------------------------------------------------- } else if (logicalTop.isAuto()) { marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth); marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth); logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); // Solve for 'top' logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias); } else if (logicalBottom.isAuto()) { marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth); marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth); logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); // Solve for 'bottom' // NOTE: It is not necessary to solve for 'bottom' because we don't ever // use the value. } else if (marginBefore.isAuto()) { marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth); logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); // Solve for 'margin-top' marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias); } else if (marginAfter.isAuto()) { marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth); logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight); // Solve for 'margin-bottom' marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias); } else { // Nothing is 'auto', just calculate the values. marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth); marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth); logicalTopValue = valueForLength(logicalTop, containerLogicalHeight); // NOTE: It is not necessary to solve for 'bottom' because we don't ever // use the value. } // --------------------------------------------------------------------------- // 6. If at this point the values are over-constrained, ignore the value for // 'bottom' and solve for that value. // --------------------------------------------------------------------------- // NOTE: It is not necessary to do this step because we don't end up using the // value of 'bottom' regardless of whether the values are over-constrained or // not. // Use computed values to calculate the vertical position. LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias; computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight); computedValues.m_position = logicalTopPos; }
void LayoutReplaced::computePositionedLogicalWidth( LogicalExtentComputedValues& computedValues) const { // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements" // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width> // (block-style-comments in this function correspond to text from the spec and // the numbers correspond to numbers in spec). // We don't use containingBlock(), since we may be positioned by an enclosing // relative positioned inline. const LayoutBoxModelObject* containerBlock = toLayoutBoxModelObject(container()); const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock); const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false); // To match WinIE, in quirks mode use the parent's 'direction' property // instead of the the container block's. TextDirection containerDirection = containerBlock->style()->direction(); // Variables to solve. bool isHorizontal = isHorizontalWritingMode(); Length logicalLeft = style()->logicalLeft(); Length logicalRight = style()->logicalRight(); Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop(); Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom(); LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end; LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start; // --------------------------------------------------------------------------- // 1. The used value of 'width' is determined as for inline replaced // elements. // --------------------------------------------------------------------------- // NOTE: This value of width is final in that the min/max width calculations // are dealt with in computeReplacedWidth(). This means that the steps to // produce correct max/min in the non-replaced version, are not necessary. computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth(); const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent; // --------------------------------------------------------------------------- // 2. If both 'left' and 'right' have the value 'auto', then if 'direction' // of the containing block is 'ltr', set 'left' to the static position; // else if 'direction' is 'rtl', set 'right' to the static position. // --------------------------------------------------------------------------- // see FIXME 1 computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth); // --------------------------------------------------------------------------- // 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left' // or 'margin-right' with '0'. // --------------------------------------------------------------------------- if (logicalLeft.isAuto() || logicalRight.isAuto()) { if (marginLogicalLeft.isAuto()) marginLogicalLeft.setValue(Fixed, 0); if (marginLogicalRight.isAuto()) marginLogicalRight.setValue(Fixed, 0); } // --------------------------------------------------------------------------- // 4. If at this point both 'margin-left' and 'margin-right' are still 'auto', // solve the equation under the extra constraint that the two margins must // get equal values, unless this would make them negative, in which case // when the direction of the containing block is 'ltr' ('rtl'), set // 'margin-left' ('margin-right') to zero and solve for 'margin-right' // ('margin-left'). // --------------------------------------------------------------------------- LayoutUnit logicalLeftValue; LayoutUnit logicalRightValue; if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { // 'left' and 'right' cannot be 'auto' due to step 3 ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto())); logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue); if (difference > LayoutUnit()) { marginLogicalLeftAlias = difference / 2; // split the difference marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences } else { // Use the containing block's direction rather than the parent block's // per CSS 2.1 reference test abspos-replaced-width-margin-000. if (containerDirection == LTR) { marginLogicalLeftAlias = LayoutUnit(); marginLogicalRightAlias = difference; // will be negative } else { marginLogicalLeftAlias = difference; // will be negative marginLogicalRightAlias = LayoutUnit(); } } // ------------------------------------------------------------------------- // 5. If at this point there is an 'auto' left, solve the equation for that // value. // ------------------------------------------------------------------------- } else if (logicalLeft.isAuto()) { marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth); logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); // Solve for 'left' logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias); } else if (logicalRight.isAuto()) { marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth); logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); // Solve for 'right' logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias); } else if (marginLogicalLeft.isAuto()) { marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth); logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); // Solve for 'margin-left' marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias); } else if (marginLogicalRight.isAuto()) { marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); // Solve for 'margin-right' marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias); } else { // Nothing is 'auto', just calculate the values. marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth); marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth); logicalRightValue = valueForLength(logicalRight, containerLogicalWidth); logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth); // If the containing block is right-to-left, then push the left position as // far to the right as possible if (containerDirection == RTL) { int totalLogicalWidth = (computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias) .toInt(); logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue); } } // --------------------------------------------------------------------------- // 6. If at this point the values are over-constrained, ignore the value for // either 'left' (in case the 'direction' property of the containing block // is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that // value. // --------------------------------------------------------------------------- // NOTE: Constraints imposed by the width of the containing block and its // content have already been accounted for above. // // FIXME: Deal with differing writing modes here. Our offset needs to be in // the containing block's coordinate space, so that // can make the result here rather complicated to compute. // // Use computed values to calculate the horizontal position. // // FIXME: This hack is needed to calculate the logical left position for a // 'rtl' relatively positioned, inline containing block because right now, it // is using the logical left position of the first line box when really it // should use the last line box. When this is fixed elsewhere, this block // should be removed. if (containerBlock->isLayoutInline() && !containerBlock->style()->isLeftToRightDirection()) { const LayoutInline* flow = toLayoutInline(containerBlock); InlineFlowBox* firstLine = flow->firstLineBox(); InlineFlowBox* lastLine = flow->lastLineBox(); if (firstLine && lastLine && firstLine != lastLine) { computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()); return; } } LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias; computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth); computedValues.m_position = logicalLeftPos; }
float SVGLengthContext::valueForLength(const Length& length, const ComputedStyle& style, float dimension) { return valueForLength(length, style.effectiveZoom(), dimension); }
CSSValueImpl *CSSComputedStyleDeclarationImpl::getPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const { NodeImpl *node = m_node.handle(); if (!node) return 0; // Make sure our layout is up to date before we allow a query on these attributes. DocumentImpl* docimpl = node->getDocument(); if (docimpl && updateLayout) docimpl->updateLayout(); RenderObject *renderer = node->renderer(); if (!renderer) return 0; RenderStyle *style = renderer->style(); if (!style) return 0; switch (propertyID) { case CSS_PROP_BACKGROUND_COLOR: return new CSSPrimitiveValueImpl(style->backgroundColor().rgb()); case CSS_PROP_BACKGROUND_IMAGE: if (style->backgroundImage()) return new CSSPrimitiveValueImpl(style->backgroundImage()->url(), CSSPrimitiveValue::CSS_URI); return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CSS_PROP_BACKGROUND_REPEAT: switch (style->backgroundRepeat()) { case khtml::REPEAT: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT); case khtml::REPEAT_X: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_X); case khtml::REPEAT_Y: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_Y); case khtml::NO_REPEAT: return new CSSPrimitiveValueImpl(CSS_VAL_NO_REPEAT); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_BACKGROUND_ATTACHMENT: if (style->backgroundAttachment()) return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); else return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); case CSS_PROP_BACKGROUND_POSITION: { DOMString string; Length length(style->backgroundXPosition()); if (length.isPercent()) string = numberAsString(length.length()) + "%"; else string = numberAsString(length.minWidth(renderer->contentWidth())); string += " "; length = style->backgroundYPosition(); if (length.isPercent()) string += numberAsString(length.length()) + "%"; else string += numberAsString(length.minWidth(renderer->contentWidth())); return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_BACKGROUND_POSITION_X: return valueForLength(style->backgroundXPosition()); case CSS_PROP_BACKGROUND_POSITION_Y: return valueForLength(style->backgroundYPosition()); #ifndef KHTML_NO_XBL case CSS_PROP__KHTML_BINDING: // FIXME: unimplemented break; #endif case CSS_PROP_BORDER_COLLAPSE: if (style->borderCollapse()) return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE); else return new CSSPrimitiveValueImpl(CSS_VAL_SEPARATE); case CSS_PROP_BORDER_SPACING: { QString string(numberAsString(style->horizontalBorderSpacing()) + "px " + numberAsString(style->verticalBorderSpacing()) + "px"); return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING); } case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: return new CSSPrimitiveValueImpl(style->horizontalBorderSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: return new CSSPrimitiveValueImpl(style->verticalBorderSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BORDER_TOP_COLOR: return new CSSPrimitiveValueImpl(style->borderLeftColor().rgb()); case CSS_PROP_BORDER_RIGHT_COLOR: return new CSSPrimitiveValueImpl(style->borderRightColor().rgb()); case CSS_PROP_BORDER_BOTTOM_COLOR: return new CSSPrimitiveValueImpl(style->borderBottomColor().rgb()); case CSS_PROP_BORDER_LEFT_COLOR: return new CSSPrimitiveValueImpl(style->borderLeftColor().rgb()); case CSS_PROP_BORDER_TOP_STYLE: return valueForBorderStyle(style->borderTopStyle()); case CSS_PROP_BORDER_RIGHT_STYLE: return valueForBorderStyle(style->borderRightStyle()); case CSS_PROP_BORDER_BOTTOM_STYLE: return valueForBorderStyle(style->borderBottomStyle()); case CSS_PROP_BORDER_LEFT_STYLE: return valueForBorderStyle(style->borderLeftStyle()); case CSS_PROP_BORDER_TOP_WIDTH: return new CSSPrimitiveValueImpl(style->borderTopWidth(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BORDER_RIGHT_WIDTH: return new CSSPrimitiveValueImpl(style->borderRightWidth(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BORDER_BOTTOM_WIDTH: return new CSSPrimitiveValueImpl(style->borderBottomWidth(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BORDER_LEFT_WIDTH: return new CSSPrimitiveValueImpl(style->borderLeftWidth(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BOTTOM: return getPositionOffsetValue(renderer, CSS_PROP_BOTTOM); case CSS_PROP__KHTML_BOX_ALIGN: switch (style->boxAlign()) { case khtml::BSTRETCH: return new CSSPrimitiveValueImpl(CSS_VAL_STRETCH); case khtml::BSTART: return new CSSPrimitiveValueImpl(CSS_VAL_START); case khtml::BCENTER: return new CSSPrimitiveValueImpl(CSS_VAL_CENTER); case khtml::BEND: return new CSSPrimitiveValueImpl(CSS_VAL_END); case khtml::BBASELINE: return new CSSPrimitiveValueImpl(CSS_VAL_BASELINE); case khtml::BJUSTIFY: break; // not allowed } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_BOX_DIRECTION: switch (style->boxDirection()) { case khtml::BNORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::BREVERSE: return new CSSPrimitiveValueImpl(CSS_VAL_REVERSE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_BOX_FLEX: return new CSSPrimitiveValueImpl(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP__KHTML_BOX_FLEX_GROUP: return new CSSPrimitiveValueImpl(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP__KHTML_BOX_LINES: switch (style->boxLines()) { case khtml::SINGLE: return new CSSPrimitiveValueImpl(CSS_VAL_SINGLE); case khtml::MULTIPLE: return new CSSPrimitiveValueImpl(CSS_VAL_MULTIPLE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_BOX_ORDINAL_GROUP: return new CSSPrimitiveValueImpl(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP__KHTML_BOX_ORIENT: switch (style->boxOrient()) { case khtml::HORIZONTAL: return new CSSPrimitiveValueImpl(CSS_VAL_HORIZONTAL); case khtml::VERTICAL: return new CSSPrimitiveValueImpl(CSS_VAL_VERTICAL); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_BOX_PACK: switch (style->boxPack()) { case khtml::BSTART: return new CSSPrimitiveValueImpl(CSS_VAL_START); case khtml::BEND: return new CSSPrimitiveValueImpl(CSS_VAL_END); case khtml::BCENTER: return new CSSPrimitiveValueImpl(CSS_VAL_CENTER); case khtml::BJUSTIFY: return new CSSPrimitiveValueImpl(CSS_VAL_JUSTIFY); case khtml::BSTRETCH: case khtml::BBASELINE: break; // not allowed } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_CAPTION_SIDE: switch (style->captionSide()) { case khtml::CAPLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case khtml::CAPRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case khtml::CAPTOP: return new CSSPrimitiveValueImpl(CSS_VAL_TOP); case khtml::CAPBOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_CLEAR: switch (style->clear()) { case khtml::CNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case khtml::CLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case khtml::CRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case khtml::CBOTH: return new CSSPrimitiveValueImpl(CSS_VAL_BOTH); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_CLIP: // FIXME: unimplemented break; case CSS_PROP_COLOR: return new CSSPrimitiveValueImpl(style->color().rgb()); case CSS_PROP_CONTENT: // FIXME: unimplemented break; case CSS_PROP_COUNTER_INCREMENT: // FIXME: unimplemented break; case CSS_PROP_COUNTER_RESET: // FIXME: unimplemented break; case CSS_PROP_CURSOR: switch (style->cursor()) { case khtml::CURSOR_AUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::CURSOR_CROSS: return new CSSPrimitiveValueImpl(CSS_VAL_CROSSHAIR); case khtml::CURSOR_DEFAULT: return new CSSPrimitiveValueImpl(CSS_VAL_DEFAULT); case khtml::CURSOR_POINTER: return new CSSPrimitiveValueImpl(CSS_VAL_POINTER); case khtml::CURSOR_MOVE: return new CSSPrimitiveValueImpl(CSS_VAL_MOVE); case khtml::CURSOR_E_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_E_RESIZE); case khtml::CURSOR_NE_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_NE_RESIZE); case khtml::CURSOR_NW_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_NW_RESIZE); case khtml::CURSOR_N_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_N_RESIZE); case khtml::CURSOR_SE_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_SE_RESIZE); case khtml::CURSOR_SW_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_SW_RESIZE); case khtml::CURSOR_S_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_S_RESIZE); case khtml::CURSOR_W_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_W_RESIZE); case khtml::CURSOR_TEXT: return new CSSPrimitiveValueImpl(CSS_VAL_TEXT); case khtml::CURSOR_WAIT: return new CSSPrimitiveValueImpl(CSS_VAL_WAIT); case khtml::CURSOR_HELP: return new CSSPrimitiveValueImpl(CSS_VAL_HELP); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_DIRECTION: switch (style->direction()) { case khtml::LTR: return new CSSPrimitiveValueImpl(CSS_VAL_LTR); case khtml::RTL: return new CSSPrimitiveValueImpl(CSS_VAL_RTL); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_DISPLAY: switch (style->display()) { case khtml::INLINE: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE); case khtml::BLOCK: return new CSSPrimitiveValueImpl(CSS_VAL_BLOCK); case khtml::LIST_ITEM: return new CSSPrimitiveValueImpl(CSS_VAL_LIST_ITEM); case khtml::RUN_IN: return new CSSPrimitiveValueImpl(CSS_VAL_RUN_IN); case khtml::COMPACT: return new CSSPrimitiveValueImpl(CSS_VAL_COMPACT); case khtml::INLINE_BLOCK: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_BLOCK); case khtml::TABLE: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE); case khtml::INLINE_TABLE: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_TABLE); case khtml::TABLE_ROW_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW_GROUP); case khtml::TABLE_HEADER_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_HEADER_GROUP); case khtml::TABLE_FOOTER_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_FOOTER_GROUP); case khtml::TABLE_ROW: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW); case khtml::TABLE_COLUMN_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN_GROUP); case khtml::TABLE_COLUMN: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN); case khtml::TABLE_CELL: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CELL); case khtml::TABLE_CAPTION: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CAPTION); case khtml::BOX: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_BOX); case khtml::INLINE_BOX: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_INLINE_BOX); case khtml::NONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_EMPTY_CELLS: switch (style->emptyCells()) { case khtml::SHOW: return new CSSPrimitiveValueImpl(CSS_VAL_SHOW); case khtml::HIDE: return new CSSPrimitiveValueImpl(CSS_VAL_HIDE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_FLOAT: switch (style->floating()) { case khtml::FNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case khtml::FLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case khtml::FRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_FONT_FAMILY: { FontDef def = style->htmlFont().getFontDef(); return new CSSPrimitiveValueImpl(def.firstFamily().family().domString(), CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_FONT_SIZE: { FontDef def = style->htmlFont().getFontDef(); return new CSSPrimitiveValueImpl(def.specifiedSize, CSSPrimitiveValue::CSS_PX); } case CSS_PROP_FONT_STRETCH: // FIXME: unimplemented break; case CSS_PROP_FONT_STYLE: { // FIXME: handle oblique? FontDef def = style->htmlFont().getFontDef(); if (def.italic) return new CSSPrimitiveValueImpl(CSS_VAL_ITALIC); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_FONT_VARIANT: { FontDef def = style->htmlFont().getFontDef(); if (def.smallCaps) return new CSSPrimitiveValueImpl(CSS_VAL_SMALL_CAPS); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_FONT_WEIGHT: { // FIXME: this does not reflect the full range of weights // that can be expressed with CSS FontDef def = style->htmlFont().getFontDef(); if (def.weight == QFont::Bold) return new CSSPrimitiveValueImpl(CSS_VAL_BOLD); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_HEIGHT: return new CSSPrimitiveValueImpl(renderer->contentHeight(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_LEFT: return getPositionOffsetValue(renderer, CSS_PROP_LEFT); case CSS_PROP_LETTER_SPACING: if (style->letterSpacing() == 0) return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); return new CSSPrimitiveValueImpl(style->letterSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP__APPLE_LINE_CLAMP: return new CSSPrimitiveValueImpl(style->lineClamp(), CSSPrimitiveValue::CSS_PERCENTAGE); case CSS_PROP_LINE_HEIGHT: { Length length(style->lineHeight()); if (length.value < 0) return new CSSPrimitiveValueImpl(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. float fontSize = style->htmlFont().getFontDef().specifiedSize; return new CSSPrimitiveValueImpl((int)(length.length() * fontSize) / 100, CSSPrimitiveValue::CSS_PX); } else { return new CSSPrimitiveValueImpl(length.length(), CSSPrimitiveValue::CSS_PX); } } case CSS_PROP_LIST_STYLE_IMAGE: if (style->listStyleImage()) return new CSSPrimitiveValueImpl(style->listStyleImage()->url(), CSSPrimitiveValue::CSS_URI); return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CSS_PROP_LIST_STYLE_POSITION: switch (style->listStylePosition()) { case khtml::OUTSIDE: return new CSSPrimitiveValueImpl(CSS_VAL_OUTSIDE); case khtml::INSIDE: return new CSSPrimitiveValueImpl(CSS_VAL_INSIDE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_LIST_STYLE_TYPE: switch (style->listStyleType()) { case khtml::LNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case khtml::DISC: return new CSSPrimitiveValueImpl(CSS_VAL_DISC); case khtml::CIRCLE: return new CSSPrimitiveValueImpl(CSS_VAL_CIRCLE); case khtml::SQUARE: return new CSSPrimitiveValueImpl(CSS_VAL_SQUARE); case khtml::LDECIMAL: return new CSSPrimitiveValueImpl(CSS_VAL_DECIMAL); case khtml::DECIMAL_LEADING_ZERO: return new CSSPrimitiveValueImpl(CSS_VAL_DECIMAL_LEADING_ZERO); case khtml::LOWER_ROMAN: return new CSSPrimitiveValueImpl(CSS_VAL_LOWER_ROMAN); case khtml::UPPER_ROMAN: return new CSSPrimitiveValueImpl(CSS_VAL_UPPER_ROMAN); case khtml::LOWER_GREEK: return new CSSPrimitiveValueImpl(CSS_VAL_LOWER_GREEK); case khtml::LOWER_ALPHA: return new CSSPrimitiveValueImpl(CSS_VAL_LOWER_ALPHA); case khtml::LOWER_LATIN: return new CSSPrimitiveValueImpl(CSS_VAL_LOWER_LATIN); case khtml::UPPER_ALPHA: return new CSSPrimitiveValueImpl(CSS_VAL_UPPER_ALPHA); case khtml::UPPER_LATIN: return new CSSPrimitiveValueImpl(CSS_VAL_UPPER_LATIN); case khtml::HEBREW: return new CSSPrimitiveValueImpl(CSS_VAL_HEBREW); case khtml::ARMENIAN: return new CSSPrimitiveValueImpl(CSS_VAL_ARMENIAN); case khtml::GEORGIAN: return new CSSPrimitiveValueImpl(CSS_VAL_GEORGIAN); case khtml::CJK_IDEOGRAPHIC: return new CSSPrimitiveValueImpl(CSS_VAL_CJK_IDEOGRAPHIC); case khtml::HIRAGANA: return new CSSPrimitiveValueImpl(CSS_VAL_HIRAGANA); case khtml::KATAKANA: return new CSSPrimitiveValueImpl(CSS_VAL_KATAKANA); case khtml::HIRAGANA_IROHA: return new CSSPrimitiveValueImpl(CSS_VAL_HIRAGANA_IROHA); case khtml::KATAKANA_IROHA: return new CSSPrimitiveValueImpl(CSS_VAL_KATAKANA_IROHA); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_MARGIN_TOP: return valueForLength(style->marginTop()); case CSS_PROP_MARGIN_RIGHT: return valueForLength(style->marginRight()); case CSS_PROP_MARGIN_BOTTOM: return valueForLength(style->marginBottom()); case CSS_PROP_MARGIN_LEFT: return valueForLength(style->marginLeft()); case CSS_PROP__KHTML_MARQUEE: // FIXME: unimplemented break; case CSS_PROP__KHTML_MARQUEE_DIRECTION: switch (style->marqueeDirection()) { case khtml::MFORWARD: return new CSSPrimitiveValueImpl(CSS_VAL_FORWARDS); case khtml::MBACKWARD: return new CSSPrimitiveValueImpl(CSS_VAL_BACKWARDS); case khtml::MAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::MUP: return new CSSPrimitiveValueImpl(CSS_VAL_UP); case khtml::MDOWN: return new CSSPrimitiveValueImpl(CSS_VAL_DOWN); case khtml::MLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case khtml::MRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_MARQUEE_INCREMENT: return valueForLength(style->marqueeIncrement()); case CSS_PROP__KHTML_MARQUEE_REPETITION: if (style->marqueeLoopCount() < 0) return new CSSPrimitiveValueImpl(CSS_VAL_INFINITE); return new CSSPrimitiveValueImpl(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP__KHTML_MARQUEE_SPEED: // FIXME: unimplemented break; case CSS_PROP__KHTML_MARQUEE_STYLE: switch (style->marqueeBehavior()) { case khtml::MNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case khtml::MSCROLL: return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); case khtml::MSLIDE: return new CSSPrimitiveValueImpl(CSS_VAL_SLIDE); case khtml::MALTERNATE: return new CSSPrimitiveValueImpl(CSS_VAL_ALTERNATE); case khtml::MUNFURL: return new CSSPrimitiveValueImpl(CSS_VAL_UNFURL); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_USER_MODIFY: switch (style->userModify()) { case khtml::READ_ONLY: return new CSSPrimitiveValueImpl(CSS_VAL_READ_ONLY); case khtml::READ_WRITE: return new CSSPrimitiveValueImpl(CSS_VAL_READ_WRITE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_MAX_HEIGHT: return valueForLength(style->maxHeight()); case CSS_PROP_MAX_WIDTH: return valueForLength(style->maxWidth()); case CSS_PROP_MIN_HEIGHT: return valueForLength(style->minHeight()); case CSS_PROP_MIN_WIDTH: return valueForLength(style->minWidth()); case CSS_PROP_OPACITY: return new CSSPrimitiveValueImpl(style->opacity(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_ORPHANS: return new CSSPrimitiveValueImpl(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_OUTLINE_COLOR: // FIXME: unimplemented break; case CSS_PROP_OUTLINE_OFFSET: // FIXME: unimplemented break; case CSS_PROP_OUTLINE_STYLE: if (style->outlineStyleIsAuto()) return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); return valueForBorderStyle(style->outlineStyle()); case CSS_PROP_OUTLINE_WIDTH: // FIXME: unimplemented break; case CSS_PROP_OVERFLOW: switch (style->overflow()) { case khtml::OVISIBLE: return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE); case khtml::OHIDDEN: return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN); case khtml::OSCROLL: return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); case khtml::OAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::OMARQUEE: return new CSSPrimitiveValueImpl(CSS_VAL_MARQUEE); case khtml::OOVERLAY: return new CSSPrimitiveValueImpl(CSS_VAL_OVERLAY); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_PADDING_TOP: return valueForLength(style->paddingTop()); case CSS_PROP_PADDING_RIGHT: return valueForLength(style->paddingRight()); case CSS_PROP_PADDING_BOTTOM: return valueForLength(style->paddingBottom()); case CSS_PROP_PADDING_LEFT: return valueForLength(style->paddingLeft()); case CSS_PROP_PAGE: // FIXME: unimplemented break; case CSS_PROP_PAGE_BREAK_AFTER: switch (style->pageBreakAfter()) { case khtml::PBAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::PBALWAYS: return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS); case khtml::PBAVOID: return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_PAGE_BREAK_BEFORE: switch (style->pageBreakBefore()) { case khtml::PBAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::PBALWAYS: return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS); case khtml::PBAVOID: return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_PAGE_BREAK_INSIDE: switch (style->pageBreakInside()) { case khtml::PBAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::PBAVOID: return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); case khtml::PBALWAYS: break; // not allowed } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_POSITION: switch (style->position()) { case khtml::STATIC: return new CSSPrimitiveValueImpl(CSS_VAL_STATIC); case khtml::RELATIVE: return new CSSPrimitiveValueImpl(CSS_VAL_RELATIVE); case khtml::ABSOLUTE: return new CSSPrimitiveValueImpl(CSS_VAL_ABSOLUTE); case khtml::FIXED: return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_QUOTES: // FIXME: unimplemented break; case CSS_PROP_RIGHT: return getPositionOffsetValue(renderer, CSS_PROP_RIGHT); case CSS_PROP_SIZE: // FIXME: unimplemented break; case CSS_PROP_TABLE_LAYOUT: switch (style->tableLayout()) { case khtml::TAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::TFIXED: return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_TEXT_ALIGN: return valueForTextAlign(style->textAlign()); case CSS_PROP_TEXT_DECORATION: { QString string; if (style->textDecoration() & khtml::UNDERLINE) string += "underline"; if (style->textDecoration() & khtml::OVERLINE) { if (string.length() > 0) string += " "; string += "overline"; } if (style->textDecoration() & khtml::LINE_THROUGH) { if (string.length() > 0) string += " "; string += "line-through"; } if (style->textDecoration() & khtml::BLINK) { if (string.length() > 0) string += " "; string += "blink"; } if (string.length() == 0) return new CSSPrimitiveValueImpl(CSS_VAL_NONE); return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING); } case CSS_PROP__KHTML_TEXT_DECORATIONS_IN_EFFECT: { QString string; if (style->textDecorationsInEffect() & khtml::UNDERLINE) string += "underline"; if (style->textDecorationsInEffect() & khtml::OVERLINE) { if (string.length() > 0) string += " "; string += "overline"; } if (style->textDecorationsInEffect() & khtml::LINE_THROUGH) { if (string.length() > 0) string += " "; string += "line-through"; } if (style->textDecorationsInEffect() & khtml::BLINK) { if (string.length() > 0) string += " "; string += "blink"; } if (string.length() == 0) return new CSSPrimitiveValueImpl(CSS_VAL_NONE); return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_TEXT_INDENT: return valueForLength(style->textIndent()); case CSS_PROP_TEXT_SHADOW: return valueForShadow(style->textShadow()); case CSS_PROP__APPLE_TEXT_SIZE_ADJUST: if (style->textSizeAdjust()) return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); else return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CSS_PROP_TEXT_TRANSFORM: switch (style->textTransform()) { case khtml::CAPITALIZE: return new CSSPrimitiveValueImpl(CSS_VAL_CAPITALIZE); case khtml::UPPERCASE: return new CSSPrimitiveValueImpl(CSS_VAL_UPPERCASE); case khtml::LOWERCASE: return new CSSPrimitiveValueImpl(CSS_VAL_LOWERCASE); case khtml::TTNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_TOP: return getPositionOffsetValue(renderer, CSS_PROP_TOP); case CSS_PROP_UNICODE_BIDI: switch (style->unicodeBidi()) { case khtml::UBNormal: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::Embed: return new CSSPrimitiveValueImpl(CSS_VAL_EMBED); case khtml::Override: return new CSSPrimitiveValueImpl(CSS_VAL_BIDI_OVERRIDE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_VERTICAL_ALIGN: switch (style->verticalAlign()) { case khtml::BASELINE: return new CSSPrimitiveValueImpl(CSS_VAL_BASELINE); case khtml::MIDDLE: return new CSSPrimitiveValueImpl(CSS_VAL_MIDDLE); case khtml::SUB: return new CSSPrimitiveValueImpl(CSS_VAL_SUB); case khtml::SUPER: return new CSSPrimitiveValueImpl(CSS_VAL_SUPER); case khtml::TEXT_TOP: return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_TOP); case khtml::TEXT_BOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_BOTTOM); case khtml::TOP: return new CSSPrimitiveValueImpl(CSS_VAL_TOP); case khtml::BOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM); case khtml::BASELINE_MIDDLE: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_BASELINE_MIDDLE); case khtml::LENGTH: return valueForLength(style->verticalAlignLength()); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_VISIBILITY: switch (style->visibility()) { case khtml::VISIBLE: return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE); case khtml::HIDDEN: return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN); case khtml::COLLAPSE: return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_WHITE_SPACE: switch (style->whiteSpace()) { case khtml::NORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::PRE: return new CSSPrimitiveValueImpl(CSS_VAL_PRE); case khtml::NOWRAP: return new CSSPrimitiveValueImpl(CSS_VAL_NOWRAP); case khtml::KHTML_NOWRAP: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_NOWRAP); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_WIDOWS: return new CSSPrimitiveValueImpl(style->widows(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_WIDTH: return new CSSPrimitiveValueImpl(renderer->contentWidth(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_WORD_SPACING: return new CSSPrimitiveValueImpl(style->wordSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_WORD_WRAP: switch (style->wordWrap()) { case khtml::WBNORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::BREAK_WORD: return new CSSPrimitiveValueImpl(CSS_VAL_BREAK_WORD); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_LINE_BREAK: switch (style->khtmlLineBreak()) { case khtml::LBNORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::AFTER_WHITE_SPACE: return new CSSPrimitiveValueImpl(CSS_VAL_AFTER_WHITE_SPACE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_NBSP_MODE: switch (style->nbspMode()) { case khtml::NBNORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::SPACE: return new CSSPrimitiveValueImpl(CSS_VAL_SPACE); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP__KHTML_MATCH_NEAREST_MAIL_BLOCKQUOTE_COLOR: switch (style->matchNearestMailBlockquoteColor()) { case khtml::BCNORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case khtml::MATCH: return new CSSPrimitiveValueImpl(CSS_VAL_MATCH); } ASSERT_NOT_REACHED(); return 0; case CSS_PROP_Z_INDEX: if (style->hasAutoZIndex()) return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); return new CSSPrimitiveValueImpl(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_BACKGROUND: // FIXME: unimplemented break; case CSS_PROP_BORDER: // FIXME: unimplemented break; case CSS_PROP_BORDER_COLOR: // FIXME: unimplemented break; case CSS_PROP_BORDER_STYLE: // FIXME: unimplemented break; case CSS_PROP_BORDER_TOP: // FIXME: unimplemented break; case CSS_PROP_BORDER_RIGHT: // FIXME: unimplemented break; case CSS_PROP_BORDER_BOTTOM: // FIXME: unimplemented break; case CSS_PROP_BORDER_LEFT: // FIXME: unimplemented break; case CSS_PROP_BORDER_WIDTH: // FIXME: unimplemented break; case CSS_PROP_FONT: // FIXME: unimplemented break; case CSS_PROP_LIST_STYLE: // FIXME: unimplemented break; case CSS_PROP_MARGIN: // FIXME: unimplemented break; case CSS_PROP_OUTLINE: // FIXME: unimplemented break; case CSS_PROP_PADDING: // FIXME: unimplemented break; #if !APPLE_CHANGES case CSS_PROP_SCROLLBAR_FACE_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_SHADOW_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_TRACK_COLOR: // FIXME: unimplemented break; case CSS_PROP_SCROLLBAR_ARROW_COLOR: // FIXME: unimplemented break; #endif #if APPLE_CHANGES case CSS_PROP__APPLE_DASHBOARD_REGION: { QValueList<StyleDashboardRegion> regions = style->dashboardRegions(); uint i, count = regions.count(); if (count == 1 && regions[0].type == StyleDashboardRegion::None) return new CSSPrimitiveValueImpl (CSS_VAL_NONE); DashboardRegionImpl *firstRegion = new DashboardRegionImpl(), *region; region = firstRegion; for (i = 0; i < count; i++) { StyleDashboardRegion styleRegion = regions[i]; region->m_label = styleRegion.label; LengthBox offset = styleRegion.offset; region->setTop (new CSSPrimitiveValueImpl(offset.top.value, CSSPrimitiveValue::CSS_PX)); region->setRight (new CSSPrimitiveValueImpl(offset.right.value, CSSPrimitiveValue::CSS_PX)); region->setBottom (new CSSPrimitiveValueImpl(offset.bottom.value, CSSPrimitiveValue::CSS_PX)); region->setLeft (new CSSPrimitiveValueImpl(offset.left.value, CSSPrimitiveValue::CSS_PX)); region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle); region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle); if (i != count-1) { DashboardRegionImpl *newRegion = new DashboardRegionImpl(); region->setNext (newRegion); region = newRegion; } } return new CSSPrimitiveValueImpl(firstRegion); } #endif } ERROR("unimplemented propertyID: %d", propertyID); return 0; }
// FIXME: Have to pass RenderStyles here for calc/computed values. This shouldn't be neecessary. void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, const RenderStyle* rootElementStyle, float effectiveZoom) { if (!value->isPrimitiveValue()) return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); FontDescriptionChangeScope scope(this); scope.fontDescription().setKeywordSize(0); float parentSize = 0; bool parentIsAbsoluteSize = false; float size = 0; // FIXME: Find out when parentStyle could be 0? if (parentStyle) { parentSize = parentStyle->fontDescription().specifiedSize(); parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize(); } if (CSSValueID valueID = primitiveValue->getValueID()) { switch (valueID) { case CSSValueXxSmall: case CSSValueXSmall: case CSSValueSmall: case CSSValueMedium: case CSSValueLarge: case CSSValueXLarge: case CSSValueXxLarge: case CSSValueWebkitXxxLarge: size = FontSize::fontSizeForKeyword(m_document, valueID, scope.fontDescription().useFixedDefaultSize()); scope.fontDescription().setKeywordSize(valueID - CSSValueXxSmall + 1); break; case CSSValueLarger: size = largerFontSize(parentSize); break; case CSSValueSmaller: size = smallerFontSize(parentSize); break; default: return; } scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize && (valueID == CSSValueLarger || valueID == CSSValueSmaller)); } else { scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue->isPercentage() || primitiveValue->isFontRelativeLength())); if (primitiveValue->isLength()) size = primitiveValue->computeLength<float>(parentStyle, rootElementStyle, 1.0, true); else if (primitiveValue->isPercentage()) size = (primitiveValue->getFloatValue() * parentSize) / 100.0f; else if (primitiveValue->isCalculatedPercentageWithLength()) size = primitiveValue->cssCalcValue()->toCalcValue(parentStyle, rootElementStyle)->evaluate(parentSize); else if (primitiveValue->isViewportPercentageLength()) size = valueForLength(primitiveValue->viewportPercentageLength(), 0, m_document->renderView()); else return; } if (size < 0) return; // Overly large font sizes will cause crashes on some platforms (such as Windows). // Cap font size here to make sure that doesn't happen. size = std::min(maximumAllowedFontSize, size); setSize(scope.fontDescription(), effectiveZoom, size); }
LayoutUnit RenderGrid::computeUsedBreadthOfSpecifiedLength(TrackSizingDirection direction, const Length& trackLength) const { // FIXME: We still need to support calc() here (https://webkit.org/b/103761). ASSERT(trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage()); return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(MainOrPreferredSize, style()->logicalHeight()), view()); }
static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView) { return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1)); }
void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, int& ascent, int& descent, bool& affectsAscent, bool& affectsDescent) const { bool ascentDescentSet = false; // Replaced boxes will return 0 for the line-height if line-box-contain says they are // not to be included. if (box->renderer().isReplaced()) { if (lineStyle().lineBoxContain() & LineBoxContainReplaced) { ascent = box->baselinePosition(baselineType()); descent = box->lineHeight() - ascent; // Replaced elements always affect both the ascent and descent. affectsAscent = true; affectsDescent = true; } return; } Vector<const SimpleFontData*>* usedFonts = 0; GlyphOverflow* glyphOverflow = 0; if (box->isInlineTextBox()) { GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(toInlineTextBox(box)); usedFonts = it == textBoxDataMap.end() ? 0 : &it->value.first; glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second; } bool includeLeading = includeLeadingForBox(box); bool includeFont = includeFontForBox(box); bool setUsedFont = false; bool setUsedFontWithLeading = false; const RenderStyle& boxLineStyle = box->lineStyle(); #if PLATFORM(IOS) if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading)) && !box->renderer().document().settings()->alwaysUseBaselineOfPrimaryFont()) { #else if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading))) { #endif usedFonts->append(boxLineStyle.font().primaryFont()); for (size_t i = 0; i < usedFonts->size(); ++i) { const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics(); int usedFontAscent = fontMetrics.ascent(baselineType()); int usedFontDescent = fontMetrics.descent(baselineType()); int halfLeading = (fontMetrics.lineSpacing() - fontMetrics.height()) / 2; int usedFontAscentAndLeading = usedFontAscent + halfLeading; int usedFontDescentAndLeading = fontMetrics.lineSpacing() - usedFontAscentAndLeading; if (includeFont) { setAscentAndDescent(ascent, descent, usedFontAscent, usedFontDescent, ascentDescentSet); setUsedFont = true; } if (includeLeading) { setAscentAndDescent(ascent, descent, usedFontAscentAndLeading, usedFontDescentAndLeading, ascentDescentSet); setUsedFontWithLeading = true; } if (!affectsAscent) affectsAscent = usedFontAscent - box->logicalTop() > 0; if (!affectsDescent) affectsDescent = usedFontDescent + box->logicalTop() > 0; } } // If leading is included for the box, then we compute that box. if (includeLeading && !setUsedFontWithLeading) { int ascentWithLeading = box->baselinePosition(baselineType()); int descentWithLeading = box->lineHeight() - ascentWithLeading; setAscentAndDescent(ascent, descent, ascentWithLeading, descentWithLeading, ascentDescentSet); // Examine the font box for inline flows and text boxes to see if any part of it is above the baseline. // If the top of our font box relative to the root box baseline is above the root box baseline, then // we are contributing to the maxAscent value. Descent is similar. If any part of our font box is below // the root box's baseline, then we contribute to the maxDescent value. affectsAscent = ascentWithLeading - box->logicalTop() > 0; affectsDescent = descentWithLeading + box->logicalTop() > 0; } if (includeFontForBox(box) && !setUsedFont) { int fontAscent = boxLineStyle.fontMetrics().ascent(baselineType()); int fontDescent = boxLineStyle.fontMetrics().descent(baselineType()); setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet); affectsAscent = fontAscent - box->logicalTop() > 0; affectsDescent = fontDescent + box->logicalTop() > 0; } if (includeGlyphsForBox(box) && glyphOverflow && glyphOverflow->computeBounds) { setAscentAndDescent(ascent, descent, glyphOverflow->top, glyphOverflow->bottom, ascentDescentSet); affectsAscent = glyphOverflow->top - box->logicalTop() > 0; affectsDescent = glyphOverflow->bottom + box->logicalTop() > 0; glyphOverflow->top = std::min(glyphOverflow->top, std::max(0, glyphOverflow->top - boxLineStyle.fontMetrics().ascent(baselineType()))); glyphOverflow->bottom = std::min(glyphOverflow->bottom, std::max(0, glyphOverflow->bottom - boxLineStyle.fontMetrics().descent(baselineType()))); } if (includeMarginForBox(box)) { LayoutUnit ascentWithMargin = boxLineStyle.fontMetrics().ascent(baselineType()); LayoutUnit descentWithMargin = boxLineStyle.fontMetrics().descent(baselineType()); if (box->parent() && !box->renderer().isTextOrLineBreak()) { ascentWithMargin += box->boxModelObject()->borderAndPaddingBefore() + box->boxModelObject()->marginBefore(); descentWithMargin += box->boxModelObject()->borderAndPaddingAfter() + box->boxModelObject()->marginAfter(); } setAscentAndDescent(ascent, descent, ascentWithMargin, descentWithMargin, ascentDescentSet); // Treat like a replaced element, since we're using the margin box. affectsAscent = true; affectsDescent = true; } } LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositionCache& verticalPositionCache) { if (box->renderer().isTextOrLineBreak()) return box->parent()->logicalTop(); RenderBoxModelObject* renderer = box->boxModelObject(); ASSERT(renderer->isInline()); if (!renderer->isInline()) return 0; // This method determines the vertical position for inline elements. bool firstLine = isFirstLine(); if (firstLine && !renderer->document().styleSheetCollection().usesFirstLineRules()) firstLine = false; // Check the cache. bool isRenderInline = renderer->isRenderInline(); if (isRenderInline && !firstLine) { LayoutUnit verticalPosition = verticalPositionCache.get(renderer, baselineType()); if (verticalPosition != PositionUndefined) return verticalPosition; } LayoutUnit verticalPosition = 0; EVerticalAlign verticalAlign = renderer->style().verticalAlign(); if (verticalAlign == TOP || verticalAlign == BOTTOM) return 0; RenderElement* parent = renderer->parent(); if (parent->isRenderInline() && parent->style().verticalAlign() != TOP && parent->style().verticalAlign() != BOTTOM) verticalPosition = box->parent()->logicalTop(); if (verticalAlign != BASELINE) { const RenderStyle& parentLineStyle = firstLine ? parent->firstLineStyle() : parent->style(); const Font& font = parentLineStyle.font(); const FontMetrics& fontMetrics = font.fontMetrics(); int fontSize = font.pixelSize(); LineDirectionMode lineDirection = parent->isHorizontalWritingMode() ? HorizontalLine : VerticalLine; if (verticalAlign == SUB) verticalPosition += fontSize / 5 + 1; else if (verticalAlign == SUPER) verticalPosition -= fontSize / 3 + 1; else if (verticalAlign == TEXT_TOP) verticalPosition += renderer->baselinePosition(baselineType(), firstLine, lineDirection) - fontMetrics.ascent(baselineType()); else if (verticalAlign == MIDDLE) verticalPosition = (verticalPosition - LayoutUnit(fontMetrics.xHeight() / 2) - renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection)).round(); else if (verticalAlign == TEXT_BOTTOM) { verticalPosition += fontMetrics.descent(baselineType()); // lineHeight - baselinePosition is always 0 for replaced elements (except inline blocks), so don't bother wasting time in that case. if (!renderer->isReplaced() || renderer->isInlineBlockOrInlineTable()) verticalPosition -= (renderer->lineHeight(firstLine, lineDirection) - renderer->baselinePosition(baselineType(), firstLine, lineDirection)); } else if (verticalAlign == BASELINE_MIDDLE) verticalPosition += -renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection); else if (verticalAlign == LENGTH) { LayoutUnit lineHeight; //Per http://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align: 'Percentages: refer to the 'line-height' of the element itself'. if (renderer->style().verticalAlignLength().isPercent()) lineHeight = renderer->style().computedLineHeight(); else lineHeight = renderer->lineHeight(firstLine, lineDirection); verticalPosition -= valueForLength(renderer->style().verticalAlignLength(), lineHeight); } } // Store the cached value. if (isRenderInline && !firstLine) verticalPositionCache.set(renderer, baselineType(), verticalPosition); return verticalPosition; } bool RootInlineBox::includeLeadingForBox(InlineBox* box) const { if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText())) return false; LineBoxContain lineBoxContain = renderer().style().lineBoxContain(); return (lineBoxContain & LineBoxContainInline) || (box == this && (lineBoxContain & LineBoxContainBlock)); } bool RootInlineBox::includeFontForBox(InlineBox* box) const { if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText())) return false; if (!box->behavesLikeText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren()) return false; // For now map "glyphs" to "font" in vertical text mode until the bounds returned by glyphs aren't garbage. LineBoxContain lineBoxContain = renderer().style().lineBoxContain(); return (lineBoxContain & LineBoxContainFont) || (!isHorizontal() && (lineBoxContain & LineBoxContainGlyphs)); } bool RootInlineBox::includeGlyphsForBox(InlineBox* box) const { if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText())) return false; if (!box->behavesLikeText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren()) return false; // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage. LineBoxContain lineBoxContain = renderer().style().lineBoxContain(); return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs); } bool RootInlineBox::includeMarginForBox(InlineBox* box) const { if (box->renderer().isReplaced() || (box->renderer().isTextOrLineBreak() && !box->behavesLikeText())) return false; LineBoxContain lineBoxContain = renderer().style().lineBoxContain(); return lineBoxContain & LineBoxContainInlineBox; } bool RootInlineBox::fitsToGlyphs() const { // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage. LineBoxContain lineBoxContain = renderer().style().lineBoxContain(); return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs); }