示例#1
0
void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f)
{
   // Use same y positioning and height as for selection, so that when the selection and this highlight are on
   // the same word there are no pieces sticking out.
    int y = selectionTop();
    int h = selectionHeight();
    
    int sPos = max(marker.startOffset - m_start, (unsigned)0);
    int ePos = min(marker.endOffset - m_start, (unsigned)m_len);    
    TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
    IntPoint startPoint = IntPoint(m_x + tx, y + ty);
    
    // Always compute and store the rect associated with this marker
    IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, sPos, ePos));
    object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
     
    // Optionally highlight the text
    if (object()->document()->frame()->markedTextMatchesAreHighlighted()) {
        Color color = theme()->platformTextSearchHighlightColor();
        pt->save();
        updateGraphicsContext(pt, color, color, 0);  // Don't draw text at all!
        pt->clip(IntRect(tx + m_x, ty + y, m_width, h));
        pt->drawHighlightForText(run, startPoint, h, color, sPos, ePos);
        pt->restore();
    }
}
示例#2
0
void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font*)
{
    // See if we have a selection to paint at all.
    int sPos, ePos;
    selectionStartEnd(sPos, ePos);
    if (sPos >= ePos)
        return;

    Color textColor = style->color();
    Color c = object()->selectionBackgroundColor();
    if (!c.isValid() || c.alpha() == 0)
        return;

    // If the text color ends up being the same as the selection background, invert the selection
    // background.  This should basically never happen, since the selection has transparency.
    if (textColor == c)
        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());

    context->save();
    updateGraphicsContext(context, c, c, 0);  // Don't draw text at all!
    int y = selectionTop();
    int h = selectionHeight();
    context->clip(IntRect(m_x + tx, y + ty, m_width, h));
    context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
    context->restore();
}
示例#3
0
LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
{
    const RootInlineBox& rootBox = root();
    LayoutUnit top = selectionTop();

    RenderObject::SelectionState blockSelectionState = rootBox.blockFlow().selectionState();
    if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
        return top;

    LayoutSize offsetToBlockBefore;
    if (RenderBlock* block = rootBox.blockFlow().blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
        if (block->isRenderBlockFlow()) {
            if (RootInlineBox* lastLine = toRenderBlockFlow(block)->lastRootBox()) {
                RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
                if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
                    return top;

                LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
                top = std::max(top, lastLineSelectionBottom);
            }
        }
    }

    return top;
}
示例#4
0
void RootInlineBox::addHighlightOverflow()
{
    // Highlight acts as a selection inflation.
    FloatRect rootRect(0, selectionTop(), width(), selectionHeight());
    IntRect inflatedRect = enclosingIntRect(object()->document()->frame()->customHighlightLineRect(object()->style()->highlight(), rootRect));
    m_leftOverflow = min(m_leftOverflow, inflatedRect.x());
    m_rightOverflow = max(m_rightOverflow, inflatedRect.right());
    m_topOverflow = min(m_topOverflow, inflatedRect.y());
    m_bottomOverflow = max(m_bottomOverflow, inflatedRect.bottom());
}
示例#5
0
void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType)
{
    if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
        return;

    // Get the inflated rect so that we can properly hit test.
    FloatRect rootRect(tx + xPos(), ty + selectionTop(), width(), selectionHeight());
    FloatRect inflatedRect = object()->document()->frame()->customHighlightLineRect(highlightType, rootRect);
    if (inflatedRect.intersects(paintInfo.rect))
        object()->document()->frame()->paintCustomHighlight(highlightType, rootRect, rootRect, false, true);
}
示例#6
0
IntRect RootInlineBox::computeCaretRect(float logicalLeftPosition, unsigned caretWidth, LayoutUnit* extraWidthToEndOfLine) const
{
    int height = selectionHeight();
    int top = selectionTop();

    // Distribute the caret's width to either side of the offset.
    float left = logicalLeftPosition;
    int caretWidthLeftOfOffset = caretWidth / 2;
    left -= caretWidthLeftOfOffset;
    int caretWidthRightOfOffset = caretWidth - caretWidthLeftOfOffset;
    left = roundf(left);

    float rootLeft = logicalLeft();
    float rootRight = logicalRight();

    if (extraWidthToEndOfLine)
        *extraWidthToEndOfLine = (logicalWidth() + rootLeft) - (left + caretWidth);

    const RenderStyle& blockStyle = blockFlow().style();

    bool rightAligned = false;
    switch (blockStyle.textAlign()) {
    case RIGHT:
    case WEBKIT_RIGHT:
        rightAligned = true;
        break;
    case LEFT:
    case WEBKIT_LEFT:
    case CENTER:
    case WEBKIT_CENTER:
        break;
    case JUSTIFY:
    case TASTART:
        rightAligned = !blockStyle.isLeftToRightDirection();
        break;
    case TAEND:
        rightAligned = blockStyle.isLeftToRightDirection();
        break;
    }

    float leftEdge = std::min<float>(0, rootLeft);
    float rightEdge = std::max<float>(blockFlow().logicalWidth(), rootRight);

    if (rightAligned) {
        left = std::max(left, leftEdge);
        left = std::min(left, rootRight - caretWidth);
    } else {
        left = std::min(left, rightEdge - caretWidthRightOfOffset);
        left = std::max(left, rootLeft);
    }
    return blockStyle.isHorizontalWritingMode() ? IntRect(left, top, caretWidth, height) : IntRect(top, left, height, caretWidth);
}
示例#7
0
void RootInlineBox::addHighlightOverflow()
{
    Frame* frame = renderer()->document()->frame();
    if (!frame)
        return;
    Page* page = frame->page();
    if (!page)
        return;

    // Highlight acts as a selection inflation.
    FloatRect rootRect(0, selectionTop(), width(), selectionHeight());
    IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(renderer()->node(), renderer()->style()->highlight(), rootRect));
    setHorizontalOverflowPositions(leftLayoutOverflow(), rightLayoutOverflow(), min(leftVisualOverflow(), inflatedRect.x()), max(rightVisualOverflow(), inflatedRect.right()));
    setVerticalOverflowPositions(topLayoutOverflow(), bottomLayoutOverflow(), min(topVisualOverflow(), inflatedRect.y()), max(bottomVisualOverflow(), inflatedRect.bottom()), height());
}
示例#8
0
void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& type)
{
    Frame* frame = object()->document()->frame();
    if (!frame)
        return;
    Page* page = frame->page();
    if (!page)
        return;

    RootInlineBox* r = root();
    FloatRect rootRect(tx + r->xPos(), ty + selectionTop(), r->width(), selectionHeight());
    FloatRect textRect(tx + xPos(), rootRect.y(), width(), rootRect.height());

    page->chrome()->client()->paintCustomHighlight(object()->node(), type, textRect, rootRect, true, false);
}
示例#9
0
void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType)
{
    if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
        return;

    Frame* frame = renderer()->document()->frame();
    if (!frame)
        return;
    Page* page = frame->page();
    if (!page)
        return;

    // Get the inflated rect so that we can properly hit test.
    FloatRect rootRect(tx + x(), ty + selectionTop(), width(), selectionHeight());
    FloatRect inflatedRect = page->chrome()->client()->customHighlightRect(renderer()->node(), highlightType, rootRect);
    if (inflatedRect.intersects(paintInfo.rect))
        page->chrome()->client()->paintCustomHighlight(renderer()->node(), highlightType, rootRect, rootRect, false, true);
}
示例#10
0
IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
{
    int sPos = max(startPos - m_start, 0);
    int ePos = min(endPos - m_start, (int)m_len);
    
    if (sPos >= ePos)
        return IntRect();

    RenderText* textObj = textObject();
    int selTop = selectionTop();
    int selHeight = selectionHeight();
    const Font& f = textObj->style(m_firstLine)->font();

    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text()->characters() + m_start, m_len, textObj->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
                                                        IntPoint(tx + m_x, ty + selTop), selHeight, sPos, ePos));
    if (r.x() > tx + m_x + m_width)
        r.setWidth(0);
    else if (r.right() - 1 > tx + m_x + m_width)
        r.setWidth(tx + m_x + m_width - r.x());
    return r;
}
示例#11
0
void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font*, int startPos, int endPos)
{
    int offset = m_start;
    int sPos = max(startPos - offset, 0);
    int ePos = min(endPos - offset, (int)m_len);

    if (sPos >= ePos)
        return;

    context->save();

    Color c = Color(225, 221, 85);
    
    updateGraphicsContext(context, c, c, 0); // Don't draw text at all!

    int y = selectionTop();
    int h = selectionHeight();
    context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
    context->restore();
}
示例#12
0
void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f, bool grammar)
{
    // Never print spelling/grammar markers (5327887)
    if (textObject()->document()->printing())
        return;

    if (m_truncation == cFullTruncation)
        return;

    int start = 0;                  // start of line to draw, relative to tx
    int width = m_width;            // how much line to draw

    // Determine whether we need to measure text
    bool markerSpansWholeBox = true;
    if (m_start <= (int)marker.startOffset)
        markerSpansWholeBox = false;
    if ((end() + 1) != marker.endOffset)      // end points at the last char, not past it
        markerSpansWholeBox = false;
    if (m_truncation != cNoTruncation)
        markerSpansWholeBox = false;

    if (!markerSpansWholeBox || grammar) {
        int startPosition = max<int>(marker.startOffset - m_start, 0);
        int endPosition = min<int>(marker.endOffset - m_start, m_len);
        
        if (m_truncation != cNoTruncation)
            endPosition = min<int>(endPosition, m_truncation);

        // Calculate start & width
        IntPoint startPoint(tx + m_x, ty + selectionTop());
        TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
        int h = selectionHeight();
        
        IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, startPosition, endPosition));
        start = markerRect.x() - startPoint.x();
        width = markerRect.width();
        
        // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to
        // display a toolTip. We don't do this for misspelling markers.
        if (grammar)
            object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
    }
    
    // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
    // make sure to fit within those bounds.  This means the top pixel(s) of the underline will overlap the
    // bottom pixel(s) of the glyphs in smaller font sizes.  The alternatives are to increase the line spacing (bad!!)
    // or decrease the underline thickness.  The overlap is actually the most useful, and matches what AppKit does.
    // So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
    // we pin to two pixels under the baseline.
    int lineThickness = cMisspellingLineThickness;
    int descent = m_height - m_baseline;
    int underlineOffset;
    if (descent <= (2 + lineThickness)) {
        // place the underline at the very bottom of the text in small/medium fonts
        underlineOffset = m_height - lineThickness;
    } else {
        // in larger fonts, tho, place the underline up near the baseline to prevent big gap
        underlineOffset = m_baseline + 2;
    }
    pt->drawLineForMisspellingOrBadGrammar(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, grammar);
}
示例#13
0
int RootInlineBox::blockDirectionPointInLine() const
{
    return !blockFlow().style().isFlippedBlocksWritingMode() ? std::max(lineTop(), selectionTop()) : std::min(lineBottom(), selectionBottom());
}