示例#1
0
void LayoutSVGInlineText::updateMetricsList(bool& lastCharacterWasWhiteSpace)
{
    m_metrics.clear();

    if (!textLength())
        return;

    TextRun run = constructTextRun(*this, 0, textLength(), styleRef().direction());
    BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
    BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
    bool bidiOverride = isOverride(styleRef().unicodeBidi());
    BidiStatus status(LTR, bidiOverride);
    if (run.is8Bit() || bidiOverride) {
        WTF::Unicode::CharDirection direction = WTF::Unicode::LeftToRight;
        // If BiDi override is in effect, use the specified direction.
        if (bidiOverride && !styleRef().isLeftToRightDirection())
            direction = WTF::Unicode::RightToLeft;
        bidiRuns.addRun(new BidiCharacterRun(0, run.charactersLength(), status.context.get(), direction));
    } else {
        status.last = status.lastStrong = WTF::Unicode::OtherNeutral;
        bidiResolver.setStatus(status);
        bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));
        const bool hardLineBreak = false;
        const bool reorderRuns = false;
        bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()), NoVisualOverride, hardLineBreak, reorderRuns);
    }

    for (const BidiCharacterRun* bidiRun = bidiRuns.firstRun(); bidiRun; bidiRun = bidiRun->next()) {
        TextRun subRun = constructTextRun(*this, bidiRun->start(), bidiRun->stop() - bidiRun->start(),
            bidiRun->direction());
        addMetricsFromRun(subRun, lastCharacterWasWhiteSpace);
    }

    bidiResolver.runs().deleteRuns();
}
示例#2
0
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
    GraphicsContext* context = paintInfo.context;
    RenderStyle* style = renderer().style(isFirstLineStyle());
    const Font& font = style->font();
    FloatPoint boxOrigin = locationIncludingFlipping();
    boxOrigin.moveBy(FloatPoint(paintOffset));
    if (!isHorizontal())
        boxOrigin.move(0, -virtualLogicalHeight());
    FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight()));
    GraphicsContextStateSaver stateSaver(*context);
    if (!isHorizontal())
        context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise));
    FloatPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent());

    bool isPrinting = renderer().document().printing();
    bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;

    if (haveSelection)
        paintSelection(context, boxOrigin, style, font);
    else if (paintInfo.phase == PaintPhaseSelection)
        return;

    TextPainter::Style textStyle = TextPainter::textPaintingStyle(renderer(), style, paintInfo.forceBlackText(), isPrinting);
    if (haveSelection)
        textStyle = TextPainter::selectionPaintingStyle(renderer(), true, paintInfo.forceBlackText(), isPrinting, textStyle);

    TextRun textRun = constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion);
    TextPainter textPainter(context, font, textRun, textOrigin, boxRect, isHorizontal());
    textPainter.paint(0, m_str.length(), m_str.length(), textStyle);

    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
}
FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style)
{
    ASSERT(startPosition < endPosition);
    ASSERT(style);

    FontCachePurgePreventer fontCachePurgePreventer;

    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
    ASSERT(textRenderer);

    float scalingFactor = textRenderer->scalingFactor();
    ASSERT(scalingFactor);

    const Font& scaledFont = textRenderer->scaledFont();
    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
    FloatPoint textOrigin(fragment.x, fragment.y);
    if (scalingFactor != 1)
        textOrigin.scale(scalingFactor, scalingFactor);

    textOrigin.move(0, -scaledFontMetrics.floatAscent());

    FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition);
    if (scalingFactor == 1)
        return selectionRect;

    selectionRect.scale(1 / scalingFactor);
    return selectionRect;
}
示例#4
0
int SVGInlineTextBox::offsetForPositionInFragment(
    const SVGTextFragment& fragment,
    LayoutUnit position,
    bool includePartialGlyphs) const {
  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());

  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);

  const ComputedStyle& style = lineLayoutItem.styleRef();

  TextRun textRun = constructTextRun(style, fragment);

  // Eventually handle lengthAdjust="spacingAndGlyphs".
  // FIXME: Handle vertical text.
  if (fragment.isTransformed()) {
    AffineTransform fragmentTransform = fragment.buildFragmentTransform();
    textRun.setHorizontalGlyphStretch(
        clampTo<float>(fragmentTransform.xScale()));
  }

  return fragment.characterOffset - start() +
         lineLayoutItem.scaledFont().offsetForPosition(
             textRun, position * scalingFactor, includePartialGlyphs);
}
示例#5
0
FloatRect SVGInlineTextBox::selectionRectForTextFragment(
    const SVGTextFragment& fragment,
    int startPosition,
    int endPosition,
    const ComputedStyle& style) const {
  ASSERT(startPosition < endPosition);

  LineLayoutSVGInlineText lineLayoutItem =
      LineLayoutSVGInlineText(this->getLineLayoutItem());

  float scalingFactor = lineLayoutItem.scalingFactor();
  ASSERT(scalingFactor);

  const Font& scaledFont = lineLayoutItem.scaledFont();
  const SimpleFontData* fontData = scaledFont.primaryFont();
  DCHECK(fontData);
  if (!fontData)
    return FloatRect();

  const FontMetrics& scaledFontMetrics = fontData->getFontMetrics();
  FloatPoint textOrigin(fragment.x, fragment.y);
  if (scalingFactor != 1)
    textOrigin.scale(scalingFactor, scalingFactor);

  textOrigin.move(0, -scaledFontMetrics.floatAscent());

  FloatRect selectionRect = scaledFont.selectionRectForText(
      constructTextRun(style, fragment), textOrigin,
      fragment.height * scalingFactor, startPosition, endPosition);
  if (scalingFactor == 1)
    return selectionRect;

  selectionRect.scale(1 / scalingFactor);
  return selectionRect;
}
示例#6
0
FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style) const
{
    ASSERT_WITH_SECURITY_IMPLICATION(startPosition < endPosition);
    ASSERT(style);

    float scalingFactor = renderer().scalingFactor();
    ASSERT(scalingFactor);

    const FontCascade& scaledFont = renderer().scaledFont();
    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
    FloatPoint textOrigin(fragment.x, fragment.y);
    if (scalingFactor != 1)
        textOrigin.scale(scalingFactor, scalingFactor);

    textOrigin.move(0, -scaledFontMetrics.floatAscent());

    LayoutRect selectionRect = LayoutRect(textOrigin, LayoutSize(0, fragment.height * scalingFactor));
    TextRun run = constructTextRun(style, fragment);
    scaledFont.adjustSelectionRectForText(run, selectionRect, startPosition, endPosition);
    FloatRect snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), run.ltr());
    if (scalingFactor == 1)
        return snappedSelectionRect;

    snappedSelectionRect.scale(1 / scalingFactor);
    return snappedSelectionRect;
}
LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos) const
{
    int sPos = std::max(startPos - m_start, 0);
    int ePos = std::min(endPos - m_start, (int)m_len);

    if (sPos > ePos)
        return LayoutRect();

    FontCachePurgePreventer fontCachePurgePreventer;

    LayoutUnit selTop = root().selectionTop();
    LayoutUnit selHeight = root().selectionHeight();
    const ComputedStyle& styleToUse = lineLayoutItem().styleRef(isFirstLineStyle());
    const Font& font = styleToUse.font();

    StringBuilder charactersWithHyphen;
    bool respectHyphen = ePos == m_len && hasHyphen();
    TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0);

    LayoutPoint startingPoint = LayoutPoint(logicalLeft(), selTop);
    LayoutRect r;
    if (sPos || ePos != static_cast<int>(m_len)) {
        r = LayoutRect(enclosingIntRect(font.selectionRectForText(textRun, FloatPoint(startingPoint), selHeight, sPos, ePos)));
    } else { // Avoid computing the font width when the entire line box is selected as an optimization.
        // FIXME: the call to rawValue() below is temporary and should be removed once the transition
        // to LayoutUnit-based types is complete (crbug.com/321237)
        r = LayoutRect(enclosingIntRect(LayoutRect(startingPoint, LayoutSize(m_logicalWidth, selHeight))));
    }

    LayoutUnit logicalWidth = r.width();
    if (r.x() > logicalRight())
        logicalWidth  = 0;
    else if (r.maxX() > logicalRight())
        logicalWidth = logicalRight() - r.x();

    LayoutPoint topPoint;
    LayoutUnit width;
    LayoutUnit height;
    if (isHorizontal()) {
        topPoint = LayoutPoint(r.x(), selTop);
        width = logicalWidth;
        height = selHeight;
        if (hasWrappedSelectionNewline()) {
            if (!isLeftToRightDirection())
                topPoint.setX(topPoint.x() - newlineSpaceWidth());
            width += newlineSpaceWidth();
        }
    } else {
        topPoint = LayoutPoint(selTop, r.x());
        width = selHeight;
        height = logicalWidth;
        // TODO(wkorman): RTL text embedded in top-to-bottom text can create
        // bottom-to-top situations. Add tests and ensure we handle correctly.
        if (hasWrappedSelectionNewline())
            height += newlineSpaceWidth();
    }

    return LayoutRect(topPoint, LayoutSize(width, height));
}
示例#8
0
FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style)
{
    ASSERT(startPosition < endPosition);

    const Font& font = style->font();
    FloatPoint textOrigin(fragment.x, fragment.y - font.fontMetrics().ascent());
    return font.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height, startPosition, endPosition);
}
void FileUploadControlPainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_renderFileUploadControl.style()->visibility() != VISIBLE)
        return;

    // Push a clip.
    GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
    if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
        IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + m_renderFileUploadControl.borderLeft(), paintOffset.y() + m_renderFileUploadControl.borderTop(),
            m_renderFileUploadControl.width() - m_renderFileUploadControl.borderLeft() - m_renderFileUploadControl.borderRight(),
            m_renderFileUploadControl.height() - m_renderFileUploadControl.borderBottom() - m_renderFileUploadControl.borderTop() + buttonShadowHeight));
        if (clipRect.isEmpty())
            return;
        stateSaver.save();
        paintInfo.context->clip(clipRect);
    }

    if (paintInfo.phase == PaintPhaseForeground) {
        const String& displayedFilename = m_renderFileUploadControl.fileTextValue();
        const Font& font = m_renderFileUploadControl.style()->font();
        TextRun textRun = constructTextRun(&m_renderFileUploadControl, font, displayedFilename, m_renderFileUploadControl.style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride);

        // Determine where the filename should be placed
        LayoutUnit contentLeft = paintOffset.x() + m_renderFileUploadControl.borderLeft() + m_renderFileUploadControl.paddingLeft();
        Node* button = m_renderFileUploadControl.uploadButton();
        if (!button)
            return;

        int buttonWidth = (button && button->renderBox()) ? button->renderBox()->pixelSnappedWidth() : 0;
        LayoutUnit buttonAndSpacingWidth = buttonWidth + RenderFileUploadControl::afterButtonSpacing;
        float textWidth = font.width(textRun);
        LayoutUnit textX;
        if (m_renderFileUploadControl.style()->isLeftToRightDirection())
            textX = contentLeft + buttonAndSpacingWidth;
        else
            textX = contentLeft + m_renderFileUploadControl.contentWidth() - buttonAndSpacingWidth - textWidth;

        LayoutUnit textY = 0;
        // We want to match the button's baseline
        // FIXME: Make this work with transforms.
        if (RenderButton* buttonRenderer = toRenderButton(button->renderer()))
            textY = paintOffset.y() + m_renderFileUploadControl.borderTop() + m_renderFileUploadControl.paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
        else
            textY = m_renderFileUploadControl.baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
        TextRunPaintInfo textRunPaintInfo(textRun);
        // FIXME: Shouldn't these offsets be rounded? crbug.com/350474
        textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - m_renderFileUploadControl.style()->fontMetrics().ascent(),
            textWidth, m_renderFileUploadControl.style()->fontMetrics().height());

        paintInfo.context->setFillColor(m_renderFileUploadControl.resolveColor(CSSPropertyColor));

        // Draw the filename
        paintInfo.context->drawBidiText(font, textRunPaintInfo, IntPoint(roundToInt(textX), roundToInt(textY)));
    }

    // Paint the children.
    m_renderFileUploadControl.RenderBlockFlow::paintObject(paintInfo, paintOffset);
}
void FileUploadControlPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (m_layoutFileUploadControl.style()->visibility() != VISIBLE)
        return;

    // Push a clip.
    Optional<ClipRecorder> clipRecorder;
    if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseDescendantBlockBackgroundsOnly) {
        IntRect clipRect = enclosingIntRect(LayoutRect(
            LayoutPoint(paintOffset.x() + m_layoutFileUploadControl.borderLeft(), paintOffset.y() + m_layoutFileUploadControl.borderTop()),
            m_layoutFileUploadControl.size() + LayoutSize(0, -m_layoutFileUploadControl.borderWidth() + buttonShadowHeight)));
        if (clipRect.isEmpty())
            return;
        clipRecorder.emplace(paintInfo.context, m_layoutFileUploadControl, DisplayItem::ClipFileUploadControlRect, clipRect);
    }

    if (paintInfo.phase == PaintPhaseForeground && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutFileUploadControl, paintInfo.phase)) {
        const String& displayedFilename = m_layoutFileUploadControl.fileTextValue();
        const Font& font = m_layoutFileUploadControl.style()->font();
        TextRun textRun = constructTextRun(font, displayedFilename, m_layoutFileUploadControl.styleRef(), RespectDirection | RespectDirectionOverride);
        textRun.setExpansionBehavior(TextRun::AllowTrailingExpansion);

        // Determine where the filename should be placed
        LayoutUnit contentLeft = paintOffset.x() + m_layoutFileUploadControl.borderLeft() + m_layoutFileUploadControl.paddingLeft();
        Node* button = m_layoutFileUploadControl.uploadButton();
        if (!button)
            return;

        int buttonWidth = (button && button->layoutBox()) ? button->layoutBox()->pixelSnappedWidth() : 0;
        LayoutUnit buttonAndSpacingWidth(buttonWidth + LayoutFileUploadControl::afterButtonSpacing);
        float textWidth = font.width(textRun);
        LayoutUnit textX;
        if (m_layoutFileUploadControl.style()->isLeftToRightDirection())
            textX = contentLeft + buttonAndSpacingWidth;
        else
            textX = LayoutUnit(contentLeft + m_layoutFileUploadControl.contentWidth() - buttonAndSpacingWidth - textWidth);

        LayoutUnit textY;
        // We want to match the button's baseline
        // FIXME: Make this work with transforms.
        if (LayoutButton* buttonLayoutObject = toLayoutButton(button->layoutObject()))
            textY = paintOffset.y() + m_layoutFileUploadControl.borderTop() + m_layoutFileUploadControl.paddingTop() + buttonLayoutObject->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
        else
            textY = LayoutUnit(m_layoutFileUploadControl.baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine));
        TextRunPaintInfo textRunPaintInfo(textRun);
        // FIXME: Shouldn't these offsets be rounded? crbug.com/350474
        textRunPaintInfo.bounds = FloatRect(textX.toFloat(), textY.toFloat() - m_layoutFileUploadControl.style()->getFontMetrics().ascent(),
            textWidth, m_layoutFileUploadControl.style()->getFontMetrics().height());

        // Draw the filename.
        LayoutObjectDrawingRecorder recorder(paintInfo.context, m_layoutFileUploadControl, paintInfo.phase, textRunPaintInfo.bounds);
        paintInfo.context.setFillColor(m_layoutFileUploadControl.resolveColor(CSSPropertyColor));
        paintInfo.context.drawBidiText(font, textRunPaintInfo, FloatPoint(roundToInt(textX), roundToInt(textY)));
    }

    // Paint the children.
    m_layoutFileUploadControl.LayoutBlockFlow::paintObject(paintInfo, paintOffset);
}
示例#11
0
TextRun constructTextRun(const Font& font,
                         const String& string,
                         const ComputedStyle& style,
                         TextRunFlags flags) {
  return constructTextRun(font, string, style,
                          string.isEmpty() || string.is8Bit()
                              ? LTR
                              : determineDirectionality(string),
                          flags);
}
float LayoutTextControl::getAvgCharWidth(AtomicString family)
{
    if (hasValidAvgCharWidth(family))
        return roundf(style()->font().primaryFont()->avgCharWidth());

    const UChar ch = '0';
    const String str = String(&ch, 1);
    const Font& font = style()->font();
    TextRun textRun = constructTextRun(this, font, str, styleRef(), TextRun::AllowTrailingExpansion);
    return font.width(textRun);
}
示例#13
0
float RenderTextControl::getAverageCharWidth()
{
    float width;
    if (style().fontCascade().fastAverageCharWidthIfAvailable(width))
        return width;

    const UChar ch = '0';
    const String str = String(&ch, 1);
    const FontCascade& font = style().fontCascade();
    TextRun textRun = constructTextRun(this, font, str, style(), AllowTrailingExpansion);
    return font.width(textRun);
}
示例#14
0
TextRun InlineTextBox::constructTextRun(
    const ComputedStyle& style,
    StringBuilder* charactersWithHyphen) const {
  ASSERT(getLineLayoutItem().text());

  String string = getLineLayoutItem().text();
  unsigned startPos = start();
  unsigned length = len();
  return constructTextRun(style, StringView(string, startPos, length),
                          getLineLayoutItem().textLength() - startPos,
                          charactersWithHyphen);
}
LayoutUnit LayoutListMarker::getWidthOfTextWithSuffix() const
{
    if (m_text.isEmpty())
        return 0;
    const Font& font = style()->font();
    LayoutUnit itemWidth = font.width(m_text);
    // TODO(wkorman): Look into constructing a text run for both text and suffix
    // and painting them together.
    UChar suffix[2] = { ListMarkerText::suffix(style()->listStyleType(), m_listItem->value()), ' ' };
    TextRun run = constructTextRun(font, suffix, 2, styleRef(), style()->direction());
    LayoutUnit suffixSpaceWidth = font.width(run);
    return itemWidth + suffixSpaceWidth;
}
TextRun InlineTextBox::constructTextRun(const ComputedStyle& style, const Font& font, StringBuilder* charactersWithHyphen) const
{
    ASSERT(lineLayoutItem().text());

    StringView string = lineLayoutItem().text().createView();
    unsigned startPos = start();
    unsigned length = len();

    if (string.length() != length || startPos)
        string.narrow(startPos, length);

    return constructTextRun(style, font, string, lineLayoutItem().textLength() - startPos, charactersWithHyphen);
}
示例#17
0
float LayoutTextControl::getAvgCharWidth(const AtomicString& family) const {
    const Font& font = style()->font();

    const SimpleFontData* primaryFont = font.primaryFont();
    if (primaryFont && hasValidAvgCharWidth(primaryFont, family))
        return roundf(primaryFont->avgCharWidth());

    const UChar ch = '0';
    const String str = String(&ch, 1);
    TextRun textRun =
        constructTextRun(font, str, styleRef(), TextRun::AllowTrailingExpansion);
    return font.width(textRun);
}
void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
{
    ASSERT(style);
    ASSERT(selectionStyle);

    int startPosition = 0;
    int endPosition = 0;
    if (hasSelection) {
        selectionStartEnd(startPosition, endPosition);
        hasSelection = mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
    }

    // Fast path if there is no selection, just draw the whole chunk part using the regular style
    TextRun textRun = constructTextRun(style, fragment);
    if (!hasSelection || startPosition >= endPosition) {
        paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length);
        return;
    }

    // Eventually draw text using regular style until the start position of the selection
    if (startPosition > 0 && !paintSelectedTextOnly)
        paintTextWithShadows(context, style, textRun, fragment, 0, startPosition);

    // Draw text using selection style from the start to the end position of the selection
    if (style != selectionStyle)
        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);

    TextRun selectionTextRun = constructTextRun(selectionStyle, fragment);
    paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);

    if (style != selectionStyle)
        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);

    // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
    if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
        paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
}
示例#19
0
void LayoutMenuList::updateOptionsWidth() const {
  float maxOptionWidth = 0;

  for (const auto& option : selectElement()->optionList()) {
    String text = option->textIndentedToRespectGroupLabel();
    const ComputedStyle* itemStyle =
        option->computedStyle() ? option->computedStyle() : style();
    applyTextTransform(itemStyle, text, ' ');
    // We apply SELECT's style, not OPTION's style because m_optionsWidth is
    // used to determine intrinsic width of the menulist box.
    TextRun textRun = constructTextRun(style()->font(), text, *style());
    maxOptionWidth = std::max(maxOptionWidth, style()->font().width(textRun));
  }
  m_optionsWidth = static_cast<int>(ceilf(maxOptionWidth));
}
int InlineTextBox::offsetForPosition(LayoutUnit lineOffset, bool includePartialGlyphs) const
{
    if (isLineBreak())
        return 0;

    if (lineOffset - logicalLeft() > logicalWidth())
        return isLeftToRightDirection() ? len() : 0;
    if (lineOffset - logicalLeft() < 0)
        return isLeftToRightDirection() ? 0 : len();

    LineLayoutText text = lineLayoutItem();
    const ComputedStyle& style = text.styleRef(isFirstLineStyle());
    const Font& font = style.font();
    return font.offsetForPosition(constructTextRun(style, font), (lineOffset - logicalLeft()).toFloat(), includePartialGlyphs);
}
示例#21
0
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
{
   float scalingFactor = renderer().scalingFactor();
    ASSERT(scalingFactor);

    TextRun textRun = constructTextRun(&renderer().style(), fragment);

    // Eventually handle lengthAdjust="spacingAndGlyphs".
    // FIXME: Handle vertical text.
    AffineTransform fragmentTransform;
    fragment.buildFragmentTransform(fragmentTransform);
    if (!fragmentTransform.isIdentity())
        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));

    return fragment.characterOffset - start() + renderer().scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
LayoutUnit InlineTextBox::positionForOffset(int offset) const
{
    ASSERT(offset >= m_start);
    ASSERT(offset <= m_start + m_len);

    if (isLineBreak())
        return logicalLeft();

    LineLayoutText text = lineLayoutItem();
    const ComputedStyle& styleToUse = text.styleRef(isFirstLineStyle());
    const Font& font = styleToUse.font();
    int from = !isLeftToRightDirection() ? offset - m_start : 0;
    int to = !isLeftToRightDirection() ? m_len : offset - m_start;
    // FIXME: Do we need to add rightBearing here?
    return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoint(logicalLeft(), 0), 0, from, to).maxX();
}
示例#23
0
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
{
    RenderText* textRenderer = this->textRenderer();
    ASSERT(textRenderer);

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

    TextRun textRun(constructTextRun(style, fragment));

    // Eventually handle lengthAdjust="spacingAndGlyphs".
    // FIXME: Handle vertical text.
    if (!fragment.transform.isIdentity())
        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragment.transform.xScale()));

    return fragment.positionListOffset - start() + style->font().offsetForPosition(textRun, position, includePartialGlyphs);
}
void InlineTextBox::characterWidths(Vector<float>& widths) const
{
    FontCachePurgePreventer fontCachePurgePreventer;

    const ComputedStyle& styleToUse = lineLayoutItem().styleRef(isFirstLineStyle());
    const Font& font = styleToUse.font();

    TextRun textRun = constructTextRun(styleToUse, font);

    SimpleShaper shaper(&font, textRun);
    float lastWidth = 0;
    widths.resize(m_len);
    for (unsigned i = 0; i < m_len; i++) {
        shaper.advance(i + 1);
        widths[i] = shaper.runWidthSoFar() - lastWidth;
        lastWidth = shaper.runWidthSoFar();
    }
}
示例#25
0
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
    GraphicsContext* context = paintInfo.context;
    RenderStyle* style = renderer().style(isFirstLineStyle());

    const Font& font = style->font();
    FloatPoint boxOrigin = locationIncludingFlipping();
    boxOrigin.moveBy(FloatPoint(paintOffset));
    FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight()));
    GraphicsContextStateSaver stateSaver(*context);
    FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent());

    Color styleTextColor = renderer().resolveColor(style, CSSPropertyWebkitTextFillColor);
    if (styleTextColor != context->fillColor())
        context->setFillColor(styleTextColor);

    if (selectionState() != RenderObject::SelectionNone) {
        paintSelection(context, boxOrigin, style, font);

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

    const ShadowList* shadowList = style->textShadow();
    bool hasShadow = shadowList;
    if (hasShadow)
        context->setDrawLooper(shadowList->createDrawLooper(DrawLooperBuilder::ShadowIgnoresAlpha));

    TextRun textRun = 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);

    if (hasShadow)
        context->clearDrawLooper();

    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
}
示例#26
0
void InlineTextBox::characterWidths(Vector<float>& widths) const {
  if (!m_len)
    return;

  FontCachePurgePreventer fontCachePurgePreventer;
  ASSERT(getLineLayoutItem().text());

  const ComputedStyle& styleToUse =
      getLineLayoutItem().styleRef(isFirstLineStyle());
  const Font& font = styleToUse.font();

  TextRun textRun = constructTextRun(styleToUse);
  Vector<CharacterRange> ranges = font.individualCharacterRanges(textRun);
  DCHECK_EQ(ranges.size(), m_len);

  widths.resize(ranges.size());
  for (unsigned i = 0; i < ranges.size(); i++)
    widths[i] = ranges[i].width();
}
示例#27
0
int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, FloatWillBeLayoutUnit position, bool includePartialGlyphs) const
{
    LayoutSVGInlineText& textLayoutObject = toLayoutSVGInlineText(this->layoutObject());

    float scalingFactor = textLayoutObject.scalingFactor();
    ASSERT(scalingFactor);

    const ComputedStyle& style = textLayoutObject.styleRef();

    TextRun textRun = constructTextRun(style, fragment);

    // Eventually handle lengthAdjust="spacingAndGlyphs".
    // FIXME: Handle vertical text.
    AffineTransform fragmentTransform;
    fragment.buildFragmentTransform(fragmentTransform);
    if (!fragmentTransform.isIdentity())
        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));

    return fragment.characterOffset - start() + textLayoutObject.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
void EllipsisBoxPainter::paintEllipsis(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, const ComputedStyle& style)
{
    bool haveSelection = !paintInfo.isPrinting() && paintInfo.phase != PaintPhaseTextClip && m_ellipsisBox.getSelectionState() != SelectionNone;

    LayoutRect paintRect(m_ellipsisBox.logicalFrameRect());
    if (haveSelection)
        paintRect.unite(LayoutRect(m_ellipsisBox.selectionRect()));
    m_ellipsisBox.logicalRectToPhysicalRect(paintRect);
    paintRect.moveBy(paintOffset);

    GraphicsContext& context = paintInfo.context;
    DisplayItem::Type displayItemType = DisplayItem::paintPhaseToDrawingType(paintInfo.phase);
    if (DrawingRecorder::useCachedDrawingIfPossible(context, m_ellipsisBox, displayItemType))
        return;

    DrawingRecorder recorder(context, m_ellipsisBox, displayItemType, FloatRect(paintRect));

    LayoutPoint boxOrigin = m_ellipsisBox.locationIncludingFlipping();
    boxOrigin.moveBy(paintOffset);
    LayoutRect boxRect(boxOrigin, LayoutSize(m_ellipsisBox.logicalWidth(), m_ellipsisBox.virtualLogicalHeight()));

    GraphicsContextStateSaver stateSaver(context);
    if (!m_ellipsisBox.isHorizontal())
        context.concatCTM(TextPainter::rotation(boxRect, TextPainter::Clockwise));

    const Font& font = style.font();

    if (haveSelection)
        paintSelection(context, boxOrigin, style, font);
    else if (paintInfo.phase == PaintPhaseSelection)
        return;

    TextPainter::Style textStyle = TextPainter::textPaintingStyle(m_ellipsisBox.getLineLayoutItem(), style, paintInfo);
    if (haveSelection)
        textStyle = TextPainter::selectionPaintingStyle(m_ellipsisBox.getLineLayoutItem(), true, paintInfo, textStyle);

    TextRun textRun = constructTextRun(font, m_ellipsisBox.ellipsisStr(), style, TextRun::AllowTrailingExpansion);
    LayoutPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.getFontMetrics().ascent());
    TextPainter textPainter(context, font, textRun, textOrigin, boxRect, m_ellipsisBox.isHorizontal());
    textPainter.paint(0, m_ellipsisBox.ellipsisStr().length(), m_ellipsisBox.ellipsisStr().length(), textStyle);
}
void InlineTextBox::characterWidths(Vector<float>& widths) const
{
    if (!m_len)
        return;

    FontCachePurgePreventer fontCachePurgePreventer;
    ASSERT(getLineLayoutItem().text());

    const ComputedStyle& styleToUse = getLineLayoutItem().styleRef(isFirstLineStyle());
    const Font& font = styleToUse.font();

    float lastWidth = 0;
    widths.resize(m_len);
    for (unsigned i = 0; i < m_len; i++) {
        StringView substringView = getLineLayoutItem().text().createView();
        substringView.narrow(start(), 1 + i);
        TextRun textRun = constructTextRun(styleToUse, font, substringView, m_len);
        widths[i] = font.width(textRun, nullptr, nullptr) - lastWidth;
        lastWidth = font.width(textRun, nullptr, nullptr);
    }
}
示例#30
0
void EllipsisBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font)
{
    Color textColor = renderer().resolveColor(style, CSSPropertyColor);
    Color c = renderer().selectionBackgroundColor();
    if (!c.alpha())
        return;

    // If the text color ends up being the same as the selection background, invert the selection
    // background.
    if (textColor == c)
        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());

    GraphicsContextStateSaver stateSaver(*context);
    LayoutUnit top = root().selectionTop();
    LayoutUnit h = root().selectionHeight();
    const int deltaY = roundToInt(logicalTop() - top);
    const FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
    FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, h.toFloat()));
    context->clip(clipRect);
    context->drawHighlightForText(font, constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), localOrigin, h, c);
}