15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/** 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2003, 2006 Apple Computer, Inc. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/EllipsisBox.h" 2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/HitTestResult.h" 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/InlineTextBox.h" 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/PaintInfo.h" 26c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/rendering/RenderBlock.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RootInlineBox.h" 287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/TextPainter.h" 29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/rendering/TextRunConstructor.h" 30f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "core/rendering/style/ShadowList.h" 31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/Font.h" 32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h" 33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/text/TextRun.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContext* context = paintInfo.context; 40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RenderStyle* style = renderer().style(isFirstLineStyle()); 4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const Font& font = style->font(); 4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatPoint boxOrigin = locationIncludingFlipping(); 43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) boxOrigin.moveBy(FloatPoint(paintOffset)); 4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!isHorizontal()) 45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) boxOrigin.move(0, -virtualLogicalHeight()); 4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), virtualLogicalHeight())); 4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*context); 4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!isHorizontal()) 4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise)); 507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci FloatPoint textOrigin(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent()); 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool isPrinting = renderer().document().printing(); 537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone; 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (haveSelection) 5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) paintSelection(context, boxOrigin, style, font); 577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci else if (paintInfo.phase == PaintPhaseSelection) 587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return; 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TextPainter::Style textStyle = TextPainter::textPaintingStyle(renderer(), style, paintInfo.forceBlackText(), isPrinting); 617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (haveSelection) 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci textStyle = TextPainter::selectionPaintingStyle(renderer(), true, paintInfo.forceBlackText(), isPrinting, textStyle); 6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 64c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) TextRun textRun = constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion); 657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TextPainter textPainter(context, font, textRun, textOrigin, boxRect, isHorizontal()); 667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci textPainter.paint(0, m_str.length(), m_str.length(), textStyle); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)InlineBox* EllipsisBox::markupBox() const 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 73d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!m_shouldPaintMarkupBox || !renderer().isRenderBlock()) 74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 0; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RenderBlock& block = toRenderBlock(renderer()); 77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RootInlineBox* lastLine = block.lineAtIndex(block.lineCount() - 1); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!lastLine) 79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 0; 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the last line-box on the last line of a block is a link, -webkit-line-clamp paints that box after the ellipsis. 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // It does not actually move the link. 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InlineBox* anchorBox = lastLine->lastChild(); 84d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!anchorBox || !anchorBox->renderer().style()->isLink()) 85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return 0; 86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return anchorBox; 88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, RenderStyle* style) 91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) InlineBox* markupBox = this->markupBox(); 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (!markupBox) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutPoint adjustedPaintOffset = paintOffset; 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(), 98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent())); 99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect EllipsisBox::selectionRect() 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 104d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RenderStyle* style = renderer().style(isFirstLineStyle()); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const Font& font = style->font(); 106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return enclosingIntRect(font.selectionRectForText(constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(logicalLeft(), logicalTop() + root().selectionTopAdjustedForPrecedingBlock()), root().selectionHeightAdjustedForPrecedingBlock())); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void EllipsisBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) Color textColor = renderer().resolveColor(style, CSSPropertyColor); 112d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) Color c = renderer().selectionBackgroundColor(); 11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!c.alpha()) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If the text color ends up being the same as the selection background, invert the selection 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // background. 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (textColor == c) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) GraphicsContextStateSaver stateSaver(*context); 122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) LayoutUnit selectionBottom = root().selectionBottom(); 123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) LayoutUnit top = root().selectionTop(); 124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) LayoutUnit h = root().selectionHeight(); 125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) const int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - top); 12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY); 127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, h.toFloat())); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) context->clip(clipRect); 129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) context->drawHighlightForText(font, constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), localOrigin, h, c); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LayoutPoint adjustedLocation = accumulatedOffset + roundedLayoutPoint(topLeft()); 135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Hit test the markup box. 137926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (InlineBox* markupBox = this->markupBox()) { 138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RenderStyle* style = renderer().style(isFirstLineStyle()); 139926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x(); 140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent()); 141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) { 142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) renderer().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty)); 143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatPoint boxOrigin = locationIncludingFlipping(); 14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) boxOrigin.moveBy(accumulatedOffset); 14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect boundsRect(boxOrigin, size()); 15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (visibleToHitTestRequest(request) && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) { 151d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation)); 152d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, boundsRect)) 153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return true; 154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 159c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 160