1 /** 2 * Copyright (C) 2003, 2006 Apple Computer, Inc. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "core/rendering/EllipsisBox.h" 22 23 #include "core/platform/graphics/DrawLooper.h" 24 #include "core/platform/graphics/Font.h" 25 #include "core/platform/graphics/GraphicsContextStateSaver.h" 26 #include "core/platform/graphics/TextRun.h" 27 #include "core/rendering/HitTestResult.h" 28 #include "core/rendering/InlineTextBox.h" 29 #include "core/rendering/PaintInfo.h" 30 #include "core/rendering/RenderBlock.h" 31 #include "core/rendering/RootInlineBox.h" 32 #include "core/rendering/style/ShadowData.h" 33 34 namespace WebCore { 35 36 void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) 37 { 38 GraphicsContext* context = paintInfo.context; 39 RenderStyle* style = m_renderer->style(isFirstLineStyle()); 40 Color styleTextColor = m_renderer->resolveColor(style, CSSPropertyWebkitTextFillColor); 41 if (styleTextColor != context->fillColor()) 42 context->setFillColor(styleTextColor); 43 44 Color textColor = styleTextColor; 45 const Font& font = style->font(); 46 if (selectionState() != RenderObject::SelectionNone) { 47 paintSelection(context, paintOffset, style, font); 48 49 // Select the correct color for painting the text. 50 Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor(); 51 if (foreground != Color::transparent && foreground != styleTextColor) 52 context->setFillColor(foreground); 53 } 54 55 // Text shadows are disabled when printing. http://crbug.com/258321 56 const ShadowData* shadow = context->printing() ? 0 : style->textShadow(); 57 bool hasShadow = shadow; 58 if (hasShadow) { 59 DrawLooper drawLooper; 60 do { 61 int shadowX = isHorizontal() ? shadow->x() : shadow->y(); 62 int shadowY = isHorizontal() ? shadow->y() : -shadow->x(); 63 FloatSize offset(shadowX, shadowY); 64 drawLooper.addShadow(offset, shadow->blur(), 65 m_renderer->resolveColor(shadow->color(), Color::stdShadowColor), 66 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha); 67 } while ((shadow = shadow->next())); 68 drawLooper.addUnmodifiedContent(); 69 context->setDrawLooper(drawLooper); 70 } 71 72 // FIXME: Why is this always LTR? Fix by passing correct text run flags below. 73 FloatPoint boxOrigin(paintOffset); 74 boxOrigin.move(x(), y()); 75 FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight())); 76 FloatPoint textOrigin(boxOrigin.x(), boxOrigin.y() + style->fontMetrics().ascent()); 77 TextRun textRun = RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion); 78 TextRunPaintInfo textRunPaintInfo(textRun); 79 textRunPaintInfo.bounds = boxRect; 80 context->drawText(font, textRunPaintInfo, textOrigin); 81 82 // Restore the regular fill color. 83 if (styleTextColor != context->fillColor()) 84 context->setFillColor(styleTextColor); 85 86 if (hasShadow) 87 context->clearDrawLooper(); 88 89 paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style); 90 } 91 92 InlineBox* EllipsisBox::markupBox() const 93 { 94 if (!m_shouldPaintMarkupBox || !m_renderer->isRenderBlock()) 95 return 0; 96 97 RenderBlock* block = toRenderBlock(m_renderer); 98 RootInlineBox* lastLine = block->lineAtIndex(block->lineCount() - 1); 99 if (!lastLine) 100 return 0; 101 102 // If the last line-box on the last line of a block is a link, -webkit-line-clamp paints that box after the ellipsis. 103 // It does not actually move the link. 104 InlineBox* anchorBox = lastLine->lastChild(); 105 if (!anchorBox || !anchorBox->renderer()->style()->isLink()) 106 return 0; 107 108 return anchorBox; 109 } 110 111 void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, RenderStyle* style) 112 { 113 InlineBox* markupBox = this->markupBox(); 114 if (!markupBox) 115 return; 116 117 LayoutPoint adjustedPaintOffset = paintOffset; 118 adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(), 119 y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent())); 120 markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom); 121 } 122 123 IntRect EllipsisBox::selectionRect() 124 { 125 RenderStyle* style = m_renderer->style(isFirstLineStyle()); 126 const Font& font = style->font(); 127 // FIXME: Why is this always LTR? Fix by passing correct text run flags below. 128 return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + root()->selectionTopAdjustedForPrecedingBlock()), root()->selectionHeightAdjustedForPrecedingBlock())); 129 } 130 131 void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& paintOffset, RenderStyle* style, const Font& font) 132 { 133 Color textColor = m_renderer->resolveColor(style, CSSPropertyColor); 134 Color c = m_renderer->selectionBackgroundColor(); 135 if (!c.alpha()) 136 return; 137 138 // If the text color ends up being the same as the selection background, invert the selection 139 // background. 140 if (textColor == c) 141 c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue()); 142 143 GraphicsContextStateSaver stateSaver(*context); 144 LayoutUnit top = root()->selectionTop(); 145 LayoutUnit h = root()->selectionHeight(); 146 FloatRect clipRect(x() + paintOffset.x(), top + paintOffset.y(), m_logicalWidth, h); 147 alignSelectionRectToDevicePixels(clipRect); 148 context->clip(clipRect); 149 // FIXME: Why is this always LTR? Fix by passing correct text run flags below. 150 context->drawHighlightForText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), roundedIntPoint(LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + top)), h, c); 151 } 152 153 bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) 154 { 155 LayoutPoint adjustedLocation = accumulatedOffset + roundedLayoutPoint(topLeft()); 156 157 // Hit test the markup box. 158 if (InlineBox* markupBox = this->markupBox()) { 159 RenderStyle* style = m_renderer->style(isFirstLineStyle()); 160 LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x(); 161 LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent()); 162 if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) { 163 renderer()->updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty)); 164 return true; 165 } 166 } 167 168 LayoutRect boundsRect(adjustedLocation, LayoutSize(m_logicalWidth, m_height)); 169 if (visibleToHitTestRequest(request) && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) { 170 renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation)); 171 if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, boundsRect)) 172 return true; 173 } 174 175 return false; 176 } 177 178 } // namespace WebCore 179