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 "RenderDetailsMarker.h"
     23 
     24 #include "GraphicsContext.h"
     25 #include "HTMLNames.h"
     26 #include "PaintInfo.h"
     27 #include "RenderDetails.h"
     28 
     29 namespace WebCore {
     30 
     31 using namespace HTMLNames;
     32 
     33 RenderDetailsMarker::RenderDetailsMarker(Node* node)
     34     : RenderBlock(node)
     35 {
     36 }
     37 
     38 bool RenderDetailsMarker::isOpen() const
     39 {
     40     if (RenderDetails* owner = details())
     41         return owner->isOpen();
     42     return false;
     43 }
     44 
     45 static Path createPath(const FloatPoint* path)
     46 {
     47     Path result;
     48     result.moveTo(FloatPoint(path[0].x(), path[0].y()));
     49     for (int i = 1; i < 4; ++i)
     50         result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
     51     return result;
     52 }
     53 
     54 static Path createDownArrowPath()
     55 {
     56     FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
     57     return createPath(points);
     58 }
     59 
     60 static Path createUpArrowPath()
     61 {
     62     FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
     63     return createPath(points);
     64 }
     65 
     66 static Path createLeftArrowPath()
     67 {
     68     FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
     69     return createPath(points);
     70 }
     71 
     72 static Path createRightArrowPath()
     73 {
     74     FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
     75     return createPath(points);
     76 }
     77 
     78 RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
     79 {
     80     switch (style()->writingMode()) {
     81     case TopToBottomWritingMode:
     82         if (style()->isLeftToRightDirection())
     83             return isOpen() ? Down : Right;
     84         return isOpen() ? Down : Left;
     85     case RightToLeftWritingMode:
     86         if (style()->isLeftToRightDirection())
     87             return isOpen() ? Left : Down;
     88         return isOpen() ? Left : Up;
     89     case LeftToRightWritingMode:
     90         if (style()->isLeftToRightDirection())
     91             return isOpen() ? Right : Down;
     92         return isOpen() ? Right : Up;
     93     case BottomToTopWritingMode:
     94         if (style()->isLeftToRightDirection())
     95             return isOpen() ? Up : Right;
     96         return isOpen() ? Up : Left;
     97     }
     98     return Right;
     99 }
    100 
    101 Path RenderDetailsMarker::getCanonicalPath() const
    102 {
    103     switch (orientation()) {
    104     case Left: return createLeftArrowPath();
    105     case Right: return createRightArrowPath();
    106     case Up: return createUpArrowPath();
    107     case Down: return createDownArrowPath();
    108     }
    109 
    110     return Path();
    111 }
    112 
    113 Path RenderDetailsMarker::getPath(const IntPoint& origin) const
    114 {
    115     Path result = getCanonicalPath();
    116     result.transform(AffineTransform().scale(logicalHeight()));
    117     result.translate(FloatSize(origin.x(), origin.y()));
    118     return result;
    119 }
    120 
    121 void RenderDetailsMarker::paint(PaintInfo& paintInfo, int tx, int ty)
    122 {
    123     if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
    124         RenderBlock::paint(paintInfo, tx, ty);
    125         return;
    126     }
    127 
    128     IntPoint boxOrigin(tx + x(), ty + y());
    129     IntRect overflowRect(visualOverflowRect());
    130     overflowRect.move(boxOrigin.x(), boxOrigin.y());
    131     overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
    132 
    133     if (!paintInfo.rect.intersects(overflowRect))
    134         return;
    135 
    136     const Color color(style()->visitedDependentColor(CSSPropertyColor));
    137     paintInfo.context->setStrokeColor(color, style()->colorSpace());
    138     paintInfo.context->setStrokeStyle(SolidStroke);
    139     paintInfo.context->setStrokeThickness(1.0f);
    140     paintInfo.context->setFillColor(color, style()->colorSpace());
    141 
    142     paintInfo.context->fillPath(getPath(boxOrigin));
    143 }
    144 
    145 RenderDetails* RenderDetailsMarker::details() const
    146 {
    147     for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
    148         if (renderer->isDetails())
    149             return toRenderDetails(renderer);
    150     }
    151 
    152     return 0;
    153 }
    154 
    155 }
    156