File: GridBaselineAlignment.h

package info (click to toggle)
wpewebkit 2.38.6-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 311,508 kB
  • sloc: cpp: 2,653,313; javascript: 289,013; ansic: 121,268; xml: 64,149; python: 35,534; ruby: 17,287; perl: 15,877; asm: 11,072; yacc: 2,326; sh: 1,863; lex: 1,319; java: 937; makefile: 146; pascal: 60
file content (179 lines) | stat: -rw-r--r-- 8,845 bytes parent folder | download | duplicates (2)
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
/*
 * Copyright (C) 2018 Igalia S.L. 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 "GridLayoutFunctions.h"
#include "RenderStyleConstants.h"
#include "WritingMode.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>

namespace WebCore {

// These classes are used to implement the Baseline Alignment logic, as described in the CSS Box Alignment
// specification.
// https://drafts.csswg.org/css-align/#baseline-terms
//
// A baseline-sharing group is composed of boxes that participate in baseline alignment together. This is
// possible only if they:
//
//   * Share an alignment context along an axis perpendicular to their baseline alignment axis.
//   * Have compatible baseline alignment preferences (i.e., the baselines that want to align are on the same
//     side of the alignment context).
//
// Once the BaselineGroup is instantiated, defined by a 'block-direction' (WritingMode) and a 'baseline-preference'
// (first/last baseline), it's ready to collect the items that will participate in the Baseline Alignment logic.
//
class BaselineGroup {
public:
    // It stores an item (if not already present) and update the max_ascent associated to this
    // baseline-sharing group.
    void update(const RenderBox&, LayoutUnit ascent);
    LayoutUnit maxAscent() const { return m_maxAscent; }
    int size() const { return m_items.size(); }

private:
    friend class BaselineContext;
    BaselineGroup(WritingMode blockFlow, ItemPosition childPreference);

    // Determines whether a baseline-sharing group is compatible with an item, based on its 'block-flow' and
    // 'baseline-preference'
    bool isCompatible(WritingMode, ItemPosition) const;

    // Determines whether the baseline-sharing group's associated block-flow is opposite (LR vs RL) to particular
    // item's writing-mode.
    bool isOppositeBlockFlow(WritingMode blockFlow) const;

    // Determines whether the baseline-sharing group's associated block-flow is orthogonal (vertical vs horizontal)
    // to particular item's writing-mode.
    bool isOrthogonalBlockFlow(WritingMode blockFlow) const;

    WritingMode m_blockFlow;
    ItemPosition m_preference;
    LayoutUnit m_maxAscent;
    HashSet<const RenderBox*> m_items;
};

// https://drafts.csswg.org/css-align-3/#shared-alignment-context
// Boxes share an alignment context along a particular axis when they are:
//
//  * table cells in the same row, along the table's row (inline) axis
//  * table cells in the same column, along the table's column (block) axis
//  * grid items in the same row, along the grid's row (inline) axis
//  * grid items in the same column, along the grid's colum (block) axis
//  * flex items in the same flex line, along the flex container's main axis
//
// https://drafts.csswg.org/css-align-3/#baseline-sharing-group
// A Baseline alignment-context may handle several baseline-sharing groups. In order to create an instance, we
// need to pass the required data to define the first baseline-sharing group; a Baseline Context must have at
// least one baseline-sharing group.
//
// By adding new items to a Baseline Context, the baseline-sharing groups it handles are automatically updated,
// if there is one that is compatible with such item. Otherwise, a new baseline-sharing group is created,
// compatible with the new item.
class BaselineContext {
    WTF_MAKE_FAST_ALLOCATED;
public:
    BaselineContext(const RenderBox& child, ItemPosition preference, LayoutUnit ascent);
    const BaselineGroup& sharedGroup(const RenderBox& child, ItemPosition preference) const;

    // Updates the baseline-sharing group compatible with the item.
    // We pass the item's baseline-preference to avoid dependencies with the LayoutGrid class, which is the one
    // managing the alignment behavior of the Grid Items.
    void updateSharedGroup(const RenderBox& child, ItemPosition preference, LayoutUnit ascent);

private:
    // Returns the baseline-sharing group compatible with an item.
    // We pass the item's baseline-preference to avoid dependencies with the LayoutGrid class, which is the one
    // managing the alignment behavior of the Grid Items.
    // FIXME: Properly implement baseline-group compatibility.
    // See https://github.com/w3c/csswg-drafts/issues/721
    BaselineGroup& findCompatibleSharedGroup(const RenderBox& child, ItemPosition preference);

    Vector<BaselineGroup> m_sharedGroups;
};

enum AllowedBaseLine {FirstLine, LastLine, BothLines};

static inline bool isBaselinePosition(ItemPosition position)
{
    return position == ItemPosition::Baseline || position == ItemPosition::LastBaseline;
}

static inline bool isFirstBaselinePosition(ItemPosition position)
{
    return position == ItemPosition::Baseline;
}

// This is the class that implements the Baseline Alignment logic, using internally the BaselineContext and
// BaselineGroupd classes (described above).
//
// The first phase is to collect the items that will participate in baseline alignment together. During this
// phase the required baseline-sharing groups will be created for each Baseline alignment-context shared by
// the items participating in the baseline alignment.
//
// Additionally, the baseline-sharing groups' offsets, max-ascend and max-descent will be computed and stored.
// This class also computes the baseline offset for a particular item, based on the max-ascent for its associated
// baseline-sharing group.
class GridBaselineAlignment {
public:
    // Collects the items participating in baseline alignment and updates the corresponding baseline-sharing
    // group of the Baseline Context the items belongs to.
    // All the baseline offsets are updated accordingly based on the added item.
    void updateBaselineAlignmentContext(ItemPosition, unsigned sharedContext, const RenderBox&, GridAxis);

    // Returns the baseline offset of a particular item, based on the max-ascent for its associated
    // baseline-sharing group
    LayoutUnit baselineOffsetForChild(ItemPosition, unsigned sharedContext, const RenderBox&, GridAxis) const;

    // Sets the Grid Container's writing-mode so that we can avoid the dependecy of the LayoutGrid class for
    // determining whether a grid item is orthogonal or not.
    void setBlockFlow(WritingMode blockFlow) { m_blockFlow = blockFlow; };

    // Clearing the Baseline Alignment context and their internal classes and data structures.
    void clear(GridAxis);

private:
    const BaselineGroup& baselineGroupForChild(ItemPosition, unsigned sharedContext, const RenderBox&, GridAxis) const;
    LayoutUnit marginOverForChild(const RenderBox&, GridAxis) const;
    LayoutUnit marginUnderForChild(const RenderBox&, GridAxis) const;
    LayoutUnit logicalAscentForChild(const RenderBox&, GridAxis) const;
    LayoutUnit ascentForChild(const RenderBox&, GridAxis) const;
    LayoutUnit descentForChild(const RenderBox&, LayoutUnit, GridAxis) const;
    bool isDescentBaselineForChild(const RenderBox&, GridAxis) const;
    bool isHorizontalBaselineAxis(GridAxis) const;
    bool isOrthogonalChildForBaseline(const RenderBox&) const;
    bool isParallelToBaselineAxisForChild(const RenderBox&, GridAxis) const;

    typedef HashMap<unsigned, std::unique_ptr<BaselineContext>, DefaultHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> BaselineContextsMap;

    // Grid Container's WritingMode, used to determine grid item's orthogonality.
    WritingMode m_blockFlow;
    BaselineContextsMap m_rowAxisAlignmentContext;
    BaselineContextsMap m_colAxisAlignmentContext;
};

} // namespace WebCore