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 "core/HTMLNames.h"
     25 #include "core/dom/Element.h"
     26 #include "core/html/HTMLElement.h"
     27 #include "core/rendering/PaintInfo.h"
     28 #include "platform/graphics/GraphicsContext.h"
     29 
     30 namespace WebCore {
     31 
     32 using namespace HTMLNames;
     33 
     34 RenderDetailsMarker::RenderDetailsMarker(Element* element)
     35     : RenderBlockFlow(element)
     36 {
     37 }
     38 
     39 static Path createPath(const FloatPoint* path)
     40 {
     41     Path result;
     42     result.moveTo(FloatPoint(path[0].x(), path[0].y()));
     43     for (int i = 1; i < 4; ++i)
     44         result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
     45     return result;
     46 }
     47 
     48 static Path createDownArrowPath()
     49 {
     50     FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
     51     return createPath(points);
     52 }
     53 
     54 static Path createUpArrowPath()
     55 {
     56     FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
     57     return createPath(points);
     58 }
     59 
     60 static Path createLeftArrowPath()
     61 {
     62     FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
     63     return createPath(points);
     64 }
     65 
     66 static Path createRightArrowPath()
     67 {
     68     FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
     69     return createPath(points);
     70 }
     71 
     72 RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
     73 {
     74     switch (style()->writingMode()) {
     75     case TopToBottomWritingMode:
     76         if (style()->isLeftToRightDirection())
     77             return isOpen() ? Down : Right;
     78         return isOpen() ? Down : Left;
     79     case RightToLeftWritingMode:
     80         if (style()->isLeftToRightDirection())
     81             return isOpen() ? Left : Down;
     82         return isOpen() ? Left : Up;
     83     case LeftToRightWritingMode:
     84         if (style()->isLeftToRightDirection())
     85             return isOpen() ? Right : Down;
     86         return isOpen() ? Right : Up;
     87     case BottomToTopWritingMode:
     88         if (style()->isLeftToRightDirection())
     89             return isOpen() ? Up : Right;
     90         return isOpen() ? Up : Left;
     91     }
     92     return Right;
     93 }
     94 
     95 Path RenderDetailsMarker::getCanonicalPath() const
     96 {
     97     switch (orientation()) {
     98     case Left: return createLeftArrowPath();
     99     case Right: return createRightArrowPath();
    100     case Up: return createUpArrowPath();
    101     case Down: return createDownArrowPath();
    102     }
    103 
    104     return Path();
    105 }
    106 
    107 Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
    108 {
    109     Path result = getCanonicalPath();
    110     result.transform(AffineTransform().scale(contentWidth().toFloat(), contentHeight().toFloat()));
    111     result.translate(FloatSize(origin.x().toFloat(), origin.y().toFloat()));
    112     return result;
    113 }
    114 
    115 void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    116 {
    117     if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
    118         RenderBlock::paint(paintInfo, paintOffset);
    119         return;
    120     }
    121 
    122     LayoutPoint boxOrigin(paintOffset + location());
    123     LayoutRect overflowRect(visualOverflowRect());
    124     overflowRect.moveBy(boxOrigin);
    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 (isHTMLDetailsElement(*renderer->node()))
    145             return !toElement(renderer->node())->getAttribute(openAttr).isNull();
    146         if (isHTMLInputElement(*renderer->node()))
    147             return true;
    148     }
    149 
    150     return false;
    151 }
    152 
    153 }
    154