1 // Copyright 2015 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.
5 #include "ios/chrome/browser/ui/rtl_geometry.h"
8 #import <UIKit/UIKit.h>
10 #include "base/ios/ios_util.h"
11 #include "base/logging.h"
12 #include "ios/chrome/browser/ui/ui_util.h"
15 return base::i18n::IsRTL() && base::ios::IsRunningOnIOS9OrLater();
18 base::i18n::TextDirection LayoutDirection() {
19 return UseRTLLayout() ? base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
22 #pragma mark - LayoutRects.
24 const LayoutRectPosition LayoutRectPositionZero = {0.0, 0.0};
26 LayoutRectPosition LayoutRectPositionMake(CGFloat leading, CGFloat originY) {
27 return {leading, originY};
30 BOOL LayoutRectPositionEqualToPosition(LayoutRectPosition a,
31 LayoutRectPosition b) {
32 CGFloat epsilon = std::numeric_limits<CGFloat>::epsilon();
33 return fabs(a.leading - b.leading) <= epsilon &&
34 fabs(a.originY - b.originY) <= epsilon;
37 LayoutRectPosition AlignLayoutRectPositionToPixel(LayoutRectPosition position) {
38 return LayoutRectPositionMake(AlignValueToPixel(position.leading),
39 AlignValueToPixel(position.originY));
42 const LayoutRect LayoutRectZero = {0.0, LayoutRectPositionZero,
43 CGSizeMake(0.0, 0.0)};
45 LayoutRect LayoutRectMake(CGFloat leading,
46 CGFloat boundingWidth,
50 return {boundingWidth, LayoutRectPositionMake(leading, originY),
51 CGSizeMake(width, height)};
54 BOOL LayoutRectEqualToRect(LayoutRect a, LayoutRect b) {
55 CGFloat epsilon = std::numeric_limits<CGFloat>::epsilon();
56 return fabs(a.boundingWidth - b.boundingWidth) <= epsilon &&
57 LayoutRectPositionEqualToPosition(a.position, b.position) &&
58 CGSizeEqualToSize(a.size, b.size);
61 CGRect LayoutRectGetRectUsingDirection(LayoutRect layout,
62 base::i18n::TextDirection direction) {
64 if (direction == base::i18n::RIGHT_TO_LEFT) {
66 layout.boundingWidth - (layout.position.leading + layout.size.width);
67 rect = CGRectMake(trailing, layout.position.originY, layout.size.width,
70 DCHECK_EQ(direction, base::i18n::LEFT_TO_RIGHT);
71 rect = CGRectMake(layout.position.leading, layout.position.originY,
72 layout.size.width, layout.size.height);
77 CGRect LayoutRectGetRect(LayoutRect layout) {
78 return LayoutRectGetRectUsingDirection(layout, LayoutDirection());
81 CGRect LayoutRectGetBoundsRect(LayoutRect layout) {
82 return CGRectMake(0, 0, layout.size.width, layout.size.height);
85 CGPoint LayoutRectGetPositionForAnchorUsingDirection(
88 base::i18n::TextDirection direction) {
89 CGRect rect = LayoutRectGetRectUsingDirection(layout, direction);
90 return CGPointMake(CGRectGetMinX(rect) + (rect.size.width * anchor.x),
91 CGRectGetMinY(rect) + (rect.size.height * anchor.y));
94 CGPoint LayoutRectGetPositionForAnchor(LayoutRect layout, CGPoint anchor) {
95 return LayoutRectGetPositionForAnchorUsingDirection(layout, anchor,
99 LayoutRect LayoutRectForRectInBoundingRectUsingDirection(
102 base::i18n::TextDirection direction) {
104 if (direction == base::i18n::RIGHT_TO_LEFT) {
105 layout.position.leading = contextRect.size.width - CGRectGetMaxX(rect);
107 layout.position.leading = CGRectGetMinX(rect);
109 layout.boundingWidth = contextRect.size.width;
110 layout.position.originY = rect.origin.y;
111 layout.size = rect.size;
115 LayoutRect LayoutRectForRectInBoundingRect(CGRect rect, CGRect contextRect) {
116 return LayoutRectForRectInBoundingRectUsingDirection(rect, contextRect,
120 LayoutRect LayoutRectGetLeadingLayout(LayoutRect layout) {
121 LayoutRect leadingLayout;
122 leadingLayout.position.leading = 0;
123 leadingLayout.boundingWidth = layout.boundingWidth;
124 leadingLayout.position.originY = leadingLayout.position.originY;
125 leadingLayout.size = CGSizeMake(layout.position.leading, layout.size.height);
126 return leadingLayout;
129 LayoutRect LayoutRectGetTrailingLayout(LayoutRect layout) {
130 LayoutRect leadingLayout;
131 CGFloat trailing = LayoutRectGetTrailingEdge(layout);
132 leadingLayout.position.leading = trailing;
133 leadingLayout.boundingWidth = layout.boundingWidth;
134 leadingLayout.position.originY = leadingLayout.position.originY;
136 CGSizeMake((layout.boundingWidth - trailing), layout.size.height);
137 return leadingLayout;
140 CGFloat LayoutRectGetTrailingEdge(LayoutRect layout) {
141 return layout.position.leading + layout.size.width;
144 #pragma mark - UIKit utilities
146 CGFloat CGRectGetLeadingEdgeUsingDirection(
148 base::i18n::TextDirection direction) {
149 return direction == base::i18n::RIGHT_TO_LEFT ? CGRectGetMaxX(rect)
150 : CGRectGetMinX(rect);
153 CGFloat CGRectGetTrailingEdgeUsingDirection(
155 base::i18n::TextDirection direction) {
156 return direction == base::i18n::RIGHT_TO_LEFT ? CGRectGetMinX(rect)
157 : CGRectGetMaxX(rect);
160 CGFloat CGRectGetLeadingEdge(CGRect rect) {
161 return CGRectGetLeadingEdgeUsingDirection(rect, LayoutDirection());
164 CGFloat CGRectGetTrailingEdge(CGRect rect) {
165 return CGRectGetTrailingEdgeUsingDirection(rect, LayoutDirection());
168 UIViewAutoresizing UIViewAutoresizingFlexibleLeadingMargin() {
169 return base::i18n::IsRTL() && base::ios::IsRunningOnIOS9OrLater()
170 ? UIViewAutoresizingFlexibleRightMargin
171 : UIViewAutoresizingFlexibleLeftMargin;
174 UIViewAutoresizing UIViewAutoresizingFlexibleTrailingMargin() {
175 return base::i18n::IsRTL() && base::ios::IsRunningOnIOS9OrLater()
176 ? UIViewAutoresizingFlexibleLeftMargin
177 : UIViewAutoresizingFlexibleRightMargin;
180 UIEdgeInsets UIEdgeInsetsMakeUsingDirection(
185 base::i18n::TextDirection direction) {
186 if (direction == base::i18n::RIGHT_TO_LEFT) {
188 swap(leading, trailing);
190 // At this point, |leading| == left, |trailing| = right.
191 return UIEdgeInsetsMake(top, leading, bottom, trailing);
194 UIEdgeInsets UIEdgeInsetsMakeDirected(CGFloat top,
198 return UIEdgeInsetsMakeUsingDirection(top, leading, bottom, trailing,
202 CGFloat UIEdgeInsetsGetLeading(UIEdgeInsets insets) {
203 return UseRTLLayout() ? insets.right : insets.left;
206 CGFloat UIEdgeInsetsGetTrailing(UIEdgeInsets insets) {
207 return UseRTLLayout() ? insets.left : insets.right;
210 #pragma mark - autolayout utilities
212 NSLayoutFormatOptions LayoutOptionForRTLSupport() {
213 if (UseRTLLayout()) {
214 return NSLayoutFormatDirectionLeadingToTrailing;
216 return NSLayoutFormatDirectionLeftToRight;