Example #1
0
GlyphOverflow visualOverflowForDecorations(const RenderStyle& lineStyle, const InlineTextBox* inlineTextBox)
{
    ASSERT(!inlineTextBox || inlineTextBox->lineStyle() == lineStyle);
    
    TextDecoration decoration = lineStyle.textDecorationsInEffect();
    if (decoration == TextDecorationNone)
        return GlyphOverflow();
    
    float strokeThickness = textDecorationStrokeThickness(lineStyle.fontSize());
    float controlPointDistance;
    float step;
    float wavyOffset;
        
    TextDecorationStyle decorationStyle = lineStyle.textDecorationStyle();
    float height = lineStyle.fontCascade().fontMetrics().floatHeight();
    GlyphOverflow overflowResult;
    
    if (decorationStyle == TextDecorationStyleWavy) {
        getWavyStrokeParameters(strokeThickness, controlPointDistance, step);
        wavyOffset = wavyOffsetFromDecoration();
        overflowResult.left = strokeThickness;
        overflowResult.right = strokeThickness;
    }

    // These metrics must match where underlines get drawn.
    if (decoration & TextDecorationUnderline) {
        // Compensate for the integral ceiling in GraphicsContext::computeLineBoundsAndAntialiasingModeForText()
        int underlineOffset = 1;
        underlineOffset += computeUnderlineOffset(lineStyle.textUnderlinePosition(), lineStyle.fontMetrics(), inlineTextBox, strokeThickness);
        if (decorationStyle == TextDecorationStyleWavy) {
            extendIntToFloat(overflowResult.bottom, underlineOffset + wavyOffset + controlPointDistance + strokeThickness - height);
            extendIntToFloat(overflowResult.top, -(underlineOffset + wavyOffset - controlPointDistance - strokeThickness));
        } else {
            extendIntToFloat(overflowResult.bottom, underlineOffset + strokeThickness - height);
            extendIntToFloat(overflowResult.top, -underlineOffset);
        }
    }
    if (decoration & TextDecorationOverline) {
        if (decorationStyle == TextDecorationStyleWavy) {
            extendIntToFloat(overflowResult.bottom, -wavyOffset + controlPointDistance + strokeThickness - height);
            extendIntToFloat(overflowResult.top, wavyOffset + controlPointDistance + strokeThickness);
        } else {
            extendIntToFloat(overflowResult.bottom, strokeThickness - height);
            // top is untouched
        }
    }
    if (decoration & TextDecorationLineThrough) {
        float baseline = lineStyle.fontMetrics().floatAscent();
        if (decorationStyle == TextDecorationStyleWavy) {
            extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + controlPointDistance + strokeThickness - height);
            extendIntToFloat(overflowResult.top, -(2 * baseline / 3 - controlPointDistance - strokeThickness));
        } else {
            extendIntToFloat(overflowResult.bottom, 2 * baseline / 3 + strokeThickness - height);
            extendIntToFloat(overflowResult.top, -(2 * baseline / 3));
        }
    }
    return overflowResult;
}
Example #2
0
bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
    LayoutPoint adjustedLocation = accumulatedOffset + roundedLayoutPoint(topLeft());

    // Hit test the markup box.
    if (InlineBox* markupBox = this->markupBox()) {
        RenderStyle* style = renderer().style(isFirstLineStyle());
        LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
        LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent());
        if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
            renderer().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
            return true;
        }
    }

    FloatPoint boxOrigin = locationIncludingFlipping();
    boxOrigin.moveBy(accumulatedOffset);
    FloatRect boundsRect(boxOrigin, size());
    if (visibleToHitTestRequest(request) && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) {
        renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
        if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, boundsRect))
            return true;
    }

    return false;
}
Example #3
0
IntRect SVGInlineTextBox::calculateBoundaries() const
{
    FloatRect textRect;

    RenderText* textRenderer = this->textRenderer();
    ASSERT(textRenderer);

    RenderStyle* style = textRenderer->style();
    ASSERT(style);

    int baseline = baselinePosition(AlphabeticBaseline);
    int heightDifference = baseline - style->fontMetrics().ascent();

    unsigned textFragmentsSize = m_textFragments.size();
    for (unsigned i = 0; i < textFragmentsSize; ++i) {
        const SVGTextFragment& fragment = m_textFragments.at(i);
        FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height + heightDifference);

        if (!fragment.transform.isIdentity())
            fragmentRect = fragment.transform.mapRect(fragmentRect);

        textRect.unite(fragmentRect);
    }

    return enclosingIntRect(textRect);
}
Example #4
0
LayoutUnit toUserUnits(const MathMLElement::Length& length, const RenderStyle& style, const LayoutUnit& referenceValue)
{
    switch (length.type) {
    case MathMLElement::LengthType::Cm:
        return length.value * cssPixelsPerInch / 2.54f;
    case MathMLElement::LengthType::Em:
        return length.value * style.fontCascade().size();
    case MathMLElement::LengthType::Ex:
        return length.value * style.fontMetrics().xHeight();
    case MathMLElement::LengthType::In:
        return length.value * cssPixelsPerInch;
    case MathMLElement::LengthType::MathUnit:
        return length.value * style.fontCascade().size() / 18;
    case MathMLElement::LengthType::Mm:
        return length.value * cssPixelsPerInch / 25.4f;
    case MathMLElement::LengthType::Pc:
        return length.value * cssPixelsPerInch / 6;
    case MathMLElement::LengthType::Percentage:
        return referenceValue * length.value / 100;
    case MathMLElement::LengthType::Pt:
        return length.value * cssPixelsPerInch / 72;
    case MathMLElement::LengthType::Px:
        return length.value;
    case MathMLElement::LengthType::UnitLess:
        return referenceValue * length.value;
    case MathMLElement::LengthType::ParsingFailed:
        return referenceValue;
    default:
        ASSERT_NOT_REACHED();
        return referenceValue;
    }
}
Example #5
0
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
    GraphicsContext* context = paintInfo.context;
    RenderStyle* style = m_renderer->style(isFirstLineStyle());
    Color styleTextColor = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
    if (styleTextColor != context->fillColor())
        context->setFillColor(styleTextColor, style->colorSpace());

    Color textColor = styleTextColor;
    const Font& font = style->font();
    if (selectionState() != RenderObject::SelectionNone) {
        paintSelection(context, paintOffset, style, font);

        // Select the correct color for painting the text.
        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
        if (foreground.isValid() && foreground != styleTextColor)
            context->setFillColor(foreground, style->colorSpace());
    }

    const ShadowData* shadow = style->textShadow();
    bool hasShadow = shadow;
    if (hasShadow) {
        // FIXME: it would be better if we could get the shadows top-to-bottom from the style.
        Vector<const ShadowData*, 4> shadows;
        do {
            shadows.append(shadow);
        } while ((shadow = shadow->next()));

        DrawLooper drawLooper;
        drawLooper.addUnmodifiedContent();
        for (int i = shadows.size() - 1; i >= 0; i--) {
            shadow = shadows[i];
            int shadowX = isHorizontal() ? shadow->x() : shadow->y();
            int shadowY = isHorizontal() ? shadow->y() : -shadow->x();
            FloatSize offset(shadowX, shadowY);
            drawLooper.addShadow(offset, shadow->blur(), shadow->color(),
                DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
        }
        context->setDrawLooper(drawLooper);
    }

    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
    FloatPoint boxOrigin(paintOffset);
    boxOrigin.move(x(), y());
    FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
    FloatPoint textOrigin(boxOrigin.x(), boxOrigin.y() + style->fontMetrics().ascent());
    TextRun textRun = RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion);
    TextRunPaintInfo textRunPaintInfo(textRun);
    textRunPaintInfo.bounds = boxRect;
    context->drawText(font, textRunPaintInfo, textOrigin);

    // Restore the regular fill color.
    if (styleTextColor != context->fillColor())
        context->setFillColor(styleTextColor, style->colorSpace());

    if (hasShadow)
        context->clearDrawLooper();

    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
}
Example #6
0
const QFontMetrics &RenderText::metrics(bool firstLine) const
{
    if( firstLine && hasFirstLine() ) {
	RenderStyle *pseudoStyle  = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
	if ( pseudoStyle )
	    return pseudoStyle->fontMetrics();
    }
    return style()->fontMetrics();
}
Example #7
0
void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, const RenderStyle& style)
{
    InlineBox* markupBox = this->markupBox();
    if (!markupBox)
        return;

    LayoutPoint adjustedPaintOffset = paintOffset;
    adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(),
        y() + style.fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent()));
    markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
}
Example #8
0
static LayoutUnit axisHeight(const RenderStyle& style)
{
    // If we have a MATH table we just return the AxisHeight constant.
    const auto& primaryFont = style.fontCascade().primaryFont();
    if (auto* mathData = primaryFont.mathData())
        return mathData->getMathConstant(primaryFont, OpenTypeMathData::AxisHeight);

    // Otherwise, the idea is to try and use the middle of operators as the math axis which we thus approximate by "half of the x-height".
    // Note that Gecko has a slower but more accurate version that measures half of the height of U+2212 MINUS SIGN.
    return style.fontMetrics().xHeight() / 2;
}
float SVGLengthContext::convertValueFromEXSToUserUnits(float value, ExceptionState& es) const
{
    RenderStyle* style = renderStyleForLengthResolving(m_context);
    if (!style) {
        es.throwDOMException(NotSupportedError);
        return 0;
    }

    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
    // if this causes problems in real world cases maybe it would be best to remove this
    return value * ceilf(style->fontMetrics().xHeight());
}
float SVGLength::convertValueFromEXSToUserUnits(float value, const SVGElement* context, ExceptionCode& ec) const
{
    if (!context || !context->renderer() || !context->renderer()->style()) {
        ec = NOT_SUPPORTED_ERR;
        return 0;
    }

    RenderStyle* style = context->renderer()->style();
    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
    // if this causes problems in real world cases maybe it would be best to remove this
    return value * ceilf(style->fontMetrics().xHeight());
}
Example #11
0
LayoutUnit RenderMathMLFraction::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
{
    if (firstChild() && firstChild()->isRenderMathMLBlock()) {
        RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
        RenderStyle* refStyle = style();
        if (previousSibling())
            refStyle = previousSibling()->style();
        else if (nextSibling())
            refStyle = nextSibling()->style();
        int shift = int(ceil((refStyle->fontMetrics().xHeight() + 1) / 2));
        return numerator->offsetHeight() + shift;
    }
    return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode);
}
float SVGLengthContext::convertValueFromUserUnitsToEXS(float value, ExceptionState& exceptionState) const
{
    RenderStyle* style = renderStyleForLengthResolving(m_context);
    if (!style) {
        exceptionState.throwDOMException(NotSupportedError, "No context could be found.");
        return 0;
    }

    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
    // if this causes problems in real world cases maybe it would be best to remove this
    float xHeight = ceilf(style->fontMetrics().xHeight());
    if (!xHeight) {
        exceptionState.throwDOMException(NotSupportedError, "No x-height could be determined.");
        return 0;
    }

    return value / xHeight;
}
Example #13
0
float SVGLengthContext::convertValueFromUserUnitsToEXS(float value, ExceptionCode& ec) const
{
    RenderStyle* style = renderStyleForLengthResolving(m_context);
    if (!style) {
        ec = NOT_SUPPORTED_ERR;
        return 0;
    }

    // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
    // if this causes problems in real world cases maybe it would be best to remove this
    float xHeight = ceilf(style->fontMetrics().xHeight());
    if (!xHeight) {
        ec = NOT_SUPPORTED_ERR;
        return 0;
    }

    return value / xHeight;
}
short RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
{
    if (firstLine) {
        RenderStyle* s = style(firstLine);
        Length lh = s->lineHeight();
        if (lh.value < 0) {
            if (s == style()) {
                if (m_lineHeight == -1)
                    m_lineHeight = RenderObject::lineHeight(false);
                return m_lineHeight;
            }
            return s->fontMetrics().lineSpacing();
	}
        if (lh.isPercent())
            return lh.minWidth(s->font().pixelSize());
        return lh.value;
    }

    if (m_lineHeight == -1)
        m_lineHeight = RenderObject::lineHeight(false);
    return m_lineHeight;
}
Example #15
0
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
    GraphicsContext* context = paintInfo.context;
    RenderStyle* style = renderer().style(isFirstLineStyle());
    Color textColor = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
    if (textColor != context->fillColor())
        context->setFillColor(textColor, style->colorSpace());
    bool setShadow = false;
    if (style->textShadow()) {
        context->setShadow(LayoutSize(style->textShadow()->x(), style->textShadow()->y()),
                           style->textShadow()->radius(), style->textShadow()->color(), style->colorSpace());
        setShadow = true;
    }

    const Font& font = style->font();
    if (selectionState() != RenderObject::SelectionNone) {
        paintSelection(context, paintOffset, style, font);

        // Select the correct color for painting the text.
        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
        if (foreground.isValid() && foreground != textColor)
            context->setFillColor(foreground, style->colorSpace());
    }

    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
    context->drawText(font, RenderBlock::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + style->fontMetrics().ascent()));

    // Restore the regular fill color.
    if (textColor != context->fillColor())
        context->setFillColor(textColor, style->colorSpace());

    if (setShadow)
        context->clearShadow();

    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
}
Example #16
0
void RenderInline::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
{
    _x = -1;

    RenderBlock *cb = containingBlock();
    bool rtl = cb->style()->direction() == RTL;
    bool outsideEnd = flags & CFOutsideEnd;
    // I need to explain that: outsideEnd contains a meaningful value if
    // and only if flags & CFOutside is set. If it is not, then randomly
    // either the first or the last line box is returned.
    // This doesn't matter because the only case this can happen is on an
    // empty inline element, whose first and last line boxes are actually
    // the same.
    InlineFlowBox *line = !outsideEnd ^ rtl ? firstLineBox() : lastLineBox();

    if(!line)
    { // umpf, handle "gracefully"
        RenderFlow::caretPos(offset, flags, _x, _y, width, height);
        return;
    }

    _x = line->xPos();
    width = 1; // ### regard CFOverride

    // Place caret outside the border
    if(flags & CFOutside)
    {
        RenderStyle *s = element() && element()->parent() && element()->parent()->renderer() ? element()->parent()->renderer()->style() : style();
        const QFontMetrics &fm = s->fontMetrics();
        _y = line->yPos() + line->baseline() - fm.ascent();
        height = fm.height();

        if(!outsideEnd ^ rtl)
        {
            _x -= line->marginBorderPaddingLeft();
        }
        else
        {
            _x += line->width() + line->marginBorderPaddingRight();
        }
    }
    else
    {
        const QFontMetrics &fm = style()->fontMetrics();
        _y = line->yPos() + line->baseline() - fm.ascent();
        height = fm.height();
    }

    int absx, absy;
    if(cb && cb->absolutePosition(absx, absy))
    {
        // kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
        _x += absx;
        _y += absy;
    }
    else
    {
        // we don't know our absolute position, and there is no point returning
        // just a relative one
        _x = _y = -1;
    }
}