OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #import <UIKit/UIKit.h> |
| 6 |
| 7 #include "base/mac/foundation_util.h" |
| 8 #include "base/mac/scoped_nsobject.h" |
| 9 #include "ios/chrome/browser/ui/util/text_region_mapper.h" |
| 10 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF
ontLoader.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "testing/gtest_mac.h" |
| 13 #include "testing/platform_test.h" |
| 14 |
| 15 namespace { |
| 16 class TextRegionMapperTest : public PlatformTest { |
| 17 protected: |
| 18 void SetUp() override { |
| 19 _string.reset(); |
| 20 _textMapper.reset(); |
| 21 } |
| 22 |
| 23 void InitMapper(NSAttributedString* string, CGRect bounds) { |
| 24 _string.reset([string copy]); |
| 25 _textMapper.reset([[CoreTextRegionMapper alloc] |
| 26 initWithAttributedString:_string |
| 27 bounds:bounds]); |
| 28 } |
| 29 |
| 30 CGRect RectAtIndex(NSArray* array, NSUInteger index) { |
| 31 NSValue* value = base::mac::ObjCCastStrict<NSValue>(array[index]); |
| 32 return [value CGRectValue]; |
| 33 } |
| 34 |
| 35 NSDictionary* AttributesForTextAlignment(NSTextAlignment alignment) { |
| 36 base::scoped_nsobject<NSMutableParagraphStyle> style; |
| 37 style.reset([[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]); |
| 38 [style setAlignment:alignment]; |
| 39 return @{NSParagraphStyleAttributeName : style}; |
| 40 } |
| 41 |
| 42 base::scoped_nsobject<NSAttributedString> _string; |
| 43 base::scoped_nsobject<CoreTextRegionMapper> _textMapper; |
| 44 }; |
| 45 } |
| 46 |
| 47 TEST_F(TextRegionMapperTest, SimpleTextTest) { |
| 48 CGRect bounds = CGRectMake(0, 0, 500, 100); |
| 49 base::scoped_nsobject<NSString> string(@"Simple Test"); |
| 50 InitMapper([[NSAttributedString alloc] initWithString:string], bounds); |
| 51 |
| 52 // Simple case: a single word in a string in a large bounding rect. |
| 53 // Rect bounding word should be inside bounding rect, and should be |
| 54 // wider than it is tall. |
| 55 NSRange range = NSMakeRange(0, 6); // "Simple". |
| 56 NSArray* rects = [_textMapper rectsForRange:range]; |
| 57 ASSERT_EQ(1UL, [rects count]); |
| 58 CGRect rect = RectAtIndex(rects, 0); |
| 59 EXPECT_TRUE(CGRectContainsRect(bounds, rect)); |
| 60 EXPECT_GT(CGRectGetWidth(rect), CGRectGetHeight(rect)); |
| 61 |
| 62 // Range that ends at end of string still generates a rect. |
| 63 range = NSMakeRange(9, 2); |
| 64 rects = [_textMapper rectsForRange:range]; |
| 65 ASSERT_EQ(1UL, [rects count]); |
| 66 rect = RectAtIndex(rects, 0); |
| 67 EXPECT_TRUE(CGRectContainsRect(bounds, rect)); |
| 68 |
| 69 // Simple null cases: range of zero length, range outside of string. |
| 70 range = NSMakeRange(6, 0); |
| 71 rects = [_textMapper rectsForRange:range]; |
| 72 EXPECT_EQ(0UL, [rects count]) << "Range has length 0."; |
| 73 |
| 74 range = NSMakeRange([_string length] + 1, 5); |
| 75 rects = [_textMapper rectsForRange:range]; |
| 76 EXPECT_EQ(0UL, [rects count]) << "Range starts beyond string."; |
| 77 |
| 78 range = NSMakeRange([_string length] - 2, 3); |
| 79 rects = [_textMapper rectsForRange:range]; |
| 80 EXPECT_EQ(0UL, [rects count]) << "Range ends beyond string."; |
| 81 } |
| 82 |
| 83 TEST_F(TextRegionMapperTest, TextAlignmentTest) { |
| 84 CGRect bounds = CGRectMake(0, 0, 500, 100); |
| 85 base::scoped_nsobject<NSAttributedString> string; |
| 86 string.reset([[NSAttributedString alloc] |
| 87 initWithString:@"Simple Test" |
| 88 attributes:AttributesForTextAlignment(NSTextAlignmentLeft)]); |
| 89 InitMapper(string, bounds); |
| 90 |
| 91 // First word of left-aligned string should at the left edge of the bounds. |
| 92 NSRange range = NSMakeRange(0, 6); // "Simple". |
| 93 NSArray* rects = [_textMapper rectsForRange:range]; |
| 94 ASSERT_EQ(1UL, [rects count]); |
| 95 CGRect rect = RectAtIndex(rects, 0); |
| 96 EXPECT_TRUE(CGRectContainsRect(bounds, rect)); |
| 97 EXPECT_GT(CGRectGetWidth(rect), CGRectGetHeight(rect)); |
| 98 EXPECT_EQ(CGRectGetMinX(rect), CGRectGetMinX(bounds)); |
| 99 |
| 100 string.reset([[NSAttributedString alloc] |
| 101 initWithString:@"Simple Test" |
| 102 attributes:AttributesForTextAlignment(NSTextAlignmentRight)]); |
| 103 InitMapper(string, bounds); |
| 104 |
| 105 // Last word of right-aligned string should at the right edge of the bounds. |
| 106 range = NSMakeRange(6, 5); // "Test". |
| 107 rects = [_textMapper rectsForRange:range]; |
| 108 ASSERT_EQ(1UL, [rects count]); |
| 109 rect = RectAtIndex(rects, 0); |
| 110 EXPECT_TRUE(CGRectContainsRect(bounds, rect)); |
| 111 EXPECT_GT(CGRectGetWidth(rect), CGRectGetHeight(rect)); |
| 112 EXPECT_EQ(CGRectGetMaxX(rect), CGRectGetMaxX(bounds)); |
| 113 } |
| 114 |
| 115 TEST_F(TextRegionMapperTest, CJKTest) { |
| 116 CGRect bounds = CGRectMake(0, 0, 345, 65); |
| 117 // clang-format off |
| 118 base::scoped_nsobject<NSString> CJKString( |
| 119 @"“触摸搜索”会将所选字词和当前页面(作为上下文)一起发送给 Google 搜索。" |
| 120 @"您可以在设置中停用此功能。"); |
| 121 // clang-format on |
| 122 base::scoped_nsobject<NSMutableDictionary> attributes([[NSMutableDictionary |
| 123 dictionaryWithDictionary:AttributesForTextAlignment(NSTextAlignmentLeft)] |
| 124 retain]); |
| 125 attributes.get()[NSFontAttributeName] = |
| 126 [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:16]; |
| 127 base::scoped_nsobject<NSAttributedString> string([[NSAttributedString alloc] |
| 128 initWithString:CJKString |
| 129 attributes:attributes]); |
| 130 InitMapper(string, bounds); |
| 131 |
| 132 NSRange range = NSMakeRange(0, 6); // "“触摸搜索”". |
| 133 NSArray* rects = [_textMapper rectsForRange:range]; |
| 134 ASSERT_EQ(1UL, [rects count]); |
| 135 } |
| 136 |
| 137 /* |
| 138 Further unit tests should cover additional cases: |
| 139 - In several languages. |
| 140 - Range split across line break == two rects |
| 141 - Bidi text with text range across scripts gets two rects. |
| 142 - Various string attributions. |
| 143 - Isolate buggy CoreText case. |
| 144 */ |
OLD | NEW |