Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: ios/chrome/browser/ui/util/manual_text_framer_unittest.mm

Issue 2580333003: Upstream Chrome on iOS source code [10/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/util/manual_text_framer_unittest.mm
diff --git a/ios/chrome/browser/ui/util/manual_text_framer_unittest.mm b/ios/chrome/browser/ui/util/manual_text_framer_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..532b351d670b7c2d766e5d604873b3b2df055a5d
--- /dev/null
+++ b/ios/chrome/browser/ui/util/manual_text_framer_unittest.mm
@@ -0,0 +1,301 @@
+// Copyright 2015 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 "ios/chrome/browser/ui/util/manual_text_framer.h"
+
+#include "base/mac/foundation_util.h"
+#import "base/mac/scoped_nsobject.h"
+#include "base/time/time.h"
+#import "ios/chrome/browser/ui/util/core_text_util.h"
+#import "ios/chrome/browser/ui/util/text_frame.h"
+#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#include "url/gurl.h"
+
+namespace {
+// Copy of ManualTextFramer's alignment function.
+enum class AlignmentFunction : short { CEIL = 0, FLOOR };
+CGFloat AlignValueToPixel(CGFloat value, AlignmentFunction function) {
+ static CGFloat scale = [[UIScreen mainScreen] scale];
+ return function == AlignmentFunction::CEIL ? ceil(value * scale) / scale
+ : floor(value * scale) / scale;
+}
+
+class ManualTextFramerTest : public PlatformTest {
+ protected:
+ void SetUp() override {
+ attributes_.reset([[NSMutableDictionary alloc] init]);
+ string_.reset([[NSMutableAttributedString alloc] init]);
+ }
+
+ NSString* text() { return [string_ string]; }
+ NSRange text_range() { return NSMakeRange(0, [string_ length]); }
+ id<TextFrame> text_frame() {
+ return static_cast<id<TextFrame>>(text_frame_.get());
+ }
+
+ void SetText(NSString* text) {
+ DCHECK(text.length);
+ [[string_ mutableString] setString:text];
+ }
+
+ void FrameTextInBounds(CGRect bounds) {
+ base::scoped_nsobject<ManualTextFramer> manual_framer(
+ [[ManualTextFramer alloc] initWithString:string_ inBounds:bounds]);
+ [manual_framer frameText];
+ id frame = [manual_framer textFrame];
+ text_frame_.reset([frame retain]);
+ }
+
+ UIFont* RobotoFontWithSize(CGFloat size) {
+ return [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:size];
+ }
+
+ NSParagraphStyle* CreateParagraphStyle(CGFloat line_height,
+ NSTextAlignment alignment,
+ NSLineBreakMode line_break_mode) {
+ NSMutableParagraphStyle* style =
+ [[[NSMutableParagraphStyle alloc] init] autorelease];
+ style.alignment = alignment;
+ style.lineBreakMode = line_break_mode;
+ style.minimumLineHeight = line_height;
+ style.maximumLineHeight = line_height;
+ return style;
+ }
+
+ NSMutableDictionary* attributes() { return attributes_; }
+
+ void ApplyAttributesForRange(NSRange range) {
+ [string_ setAttributes:attributes_ range:range];
+ }
+
+ void CheckForLineCountAndFramedRange(NSUInteger line_count,
+ NSRange framed_range) {
+ EXPECT_EQ(line_count, text_frame().lines.count);
+ EXPECT_EQ(framed_range.location, text_frame().framedRange.location);
+ EXPECT_EQ(framed_range.length, text_frame().framedRange.length);
+ }
+
+ base::scoped_nsobject<NSMutableDictionary> attributes_;
+ base::scoped_nsobject<NSMutableAttributedString> string_;
+ base::scoped_nsprotocol<id<TextFrame>> text_frame_;
+};
+
+// Tests that newline characters cause an attributed string to be laid out on
+// multiple lines.
+TEST_F(ManualTextFramerTest, NewlineTest) {
+ SetText(@"line one\nline two\nline three");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 500);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(3, text_range());
+}
+
+// Tests that strings with no spaces fail correctly.
+TEST_F(ManualTextFramerTest, NoSpacesText) {
+ // "St. Mary's church in the hollow of the white hazel near the the rapid
+ // whirlpool of Llantysilio of the red cave."
+ SetText(
+ @"Llanfair­pwllgwyngyll­gogery­chwyrn­drobwll­llan­tysilio­gogo­goch");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(16.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 200, 60);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(0, NSMakeRange(0, 0));
+}
+
+// Tests that multiple newlines are accounted for. Only the first three
+// newlines should be added to |lines_|.
+TEST_F(ManualTextFramerTest, MultipleNewlineTest) {
+ SetText(@"\n\n\ntext");
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 60);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(3, NSMakeRange(0, 3));
+}
+
+// Tests that the framed range for text that will be rendered with ligatures is
+// corresponds with the actual range of the text.
+TEST_F(ManualTextFramerTest, LigatureTest) {
+ SetText(@"fffi");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 20);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(1, text_range());
+}
+
+// Tests that ManualTextFramer correctly frames Å
+TEST_F(ManualTextFramerTest, DiacriticTest) {
+ SetText(@"A\u030A");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 20);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(1, text_range());
+}
+
+// String text, attributes, and bounds are chosen to match the "Terms of
+// Service" text in WelcomeToChromeView, as the text is not properly framed by
+// CTFrameSetter. http://crbug.com/537212
+TEST_F(ManualTextFramerTest, TOSTextTest) {
+ CGRect bounds = CGRectMake(0, 0, 300.0, 40.0);
+ NSString* const kTOSLinkText = @"Terms of Service";
+ NSString* const kTOSText =
+ @"By using this application, you agree to Chrome’s Terms of Service.";
+ SetText(kTOSText);
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentCenter, NSLineBreakByTruncatingTail);
+ attributes()[NSForegroundColorAttributeName] = [UIColor blackColor];
+ ApplyAttributesForRange(text_range());
+ attributes()[NSForegroundColorAttributeName] = [UIColor blueColor];
+ ApplyAttributesForRange([kTOSText rangeOfString:kTOSLinkText]);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(2, text_range());
+}
+
+// Tests that the origin of a left-aligned single line is correct.
+TEST_F(ManualTextFramerTest, SimpleOriginTest) {
+ SetText(@"test");
+ UIFont* font = RobotoFontWithSize(14.0);
+ attributes()[NSFontAttributeName] = font;
+ CGFloat line_height = 20.0;
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ line_height, NSTextAlignmentLeft, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 21);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(1, text_range());
+ FramedLine* line = [text_frame().lines firstObject];
+ EXPECT_EQ(0, line.origin.x);
+ EXPECT_EQ(
+ AlignValueToPixel(CGRectGetHeight(bounds) - line_height - font.descender,
+ AlignmentFunction::FLOOR),
+ line.origin.y);
+}
+
+// Tests that lines that are laid out in RTL are right aligned.
+TEST_F(ManualTextFramerTest, OriginRTLTest) {
+ SetText(@"\u0641\u064e\u0628\u064e\u0642\u064e\u064a\u0652\u062a\u064f\u0020"
+ @"\u0645\u064f\u062a\u064e\u0627\u0628\u0650\u0639\u064e\u0627\u064b"
+ @"\u0020\u0028\u0634\u064f\u063a\u0652\u0644\u0650\u064a\u0029\u0020"
+ @"\u0644\u064e\u0639\u064e\u0644\u064e\u0643\u0650\u0020\u062a\u064e"
+ @"\u062a\u064e\u0639\u064e\u0644\u0651\u064e\u0645\u064e\u0020\u0627"
+ @"\u0644\u062d\u0650\u0631\u0652\u0635\u064e\u0020\u0639\u064e\u0644"
+ @"\u064e\u0649\u0020\u0627\u0644\u0648\u064e\u0642\u0652\u062a\u0650"
+ @"\u0020\u002e\u0020\u0641\u064e\u0627\u0644\u062d\u064e\u064a\u064e"
+ @"\u0627\u0629\u064f");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 100.0, 60.0);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(3, text_range());
+ for (FramedLine* line in text_frame().lines) {
+ CGFloat line_width =
+ AlignValueToPixel(core_text_util::GetTrimmedLineWidth(line.line),
+ AlignmentFunction::CEIL);
+ EXPECT_EQ(CGRectGetMaxX(bounds), line.origin.x + line_width);
+ }
+}
+
+TEST_F(ManualTextFramerTest, CJKLineBreakTest) {
+ // Example from our strings. Framer will put “触摸搜索” on one line, and then
+ // fail to frame the second.
+ // clang-format off
+ SetText(@"“触摸搜索”会将所选字词和当前页面(作为上下文)一起发送给 Google 搜索。"
+ @"您可以在设置中停用此功能。");
+ // clang-format on
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(16.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 16 * 1.15, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 300.0, 65.0);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(3, NSMakeRange(0, 53));
+
+ // Example without any space-ish characters:
+ // clang-format off
+ SetText(@"会将所选字词和当前页面(作为上下文)一起发送给Google搜索。"
+ @"您可以在设置中停用此功能。");
+ // clang-format on
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(16.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 16 * 1.15, NSTextAlignmentNatural, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(2, NSMakeRange(0, 45));
+}
+
+// Tests that paragraphs with NSTextAlignmentCenter are actually centered.
+TEST_F(ManualTextFramerTest, CenterAlignedTest) {
+ SetText(@"xxxx\nyyy\nwww");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentCenter, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 200.0, 60.0);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(3, text_range());
+ for (FramedLine* line in text_frame().lines) {
+ CGFloat line_width =
+ AlignValueToPixel(core_text_util::GetTrimmedLineWidth(line.line),
+ AlignmentFunction::CEIL);
+ EXPECT_EQ(AlignValueToPixel(CGRectGetMidX(bounds) - 0.5 * line_width,
+ AlignmentFunction::FLOOR),
+ line.origin.x);
+ }
+}
+
+// Tests that words with a large line height will not be framed if they don't
+// fit in the bounding height.
+TEST_F(ManualTextFramerTest, LargeLineHeightTest) {
+ SetText(@"the last word is very LARGE");
+ attributes()[NSFontAttributeName] = RobotoFontWithSize(14.0);
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 20.0, NSTextAlignmentCenter, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(text_range());
+ attributes()[NSParagraphStyleAttributeName] = CreateParagraphStyle(
+ 500.0, NSTextAlignmentCenter, NSLineBreakByWordWrapping);
+ ApplyAttributesForRange(NSMakeRange(22, 5)); // "LARGE"
+ CGRect bounds = CGRectMake(0, 0, 500, 20.0);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(1, NSMakeRange(0, 22));
+}
+
+// Tests a preexisting error condition in which a BiDi string containing Arabic
+// is correctly laid out (crbug.com/584549).
+TEST_F(ManualTextFramerTest, RTLTest) {
+ SetText(@"\u0642\u062F\u0020\u064A\u0633\u062A\u062E\u062F\u0645\u0020\u0047"
+ "\u006F\u006F\u0067\u006C\u0065\u0020\u0043\u0068\u0072\u006F\u006D"
+ "\u0065\u0020\u062E\u062F\u0645\u0627\u062A\u0020\u0627\u0644\u0648"
+ "\u064A\u0628\u0020\u0644\u062A\u062D\u0633\u064A\u0646\u0020\u062A"
+ "\u062C\u0631\u0628\u0629\u0020\u0627\u0644\u062A\u0635\u0641\u062D"
+ "\u002E\u0020\u0648\u064A\u0645\u0643\u0646\u0643\u0020\u0628\u0634"
+ "\u0643\u0644\u0020\u0627\u062E\u062A\u064A\u0627\u0631\u064A\u0020"
+ "\u062A\u0639\u0637\u064A\u0644\u0020\u0647\u0630\u0647\u0020\u0627"
+ "\u0644\u062E\u062F\u0645\u0627\u062A\u002E");
+ attributes()[NSFontAttributeName] = [UIFont systemFontOfSize:20.0];
+ ApplyAttributesForRange(text_range());
+ CGRect bounds = CGRectMake(0, 0, 500, 100);
+ FrameTextInBounds(bounds);
+ CheckForLineCountAndFramedRange(2, text_range());
+}
+
+} // namespace
« no previous file with comments | « ios/chrome/browser/ui/util/manual_text_framer.mm ('k') | ios/chrome/browser/ui/util/relaxed_bounds_constraints_hittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698