| /* |
| * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #include "config.h" |
| #include "RenderDetailsMarker.h" |
| |
| #include "Element.h" |
| #include "GraphicsContext.h" |
| #include "HTMLDetailsElement.h" |
| #include "HTMLInputElement.h" |
| #include "HTMLNames.h" |
| #include "PaintInfo.h" |
| #include <wtf/IsoMallocInlines.h> |
| |
| namespace WebCore { |
| |
| using namespace HTMLNames; |
| |
| WTF_MAKE_ISO_ALLOCATED_IMPL(RenderDetailsMarker); |
| |
| RenderDetailsMarker::RenderDetailsMarker(DetailsMarkerControl& element, RenderStyle&& style) |
| : RenderBlockFlow(element, WTFMove(style)) |
| { |
| } |
| |
| static Path createPath(const FloatPoint* path) |
| { |
| Path result; |
| result.moveTo(FloatPoint(path[0].x(), path[0].y())); |
| for (int i = 1; i < 4; ++i) |
| result.addLineTo(FloatPoint(path[i].x(), path[i].y())); |
| return result; |
| } |
| |
| static Path createDownArrowPath() |
| { |
| FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) }; |
| return createPath(points); |
| } |
| |
| static Path createUpArrowPath() |
| { |
| FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) }; |
| return createPath(points); |
| } |
| |
| static Path createLeftArrowPath() |
| { |
| FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) }; |
| return createPath(points); |
| } |
| |
| static Path createRightArrowPath() |
| { |
| FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) }; |
| return createPath(points); |
| } |
| |
| RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const |
| { |
| switch (style().writingMode()) { |
| case TopToBottomWritingMode: |
| if (style().isLeftToRightDirection()) |
| return isOpen() ? Down : Right; |
| return isOpen() ? Down : Left; |
| case RightToLeftWritingMode: |
| if (style().isLeftToRightDirection()) |
| return isOpen() ? Left : Down; |
| return isOpen() ? Left : Up; |
| case LeftToRightWritingMode: |
| if (style().isLeftToRightDirection()) |
| return isOpen() ? Right : Down; |
| return isOpen() ? Right : Up; |
| case BottomToTopWritingMode: |
| if (style().isLeftToRightDirection()) |
| return isOpen() ? Up : Right; |
| return isOpen() ? Up : Left; |
| } |
| return Right; |
| } |
| |
| Path RenderDetailsMarker::getCanonicalPath() const |
| { |
| switch (orientation()) { |
| case Left: return createLeftArrowPath(); |
| case Right: return createRightArrowPath(); |
| case Up: return createUpArrowPath(); |
| case Down: return createDownArrowPath(); |
| } |
| |
| return Path(); |
| } |
| |
| Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const |
| { |
| Path result = getCanonicalPath(); |
| result.transform(AffineTransform().scale(contentWidth(), contentHeight())); |
| result.translate(FloatSize(origin.x(), origin.y())); |
| return result; |
| } |
| |
| void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
| { |
| if (paintInfo.phase != PaintPhase::Foreground || style().visibility() != Visibility::Visible) { |
| RenderBlockFlow::paint(paintInfo, paintOffset); |
| return; |
| } |
| |
| LayoutPoint boxOrigin(paintOffset + location()); |
| LayoutRect overflowRect(visualOverflowRect()); |
| overflowRect.moveBy(boxOrigin); |
| |
| if (!paintInfo.rect.intersects(snappedIntRect(overflowRect))) |
| return; |
| |
| const Color color(style().visitedDependentColorWithColorFilter(CSSPropertyColor)); |
| paintInfo.context().setStrokeColor(color); |
| paintInfo.context().setStrokeStyle(SolidStroke); |
| paintInfo.context().setStrokeThickness(1.0f); |
| paintInfo.context().setFillColor(color); |
| |
| boxOrigin.move(borderLeft() + paddingLeft(), borderTop() + paddingTop()); |
| paintInfo.context().fillPath(getPath(boxOrigin)); |
| } |
| |
| bool RenderDetailsMarker::isOpen() const |
| { |
| for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) { |
| if (!renderer->node()) |
| continue; |
| if (is<HTMLDetailsElement>(*renderer->node())) |
| return !downcast<HTMLDetailsElement>(*renderer->node()).attributeWithoutSynchronization(openAttr).isNull(); |
| if (is<HTMLInputElement>(*renderer->node())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| } |