1 // Copyright (c) 2012 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 #include "ui/views/controls/label.h" 6 7 #include "base/i18n/rtl.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 #include "ui/accessibility/ax_view_state.h" 11 #include "ui/base/l10n/l10n_util.h" 12 #include "ui/gfx/canvas.h" 13 #include "ui/views/border.h" 14 #include "ui/views/test/views_test_base.h" 15 #include "ui/views/widget/widget.h" 16 17 using base::ASCIIToUTF16; 18 19 namespace views { 20 21 typedef ViewsTestBase LabelTest; 22 23 // All text sizing measurements (width and height) should be greater than this. 24 const int kMinTextDimension = 4; 25 26 // A test utility function to set the application default text direction. 27 void SetRTL(bool rtl) { 28 // Override the current locale/direction. 29 base::i18n::SetICUDefaultLocale(rtl ? "he" : "en"); 30 EXPECT_EQ(rtl, base::i18n::IsRTL()); 31 } 32 33 TEST_F(LabelTest, FontPropertySymbol) { 34 Label label; 35 std::string font_name("symbol"); 36 gfx::Font font(font_name, 26); 37 label.SetFontList(gfx::FontList(font)); 38 gfx::Font font_used = label.font_list().GetPrimaryFont(); 39 EXPECT_EQ(font_name, font_used.GetFontName()); 40 EXPECT_EQ(26, font_used.GetFontSize()); 41 } 42 43 TEST_F(LabelTest, FontPropertyArial) { 44 Label label; 45 std::string font_name("arial"); 46 gfx::Font font(font_name, 30); 47 label.SetFontList(gfx::FontList(font)); 48 gfx::Font font_used = label.font_list().GetPrimaryFont(); 49 EXPECT_EQ(font_name, font_used.GetFontName()); 50 EXPECT_EQ(30, font_used.GetFontSize()); 51 } 52 53 TEST_F(LabelTest, TextProperty) { 54 Label label; 55 base::string16 test_text(ASCIIToUTF16("A random string.")); 56 label.SetText(test_text); 57 EXPECT_EQ(test_text, label.text()); 58 } 59 60 TEST_F(LabelTest, ColorProperty) { 61 Label label; 62 SkColor color = SkColorSetARGB(20, 40, 10, 5); 63 label.SetAutoColorReadabilityEnabled(false); 64 label.SetEnabledColor(color); 65 EXPECT_EQ(color, label.enabled_color()); 66 } 67 68 TEST_F(LabelTest, AlignmentProperty) { 69 const bool was_rtl = base::i18n::IsRTL(); 70 71 Label label; 72 for (size_t i = 0; i < 2; ++i) { 73 // Toggle the application default text direction (to try each direction). 74 SetRTL(!base::i18n::IsRTL()); 75 bool reverse_alignment = base::i18n::IsRTL(); 76 77 // The alignment should be flipped in RTL UI. 78 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 79 EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT, 80 label.GetHorizontalAlignment()); 81 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 82 EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT, 83 label.GetHorizontalAlignment()); 84 label.SetHorizontalAlignment(gfx::ALIGN_CENTER); 85 EXPECT_EQ(gfx::ALIGN_CENTER, label.GetHorizontalAlignment()); 86 87 for (size_t j = 0; j < 2; ++j) { 88 label.SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); 89 const bool rtl = j == 0; 90 label.SetText(rtl ? base::WideToUTF16(L"\x5d0") : ASCIIToUTF16("A")); 91 EXPECT_EQ(rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT, 92 label.GetHorizontalAlignment()); 93 } 94 } 95 96 EXPECT_EQ(was_rtl, base::i18n::IsRTL()); 97 } 98 99 TEST_F(LabelTest, MultiLineProperty) { 100 Label label; 101 EXPECT_FALSE(label.multi_line()); 102 label.SetMultiLine(true); 103 EXPECT_TRUE(label.multi_line()); 104 label.SetMultiLine(false); 105 EXPECT_FALSE(label.multi_line()); 106 } 107 108 TEST_F(LabelTest, ObscuredProperty) { 109 Label label; 110 base::string16 test_text(ASCIIToUTF16("Password!")); 111 label.SetText(test_text); 112 113 // The text should be unobscured by default. 114 EXPECT_FALSE(label.obscured()); 115 EXPECT_EQ(test_text, label.GetLayoutTextForTesting()); 116 EXPECT_EQ(test_text, label.text()); 117 118 label.SetObscured(true); 119 EXPECT_TRUE(label.obscured()); 120 EXPECT_EQ(ASCIIToUTF16("*********"), label.GetLayoutTextForTesting()); 121 EXPECT_EQ(test_text, label.text()); 122 123 label.SetText(test_text + test_text); 124 EXPECT_EQ(ASCIIToUTF16("******************"), 125 label.GetLayoutTextForTesting()); 126 EXPECT_EQ(test_text + test_text, label.text()); 127 128 label.SetObscured(false); 129 EXPECT_FALSE(label.obscured()); 130 EXPECT_EQ(test_text + test_text, label.GetLayoutTextForTesting()); 131 EXPECT_EQ(test_text + test_text, label.text()); 132 } 133 134 TEST_F(LabelTest, ObscuredSurrogatePair) { 135 // 'MUSICAL SYMBOL G CLEF': represented in UTF-16 as two characters 136 // forming the surrogate pair 0x0001D11E. 137 Label label; 138 base::string16 test_text = base::UTF8ToUTF16("\xF0\x9D\x84\x9E"); 139 label.SetText(test_text); 140 141 label.SetObscured(true); 142 EXPECT_EQ(ASCIIToUTF16("*"), label.GetLayoutTextForTesting()); 143 EXPECT_EQ(test_text, label.text()); 144 } 145 146 TEST_F(LabelTest, TooltipProperty) { 147 Label label; 148 label.SetText(ASCIIToUTF16("My cool string.")); 149 150 base::string16 tooltip; 151 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 152 EXPECT_EQ(label.text(), tooltip); 153 154 base::string16 tooltip_text(ASCIIToUTF16("The tooltip!")); 155 label.SetTooltipText(tooltip_text); 156 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 157 EXPECT_EQ(tooltip_text, tooltip); 158 159 label.SetTooltipText(base::string16()); 160 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 161 EXPECT_EQ(label.text(), tooltip); 162 163 // Make the label big enough to hold the text 164 // and expect there to be no tooltip. 165 label.SetBounds(0, 0, 1000, 40); 166 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip)); 167 168 // Shrinking the single-line label's height shouldn't trigger a tooltip. 169 label.SetBounds(0, 0, 1000, label.GetPreferredSize().height() / 2); 170 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip)); 171 172 // Verify that explicitly set tooltip text is shown, regardless of size. 173 label.SetTooltipText(tooltip_text); 174 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 175 EXPECT_EQ(tooltip_text, tooltip); 176 // Clear out the explicitly set tooltip text. 177 label.SetTooltipText(base::string16()); 178 179 // Shrink the bounds and the tooltip should come back. 180 label.SetBounds(0, 0, 10, 10); 181 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 182 183 // Make the label obscured and there is no tooltip. 184 label.SetObscured(true); 185 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip)); 186 187 // Obscuring the text shouldn't permanently clobber the tooltip. 188 label.SetObscured(false); 189 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 190 191 // Making the label multiline shouldn't eliminate the tooltip. 192 label.SetMultiLine(true); 193 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 194 // Expanding the multiline label bounds should eliminate the tooltip. 195 label.SetBounds(0, 0, 1000, 1000); 196 EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip)); 197 198 // Verify that setting the tooltip still shows it. 199 label.SetTooltipText(tooltip_text); 200 EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip)); 201 EXPECT_EQ(tooltip_text, tooltip); 202 // Clear out the tooltip. 203 label.SetTooltipText(base::string16()); 204 } 205 206 TEST_F(LabelTest, Accessibility) { 207 Label label; 208 label.SetText(ASCIIToUTF16("My special text.")); 209 210 ui::AXViewState state; 211 label.GetAccessibleState(&state); 212 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, state.role); 213 EXPECT_EQ(label.text(), state.name); 214 EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY)); 215 } 216 217 TEST_F(LabelTest, EmptyLabelSizing) { 218 Label label; 219 const gfx::Size expected_size(0, gfx::FontList().GetHeight()); 220 EXPECT_EQ(expected_size, label.GetPreferredSize()); 221 label.SetMultiLine(!label.multi_line()); 222 EXPECT_EQ(expected_size, label.GetPreferredSize()); 223 } 224 225 TEST_F(LabelTest, SingleLineSizing) { 226 Label label; 227 label.SetText(ASCIIToUTF16("A not so random string in one line.")); 228 const gfx::Size size = label.GetPreferredSize(); 229 EXPECT_GT(size.height(), kMinTextDimension); 230 EXPECT_GT(size.width(), kMinTextDimension); 231 232 // Setting a size smaller than preferred should not change the preferred size. 233 label.SetSize(gfx::Size(size.width() / 2, size.height() / 2)); 234 EXPECT_EQ(size, label.GetPreferredSize()); 235 236 const gfx::Insets border(10, 20, 30, 40); 237 label.SetBorder(Border::CreateEmptyBorder( 238 border.top(), border.left(), border.bottom(), border.right())); 239 const gfx::Size size_with_border = label.GetPreferredSize(); 240 EXPECT_EQ(size_with_border.height(), size.height() + border.height()); 241 EXPECT_EQ(size_with_border.width(), size.width() + border.width()); 242 } 243 244 TEST_F(LabelTest, MultilineSmallAvailableWidthSizing) { 245 Label label; 246 label.SetMultiLine(true); 247 label.SetAllowCharacterBreak(true); 248 label.SetText(ASCIIToUTF16("Too Wide.")); 249 250 // Check that Label can be laid out at a variety of small sizes, 251 // splitting the words into up to one character per line if necessary. 252 // Incorrect word splitting may cause infinite loops in text layout. 253 gfx::Size required_size = label.GetPreferredSize(); 254 for (int i = 1; i < required_size.width(); ++i) 255 EXPECT_GT(label.GetHeightForWidth(i), 0); 256 } 257 258 TEST_F(LabelTest, MultiLineSizing) { 259 Label label; 260 label.SetFocusable(false); 261 label.SetText( 262 ASCIIToUTF16("A random string\nwith multiple lines\nand returns!")); 263 label.SetMultiLine(true); 264 265 // GetPreferredSize 266 gfx::Size required_size = label.GetPreferredSize(); 267 EXPECT_GT(required_size.height(), kMinTextDimension); 268 EXPECT_GT(required_size.width(), kMinTextDimension); 269 270 // SizeToFit with unlimited width. 271 label.SizeToFit(0); 272 int required_width = label.GetLocalBounds().width(); 273 EXPECT_GT(required_width, kMinTextDimension); 274 275 // SizeToFit with limited width. 276 label.SizeToFit(required_width - 1); 277 int constrained_width = label.GetLocalBounds().width(); 278 #if defined(OS_WIN) 279 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc) 280 // has to be fixed to return the size that fits to given width/height. 281 EXPECT_LT(constrained_width, required_width); 282 #endif 283 EXPECT_GT(constrained_width, kMinTextDimension); 284 285 // Change the width back to the desire width. 286 label.SizeToFit(required_width); 287 EXPECT_EQ(required_width, label.GetLocalBounds().width()); 288 289 // General tests for GetHeightForWidth. 290 int required_height = label.GetHeightForWidth(required_width); 291 EXPECT_GT(required_height, kMinTextDimension); 292 int height_for_constrained_width = label.GetHeightForWidth(constrained_width); 293 #if defined(OS_WIN) 294 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc) 295 // has to be fixed to return the size that fits to given width/height. 296 EXPECT_GT(height_for_constrained_width, required_height); 297 #endif 298 // Using the constrained width or the required_width - 1 should give the 299 // same result for the height because the constrainted width is the tight 300 // width when given "required_width - 1" as the max width. 301 EXPECT_EQ(height_for_constrained_width, 302 label.GetHeightForWidth(required_width - 1)); 303 304 // Test everything with borders. 305 gfx::Insets border(10, 20, 30, 40); 306 label.SetBorder(Border::CreateEmptyBorder( 307 border.top(), border.left(), border.bottom(), border.right())); 308 309 // SizeToFit and borders. 310 label.SizeToFit(0); 311 int required_width_with_border = label.GetLocalBounds().width(); 312 EXPECT_EQ(required_width_with_border, required_width + border.width()); 313 314 // GetHeightForWidth and borders. 315 int required_height_with_border = 316 label.GetHeightForWidth(required_width_with_border); 317 EXPECT_EQ(required_height_with_border, required_height + border.height()); 318 319 // Test that the border width is subtracted before doing the height 320 // calculation. If it is, then the height will grow when width 321 // is shrunk. 322 int height1 = label.GetHeightForWidth(required_width_with_border - 1); 323 #if defined(OS_WIN) 324 // Canvas::SizeStringInt (in ui/gfx/canvas_linux.cc) 325 // has to be fixed to return the size that fits to given width/height. 326 EXPECT_GT(height1, required_height_with_border); 327 #endif 328 EXPECT_EQ(height1, height_for_constrained_width + border.height()); 329 330 // GetPreferredSize and borders. 331 label.SetBounds(0, 0, 0, 0); 332 gfx::Size required_size_with_border = label.GetPreferredSize(); 333 EXPECT_EQ(required_size_with_border.height(), 334 required_size.height() + border.height()); 335 EXPECT_EQ(required_size_with_border.width(), 336 required_size.width() + border.width()); 337 } 338 339 TEST_F(LabelTest, DirectionalityFromText) { 340 Label label; 341 label.SetBounds(0, 0, 1000, 1000); 342 base::string16 paint_text; 343 gfx::Rect text_bounds; 344 int flags = -1; 345 346 // Test text starts with RTL character. 347 label.SetText(base::WideToUTF16(L" \x5d0\x5d1\x5d2 abc")); 348 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 349 EXPECT_EQ(gfx::Canvas::FORCE_RTL_DIRECTIONALITY, 350 flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY | 351 gfx::Canvas::FORCE_LTR_DIRECTIONALITY)); 352 353 // Test text starts with LTR character. 354 label.SetText(base::WideToUTF16(L"ltr \x5d0\x5d1\x5d2 abc")); 355 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 356 EXPECT_EQ(gfx::Canvas::FORCE_LTR_DIRECTIONALITY, 357 flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY | 358 gfx::Canvas::FORCE_LTR_DIRECTIONALITY)); 359 } 360 361 TEST_F(LabelTest, DrawSingleLineString) { 362 Label label; 363 label.SetFocusable(false); 364 365 label.SetText(ASCIIToUTF16("Here's a string with no returns.")); 366 gfx::Size required_size(label.GetPreferredSize()); 367 gfx::Size extra(22, 8); 368 label.SetBounds(0, 0, required_size.width() + extra.width(), 369 required_size.height() + extra.height()); 370 371 // Do some basic verifications for all three alignments. 372 base::string16 paint_text; 373 gfx::Rect text_bounds; 374 int flags = -1; 375 376 // Centered text. 377 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 378 EXPECT_EQ(label.text(), paint_text); 379 // The text should be centered horizontally and vertically. 380 EXPECT_EQ(extra.width() / 2, text_bounds.x()); 381 EXPECT_EQ(0, text_bounds.y()); 382 EXPECT_EQ(required_size.width(), text_bounds.width()); 383 EXPECT_EQ(label.height(), text_bounds.height()); 384 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_CENTER, 385 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 386 gfx::Canvas::TEXT_ALIGN_CENTER | 387 gfx::Canvas::TEXT_ALIGN_RIGHT)); 388 389 // Left aligned text. 390 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 391 paint_text.clear(); 392 text_bounds.SetRect(0, 0, 0, 0); 393 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 394 EXPECT_EQ(label.text(), paint_text); 395 // The text should be left aligned horizontally and centered vertically. 396 EXPECT_EQ(0, text_bounds.x()); 397 EXPECT_EQ(0, text_bounds.y()); 398 EXPECT_EQ(required_size.width(), text_bounds.width()); 399 EXPECT_EQ(label.height(), text_bounds.height()); 400 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_LEFT, 401 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 402 gfx::Canvas::TEXT_ALIGN_CENTER | 403 gfx::Canvas::TEXT_ALIGN_RIGHT)); 404 405 // Right aligned text. 406 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 407 paint_text.clear(); 408 text_bounds.SetRect(0, 0, 0, 0); 409 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 410 EXPECT_EQ(label.text(), paint_text); 411 // The text should be right aligned horizontally and centered vertically. 412 EXPECT_EQ(extra.width(), text_bounds.x()); 413 EXPECT_EQ(0, text_bounds.y()); 414 EXPECT_EQ(required_size.width(), text_bounds.width()); 415 EXPECT_EQ(label.height(), text_bounds.height()); 416 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_RIGHT, 417 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 418 gfx::Canvas::TEXT_ALIGN_CENTER | 419 gfx::Canvas::TEXT_ALIGN_RIGHT)); 420 421 // Test single line drawing with a border. 422 gfx::Insets border(39, 34, 8, 96); 423 label.SetBorder(Border::CreateEmptyBorder( 424 border.top(), border.left(), border.bottom(), border.right())); 425 426 gfx::Size required_size_with_border(label.GetPreferredSize()); 427 EXPECT_EQ(required_size.width() + border.width(), 428 required_size_with_border.width()); 429 EXPECT_EQ(required_size.height() + border.height(), 430 required_size_with_border.height()); 431 label.SetBounds(0, 0, required_size_with_border.width() + extra.width(), 432 required_size_with_border.height() + extra.height()); 433 434 // Centered text with border. 435 label.SetHorizontalAlignment(gfx::ALIGN_CENTER); 436 paint_text.clear(); 437 text_bounds.SetRect(0, 0, 0, 0); 438 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 439 EXPECT_EQ(label.text(), paint_text); 440 // The text should be centered horizontally and vertically within the border. 441 EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x()); 442 EXPECT_EQ(border.top(), text_bounds.y()); 443 EXPECT_EQ(required_size.width(), text_bounds.width()); 444 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 445 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_CENTER, 446 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 447 gfx::Canvas::TEXT_ALIGN_CENTER | 448 gfx::Canvas::TEXT_ALIGN_RIGHT)); 449 450 // Left aligned text with border. 451 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 452 paint_text.clear(); 453 text_bounds.SetRect(0, 0, 0, 0); 454 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 455 EXPECT_EQ(label.text(), paint_text); 456 // The text should be left aligned horizontally and centered vertically. 457 EXPECT_EQ(border.left(), text_bounds.x()); 458 EXPECT_EQ(border.top(), text_bounds.y()); 459 EXPECT_EQ(required_size.width(), text_bounds.width()); 460 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 461 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_LEFT, 462 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 463 gfx::Canvas::TEXT_ALIGN_CENTER | 464 gfx::Canvas::TEXT_ALIGN_RIGHT)); 465 466 // Right aligned text. 467 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 468 paint_text.clear(); 469 text_bounds.SetRect(0, 0, 0, 0); 470 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 471 EXPECT_EQ(label.text(), paint_text); 472 // The text should be right aligned horizontally and centered vertically. 473 EXPECT_EQ(border.left() + extra.width(), text_bounds.x()); 474 EXPECT_EQ(border.top(), text_bounds.y()); 475 EXPECT_EQ(required_size.width(), text_bounds.width()); 476 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 477 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_RIGHT, 478 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 479 gfx::Canvas::TEXT_ALIGN_CENTER | 480 gfx::Canvas::TEXT_ALIGN_RIGHT)); 481 } 482 483 // Pango needs a max height to elide multiline text; that is not supported here. 484 TEST_F(LabelTest, DrawMultiLineString) { 485 Label label; 486 label.SetFocusable(false); 487 // Set a background color to prevent gfx::Canvas::NO_SUBPIXEL_RENDERING flags. 488 label.SetBackgroundColor(SK_ColorWHITE); 489 490 label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!")); 491 label.SetMultiLine(true); 492 label.SizeToFit(0); 493 gfx::Size extra(50, 10); 494 label.SetBounds(label.x(), label.y(), 495 label.width() + extra.width(), 496 label.height() + extra.height()); 497 498 // Do some basic verifications for all three alignments. 499 base::string16 paint_text; 500 gfx::Rect text_bounds; 501 int flags = -1; 502 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 503 EXPECT_EQ(label.text(), paint_text); 504 EXPECT_EQ(extra.width() / 2, text_bounds.x()); 505 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 506 EXPECT_GT(text_bounds.width(), kMinTextDimension); 507 EXPECT_GT(text_bounds.height(), kMinTextDimension); 508 int expected_flags = gfx::Canvas::MULTI_LINE | 509 gfx::Canvas::TEXT_ALIGN_CENTER | 510 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 511 #if !defined(OS_WIN) 512 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 513 #endif 514 EXPECT_EQ(expected_flags, expected_flags); 515 gfx::Rect center_bounds(text_bounds); 516 517 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 518 paint_text.clear(); 519 text_bounds.SetRect(0, 0, 0, 0); 520 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 521 EXPECT_EQ(label.text(), paint_text); 522 EXPECT_EQ(0, text_bounds.x()); 523 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 524 EXPECT_GT(text_bounds.width(), kMinTextDimension); 525 EXPECT_GT(text_bounds.height(), kMinTextDimension); 526 expected_flags = gfx::Canvas::MULTI_LINE | 527 gfx::Canvas::TEXT_ALIGN_LEFT | 528 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 529 #if !defined(OS_WIN) 530 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 531 #endif 532 EXPECT_EQ(expected_flags, expected_flags); 533 534 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 535 paint_text.clear(); 536 text_bounds.SetRect(0, 0, 0, 0); 537 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 538 EXPECT_EQ(label.text(), paint_text); 539 EXPECT_EQ(extra.width(), text_bounds.x()); 540 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 541 EXPECT_GT(text_bounds.width(), kMinTextDimension); 542 EXPECT_GT(text_bounds.height(), kMinTextDimension); 543 expected_flags = gfx::Canvas::MULTI_LINE | 544 gfx::Canvas::TEXT_ALIGN_RIGHT | 545 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 546 #if !defined(OS_WIN) 547 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 548 #endif 549 EXPECT_EQ(expected_flags, expected_flags); 550 551 // Test multiline drawing with a border. 552 gfx::Insets border(19, 92, 23, 2); 553 label.SetBorder(Border::CreateEmptyBorder( 554 border.top(), border.left(), border.bottom(), border.right())); 555 label.SizeToFit(0); 556 label.SetBounds(label.x(), label.y(), 557 label.width() + extra.width(), 558 label.height() + extra.height()); 559 560 label.SetHorizontalAlignment(gfx::ALIGN_CENTER); 561 paint_text.clear(); 562 text_bounds.SetRect(0, 0, 0, 0); 563 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 564 EXPECT_EQ(label.text(), paint_text); 565 EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x()); 566 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 567 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 568 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 569 expected_flags = gfx::Canvas::MULTI_LINE | 570 gfx::Canvas::TEXT_ALIGN_CENTER | 571 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 572 #if !defined(OS_WIN) 573 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 574 #endif 575 EXPECT_EQ(expected_flags, expected_flags); 576 577 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 578 paint_text.clear(); 579 text_bounds.SetRect(0, 0, 0, 0); 580 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 581 EXPECT_EQ(label.text(), paint_text); 582 EXPECT_EQ(border.left(), text_bounds.x()); 583 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 584 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 585 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 586 expected_flags = gfx::Canvas::MULTI_LINE | 587 gfx::Canvas::TEXT_ALIGN_LEFT | 588 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 589 #if !defined(OS_WIN) 590 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 591 #endif 592 EXPECT_EQ(expected_flags, expected_flags); 593 594 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 595 paint_text.clear(); 596 text_bounds.SetRect(0, 0, 0, 0); 597 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 598 EXPECT_EQ(label.text(), paint_text); 599 EXPECT_EQ(extra.width() + border.left(), text_bounds.x()); 600 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 601 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 602 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 603 expected_flags = gfx::Canvas::MULTI_LINE | 604 gfx::Canvas::TEXT_ALIGN_RIGHT | 605 gfx::Canvas::FORCE_LTR_DIRECTIONALITY; 606 #if !defined(OS_WIN) 607 expected_flags |= gfx::Canvas::NO_ELLIPSIS; 608 #endif 609 EXPECT_EQ(expected_flags, expected_flags); 610 } 611 612 TEST_F(LabelTest, DrawSingleLineStringInRTL) { 613 Label label; 614 label.SetFocusable(false); 615 616 std::string locale = l10n_util::GetApplicationLocale(""); 617 base::i18n::SetICUDefaultLocale("he"); 618 619 label.SetText(ASCIIToUTF16("Here's a string with no returns.")); 620 gfx::Size required_size(label.GetPreferredSize()); 621 gfx::Size extra(22, 8); 622 label.SetBounds(0, 0, required_size.width() + extra.width(), 623 required_size.height() + extra.height()); 624 625 // Do some basic verifications for all three alignments. 626 base::string16 paint_text; 627 gfx::Rect text_bounds; 628 int flags = -1; 629 630 // Centered text. 631 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 632 EXPECT_EQ(label.text(), paint_text); 633 // The text should be centered horizontally and vertically. 634 EXPECT_EQ(extra.width() / 2, text_bounds.x()); 635 EXPECT_EQ(0, text_bounds.y()); 636 EXPECT_EQ(required_size.width(), text_bounds.width()); 637 EXPECT_EQ(label.height(), text_bounds.height()); 638 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_CENTER, 639 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 640 gfx::Canvas::TEXT_ALIGN_CENTER | 641 gfx::Canvas::TEXT_ALIGN_RIGHT)); 642 643 // ALIGN_LEFT label. 644 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 645 paint_text.clear(); 646 text_bounds.SetRect(0, 0, 0, 0); 647 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 648 EXPECT_EQ(label.text(), paint_text); 649 // The text should be right aligned horizontally and centered vertically. 650 EXPECT_EQ(extra.width(), text_bounds.x()); 651 EXPECT_EQ(0, text_bounds.y()); 652 EXPECT_EQ(required_size.width(), text_bounds.width()); 653 EXPECT_EQ(label.height(), text_bounds.height()); 654 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_RIGHT, 655 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 656 gfx::Canvas::TEXT_ALIGN_CENTER | 657 gfx::Canvas::TEXT_ALIGN_RIGHT)); 658 659 // ALIGN_RIGHT label. 660 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 661 paint_text.clear(); 662 text_bounds.SetRect(0, 0, 0, 0); 663 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 664 EXPECT_EQ(label.text(), paint_text); 665 // The text should be left aligned horizontally and centered vertically. 666 EXPECT_EQ(0, text_bounds.x()); 667 EXPECT_EQ(0, text_bounds.y()); 668 EXPECT_EQ(required_size.width(), text_bounds.width()); 669 EXPECT_EQ(label.height(), text_bounds.height()); 670 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_LEFT, 671 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 672 gfx::Canvas::TEXT_ALIGN_CENTER | 673 gfx::Canvas::TEXT_ALIGN_RIGHT)); 674 675 676 // Test single line drawing with a border. 677 gfx::Insets border(39, 34, 8, 96); 678 label.SetBorder(Border::CreateEmptyBorder( 679 border.top(), border.left(), border.bottom(), border.right())); 680 681 gfx::Size required_size_with_border(label.GetPreferredSize()); 682 EXPECT_EQ(required_size.width() + border.width(), 683 required_size_with_border.width()); 684 EXPECT_EQ(required_size.height() + border.height(), 685 required_size_with_border.height()); 686 label.SetBounds(0, 0, required_size_with_border.width() + extra.width(), 687 required_size_with_border.height() + extra.height()); 688 689 // Centered text with border. 690 label.SetHorizontalAlignment(gfx::ALIGN_CENTER); 691 paint_text.clear(); 692 text_bounds.SetRect(0, 0, 0, 0); 693 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 694 EXPECT_EQ(label.text(), paint_text); 695 // The text should be centered horizontally and vertically within the border. 696 EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x()); 697 EXPECT_EQ(border.top(), text_bounds.y()); 698 EXPECT_EQ(required_size.width(), text_bounds.width()); 699 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 700 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_CENTER, 701 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 702 gfx::Canvas::TEXT_ALIGN_CENTER | 703 gfx::Canvas::TEXT_ALIGN_RIGHT)); 704 705 // ALIGN_LEFT text with border. 706 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 707 paint_text.clear(); 708 text_bounds.SetRect(0, 0, 0, 0); 709 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 710 EXPECT_EQ(label.text(), paint_text); 711 // The text should be right aligned horizontally and centered vertically. 712 EXPECT_EQ(border.left() + extra.width(), text_bounds.x()); 713 EXPECT_EQ(border.top(), text_bounds.y()); 714 EXPECT_EQ(required_size.width(), text_bounds.width()); 715 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 716 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_RIGHT, 717 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 718 gfx::Canvas::TEXT_ALIGN_CENTER | 719 gfx::Canvas::TEXT_ALIGN_RIGHT)); 720 721 // ALIGN_RIGHT text. 722 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 723 paint_text.clear(); 724 text_bounds.SetRect(0, 0, 0, 0); 725 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 726 EXPECT_EQ(label.text(), paint_text); 727 // The text should be left aligned horizontally and centered vertically. 728 EXPECT_EQ(border.left(), text_bounds.x()); 729 EXPECT_EQ(border.top(), text_bounds.y()); 730 EXPECT_EQ(required_size.width(), text_bounds.width()); 731 EXPECT_EQ(label.GetContentsBounds().height(), text_bounds.height()); 732 EXPECT_EQ(gfx::Canvas::TEXT_ALIGN_LEFT, 733 flags & (gfx::Canvas::TEXT_ALIGN_LEFT | 734 gfx::Canvas::TEXT_ALIGN_CENTER | 735 gfx::Canvas::TEXT_ALIGN_RIGHT)); 736 737 // Reset locale. 738 base::i18n::SetICUDefaultLocale(locale); 739 } 740 741 // On Linux the underlying pango routines require a max height in order to 742 // ellide multiline text. So until that can be resolved, we set all 743 // multiline lables to not ellide in Linux only. 744 TEST_F(LabelTest, DrawMultiLineStringInRTL) { 745 Label label; 746 label.SetFocusable(false); 747 748 // Test for RTL. 749 std::string locale = l10n_util::GetApplicationLocale(""); 750 base::i18n::SetICUDefaultLocale("he"); 751 752 label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!")); 753 label.SetMultiLine(true); 754 label.SizeToFit(0); 755 gfx::Size extra(50, 10); 756 label.SetBounds(label.x(), label.y(), 757 label.width() + extra.width(), 758 label.height() + extra.height()); 759 760 // Do some basic verifications for all three alignments. 761 base::string16 paint_text; 762 gfx::Rect text_bounds; 763 int flags = -1; 764 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 765 EXPECT_EQ(label.text(), paint_text); 766 EXPECT_EQ(extra.width() / 2, text_bounds.x()); 767 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 768 EXPECT_GT(text_bounds.width(), kMinTextDimension); 769 EXPECT_GT(text_bounds.height(), kMinTextDimension); 770 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 771 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_CENTER & flags); 772 #if !defined(OS_WIN) 773 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 774 #endif 775 gfx::Rect center_bounds(text_bounds); 776 777 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 778 paint_text.clear(); 779 text_bounds.SetRect(0, 0, 0, 0); 780 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 781 EXPECT_EQ(label.text(), paint_text); 782 EXPECT_EQ(extra.width(), text_bounds.x()); 783 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 784 EXPECT_GT(text_bounds.width(), kMinTextDimension); 785 EXPECT_GT(text_bounds.height(), kMinTextDimension); 786 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 787 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_RIGHT & flags); 788 #if !defined(OS_WIN) 789 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 790 #endif 791 792 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 793 paint_text.clear(); 794 text_bounds.SetRect(0, 0, 0, 0); 795 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 796 EXPECT_EQ(label.text(), paint_text); 797 EXPECT_EQ(0, text_bounds.x()); 798 EXPECT_EQ(extra.height() / 2, text_bounds.y()); 799 EXPECT_GT(text_bounds.width(), kMinTextDimension); 800 EXPECT_GT(text_bounds.height(), kMinTextDimension); 801 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 802 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_LEFT & flags); 803 #if !defined(OS_WIN) 804 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 805 #endif 806 807 // Test multiline drawing with a border. 808 gfx::Insets border(19, 92, 23, 2); 809 label.SetBorder(Border::CreateEmptyBorder( 810 border.top(), border.left(), border.bottom(), border.right())); 811 label.SizeToFit(0); 812 label.SetBounds(label.x(), label.y(), 813 label.width() + extra.width(), 814 label.height() + extra.height()); 815 816 label.SetHorizontalAlignment(gfx::ALIGN_CENTER); 817 paint_text.clear(); 818 text_bounds.SetRect(0, 0, 0, 0); 819 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 820 EXPECT_EQ(label.text(), paint_text); 821 EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x()); 822 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 823 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 824 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 825 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 826 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_CENTER & flags); 827 #if !defined(OS_WIN) 828 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 829 #endif 830 831 label.SetHorizontalAlignment(gfx::ALIGN_LEFT); 832 paint_text.clear(); 833 text_bounds.SetRect(0, 0, 0, 0); 834 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 835 EXPECT_EQ(label.text(), paint_text); 836 EXPECT_EQ(border.left() + extra.width(), text_bounds.x()); 837 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 838 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 839 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 840 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 841 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_RIGHT & flags); 842 #if !defined(OS_WIN) 843 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 844 #endif 845 846 label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); 847 paint_text.clear(); 848 text_bounds.SetRect(0, 0, 0, 0); 849 label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); 850 EXPECT_EQ(label.text(), paint_text); 851 EXPECT_EQ(border.left(), text_bounds.x()); 852 EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y()); 853 EXPECT_EQ(center_bounds.width(), text_bounds.width()); 854 EXPECT_EQ(center_bounds.height(), text_bounds.height()); 855 EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags); 856 EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_LEFT & flags); 857 #if !defined(OS_WIN) 858 EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags); 859 #endif 860 861 // Reset Locale 862 base::i18n::SetICUDefaultLocale(locale); 863 } 864 865 // Ensure the subpixel rendering flag and background color alpha are respected. 866 TEST_F(LabelTest, DisableSubpixelRendering) { 867 Label label; 868 label.SetBackgroundColor(SK_ColorWHITE); 869 const int flag = gfx::Canvas::NO_SUBPIXEL_RENDERING; 870 EXPECT_EQ(0, label.ComputeDrawStringFlags() & flag); 871 label.SetSubpixelRenderingEnabled(false); 872 EXPECT_EQ(flag, label.ComputeDrawStringFlags() & flag); 873 label.SetSubpixelRenderingEnabled(true); 874 EXPECT_EQ(0, label.ComputeDrawStringFlags() & flag); 875 // Text cannot be drawn with subpixel rendering on transparent backgrounds. 876 label.SetBackgroundColor(SkColorSetARGB(64, 255, 255, 255)); 877 EXPECT_EQ(flag, label.ComputeDrawStringFlags() & flag); 878 } 879 880 // Check that labels support GetTooltipHandlerForPoint. 881 TEST_F(LabelTest, GetTooltipHandlerForPoint) { 882 // A root view must be defined for this test because the hit-testing 883 // behaviour used by GetTooltipHandlerForPoint() is defined by 884 // the ViewTargeter installed on the root view. 885 Widget widget; 886 Widget::InitParams init_params = 887 CreateParams(Widget::InitParams::TYPE_POPUP); 888 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 889 init_params.bounds = gfx::Rect(0, 0, 200, 200); 890 widget.Init(init_params); 891 892 Label label; 893 label.SetText( 894 ASCIIToUTF16("A string that's long enough to exceed the bounds")); 895 label.SetBounds(0, 0, 10, 10); 896 widget.SetContentsView(&label); 897 898 // There's a default tooltip if the text is too big to fit. 899 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(2, 2))); 900 901 // If there's no default tooltip, this should return NULL. 902 label.SetBounds(0, 0, 500, 50); 903 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 2))); 904 905 label.SetTooltipText(ASCIIToUTF16("a tooltip")); 906 // If the point hits the label, and tooltip is set, the label should be 907 // returned as its tooltip handler. 908 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(2, 2))); 909 910 // Additionally, GetTooltipHandlerForPoint should verify that the label 911 // actually contains the point. 912 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(2, 51))); 913 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(-1, 20))); 914 915 // GetTooltipHandlerForPoint works should work in child bounds. 916 label.SetBounds(2, 2, 10, 10); 917 EXPECT_EQ(&label, label.GetTooltipHandlerForPoint(gfx::Point(1, 5))); 918 EXPECT_FALSE(label.GetTooltipHandlerForPoint(gfx::Point(3, 11))); 919 } 920 921 } // namespace views 922