diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gfx/DEPS | 1 | ||||
-rw-r--r-- | ui/gfx/gfx.gyp | 3 | ||||
-rw-r--r-- | ui/gfx/platform_font_ios.mm | 8 | ||||
-rw-r--r-- | ui/gfx/text_utils_ios.mm | 6 | ||||
-rw-r--r-- | ui/ios/NSString+CrStringDrawing.h | 35 | ||||
-rw-r--r-- | ui/ios/NSString+CrStringDrawing.mm | 37 | ||||
-rw-r--r-- | ui/ios/NSString+CrStringDrawing_unittest.mm | 107 | ||||
-rw-r--r-- | ui/ios/ui_ios.gyp | 27 | ||||
-rw-r--r-- | ui/ios/ui_ios_tests.gyp | 25 |
9 files changed, 239 insertions, 10 deletions
diff --git a/ui/gfx/DEPS b/ui/gfx/DEPS index 758e42a..a1bf2f7 100644 --- a/ui/gfx/DEPS +++ b/ui/gfx/DEPS @@ -3,4 +3,5 @@ include_rules = [ "+skia/ext", "+third_party/harfbuzz-ng", "+third_party/skia", + "+ui/ios", ] diff --git a/ui/gfx/gfx.gyp b/ui/gfx/gfx.gyp index 99835fc..85ea553 100644 --- a/ui/gfx/gfx.gyp +++ b/ui/gfx/gfx.gyp @@ -309,6 +309,9 @@ ], 'conditions': [ ['OS=="ios"', { + 'dependencies': [ + '<(DEPTH)/ui/ios/ui_ios.gyp:ui_ios', + ], # iOS only uses a subset of UI. 'sources/': [ ['exclude', '^codec/jpeg_codec\\.cc$'], diff --git a/ui/gfx/platform_font_ios.mm b/ui/gfx/platform_font_ios.mm index 0fd824f..502f1a4 100644 --- a/ui/gfx/platform_font_ios.mm +++ b/ui/gfx/platform_font_ios.mm @@ -13,6 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/gfx/font.h" #include "ui/gfx/font_render_params.h" +#include "ui/ios/NSString+CrStringDrawing.h" namespace gfx { @@ -112,12 +113,7 @@ void PlatformFontIOS::CalculateMetrics() { height_ = font.lineHeight; ascent_ = font.ascender; cap_height_ = font.capHeight; - if (font) { - NSDictionary* attributes = @{ NSFontAttributeName : font }; - average_width_ = std::ceil([@"x" sizeWithAttributes:attributes].width); - } else { - average_width_ = 0; - } + average_width_ = [@"x" cr_sizeWithFont:font].width; } //////////////////////////////////////////////////////////////////////////////// diff --git a/ui/gfx/text_utils_ios.mm b/ui/gfx/text_utils_ios.mm index e687f35..c6b8570 100644 --- a/ui/gfx/text_utils_ios.mm +++ b/ui/gfx/text_utils_ios.mm @@ -10,6 +10,7 @@ #include "base/strings/sys_string_conversions.h" #include "ui/gfx/font_list.h" +#include "ui/ios/NSString+CrStringDrawing.h" namespace gfx { @@ -20,10 +21,7 @@ int GetStringWidth(const base::string16& text, const FontList& font_list) { float GetStringWidthF(const base::string16& text, const FontList& font_list) { NSString* ns_text = base::SysUTF16ToNSString(text); NativeFont native_font = font_list.GetPrimaryFont().GetNativeFont(); - if (!native_font) - return 0; - NSDictionary* attributes = @{ NSFontAttributeName : native_font }; - return std::ceil([ns_text sizeWithAttributes:attributes].width); + return [ns_text cr_sizeWithFont:native_font].width; } } // namespace gfx diff --git a/ui/ios/NSString+CrStringDrawing.h b/ui/ios/NSString+CrStringDrawing.h new file mode 100644 index 0000000..330593e --- /dev/null +++ b/ui/ios/NSString+CrStringDrawing.h @@ -0,0 +1,35 @@ +// 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_IOS_NSSTRING_CR_STRING_DRAWING_H_ +#define UI_IOS_NSSTRING_CR_STRING_DRAWING_H_ + +#import <UIKit/UIKit.h> + +@interface NSString (CrStringDrawing) + +// 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_IOS_NSSTRING_CR_STRING_DRAWING_H_ diff --git a/ui/ios/NSString+CrStringDrawing.mm b/ui/ios/NSString+CrStringDrawing.mm new file mode 100644 index 0000000..9f7d88b --- /dev/null +++ b/ui/ios/NSString+CrStringDrawing.mm @@ -0,0 +1,37 @@ +// 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/ios/NSString+CrStringDrawing.h" + +#include "base/logging.h" + +namespace { +// Returns the closest pixel-aligned value higher than |value|, taking the scale +// factor into account. At a scale of 1, equivalent to ceil(). +// TODO(lliabraa): Move this method to a common util file (crbug.com/409823). +CGFloat alignValueToUpperPixel(CGFloat value) { + CGFloat scale = [[UIScreen mainScreen] scale]; + return ceil(value * scale) / scale; +} +} // namespace + +@implementation NSString (CrStringDrawing) + +- (CGSize)cr_pixelAlignedSizeWithFont:(UIFont*)font { + DCHECK(font) << "|font| can not be nil; it is used as a NSDictionary value"; + NSDictionary* attributes = @{ NSFontAttributeName : font }; + CGSize size = [self sizeWithAttributes:attributes]; + return CGSizeMake(alignValueToUpperPixel(size.width), + alignValueToUpperPixel(size.height)); +} + +- (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/ios/NSString+CrStringDrawing_unittest.mm b/ui/ios/NSString+CrStringDrawing_unittest.mm new file mode 100644 index 0000000..6f0497d --- /dev/null +++ b/ui/ios/NSString+CrStringDrawing_unittest.mm @@ -0,0 +1,107 @@ +// 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/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 test verifies 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" + +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/ios/ui_ios.gyp b/ui/ios/ui_ios.gyp new file mode 100644 index 0000000..afec667 --- /dev/null +++ b/ui/ios/ui_ios.gyp @@ -0,0 +1,27 @@ +# 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'ui_ios', + 'type': 'static_library', + # Linkable dependents need to set the linker flag '-ObjC' in order to use + # the categories in this target (e.g. NSString+CrStringDrawing.h). + 'link_settings': { + 'xcode_settings': {'OTHER_LDFLAGS': ['-ObjC']}, + }, + 'include_dirs': [ + '../..', + ], + 'sources': [ + 'NSString+CrStringDrawing.h', + 'NSString+CrStringDrawing.mm', + ], + }, + ], +} diff --git a/ui/ios/ui_ios_tests.gyp b/ui/ios/ui_ios_tests.gyp new file mode 100644 index 0000000..08f7e46 --- /dev/null +++ b/ui/ios/ui_ios_tests.gyp @@ -0,0 +1,25 @@ +# 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'ui_ios_unittests', + 'type': '<(gtest_target_type)', + 'dependencies': [ + '../../base/base.gyp:base', + '../../base/base.gyp:run_all_unittests', + '../../base/base.gyp:test_support_base', + '../../testing/gtest.gyp:gtest', + 'ui_ios.gyp:ui_ios', + ], + 'sources' : [ + 'NSString+CrStringDrawing_unittest.mm', + ], + }, + ], +}
\ No newline at end of file |