Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
      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 
     21 #include "config.h"
     22 #include "core/rendering/RenderDetailsMarker.h"
     23 
     24 #include "HTMLNames.h"
     25 #include "core/dom/Element.h"
     26 #include "core/platform/graphics/GraphicsContext.h"
     27 #include "core/rendering/PaintInfo.h"
     28 
     29 namespace WebCore {
     30 
     31 using namespace HTMLNames;
     32 
     33 RenderDetailsMarker::RenderDetailsMarker(Element* element)
     34     : RenderBlock(element)
     35 {
     36 }
     37 
     38 static Path createPath(const FloatPoint* path)
     39 {
     40     Path result;
     41     result.moveTo(FloatPoint(path[0].x(), path[0].y()));
     42     for (int i = 1; i < 4; ++i)
     43         result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
     44     return result;
     45 }
     46 
     47 static Path createDownArrowPath()
     48 {
     49     FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
     50     return createPath(points);
     51 }
     52 
     53 static Path createUpArrowPath()
     54 {
     55     FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
     56     return createPath(points);
     57 }
     58 
     59 static Path createLeftArrowPath()
     60 {
     61     FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
     62     return createPath(points);
     63 }
     64 
     65 static Path createRightArrowPath()
     66 {
     67     FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
     68     return createPath(points);
     69 }
     70 
     71 RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
     72 {
     73     switch (style()->writingMode()) {
     74     case TopToBottomWritingMode:
     75         if (style()->isLeftToRightDirection())
     76             return isOpen() ? Down : Right;
     77         return isOpen() ? Down : Left;
     78     case RightToLeftWritingMode:
     79         if (style()->isLeftToRightDirection())
     80             return isOpen() ? Left : Down;
     81         return isOpen() ? Left : Up;
     82     case LeftToRightWritingMode:
     83         if (style()->isLeftToRightDirection())
     84             return isOpen() ? Right : Down;
     85         return isOpen() ? Right : Up;
     86     case BottomToTopWritingMode:
     87         if (style()->isLeftToRightDirection())
     88             return isOpen() ? Up : Right;
     89         return isOpen() ? Up : Left;
     90     }
     91     return Right;
     92 }
     93 
     94 Path RenderDetailsMarker::getCanonicalPath() const
     95 {
     96     switch (orientation()) {
     97     case Left: return createLeftArrowPath();
     98     case Right: return createRightArrowPath();
     99     case Up: return createUpArrowPath();
    100     case Down: return createDownArrowPath();
    101     }
    102 
    103     return Path();
    104 }
    105 
    106 Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
    107 {
    108     Path result = getCanonicalPath();
    109     result.transform(AffineTransform().scale(contentWidth(), contentHeight()));
    110     result.translate(FloatSize(origin.x(), origin.y()));
    111     return result;
    112 }
    113 
    114 void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    115 {
    116     if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
    117         RenderBlock::paint(paintInfo, paintOffset);
    118         return;
    119     }
    120 
    121     LayoutPoint boxOrigin(paintOffset + location());
    122     LayoutRect overflowRect(visualOverflowRect());
    123     overflowRect.moveBy(boxOrigin);
    124     overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
    125 
    126     if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
    127         return;
    128 
    129     const Color color(resolveColor(CSSPropertyColor));
    130     paintInfo.context->setStrokeColor(color);
    131     paintInfo.context->setStrokeStyle(SolidStroke);
    132     paintInfo.context->setStrokeThickness(1.0f);
    133     paintInfo.context->setFillColor(color);
    134 
    135     boxOrigin.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
    136     paintInfo.context->fillPath(getPath(boxOrigin));
    137 }
    138 
    139 bool RenderDetailsMarker::isOpen() const
    140 {
    141     for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
    142         if (!renderer->node())
    143             continue;
    144         if (renderer->node()->hasTagName(detailsTag))
    145             return !toElement(renderer->node())->getAttribute(openAttr).isNull();
    146         if (renderer->node()->hasTagName(inputTag))
    147             return true;
    148     }
    149 
    150     return false;
    151 }
    152 
    153 }
    154