1 // Copyright 2014 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 #include <algorithm>
6 
7 #include "base/macros.h"
8 #include "base/strings/stringprintf.h"
9 #include "ui/gfx/geometry/point_conversions.h"
10 #include "ui/gfx/geometry/rect.h"
11 #include "ui/gfx/geometry/rect_f.h"
12 #include "ui/gfx/selection_bound.h"
13 
14 namespace gfx {
15 
SelectionBound()16 SelectionBound::SelectionBound() : type_(EMPTY), visible_(false) {}
17 
18 SelectionBound::SelectionBound(const SelectionBound& other) = default;
19 
~SelectionBound()20 SelectionBound::~SelectionBound() {}
21 
SetEdgeStart(const gfx::PointF & value)22 void SelectionBound::SetEdgeStart(const gfx::PointF& value) {
23   edge_start_ = value;
24   edge_start_rounded_ = gfx::ToRoundedPoint(value);
25 }
26 
SetVisibleEdgeStart(const gfx::PointF & value)27 void SelectionBound::SetVisibleEdgeStart(const gfx::PointF& value) {
28   visible_edge_start_ = value;
29 }
30 
SetEdgeEnd(const gfx::PointF & value)31 void SelectionBound::SetEdgeEnd(const gfx::PointF& value) {
32   edge_end_ = value;
33   edge_end_rounded_ = gfx::ToRoundedPoint(value);
34 }
35 
SetVisibleEdgeEnd(const gfx::PointF & value)36 void SelectionBound::SetVisibleEdgeEnd(const gfx::PointF& value) {
37   visible_edge_end_ = value;
38 }
39 
SetEdge(const gfx::PointF & start,const gfx::PointF & end)40 void SelectionBound::SetEdge(const gfx::PointF& start, const gfx::PointF& end) {
41   SetEdgeStart(start);
42   SetEdgeEnd(end);
43 }
44 
SetVisibleEdge(const gfx::PointF & start,const gfx::PointF & end)45 void SelectionBound::SetVisibleEdge(const gfx::PointF& start,
46                                     const gfx::PointF& end) {
47   SetVisibleEdgeStart(start);
48   SetVisibleEdgeEnd(end);
49 }
50 
GetHeight() const51 int SelectionBound::GetHeight() const {
52   return edge_end_rounded_.y() - edge_start_rounded_.y();
53 }
54 
ToString() const55 std::string SelectionBound::ToString() const {
56   return base::StringPrintf(
57       "SelectionBound(%s, %s, %s, %s, %d)", edge_start_.ToString().c_str(),
58       edge_end_.ToString().c_str(), edge_start_rounded_.ToString().c_str(),
59       edge_end_rounded_.ToString().c_str(), visible_);
60 }
61 
operator ==(const SelectionBound & lhs,const SelectionBound & rhs)62 bool operator==(const SelectionBound& lhs, const SelectionBound& rhs) {
63   return lhs.type() == rhs.type() && lhs.visible() == rhs.visible() &&
64          lhs.edge_start() == rhs.edge_start() &&
65          lhs.edge_end() == rhs.edge_end() &&
66          lhs.visible_edge_start() == rhs.visible_edge_start() &&
67          lhs.visible_edge_end() == rhs.visible_edge_end();
68 }
69 
operator !=(const SelectionBound & lhs,const SelectionBound & rhs)70 bool operator!=(const SelectionBound& lhs, const SelectionBound& rhs) {
71   return !(lhs == rhs);
72 }
73 
RectBetweenSelectionBounds(const SelectionBound & b1,const SelectionBound & b2)74 gfx::Rect RectBetweenSelectionBounds(const SelectionBound& b1,
75                                      const SelectionBound& b2) {
76   gfx::Point top_left(b1.edge_start_rounded());
77   top_left.SetToMin(b1.edge_end_rounded());
78   top_left.SetToMin(b2.edge_start_rounded());
79   top_left.SetToMin(b2.edge_end_rounded());
80 
81   gfx::Point bottom_right(b1.edge_start_rounded());
82   bottom_right.SetToMax(b1.edge_end_rounded());
83   bottom_right.SetToMax(b2.edge_start_rounded());
84   bottom_right.SetToMax(b2.edge_end_rounded());
85 
86   gfx::Vector2d diff = bottom_right - top_left;
87   return gfx::Rect(top_left, gfx::Size(diff.x(), diff.y()));
88 }
89 
RectFBetweenSelectionBounds(const SelectionBound & b1,const SelectionBound & b2)90 gfx::RectF RectFBetweenSelectionBounds(const SelectionBound& b1,
91                                        const SelectionBound& b2) {
92   gfx::PointF top_left(b1.edge_start());
93   top_left.SetToMin(b1.edge_end());
94   top_left.SetToMin(b2.edge_start());
95   top_left.SetToMin(b2.edge_end());
96 
97   gfx::PointF bottom_right(b1.edge_start());
98   bottom_right.SetToMax(b1.edge_end());
99   bottom_right.SetToMax(b2.edge_start());
100   bottom_right.SetToMax(b2.edge_end());
101 
102   gfx::Vector2dF diff = bottom_right - top_left;
103   return gfx::RectF(top_left, gfx::SizeF(diff.x(), diff.y()));
104 }
105 
RectFBetweenVisibleSelectionBounds(const SelectionBound & b1,const SelectionBound & b2)106 gfx::RectF RectFBetweenVisibleSelectionBounds(const SelectionBound& b1,
107                                               const SelectionBound& b2) {
108   // The selection bound is determined by the |start| and |end| points. For the
109   // writing-mode is vertical-*, the bounds are horizontal, the |end| might
110   // be on the left side of the |start|.
111   gfx::PointF top_left(b1.visible_edge_start());
112   top_left.SetToMin(b1.visible_edge_end());
113   top_left.SetToMin(b2.visible_edge_start());
114   top_left.SetToMin(b2.visible_edge_end());
115 
116   gfx::PointF bottom_right(b1.visible_edge_start());
117   bottom_right.SetToMax(b1.visible_edge_end());
118   bottom_right.SetToMax(b2.visible_edge_start());
119   bottom_right.SetToMax(b2.visible_edge_end());
120 
121   gfx::Vector2dF diff = bottom_right - top_left;
122   return gfx::RectF(top_left, gfx::SizeF(diff.x(), diff.y()));
123 }
124 
125 }  // namespace gfx
126