summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/geometry/physical_offset.h
blob: a2e93b6e48e989d9472ed225513d04752511381e (plain)
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
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/text/writing_direction_mode.h"

namespace blink {

class LayoutPoint;
class LayoutSize;
struct LogicalOffset;
struct PhysicalSize;

// PhysicalOffset is the position of a rect (typically a fragment) relative to
// its parent rect in the physical coordinate system.
// For more information about physical and logical coordinate systems, see:
// https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/layout/README.md#coordinate-spaces
struct CORE_EXPORT PhysicalOffset {
  constexpr PhysicalOffset() = default;
  constexpr PhysicalOffset(LayoutUnit left, LayoutUnit top)
      : left(left), top(top) {}

  // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
  inline PhysicalOffset(int left, int top);

  LayoutUnit left;
  LayoutUnit top;

  // Converts a physical offset to a logical offset. See:
  // https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
  // @param outer_size the size of the rect (typically a fragment).
  // @param inner_size the size of the inner rect (typically a child fragment).
  LogicalOffset ConvertToLogical(WritingDirectionMode writing_direction,
                                 PhysicalSize outer_size,
                                 PhysicalSize inner_size) const;
  LogicalOffset ConvertToLogical(WritingMode writing_mode,
                                 TextDirection direction,
                                 PhysicalSize outer_size,
                                 PhysicalSize inner_size) const;

  constexpr bool IsZero() const { return !left && !top; }
  constexpr bool HasFraction() const {
    return left.HasFraction() || top.HasFraction();
  }

  void ClampNegativeToZero() {
    left = std::max(left, LayoutUnit());
    top = std::max(top, LayoutUnit());
  }

  PhysicalOffset operator+(const PhysicalOffset& other) const {
    return PhysicalOffset{this->left + other.left, this->top + other.top};
  }
  PhysicalOffset& operator+=(const PhysicalOffset& other) {
    *this = *this + other;
    return *this;
  }

  PhysicalOffset operator-() const {
    return PhysicalOffset{-this->left, -this->top};
  }
  PhysicalOffset operator-(const PhysicalOffset& other) const {
    return PhysicalOffset{this->left - other.left, this->top - other.top};
  }
  PhysicalOffset& operator-=(const PhysicalOffset& other) {
    *this = *this - other;
    return *this;
  }

  constexpr bool operator==(const PhysicalOffset& other) const {
    return other.left == left && other.top == top;
  }

  constexpr bool operator!=(const PhysicalOffset& other) const {
    return !(*this == other);
  }

  // Conversions from/to existing code. New code prefers type safety for
  // logical/physical distinctions.
  constexpr explicit PhysicalOffset(const LayoutPoint& point)
      : left(point.X()), top(point.Y()) {}
  constexpr explicit PhysicalOffset(const LayoutSize& size)
      : left(size.Width()), top(size.Height()) {}

  // Conversions from/to existing code. New code prefers type safety for
  // logical/physical distinctions.
  constexpr LayoutPoint ToLayoutPoint() const { return {left, top}; }
  constexpr LayoutSize ToLayoutSize() const { return {left, top}; }

  explicit PhysicalOffset(const IntPoint& point)
      : left(point.X()), top(point.Y()) {}
  explicit PhysicalOffset(const IntSize& size)
      : left(size.Width()), top(size.Height()) {}
  explicit PhysicalOffset(const gfx::Point& point)
      : left(point.x()), top(point.y()) {}

  static PhysicalOffset FromFloatPointFloor(const FloatPoint& point) {
    return {LayoutUnit::FromFloatFloor(point.X()),
            LayoutUnit::FromFloatFloor(point.Y())};
  }
  static PhysicalOffset FromFloatPointRound(const FloatPoint& point) {
    return {LayoutUnit::FromFloatRound(point.X()),
            LayoutUnit::FromFloatRound(point.Y())};
  }
  static PhysicalOffset FromFloatSizeFloor(const FloatSize& size) {
    return {LayoutUnit::FromFloatFloor(size.Width()),
            LayoutUnit::FromFloatFloor(size.Height())};
  }
  static PhysicalOffset FromFloatSizeRound(const FloatSize& size) {
    return {LayoutUnit::FromFloatRound(size.Width()),
            LayoutUnit::FromFloatRound(size.Height())};
  }

  void Scale(float s) {
    left *= s;
    top *= s;
  }

  constexpr explicit operator FloatPoint() const { return {left, top}; }
  constexpr explicit operator FloatSize() const { return {left, top}; }

  String ToString() const;
};

// TODO(crbug.com/962299): These functions should upgraded to force correct
// pixel snapping in a type-safe way.
inline IntPoint RoundedIntPoint(const PhysicalOffset& o) {
  return {o.left.Round(), o.top.Round()};
}
inline IntPoint FlooredIntPoint(const PhysicalOffset& o) {
  return {o.left.Floor(), o.top.Floor()};
}
inline IntPoint CeiledIntPoint(const PhysicalOffset& o) {
  return {o.left.Ceil(), o.top.Ceil()};
}

// TODO(wangxianzhu): For temporary conversion from LayoutPoint/LayoutSize to
// PhysicalOffset, where the input will be changed to PhysicalOffset soon, to
// avoid redundant PhysicalOffset() which can't be discovered by the compiler.
inline PhysicalOffset PhysicalOffsetToBeNoop(const LayoutPoint& p) {
  return PhysicalOffset(p);
}
inline PhysicalOffset PhysicalOffsetToBeNoop(const LayoutSize& s) {
  return PhysicalOffset(s);
}

CORE_EXPORT std::ostream& operator<<(std::ostream&, const PhysicalOffset&);

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_