summaryrefslogtreecommitdiffstats
path: root/ui/gfx/ios
diff options
context:
space:
mode:
authorstuartmorgan <stuartmorgan@chromium.org>2015-03-09 13:19:15 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-09 20:20:12 +0000
commit018f5c02de9fc3e41c273b19e8eb60a503b05d57 (patch)
tree01d854a2bc80bc57be906d82e51d7065e62e146c /ui/gfx/ios
parent9b40df656981fa2e9eaf158f22016b0d566bdaa8 (diff)
downloadchromium_src-018f5c02de9fc3e41c273b19e8eb60a503b05d57.zip
chromium_src-018f5c02de9fc3e41c273b19e8eb60a503b05d57.tar.gz
chromium_src-018f5c02de9fc3e41c273b19e8eb60a503b05d57.tar.bz2
Eliminate ui/ios
Per the explanation in the bug, ui/ios should not have been created in the first place; this code belongs in the ui/gfx subcomponent. BUG=446643 Review URL: https://codereview.chromium.org/983413004 Cr-Commit-Position: refs/heads/master@{#319720}
Diffstat (limited to 'ui/gfx/ios')
-rw-r--r--ui/gfx/ios/NSString+CrStringDrawing.h55
-rw-r--r--ui/gfx/ios/NSString+CrStringDrawing.mm40
-rw-r--r--ui/gfx/ios/NSString+CrStringDrawing_unittest.mm151
-rw-r--r--ui/gfx/ios/OWNERS3
-rw-r--r--ui/gfx/ios/uikit_util.h26
-rw-r--r--ui/gfx/ios/uikit_util.mm23
-rw-r--r--ui/gfx/ios/uikit_util_unittest.mm51
7 files changed, 349 insertions, 0 deletions
diff --git a/ui/gfx/ios/NSString+CrStringDrawing.h b/ui/gfx/ios/NSString+CrStringDrawing.h
new file mode 100644
index 0000000..10916e9
--- /dev/null
+++ b/ui/gfx/ios/NSString+CrStringDrawing.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
+#define UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
+
+#import <UIKit/UIKit.h>
+
+@interface NSString (CrStringDrawing)
+
+// Calculates and returns the bounding rect for the receiver drawn using the
+// given size and font.
+// This method is implemented as a wrapper around
+// |boundingRectWithSize:options:attributes:context:| using the following values
+// for the parameters:
+// - size: the provided |size|
+// - options: NSStringDrawingUsesLineFragmentOrigin
+// - attributes: a NSDictionary with the provided |font|
+// - context: nil.
+//
+// Note that the rect returned may contain fractional values.
+- (CGRect)cr_boundingRectWithSize:(CGSize)size
+ font:(UIFont*)font;
+
+// Convenience wrapper to just return the size of |boundingRectWithSize:font:|.
+//
+// Note that the size returned may contain fractional values.
+- (CGSize)cr_boundingSizeWithSize:(CGSize)size
+ font:(UIFont*)font;
+
+// Returns the size of the string if it were to be rendered with the specified
+// font on a single line. The width and height of the CGSize returned are
+// pixel-aligned.
+//
+// This method is a convenience wrapper around sizeWithAttributes: to avoid
+// boilerplate required to put |font| in a dictionary of attributes. Do not pass
+// nil into this method.
+- (CGSize)cr_pixelAlignedSizeWithFont:(UIFont*)font;
+
+// Deprecated: Use cr_pixelAlignedSizeWithFont: or sizeWithAttributes:
+// Provides a drop-in replacement for sizeWithFont:, which was deprecated in iOS
+// 7 in favor of -sizeWithAttributes:. Specifically, this method will return
+// CGSizeZero if |font| is nil, and the width and height returned are rounded up
+// to integer values.
+// TODO(lliabraa): This method was added to ease the transition off of the
+// deprecated sizeWithFont: method. New call sites should not be added and
+// existing call sites should be audited to determine the correct behavior for
+// nil |font| and rounding, then replaced with cr_pixelAlignedSizeWithFont: or
+// sizeWithAttributes: (crbug.com/364419).
+- (CGSize)cr_sizeWithFont:(UIFont*)font;
+
+@end
+
+#endif // UI_GFX_IOS_NSSTRING_CR_STRING_DRAWING_H_
diff --git a/ui/gfx/ios/NSString+CrStringDrawing.mm b/ui/gfx/ios/NSString+CrStringDrawing.mm
new file mode 100644
index 0000000..0d6d0b4
--- /dev/null
+++ b/ui/gfx/ios/NSString+CrStringDrawing.mm
@@ -0,0 +1,40 @@
+// Copyright 2014 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.
+
+#import "ui/gfx/ios/NSString+CrStringDrawing.h"
+
+#include "base/logging.h"
+#include "ui/gfx/ios/uikit_util.h"
+
+@implementation NSString (CrStringDrawing)
+
+- (CGRect)cr_boundingRectWithSize:(CGSize)size
+ font:(UIFont*)font {
+ NSDictionary* attributes = font ? @{NSFontAttributeName: font} : @{};
+ return [self boundingRectWithSize:size
+ options:NSStringDrawingUsesLineFragmentOrigin
+ attributes:attributes
+ context:nil];
+}
+
+- (CGSize)cr_boundingSizeWithSize:(CGSize)size
+ font:(UIFont*)font {
+ return [self cr_boundingRectWithSize:size font:font].size;
+}
+
+- (CGSize)cr_pixelAlignedSizeWithFont:(UIFont*)font {
+ DCHECK(font) << "|font| can not be nil; it is used as a NSDictionary value";
+ NSDictionary* attributes = @{ NSFontAttributeName : font };
+ return ui::AlignSizeToUpperPixel([self sizeWithAttributes:attributes]);
+}
+
+- (CGSize)cr_sizeWithFont:(UIFont*)font {
+ if (!font)
+ return CGSizeZero;
+ NSDictionary* attributes = @{ NSFontAttributeName : font };
+ CGSize size = [self sizeWithAttributes:attributes];
+ return CGSizeMake(ceil(size.width), ceil(size.height));
+}
+
+@end
diff --git a/ui/gfx/ios/NSString+CrStringDrawing_unittest.mm b/ui/gfx/ios/NSString+CrStringDrawing_unittest.mm
new file mode 100644
index 0000000..02fc3c2
--- /dev/null
+++ b/ui/gfx/ios/NSString+CrStringDrawing_unittest.mm
@@ -0,0 +1,151 @@
+// Copyright 2014 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.
+#import "ui/gfx/ios/NSString+CrStringDrawing.h"
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace {
+
+typedef PlatformTest NSStringCrStringDrawing;
+
+// These tests verify that the category methods return the same values as the
+// deprecated methods, so ignore warnings about using deprecated methods.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+// Verifies that |cr_boundingSizeWithSize| returns the same size as the
+// deprecated |sizeWithFont:constrainedToSize| for most values.
+// Note that the methods return different values in a few cases (so they are not
+// included in the test cases):
+// - the constrained size.width is less than a character.
+// - the constrained size.height is less than the font height.
+// - the string is empty.
+TEST_F(NSStringCrStringDrawing, BoundingSizeWithSize) {
+ NSArray* fonts = @[
+ [UIFont systemFontOfSize:16],
+ [UIFont boldSystemFontOfSize:10],
+ [UIFont fontWithName:@"Helvetica" size:12.0],
+ ];
+ NSArray* strings = @[
+ @"Test",
+ @"multi word test",
+ @"你好",
+ @"★ This is a test string that is very long.",
+ ];
+ NSArray* sizes = @[
+ [NSValue valueWithCGSize:CGSizeMake(20, 100)],
+ [NSValue valueWithCGSize:CGSizeMake(100, 100)],
+ [NSValue valueWithCGSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)],
+ ];
+ for (UIFont* font in fonts) {
+ for (NSString* string in strings) {
+ for (NSValue* sizeValue in sizes) {
+ CGSize test_size = [sizeValue CGSizeValue];
+ std::string test_tag = base::StringPrintf(
+ "for string '%s' with font %s and size %s",
+ base::SysNSStringToUTF8(string).c_str(),
+ base::SysNSStringToUTF8([font description]).c_str(),
+ base::SysNSStringToUTF8(NSStringFromCGSize(test_size)).c_str());
+
+ CGSize size_with_font =
+ [string sizeWithFont:font constrainedToSize:test_size];
+ CGSize bounding_size =
+ [string cr_boundingSizeWithSize:test_size font:font];
+ EXPECT_EQ(size_with_font.width, bounding_size.width) << test_tag;
+ EXPECT_EQ(size_with_font.height, bounding_size.height) << test_tag;
+ }
+ }
+ }
+}
+
+TEST_F(NSStringCrStringDrawing, SizeWithFont) {
+ NSArray* fonts = @[
+ [NSNull null],
+ [UIFont systemFontOfSize:16],
+ [UIFont boldSystemFontOfSize:10],
+ [UIFont fontWithName:@"Helvetica" size:12.0],
+ ];
+ for (UIFont* font in fonts) {
+ if ([font isEqual:[NSNull null]])
+ font = nil;
+ std::string font_tag = "with font ";
+ font_tag.append(
+ base::SysNSStringToUTF8(font ? [font description] : @"nil"));
+ EXPECT_EQ([@"" sizeWithFont:font].width,
+ [@"" cr_sizeWithFont:font].width) << font_tag;
+ EXPECT_EQ([@"" sizeWithFont:font].height,
+ [@"" cr_sizeWithFont:font].height) << font_tag;
+ EXPECT_EQ([@"Test" sizeWithFont:font].width,
+ [@"Test" cr_sizeWithFont:font].width) << font_tag;
+ EXPECT_EQ([@"Test" sizeWithFont:font].height,
+ [@"Test" cr_sizeWithFont:font].height) << font_tag;
+ EXPECT_EQ([@"你好" sizeWithFont:font].width,
+ [@"你好" cr_sizeWithFont:font].width) << font_tag;
+ EXPECT_EQ([@"你好" sizeWithFont:font].height,
+ [@"你好" cr_sizeWithFont:font].height) << font_tag;
+ NSString* long_string = @"★ This is a test string that is very long.";
+ EXPECT_EQ([long_string sizeWithFont:font].width,
+ [long_string cr_sizeWithFont:font].width) << font_tag;
+ EXPECT_EQ([long_string sizeWithFont:font].height,
+ [long_string cr_sizeWithFont:font].height) << font_tag;
+ }
+}
+#pragma clang diagnostic pop // ignored "-Wdeprecated-declarations"
+
+TEST_F(NSStringCrStringDrawing, PixelAlignedSizeWithFont) {
+ NSArray* fonts = @[
+ [UIFont systemFontOfSize:16],
+ [UIFont boldSystemFontOfSize:10],
+ [UIFont fontWithName:@"Helvetica" size:12.0],
+ ];
+ NSArray* strings = @[
+ @"",
+ @"Test",
+ @"你好",
+ @"★ This is a test string that is very long.",
+ ];
+ for (UIFont* font in fonts) {
+ NSDictionary* attributes = @{ NSFontAttributeName : font };
+
+ for (NSString* string in strings) {
+ std::string test_tag = base::StringPrintf("for string '%s' with font %s",
+ base::SysNSStringToUTF8(string).c_str(),
+ base::SysNSStringToUTF8([font description]).c_str());
+
+ CGSize size_with_attributes = [string sizeWithAttributes:attributes];
+ CGSize size_with_pixel_aligned =
+ [string cr_pixelAlignedSizeWithFont:font];
+
+ // Verify that the pixel_aligned size is always rounded up (i.e. the size
+ // returned from sizeWithAttributes: is less than or equal to the pixel-
+ // aligned size).
+ EXPECT_LE(size_with_attributes.width,
+ size_with_pixel_aligned.width) << test_tag;
+ EXPECT_LE(size_with_attributes.height,
+ size_with_pixel_aligned.height) << test_tag;
+
+ // Verify that the pixel_aligned size is never more than a pixel different
+ // than the size returned from sizeWithAttributes:.
+ static CGFloat scale = [[UIScreen mainScreen] scale];
+ EXPECT_NEAR(size_with_attributes.width * scale,
+ size_with_pixel_aligned.width * scale,
+ 0.9999) << test_tag;
+ EXPECT_NEAR(size_with_attributes.height * scale,
+ size_with_pixel_aligned.height * scale,
+ 0.9999) << test_tag;
+
+ // Verify that the pixel-aligned value is pixel-aligned.
+ EXPECT_FLOAT_EQ(roundf(size_with_pixel_aligned.width * scale),
+ size_with_pixel_aligned.width * scale) << test_tag;
+ EXPECT_FLOAT_EQ(roundf(size_with_pixel_aligned.height * scale),
+ size_with_pixel_aligned.height * scale) << test_tag;
+ }
+ }
+}
+
+} // namespace
diff --git a/ui/gfx/ios/OWNERS b/ui/gfx/ios/OWNERS
new file mode 100644
index 0000000..f2fff55
--- /dev/null
+++ b/ui/gfx/ios/OWNERS
@@ -0,0 +1,3 @@
+lliabraa@chromium.org
+rohitrao@chromium.org
+sdefresne@chromium.org
diff --git a/ui/gfx/ios/uikit_util.h b/ui/gfx/ios/uikit_util.h
new file mode 100644
index 0000000..fbacda3
--- /dev/null
+++ b/ui/gfx/ios/uikit_util.h
@@ -0,0 +1,26 @@
+// Copyright 2014 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 UI_GFX_IOS_UIKIT_UTIL_H_
+#define UI_GFX_IOS_UIKIT_UTIL_H_
+
+#import <UIKit/UIKit.h>
+
+#include "base/compiler_specific.h"
+
+// UI Util containing functions that require UIKit.
+
+namespace ui {
+
+// Returns the closest pixel-aligned value higher than |value|, taking the scale
+// factor into account. At a scale of 1, equivalent to ceil().
+CGFloat AlignValueToUpperPixel(CGFloat value) WARN_UNUSED_RESULT;
+
+// Returns the size resulting from applying AlignToUpperPixel to both
+// components.
+CGSize AlignSizeToUpperPixel(CGSize size) WARN_UNUSED_RESULT;
+
+} // namespace ui
+
+#endif // UI_GFX_IOS_UIKIT_UTIL_H_
diff --git a/ui/gfx/ios/uikit_util.mm b/ui/gfx/ios/uikit_util.mm
new file mode 100644
index 0000000..2e0bfdb
--- /dev/null
+++ b/ui/gfx/ios/uikit_util.mm
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+#include "ui/gfx/ios/uikit_util.h"
+
+#import <UIKit/UIKit.h>
+
+#include <cmath>
+
+namespace ui {
+
+CGFloat AlignValueToUpperPixel(CGFloat value) {
+ CGFloat scale = [[UIScreen mainScreen] scale];
+ return std::ceil(value * scale) / scale;
+}
+
+CGSize AlignSizeToUpperPixel(CGSize size) {
+ return CGSizeMake(AlignValueToUpperPixel(size.width),
+ AlignValueToUpperPixel(size.height));
+}
+
+} // namespace ui
diff --git a/ui/gfx/ios/uikit_util_unittest.mm b/ui/gfx/ios/uikit_util_unittest.mm
new file mode 100644
index 0000000..b343f4e
--- /dev/null
+++ b/ui/gfx/ios/uikit_util_unittest.mm
@@ -0,0 +1,51 @@
+// Copyright 2014 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.
+
+#import <Foundation/Foundation.h>
+
+#include "base/basictypes.h"
+#include "testing/platform_test.h"
+#import "ui/gfx/ios/uikit_util.h"
+
+namespace {
+
+typedef PlatformTest UIKitUtilTest;
+
+TEST_F(UIKitUtilTest, AlignValueToUpperPixel) {
+ CGFloat scale = [[UIScreen mainScreen] scale];
+ // Pick a few interesting values: already aligned, aligned on retina, and
+ // some unaligned values that would round differently. Ensure that all are
+ // "integer" values within <1 of the original value in the scaled space.
+ CGFloat test_values[] = { 10.0, 55.5, 3.1, 2.9 };
+ const CGFloat kMaxAlignDelta = 0.9999;
+ size_t value_count = arraysize(test_values);
+ for (unsigned int i = 0; i < value_count; ++i) {
+ CGFloat aligned = ui::AlignValueToUpperPixel(test_values[i]);
+ EXPECT_FLOAT_EQ(aligned * scale, floor(aligned * scale));
+ EXPECT_NEAR(aligned * scale, test_values[i] * scale, kMaxAlignDelta);
+ }
+}
+
+TEST_F(UIKitUtilTest, AlignSizeToUpperPixel) {
+ CGFloat scale = [[UIScreen mainScreen] scale];
+ // Pick a few interesting values: already aligned, aligned on retina, and
+ // some unaligned values that would round differently. Ensure that all are
+ // "integer" values within <1 of the original value in the scaled space.
+ CGFloat test_values[] = { 10.0, 55.5, 3.1, 2.9 };
+ const CGFloat kMaxAlignDelta = 0.9999;
+ size_t value_count = arraysize(test_values);
+ for (unsigned int i = 0; i < value_count; ++i) {
+ CGFloat width = test_values[i];
+ CGFloat height = test_values[(i + 1) % value_count];
+ CGSize alignedSize = ui::AlignSizeToUpperPixel(CGSizeMake(width, height));
+ EXPECT_FLOAT_EQ(floor(alignedSize.width * scale),
+ alignedSize.width * scale);
+ EXPECT_FLOAT_EQ(floor(alignedSize.height * scale),
+ alignedSize.height * scale);
+ EXPECT_NEAR(width * scale, alignedSize.width * scale, kMaxAlignDelta);
+ EXPECT_NEAR(height * scale, alignedSize.height * scale, kMaxAlignDelta);
+ }
+}
+
+} // namespace