Home | History | Annotate | Download | only in rendering
      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 "EllipsisBox.h"
     22 
     23 #include "Document.h"
     24 #include "GraphicsContext.h"
     25 #include "HitTestResult.h"
     26 #include "PaintInfo.h"
     27 #include "RootInlineBox.h"
     28 #include "TextRun.h"
     29 
     30 namespace WebCore {
     31 
     32 void EllipsisBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)
     33 {
     34     GraphicsContext* context = paintInfo.context;
     35     RenderStyle* style = m_renderer->style(m_firstLine);
     36     Color textColor = style->visitedDependentColor(CSSPropertyColor);
     37     if (textColor != context->fillColor())
     38         context->setFillColor(textColor, style->colorSpace());
     39     bool setShadow = false;
     40     if (style->textShadow()) {
     41         context->setShadow(IntSize(style->textShadow()->x(), style->textShadow()->y()),
     42                            style->textShadow()->blur(), style->textShadow()->color(), style->colorSpace());
     43         setShadow = true;
     44     }
     45 
     46     if (selectionState() != RenderObject::SelectionNone) {
     47         paintSelection(context, tx, ty, style, style->font());
     48 
     49         // Select the correct color for painting the text.
     50         Color foreground = paintInfo.forceBlackText ? Color::black : renderer()->selectionForegroundColor();
     51         if (foreground.isValid() && foreground != textColor)
     52             context->setFillColor(foreground, style->colorSpace());
     53     }
     54 
     55     const String& str = m_str;
     56     context->drawText(style->font(), TextRun(str.characters(), str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + style->fontMetrics().ascent()));
     57 
     58     // Restore the regular fill color.
     59     if (textColor != context->fillColor())
     60         context->setFillColor(textColor, style->colorSpace());
     61 
     62     if (setShadow)
     63         context->clearShadow();
     64 
     65     if (m_markupBox) {
     66         // Paint the markup box
     67         tx += m_x + m_logicalWidth - m_markupBox->x();
     68         ty += m_y + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent());
     69         m_markupBox->paint(paintInfo, tx, ty, lineTop, lineBottom);
     70     }
     71 }
     72 
     73 IntRect EllipsisBox::selectionRect(int tx, int ty)
     74 {
     75     RenderStyle* style = m_renderer->style(m_firstLine);
     76     const Font& f = style->font();
     77     return enclosingIntRect(f.selectionRectForText(TextRun(m_str.characters(), m_str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()),
     78             IntPoint(m_x + tx, m_y + ty + root()->selectionTop()), root()->selectionHeight()));
     79 }
     80 
     81 void EllipsisBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font)
     82 {
     83     Color textColor = style->visitedDependentColor(CSSPropertyColor);
     84     Color c = m_renderer->selectionBackgroundColor();
     85     if (!c.isValid() || !c.alpha())
     86         return;
     87 
     88     // If the text color ends up being the same as the selection background, invert the selection
     89     // background.
     90     if (textColor == c)
     91         c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
     92 
     93     context->save();
     94     int y = root()->selectionTop();
     95     int h = root()->selectionHeight();
     96     context->clip(IntRect(m_x + tx, y + ty, m_logicalWidth, h));
     97     context->drawHighlightForText(font, TextRun(m_str.characters(), m_str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()),
     98         IntPoint(m_x + tx, m_y + ty + y), h, c, style->colorSpace());
     99     context->restore();
    100 }
    101 
    102 bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, int lineTop, int lineBottom)
    103 {
    104     tx += m_x;
    105     ty += m_y;
    106 
    107     // Hit test the markup box.
    108     if (m_markupBox) {
    109         RenderStyle* style = m_renderer->style(m_firstLine);
    110         int mtx = tx + m_logicalWidth - m_markupBox->x();
    111         int mty = ty + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent());
    112         if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty, lineTop, lineBottom)) {
    113             renderer()->updateHitTestResult(result, IntPoint(x - mtx, y - mty));
    114             return true;
    115         }
    116     }
    117 
    118     IntRect boundsRect = IntRect(tx, ty, m_logicalWidth, m_height);
    119     if (visibleToHitTesting() && boundsRect.intersects(result.rectForPoint(x, y))) {
    120         renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
    121         if (!result.addNodeToRectBasedTestResult(renderer()->node(), x, y, boundsRect))
    122             return true;
    123     }
    124 
    125     return false;
    126 }
    127 
    128 } // namespace WebCore
    129