SimpleLineLayoutFunctions.cpp 6.72 KB
Newer Older
antti@apple.com's avatar
antti@apple.com committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "SimpleLineLayoutFunctions.h"

#include "FontCache.h"
30
#include "Frame.h"
antti@apple.com's avatar
antti@apple.com committed
31
32
33
34
35
36
37
38
39
40
#include "GraphicsContext.h"
#include "HitTestLocation.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
#include "LineWidth.h"
#include "PaintInfo.h"
#include "RenderBlockFlow.h"
#include "RenderStyle.h"
#include "RenderText.h"
antti@apple.com's avatar
antti@apple.com committed
41
#include "RenderView.h"
42
#include "Settings.h"
antti@apple.com's avatar
antti@apple.com committed
43
44
45
46
47
48
49
50
#include "SimpleLineLayoutResolver.h"
#include "Text.h"
#include "TextPaintStyle.h"
#include <wtf/unicode/Unicode.h>

namespace WebCore {
namespace SimpleLineLayout {

51
52
static void paintDebugBorders(GraphicsContext& context, const LayoutRect& borderRect, const LayoutPoint& paintOffset)
{
53
54
    if (borderRect.isEmpty())
        return;
55
56
57
58
59
60
61
62
    GraphicsContextStateSaver stateSaver(context);
    context.setStrokeColor(Color(0, 255, 0), ColorSpaceDeviceRGB);
    context.setFillColor(Color::transparent, ColorSpaceDeviceRGB);
    IntRect rect(pixelSnappedIntRect(borderRect));
    rect.moveBy(flooredIntPoint(paintOffset));
    context.drawRect(rect);
}

63
void paintFlow(const RenderBlockFlow& flow, const Layout& layout, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
antti@apple.com's avatar
antti@apple.com committed
64
65
66
67
68
69
{
    if (paintInfo.phase != PaintPhaseForeground)
        return;
    RenderText& textRenderer = toRenderText(*flow.firstChild());
    ASSERT(!textRenderer.firstTextBox());

70
71
    bool debugBordersEnabled = flow.frame().settings().simpleLineLayoutDebugBordersEnabled();

72
    RenderStyle& style = flow.style();
antti@apple.com's avatar
antti@apple.com committed
73
74
75
76
77
78
79
80
81
    const Font& font = style.font();

    GraphicsContext& context = *paintInfo.context;

    TextPaintStyle textPaintStyle = computeTextPaintStyle(textRenderer, style, paintInfo);
    GraphicsContextStateSaver stateSaver(context, textPaintStyle.strokeWidth > 0);

    updateGraphicsContext(context, textPaintStyle);

82
    auto resolver = runResolver(flow, layout);
antti@apple.com's avatar
antti@apple.com committed
83
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
84
        auto run = *it;
85
86
87
        TextRun textRun(run.text());
        textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
        context.drawText(font, textRun, run.baseline() + paintOffset);
88
89
        if (debugBordersEnabled)
            paintDebugBorders(context, run.rect(), paintOffset);
antti@apple.com's avatar
antti@apple.com committed
90
91
92
    }
}

93
bool hitTestFlow(const RenderBlockFlow& flow, const Layout& layout, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
antti@apple.com's avatar
antti@apple.com committed
94
95
96
97
{
    if (hitTestAction != HitTestForeground)
        return false;

98
    if (!layout.runCount())
antti@apple.com's avatar
antti@apple.com committed
99
100
        return false;

101
    RenderStyle& style = flow.style();
antti@apple.com's avatar
antti@apple.com committed
102
103
104
105
106
    if (style.visibility() != VISIBLE || style.pointerEvents() == PE_NONE)
        return false;

    RenderText& textRenderer = toRenderText(*flow.firstChild());

107
    auto resolver = lineResolver(flow, layout);
antti@apple.com's avatar
antti@apple.com committed
108
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
109
        auto lineRect = *it;
antti@apple.com's avatar
antti@apple.com committed
110
111
112
113
114
115
116
117
118
119
120
        lineRect.moveBy(accumulatedOffset);
        if (!locationInContainer.intersects(lineRect))
            continue;
        textRenderer.updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
        if (!result.addNodeToRectBasedTestResult(textRenderer.textNode(), request, locationInContainer, lineRect))
            return true;
    }

    return false;
}

121
void collectFlowOverflow(RenderBlockFlow& flow, const Layout& layout)
antti@apple.com's avatar
antti@apple.com committed
122
{
123
    auto resolver = lineResolver(flow, layout);
antti@apple.com's avatar
antti@apple.com committed
124
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
125
        auto rect = *it;
antti@apple.com's avatar
antti@apple.com committed
126
127
128
129
130
        flow.addLayoutOverflow(rect);
        flow.addVisualOverflow(rect);
    }
}

131
IntRect computeTextBoundingBox(const RenderText& textRenderer, const Layout& layout)
antti@apple.com's avatar
antti@apple.com committed
132
{
133
    auto resolver = lineResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
antti@apple.com's avatar
antti@apple.com committed
134
135
136
137
    auto it = resolver.begin();
    auto end = resolver.end();
    if (it == end)
        return IntRect();
138
    auto firstLineRect = *it;
antti@apple.com's avatar
antti@apple.com committed
139
140
    float left = firstLineRect.x();
    float right = firstLineRect.maxX();
141
    float bottom = firstLineRect.maxY();
antti@apple.com's avatar
antti@apple.com committed
142
    for (++it; it != end; ++it) {
143
        auto rect = *it;
antti@apple.com's avatar
antti@apple.com committed
144
145
146
147
        if (rect.x() < left)
            left = rect.x();
        if (rect.maxX() > right)
            right = rect.maxX();
148
149
        if (rect.maxY() > bottom)
            bottom = rect.maxY();
antti@apple.com's avatar
antti@apple.com committed
150
151
152
153
    }
    float x = firstLineRect.x();
    float y = firstLineRect.y();
    float width = right - left;
154
    float height = bottom - y;
antti@apple.com's avatar
antti@apple.com committed
155
156
157
    return enclosingIntRect(FloatRect(x, y, width, height));
}

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
Vector<IntRect> collectTextAbsoluteRects(const RenderText& textRenderer, const Layout& layout, const LayoutPoint& accumulatedOffset)
{
    Vector<IntRect> rects;
    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
        auto run = *it;
        auto rect = run.rect();
        rects.append(enclosingIntRect(FloatRect(accumulatedOffset + rect.location(), rect.size())));
    }
    return rects;
}

Vector<FloatQuad> collectTextAbsoluteQuads(const RenderText& textRenderer, const Layout& layout, bool* wasFixed)
{
    Vector<FloatQuad> quads;
    auto resolver = runResolver(toRenderBlockFlow(*textRenderer.parent()), layout);
    for (auto it = resolver.begin(), end = resolver.end(); it != end; ++it) {
        auto run = *it;
        auto rect = run.rect();
        quads.append(textRenderer.localToAbsoluteQuad(FloatQuad(rect), 0, wasFixed));
    }
    return quads;
}

antti@apple.com's avatar
antti@apple.com committed
182
183
}
}