1 // Copyright 2016 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 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_
7 
8 #include "third_party/blink/renderer/core/core_export.h"
9 #include "third_party/blink/renderer/platform/geometry/layout_point.h"
10 #include "third_party/blink/renderer/platform/geometry/layout_size.h"
11 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
12 #include "third_party/blink/renderer/platform/text/text_direction.h"
13 #include "third_party/blink/renderer/platform/text/writing_mode.h"
14 
15 namespace blink {
16 
17 class LayoutPoint;
18 class LayoutSize;
19 struct LogicalOffset;
20 struct PhysicalSize;
21 
22 // PhysicalOffset is the position of a rect (typically a fragment) relative to
23 // its parent rect in the physical coordinate system.
24 // For more information about physical and logical coordinate systems, see:
25 // https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/layout/README.md#coordinate-spaces
26 struct CORE_EXPORT PhysicalOffset {
27   constexpr PhysicalOffset() = default;
PhysicalOffsetPhysicalOffset28   constexpr PhysicalOffset(LayoutUnit left, LayoutUnit top)
29       : left(left), top(top) {}
30 
31   // For testing only. It's defined in core/testing/core_unit_test_helpers.h.
32   inline PhysicalOffset(int left, int top);
33 
34   LayoutUnit left;
35   LayoutUnit top;
36 
37   // Converts a physical offset to a logical offset. See:
38   // https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
39   // @param outer_size the size of the rect (typically a fragment).
40   // @param inner_size the size of the inner rect (typically a child fragment).
41   LogicalOffset ConvertToLogical(WritingMode,
42                                  TextDirection,
43                                  PhysicalSize outer_size,
44                                  PhysicalSize inner_size) const;
45 
IsZeroPhysicalOffset46   constexpr bool IsZero() const { return !left && !top; }
HasFractionPhysicalOffset47   constexpr bool HasFraction() const {
48     return left.HasFraction() || top.HasFraction();
49   }
50 
ClampNegativeToZeroPhysicalOffset51   void ClampNegativeToZero() {
52     left = std::max(left, LayoutUnit());
53     top = std::max(top, LayoutUnit());
54   }
55 
56   PhysicalOffset operator+(const PhysicalOffset& other) const {
57     return PhysicalOffset{this->left + other.left, this->top + other.top};
58   }
59   PhysicalOffset& operator+=(const PhysicalOffset& other) {
60     *this = *this + other;
61     return *this;
62   }
63 
64   PhysicalOffset operator-() const {
65     return PhysicalOffset{-this->left, -this->top};
66   }
67   PhysicalOffset operator-(const PhysicalOffset& other) const {
68     return PhysicalOffset{this->left - other.left, this->top - other.top};
69   }
70   PhysicalOffset& operator-=(const PhysicalOffset& other) {
71     *this = *this - other;
72     return *this;
73   }
74 
75   constexpr bool operator==(const PhysicalOffset& other) const {
76     return other.left == left && other.top == top;
77   }
78 
79   constexpr bool operator!=(const PhysicalOffset& other) const {
80     return !(*this == other);
81   }
82 
83   // Conversions from/to existing code. New code prefers type safety for
84   // logical/physical distinctions.
PhysicalOffsetPhysicalOffset85   constexpr explicit PhysicalOffset(const LayoutPoint& point)
86       : left(point.X()), top(point.Y()) {}
PhysicalOffsetPhysicalOffset87   constexpr explicit PhysicalOffset(const LayoutSize& size)
88       : left(size.Width()), top(size.Height()) {}
89 
90   // Conversions from/to existing code. New code prefers type safety for
91   // logical/physical distinctions.
ToLayoutPointPhysicalOffset92   constexpr LayoutPoint ToLayoutPoint() const { return {left, top}; }
ToLayoutSizePhysicalOffset93   constexpr LayoutSize ToLayoutSize() const { return {left, top}; }
94 
PhysicalOffsetPhysicalOffset95   explicit PhysicalOffset(const IntPoint& point)
96       : left(point.X()), top(point.Y()) {}
PhysicalOffsetPhysicalOffset97   explicit PhysicalOffset(const IntSize& size)
98       : left(size.Width()), top(size.Height()) {}
PhysicalOffsetPhysicalOffset99   explicit PhysicalOffset(const gfx::Point& point)
100       : left(point.x()), top(point.y()) {}
101 
FromFloatPointFloorPhysicalOffset102   static PhysicalOffset FromFloatPointFloor(const FloatPoint& point) {
103     return {LayoutUnit::FromFloatFloor(point.X()),
104             LayoutUnit::FromFloatFloor(point.Y())};
105   }
FromFloatPointRoundPhysicalOffset106   static PhysicalOffset FromFloatPointRound(const FloatPoint& point) {
107     return {LayoutUnit::FromFloatRound(point.X()),
108             LayoutUnit::FromFloatRound(point.Y())};
109   }
FromFloatSizeFloorPhysicalOffset110   static PhysicalOffset FromFloatSizeFloor(const FloatSize& size) {
111     return {LayoutUnit::FromFloatFloor(size.Width()),
112             LayoutUnit::FromFloatFloor(size.Height())};
113   }
FromFloatSizeRoundPhysicalOffset114   static PhysicalOffset FromFloatSizeRound(const FloatSize& size) {
115     return {LayoutUnit::FromFloatRound(size.Width()),
116             LayoutUnit::FromFloatRound(size.Height())};
117   }
118 
FloatPointPhysicalOffset119   constexpr explicit operator FloatPoint() const { return {left, top}; }
FloatSizePhysicalOffset120   constexpr explicit operator FloatSize() const { return {left, top}; }
121 
122   String ToString() const;
123 };
124 
125 // TODO(crbug.com/962299): These functions should upgraded to force correct
126 // pixel snapping in a type-safe way.
RoundedIntPoint(const PhysicalOffset & o)127 inline IntPoint RoundedIntPoint(const PhysicalOffset& o) {
128   return {o.left.Round(), o.top.Round()};
129 }
FlooredIntPoint(const PhysicalOffset & o)130 inline IntPoint FlooredIntPoint(const PhysicalOffset& o) {
131   return {o.left.Floor(), o.top.Floor()};
132 }
CeiledIntPoint(const PhysicalOffset & o)133 inline IntPoint CeiledIntPoint(const PhysicalOffset& o) {
134   return {o.left.Ceil(), o.top.Ceil()};
135 }
136 
137 // TODO(wangxianzhu): For temporary conversion from LayoutPoint/LayoutSize to
138 // PhysicalOffset, where the input will be changed to PhysicalOffset soon, to
139 // avoid redundant PhysicalOffset() which can't be discovered by the compiler.
PhysicalOffsetToBeNoop(const LayoutPoint & p)140 inline PhysicalOffset PhysicalOffsetToBeNoop(const LayoutPoint& p) {
141   return PhysicalOffset(p);
142 }
PhysicalOffsetToBeNoop(const LayoutSize & s)143 inline PhysicalOffset PhysicalOffsetToBeNoop(const LayoutSize& s) {
144   return PhysicalOffset(s);
145 }
146 
147 CORE_EXPORT std::ostream& operator<<(std::ostream&, const PhysicalOffset&);
148 
149 }  // namespace blink
150 
151 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_PHYSICAL_OFFSET_H_
152