File: InlineDisplayLine.h

package info (click to toggle)
webkit2gtk 2.48.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 429,764 kB
  • sloc: cpp: 3,697,587; javascript: 194,444; ansic: 169,997; python: 46,499; asm: 19,295; ruby: 18,528; perl: 16,602; xml: 4,650; yacc: 2,360; sh: 2,098; java: 1,993; lex: 1,327; pascal: 366; makefile: 298
file content (207 lines) | stat: -rw-r--r-- 9,924 bytes parent folder | download | duplicates (7)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * Copyright (C) 2020 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.
 */

#pragma once

#include "FontBaseline.h"
#include "InlineRect.h"
#include "TextRun.h"
#include "TextUtil.h"
#include <wtf/TZoneMallocInlines.h>

namespace WebCore {
namespace InlineDisplay {

class Line {
    WTF_MAKE_TZONE_ALLOCATED_INLINE(Line);
public:
    struct EnclosingTopAndBottom {
        // This values encloses the root inline box and any other inline level box's border box.
        float top { 0 };
        float bottom { 0 };
    };
    Line(const FloatRect& lineBoxLogicalRect, const FloatRect& lineBoxRect, const FloatRect& contentOverflow, EnclosingTopAndBottom, float alignmentBaseline, FontBaseline baselineType, float contentLogicalLeft, float contentLogicalLeftIgnoringInlineDirection, float contentLogicalWidth, bool isLeftToRightDirection, bool isHorizontal, bool isTruncatedInBlockDirection);

    float left() const { return m_lineBoxRect.x(); }
    float right() const { return m_lineBoxRect.maxX(); }
    float top() const { return m_lineBoxRect.y(); }
    float bottom() const { return m_lineBoxRect.maxY(); }

    FloatPoint topLeft() const { return m_lineBoxRect.location(); }

    float lineBoxTop() const { return m_lineBoxRect.y(); }
    float lineBoxBottom() const { return m_lineBoxRect.maxY(); }
    float lineBoxLeft() const { return m_lineBoxRect.x(); }
    float lineBoxRight() const { return m_lineBoxRect.maxX(); }
    float lineBoxHeight() const { return m_lineBoxRect.height(); }
    float lineBoxWidth() const { return m_lineBoxRect.width(); }

    const FloatRect& lineBoxRect() const { return m_lineBoxRect; }
    const FloatRect& lineBoxLogicalRect() const { return m_lineBoxLogicalRect; }
    const FloatRect& scrollableOverflow() const { return m_scrollableOverflow; }
    const FloatRect& contentOverflow() const { return m_contentOverflow; }
    const FloatRect& inkOverflow() const { return m_inkOverflow; }

    FloatRect visibleRectIgnoringBlockDirection() const;

    float enclosingContentLogicalTop() const { return m_enclosingLogicalTopAndBottom.top; }
    float enclosingContentLogicalBottom() const { return m_enclosingLogicalTopAndBottom.bottom; }

    float baseline() const { return m_alignmentBaseline; }
    FontBaseline baselineType() const { return m_baselineType; }

    bool isHorizontal() const { return m_isHorizontal; }
    bool isLeftToRightInlineDirection() const { return m_isLeftToRightDirection; }

    float contentLogicalLeft() const { return m_contentLogicalLeft; }
    // This is "visual" left in inline direction (it is still considered logical as there's no flip for writing mode).
    float contentLogicalLeftIgnoringInlineDirection() const { return m_contentLogicalLeftIgnoringInlineDirection; }
    float contentLogicalWidth() const { return m_contentLogicalWidth; }

    size_t firstBoxIndex() const { return m_firstBoxIndex; }
    size_t lastBoxIndex() const { return firstBoxIndex() + boxCount() - 1; }
    size_t boxCount() const { return m_boxCount; }
    bool isFirstAfterPageBreak() const { return m_isFirstAfterPageBreak; }

    void moveInBlockDirection(float offset, bool isHorizontalWritingMode);
    struct Ellipsis {
        enum class Type : uint8_t { Inline, Block };
        Type type { Type::Inline };
        // This is visual rect ignoring block direction.
        FloatRect visualRect;
        AtomString text;
    };
    void setEllipsis(const Ellipsis& ellipsis) { m_ellipsis = ellipsis; }
    std::optional<Ellipsis> ellipsis() const { return m_ellipsis; }
    bool hasEllipsis() const { return !!m_ellipsis; }

    bool isFullyTruncatedInBlockDirection() const { return m_isFullyTruncatedInBlockDirection; }

    bool hasContentAfterEllipsisBox() const { return m_hasContentAfterEllipsisBox; }
    void setHasContentAfterEllipsisBox() { m_hasContentAfterEllipsisBox = true; }

    void setFirstBoxIndex(size_t firstBoxIndex) { m_firstBoxIndex = firstBoxIndex; }
    void setBoxCount(size_t boxCount) { m_boxCount = boxCount; }
    void setIsFirstAfterPageBreak() { m_isFirstAfterPageBreak = true; }
    void setInkOverflow(const FloatRect inkOverflowRect) { m_inkOverflow = inkOverflowRect; }
    void setScrollableOverflow(const FloatRect scrollableOverflow) { m_scrollableOverflow = scrollableOverflow; }
    void setLineBoxRectForSVGText(const FloatRect&);

private:
    // FIXME: Move these to a side structure.
    size_t m_firstBoxIndex { 0 };
    size_t m_boxCount { 0 };

    // This is line box geometry (see https://www.w3.org/TR/css-inline-3/#line-box).
    FloatRect m_lineBoxRect;
    FloatRect m_lineBoxLogicalRect;
    FloatRect m_scrollableOverflow;
    // FIXME: Merge this with scrollable overflow (see InlineContentBuilder::updateLineOverflow).
    FloatRect m_contentOverflow;
    // FIXME: This should be transitioned to spec aligned overflow value.
    FloatRect m_inkOverflow;
    // Enclosing top and bottom includes all inline level boxes (border box) vertically.
    // While the line box usually enclose them as well, its vertical geometry is based on
    // the layout bounds of the inline level boxes which may be different when line-height is present.
    EnclosingTopAndBottom m_enclosingLogicalTopAndBottom;
    float m_alignmentBaseline { 0.f };
    // Content is mostly in flush with the line box edge except for cases like text-align.
    float m_contentLogicalLeft { 0.f };
    float m_contentLogicalLeftIgnoringInlineDirection { 0.f };
    float m_contentLogicalWidth { 0.f };
    FontBaseline m_baselineType { AlphabeticBaseline };
    bool m_isLeftToRightDirection : 1 { true };
    bool m_isHorizontal : 1 { true };
    bool m_isFirstAfterPageBreak : 1 { false };
    bool m_isFullyTruncatedInBlockDirection : 1 { false };
    bool m_hasContentAfterEllipsisBox : 1 { false };
    std::optional<Ellipsis> m_ellipsis { };
};

inline Line::Line(const FloatRect& lineBoxLogicalRect, const FloatRect& lineBoxRect, const FloatRect& contentOverflow, EnclosingTopAndBottom enclosingLogicalTopAndBottom, float alignmentBaseline, FontBaseline baselineType, float contentLogicalLeft, float contentLogicalLeftIgnoringInlineDirection, float contentLogicalWidth, bool isLeftToRightDirection, bool isHorizontal, bool isTruncatedInBlockDirection)
    : m_lineBoxRect(lineBoxRect)
    , m_lineBoxLogicalRect(lineBoxLogicalRect)
    , m_contentOverflow(contentOverflow)
    , m_enclosingLogicalTopAndBottom(enclosingLogicalTopAndBottom)
    , m_alignmentBaseline(alignmentBaseline)
    , m_contentLogicalLeft(contentLogicalLeft)
    , m_contentLogicalLeftIgnoringInlineDirection(contentLogicalLeftIgnoringInlineDirection)
    , m_contentLogicalWidth(contentLogicalWidth)
    , m_baselineType(baselineType)
    , m_isLeftToRightDirection(isLeftToRightDirection)
    , m_isHorizontal(isHorizontal)
    , m_isFullyTruncatedInBlockDirection(isTruncatedInBlockDirection)
{
}

inline void Line::moveInBlockDirection(float offset, bool isHorizontalWritingMode)
{
    ASSERT(isHorizontalWritingMode == m_isHorizontal);

    if (!offset)
        return;

    auto physicalOffset = isHorizontalWritingMode ? FloatSize { { }, offset } : FloatSize { offset, { } };

    m_lineBoxRect.move(physicalOffset);
    m_scrollableOverflow.move(physicalOffset);
    m_contentOverflow.move(physicalOffset);
    m_inkOverflow.move(physicalOffset);
    if (m_ellipsis)
        m_ellipsis->visualRect.move(physicalOffset);

    m_lineBoxLogicalRect.move({ { }, offset });
    m_enclosingLogicalTopAndBottom.top += offset;
    m_enclosingLogicalTopAndBottom.bottom += offset;
}

inline FloatRect Line::visibleRectIgnoringBlockDirection() const
{
    if (m_isFullyTruncatedInBlockDirection)
        return { };
    if (!hasEllipsis() || hasContentAfterEllipsisBox())
        return m_inkOverflow;
    if (m_isLeftToRightDirection) {
        auto visibleLineBoxRight = std::min(m_lineBoxRect.maxX(), m_ellipsis->visualRect.maxX());
        return { m_lineBoxRect.location(), FloatPoint { visibleLineBoxRight, m_lineBoxRect.maxY() } };
    }
    auto visibleLineBoxLeft = std::max(m_lineBoxRect.x(), m_ellipsis->visualRect.x());
    return { FloatPoint { visibleLineBoxLeft, m_lineBoxRect.y() }, FloatPoint { m_lineBoxRect.maxX(), m_lineBoxRect.maxY() } };
}

inline void Line::setLineBoxRectForSVGText(const FloatRect& rect)
{
    m_lineBoxRect = rect;
    m_scrollableOverflow = rect;
    m_contentOverflow = rect;
    m_inkOverflow = rect;
    m_lineBoxLogicalRect = m_isHorizontal ? rect : rect.transposedRect();
    m_enclosingLogicalTopAndBottom.top = m_lineBoxLogicalRect.y();
    m_enclosingLogicalTopAndBottom.bottom = m_lineBoxLogicalRect.maxY();
}

}
}