Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / paint / InlinePainter.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/paint/InlinePainter.h"
7
8 #include "core/paint/BoxPainter.h"
9 #include "core/paint/LineBoxListPainter.h"
10 #include "core/paint/ObjectPainter.h"
11 #include "core/rendering/GraphicsContextAnnotator.h"
12 #include "core/rendering/PaintInfo.h"
13 #include "core/rendering/RenderInline.h"
14 #include "core/rendering/RenderTheme.h"
15 #include "core/rendering/RootInlineBox.h"
16 #include "platform/geometry/LayoutPoint.h"
17
18 namespace blink {
19
20 void InlinePainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
21 {
22     ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderInline);
23     LineBoxListPainter(*m_renderInline.lineBoxes()).paint(&m_renderInline, paintInfo, paintOffset);
24 }
25
26 void InlinePainter::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
27 {
28     RenderStyle* styleToUse = m_renderInline.style();
29     if (!styleToUse->hasOutline())
30         return;
31
32     if (styleToUse->outlineStyleIsAuto()) {
33         if (RenderTheme::theme().shouldDrawDefaultFocusRing(&m_renderInline)) {
34             // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
35             ObjectPainter(m_renderInline).paintFocusRing(paintInfo, paintOffset, styleToUse);
36         }
37         return;
38     }
39
40     if (styleToUse->outlineStyle() == BNONE)
41         return;
42
43     Vector<LayoutRect> rects;
44
45     rects.append(LayoutRect());
46     for (InlineFlowBox* curr = m_renderInline.firstLineBox(); curr; curr = curr->nextLineBox()) {
47         RootInlineBox& root = curr->root();
48         LayoutUnit top = std::max<LayoutUnit>(root.lineTop(), curr->logicalTop());
49         LayoutUnit bottom = std::min<LayoutUnit>(root.lineBottom(), curr->logicalBottom());
50         rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
51     }
52     rects.append(LayoutRect());
53
54     Color outlineColor = m_renderInline.resolveColor(styleToUse, CSSPropertyOutlineColor);
55     bool useTransparencyLayer = outlineColor.hasAlpha();
56
57     GraphicsContext* graphicsContext = paintInfo.context;
58     if (useTransparencyLayer) {
59         graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
60         outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
61     }
62
63     for (unsigned i = 1; i < rects.size() - 1; i++)
64         paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
65
66     if (useTransparencyLayer)
67         graphicsContext->endLayer();
68 }
69
70 void InlinePainter::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset,
71     const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline, const Color outlineColor)
72 {
73     RenderStyle* styleToUse = m_renderInline.style();
74     int outlineWidth = styleToUse->outlineWidth();
75     EBorderStyle outlineStyle = styleToUse->outlineStyle();
76
77     bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext);
78
79     int offset = m_renderInline.style()->outlineOffset();
80
81     LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset),
82         LayoutSize(thisline.width() + offset, thisline.height() + offset));
83
84     IntRect pixelSnappedBox = pixelSnappedIntRect(box);
85     if (pixelSnappedBox.width() < 0 || pixelSnappedBox.height() < 0)
86         return;
87     IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
88     IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
89
90     // left edge
91     ObjectPainter::drawLineForBoxSide(graphicsContext,
92         pixelSnappedBox.x() - outlineWidth,
93         pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
94         pixelSnappedBox.x(),
95         pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
96         BSLeft,
97         outlineColor, outlineStyle,
98         (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
99         (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
100         antialias);
101
102     // right edge
103     ObjectPainter::drawLineForBoxSide(graphicsContext,
104         pixelSnappedBox.maxX(),
105         pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0),
106         pixelSnappedBox.maxX() + outlineWidth,
107         pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0),
108         BSRight,
109         outlineColor, outlineStyle,
110         (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth),
111         (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth),
112         antialias);
113     // upper edge
114     if (thisline.x() < lastline.x()) {
115         ObjectPainter::drawLineForBoxSide(graphicsContext,
116             pixelSnappedBox.x() - outlineWidth,
117             pixelSnappedBox.y() - outlineWidth,
118             std::min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())),
119             pixelSnappedBox.y(),
120             BSTop, outlineColor, outlineStyle,
121             outlineWidth,
122             (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
123             antialias);
124     }
125
126     if (lastline.maxX() < thisline.maxX()) {
127         ObjectPainter::drawLineForBoxSide(graphicsContext,
128             std::max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth),
129             pixelSnappedBox.y() - outlineWidth,
130             pixelSnappedBox.maxX() + outlineWidth,
131             pixelSnappedBox.y(),
132             BSTop, outlineColor, outlineStyle,
133             (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth,
134             outlineWidth, antialias);
135     }
136
137     if (thisline.x() == thisline.maxX()) {
138         ObjectPainter::drawLineForBoxSide(graphicsContext,
139             pixelSnappedBox.x() - outlineWidth,
140             pixelSnappedBox.y() - outlineWidth,
141             pixelSnappedBox.maxX() + outlineWidth,
142             pixelSnappedBox.y(),
143             BSTop, outlineColor, outlineStyle,
144             outlineWidth,
145             outlineWidth,
146             antialias);
147     }
148
149     // lower edge
150     if (thisline.x() < nextline.x()) {
151         ObjectPainter::drawLineForBoxSide(graphicsContext,
152             pixelSnappedBox.x() - outlineWidth,
153             pixelSnappedBox.maxY(),
154             std::min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000),
155             pixelSnappedBox.maxY() + outlineWidth,
156             BSBottom, outlineColor, outlineStyle,
157             outlineWidth,
158             (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
159             antialias);
160     }
161
162     if (nextline.maxX() < thisline.maxX()) {
163         ObjectPainter::drawLineForBoxSide(graphicsContext,
164             std::max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
165             pixelSnappedBox.maxY(),
166             pixelSnappedBox.maxX() + outlineWidth,
167             pixelSnappedBox.maxY() + outlineWidth,
168             BSBottom, outlineColor, outlineStyle,
169             (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth,
170             outlineWidth, antialias);
171     }
172
173     if (thisline.x() == thisline.maxX()) {
174         ObjectPainter::drawLineForBoxSide(graphicsContext,
175             pixelSnappedBox.x() - outlineWidth,
176             pixelSnappedBox.maxY(),
177             pixelSnappedBox.maxX() + outlineWidth,
178             pixelSnappedBox.maxY() + outlineWidth,
179             BSBottom, outlineColor, outlineStyle,
180             outlineWidth,
181             outlineWidth,
182             antialias);
183     }
184 }
185
186 } // namespace blink