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

Side by Side Diff: ui/gfx/render_text.cc

Issue 354963003: Move gfx::ElideText functionality to RenderText. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync and rebase. Created 6 years, 5 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/render_text.h ('k') | ui/gfx/render_text_pango.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/render_text.h" 5 #include "ui/gfx/render_text.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <climits> 8 #include <climits>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/i18n/break_iterator.h" 11 #include "base/i18n/break_iterator.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "third_party/icu/source/common/unicode/rbbi.h" 16 #include "third_party/icu/source/common/unicode/rbbi.h"
17 #include "third_party/icu/source/common/unicode/utf16.h" 17 #include "third_party/icu/source/common/unicode/utf16.h"
18 #include "third_party/skia/include/core/SkTypeface.h" 18 #include "third_party/skia/include/core/SkTypeface.h"
19 #include "third_party/skia/include/effects/SkGradientShader.h" 19 #include "third_party/skia/include/effects/SkGradientShader.h"
20 #include "ui/gfx/canvas.h" 20 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/insets.h" 21 #include "ui/gfx/insets.h"
22 #include "ui/gfx/render_text_harfbuzz.h" 22 #include "ui/gfx/render_text_harfbuzz.h"
23 #include "ui/gfx/scoped_canvas.h" 23 #include "ui/gfx/scoped_canvas.h"
24 #include "ui/gfx/skia_util.h" 24 #include "ui/gfx/skia_util.h"
25 #include "ui/gfx/switches.h" 25 #include "ui/gfx/switches.h"
26 #include "ui/gfx/text_constants.h"
27 #include "ui/gfx/text_elider.h" 26 #include "ui/gfx/text_elider.h"
28 #include "ui/gfx/text_utils.h" 27 #include "ui/gfx/text_utils.h"
29 #include "ui/gfx/utf16_indexing.h" 28 #include "ui/gfx/utf16_indexing.h"
30 29
31 namespace gfx { 30 namespace gfx {
32 31
33 namespace { 32 namespace {
34 33
35 // All chars are replaced by this char when the password style is set. 34 // All chars are replaced by this char when the password style is set.
36 // TODO(benrg): GTK uses the first of U+25CF, U+2022, U+2731, U+273A, '*' 35 // TODO(benrg): GTK uses the first of U+25CF, U+2022, U+2731, U+273A, '*'
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 UpdateLayoutText(); 506 UpdateLayoutText();
508 } 507 }
509 } 508 }
510 509
511 void RenderText::SetDisplayRect(const Rect& r) { 510 void RenderText::SetDisplayRect(const Rect& r) {
512 if (r != display_rect_) { 511 if (r != display_rect_) {
513 display_rect_ = r; 512 display_rect_ = r;
514 baseline_ = kInvalidBaseline; 513 baseline_ = kInvalidBaseline;
515 cached_bounds_and_offset_valid_ = false; 514 cached_bounds_and_offset_valid_ = false;
516 lines_.clear(); 515 lines_.clear();
517 if (elide_behavior_ != TRUNCATE) 516 if (elide_behavior_ != NO_ELIDE)
518 UpdateLayoutText(); 517 UpdateLayoutText();
519 } 518 }
520 } 519 }
521 520
522 void RenderText::SetCursorPosition(size_t position) { 521 void RenderText::SetCursorPosition(size_t position) {
523 MoveCursorTo(position, false); 522 MoveCursorTo(position, false);
524 } 523 }
525 524
526 void RenderText::MoveCursor(BreakType break_type, 525 void RenderText::MoveCursor(BreakType break_type,
527 VisualCursorDirection direction, 526 VisualCursorDirection direction,
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() { 738 VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() {
740 return GetTextDirection() == base::i18n::LEFT_TO_RIGHT ? 739 return GetTextDirection() == base::i18n::LEFT_TO_RIGHT ?
741 CURSOR_RIGHT : CURSOR_LEFT; 740 CURSOR_RIGHT : CURSOR_LEFT;
742 } 741 }
743 742
744 SizeF RenderText::GetStringSizeF() { 743 SizeF RenderText::GetStringSizeF() {
745 const Size size = GetStringSize(); 744 const Size size = GetStringSize();
746 return SizeF(size.width(), size.height()); 745 return SizeF(size.width(), size.height());
747 } 746 }
748 747
749 int RenderText::GetContentWidth() { 748 float RenderText::GetContentWidth() {
750 return GetStringSize().width() + (cursor_enabled_ ? 1 : 0); 749 return GetStringSizeF().width() + (cursor_enabled_ ? 1 : 0);
751 } 750 }
752 751
753 int RenderText::GetBaseline() { 752 int RenderText::GetBaseline() {
754 if (baseline_ == kInvalidBaseline) 753 if (baseline_ == kInvalidBaseline)
755 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list()); 754 baseline_ = DetermineBaselineCenteringText(display_rect(), font_list());
756 DCHECK_NE(kInvalidBaseline, baseline_); 755 DCHECK_NE(kInvalidBaseline, baseline_);
757 return baseline_; 756 return baseline_;
758 } 757 }
759 758
760 void RenderText::Draw(Canvas* canvas) { 759 void RenderText::Draw(Canvas* canvas) {
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 selection_color_(kDefaultColor), 919 selection_color_(kDefaultColor),
921 selection_background_focused_color_(kDefaultSelectionBackgroundColor), 920 selection_background_focused_color_(kDefaultSelectionBackgroundColor),
922 focused_(false), 921 focused_(false),
923 composition_range_(Range::InvalidRange()), 922 composition_range_(Range::InvalidRange()),
924 colors_(kDefaultColor), 923 colors_(kDefaultColor),
925 styles_(NUM_TEXT_STYLES), 924 styles_(NUM_TEXT_STYLES),
926 composition_and_selection_styles_applied_(false), 925 composition_and_selection_styles_applied_(false),
927 obscured_(false), 926 obscured_(false),
928 obscured_reveal_index_(-1), 927 obscured_reveal_index_(-1),
929 truncate_length_(0), 928 truncate_length_(0),
930 elide_behavior_(TRUNCATE), 929 elide_behavior_(NO_ELIDE),
931 multiline_(false), 930 multiline_(false),
932 background_is_transparent_(false), 931 background_is_transparent_(false),
933 clip_to_display_rect_(true), 932 clip_to_display_rect_(true),
934 baseline_(kInvalidBaseline), 933 baseline_(kInvalidBaseline),
935 cached_bounds_and_offset_valid_(false) { 934 cached_bounds_and_offset_valid_(false) {
936 } 935 }
937 936
938 SelectionModel RenderText::GetAdjacentSelectionModel( 937 SelectionModel RenderText::GetAdjacentSelectionModel(
939 const SelectionModel& current, 938 const SelectionModel& current,
940 BreakType break_type, 939 BreakType break_type,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 layout_text_.replace(cp_start, 1, text_.substr(start, end - start)); 1183 layout_text_.replace(cp_start, 1, text_.substr(start, end - start));
1185 } 1184 }
1186 } else { 1185 } else {
1187 layout_text_ = text_; 1186 layout_text_ = text_;
1188 } 1187 }
1189 1188
1190 const base::string16& text = layout_text_; 1189 const base::string16& text = layout_text_;
1191 if (truncate_length_ > 0 && truncate_length_ < text.length()) { 1190 if (truncate_length_ > 0 && truncate_length_ < text.length()) {
1192 // Truncate the text at a valid character break and append an ellipsis. 1191 // Truncate the text at a valid character break and append an ellipsis.
1193 icu::StringCharacterIterator iter(text.c_str()); 1192 icu::StringCharacterIterator iter(text.c_str());
1194 iter.setIndex32(truncate_length_ - 1); 1193 // Respect ELIDE_HEAD and ELIDE_MIDDLE preferences during truncation.
1195 layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16); 1194 if (elide_behavior_ == ELIDE_HEAD) {
1195 iter.setIndex32(text.length() - truncate_length_ + 1);
1196 layout_text_.assign(kEllipsisUTF16 + text.substr(iter.getIndex()));
1197 } else if (elide_behavior_ == ELIDE_MIDDLE) {
1198 iter.setIndex32(truncate_length_ / 2);
1199 const size_t ellipsis_start = iter.getIndex();
1200 iter.setIndex32(text.length() - (truncate_length_ / 2));
1201 const size_t ellipsis_end = iter.getIndex();
1202 DCHECK_LE(ellipsis_start, ellipsis_end);
1203 layout_text_.assign(text.substr(0, ellipsis_start) + kEllipsisUTF16 +
1204 text.substr(ellipsis_end));
1205 } else {
1206 iter.setIndex32(truncate_length_ - 1);
1207 layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16);
1208 }
1196 } 1209 }
1197 1210
1198 if (elide_behavior_ != TRUNCATE && elide_behavior_ != FADE_TAIL && 1211 if (elide_behavior_ != NO_ELIDE && elide_behavior_ != FADE_TAIL &&
1199 display_rect_.width() > 0 && !layout_text_.empty() && 1212 !layout_text_.empty() && GetContentWidth() > display_rect_.width()) {
1200 GetContentWidth() > display_rect_.width()) {
1201 // This doesn't trim styles so ellipsis may get rendered as a different 1213 // This doesn't trim styles so ellipsis may get rendered as a different
1202 // style than the preceding text. See crbug.com/327850. 1214 // style than the preceding text. See crbug.com/327850.
1203 layout_text_.assign(ElideText(layout_text_)); 1215 layout_text_.assign(
1216 Elide(layout_text_, display_rect_.width(), elide_behavior_));
1204 } 1217 }
1205 1218
1206 // Replace the newline character with a newline symbol in single line mode. 1219 // Replace the newline character with a newline symbol in single line mode.
1207 static const base::char16 kNewline[] = { '\n', 0 }; 1220 static const base::char16 kNewline[] = { '\n', 0 };
1208 static const base::char16 kNewlineSymbol[] = { 0x2424, 0 }; 1221 static const base::char16 kNewlineSymbol[] = { 0x2424, 0 };
1209 if (!multiline_) 1222 if (!multiline_)
1210 base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_); 1223 base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_);
1211 1224
1212 ResetLayout(); 1225 ResetLayout();
1213 } 1226 }
1214 1227
1215 // TODO(skanuj): Fix code duplication with ElideText in ui/gfx/text_elider.cc 1228 base::string16 RenderText::Elide(const base::string16& text,
1216 // See crbug.com/327846 1229 float available_width,
1217 base::string16 RenderText::ElideText(const base::string16& text) { 1230 ElideBehavior behavior) {
1218 const bool insert_ellipsis = (elide_behavior_ != TRUNCATE); 1231 if (available_width <= 0 || text.empty())
1232 return base::string16();
1233 if (behavior == ELIDE_EMAIL)
1234 return ElideEmail(text, available_width);
1235
1219 // Create a RenderText copy with attributes that affect the rendering width. 1236 // Create a RenderText copy with attributes that affect the rendering width.
1220 scoped_ptr<RenderText> render_text(CreateInstance()); 1237 scoped_ptr<RenderText> render_text(CreateInstance());
1221 render_text->SetFontList(font_list_); 1238 render_text->SetFontList(font_list_);
1222 render_text->SetDirectionalityMode(directionality_mode_); 1239 render_text->SetDirectionalityMode(directionality_mode_);
1223 render_text->SetCursorEnabled(cursor_enabled_); 1240 render_text->SetCursorEnabled(cursor_enabled_);
1224 1241 render_text->set_truncate_length(truncate_length_);
1225 render_text->styles_ = styles_; 1242 render_text->styles_ = styles_;
1226 render_text->colors_ = colors_; 1243 render_text->colors_ = colors_;
1227 render_text->SetText(text); 1244 render_text->SetText(text);
1228 const int current_text_pixel_width = render_text->GetContentWidth(); 1245 if (render_text->GetContentWidth() <= available_width)
1246 return text;
1229 1247
1230 const base::string16 ellipsis = base::string16(kEllipsisUTF16); 1248 const base::string16 ellipsis = base::string16(kEllipsisUTF16);
1231 const bool elide_in_middle = false; 1249 const bool insert_ellipsis = (behavior != TRUNCATE);
1232 const bool elide_at_beginning = false; 1250 const bool elide_in_middle = (behavior == ELIDE_MIDDLE);
1251 const bool elide_at_beginning = (behavior == ELIDE_HEAD);
1233 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning); 1252 StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning);
1234 1253
1235 // Pango will return 0 width for absurdly long strings. Cut the string in 1254 render_text->SetText(ellipsis);
1236 // half and try again. 1255 const float ellipsis_width = render_text->GetContentWidth();
1237 // This is caused by an int overflow in Pango (specifically, in
1238 // pango_glyph_string_extents_range). It's actually more subtle than just
1239 // returning 0, since on super absurdly long strings, the int can wrap and
1240 // return positive numbers again. Detecting that is probably not worth it
1241 // (eliding way too much from a ridiculous string is probably still
1242 // ridiculous), but we should check other widths for bogus values as well.
1243 if (current_text_pixel_width <= 0 && !text.empty())
1244 return ElideText(slicer.CutString(text.length() / 2, insert_ellipsis));
1245 1256
1246 if (current_text_pixel_width <= display_rect_.width()) 1257 if (insert_ellipsis && (ellipsis_width > available_width))
1247 return text;
1248
1249 render_text->SetText(base::string16());
1250 render_text->SetText(ellipsis);
1251 const int ellipsis_width = render_text->GetContentWidth();
1252
1253 if (insert_ellipsis && (ellipsis_width >= display_rect_.width()))
1254 return base::string16(); 1258 return base::string16();
1255 1259
1256 // Use binary search to compute the elided text. 1260 // Use binary search to compute the elided text.
1257 size_t lo = 0; 1261 size_t lo = 0;
1258 size_t hi = text.length() - 1; 1262 size_t hi = text.length() - 1;
1259 const base::i18n::TextDirection text_direction = GetTextDirection(); 1263 const base::i18n::TextDirection text_direction = GetTextDirection();
1260 for (size_t guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) { 1264 for (size_t guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
1261 // Restore styles and colors. They will be truncated to size by SetText. 1265 // Restore styles and colors. They will be truncated to size by SetText.
1262 render_text->styles_ = styles_; 1266 render_text->styles_ = styles_;
1263 render_text->colors_ = colors_; 1267 render_text->colors_ = colors_;
1264 base::string16 new_text = slicer.CutString(guess, false); 1268 base::string16 new_text =
1269 slicer.CutString(guess, insert_ellipsis && behavior != ELIDE_TAIL);
1265 render_text->SetText(new_text); 1270 render_text->SetText(new_text);
1266 1271
1267 // This has to be an additional step so that the ellipsis is rendered with 1272 // This has to be an additional step so that the ellipsis is rendered with
1268 // same style as trailing part of the text. 1273 // same style as trailing part of the text.
1269 if (insert_ellipsis) { 1274 if (insert_ellipsis && behavior == ELIDE_TAIL) {
1270 // When ellipsis follows text whose directionality is not the same as that 1275 // When ellipsis follows text whose directionality is not the same as that
1271 // of the whole text, it will be rendered with the directionality of the 1276 // of the whole text, it will be rendered with the directionality of the
1272 // whole text. Since we want ellipsis to indicate continuation of the 1277 // whole text. Since we want ellipsis to indicate continuation of the
1273 // preceding text, we force the directionality of ellipsis to be same as 1278 // preceding text, we force the directionality of ellipsis to be same as
1274 // the preceding text using LTR or RTL markers. 1279 // the preceding text using LTR or RTL markers.
1275 base::i18n::TextDirection trailing_text_direction = 1280 base::i18n::TextDirection trailing_text_direction =
1276 base::i18n::GetLastStrongCharacterDirection(new_text); 1281 base::i18n::GetLastStrongCharacterDirection(new_text);
1277 new_text.append(ellipsis); 1282 new_text.append(ellipsis);
1278 if (trailing_text_direction != text_direction) { 1283 if (trailing_text_direction != text_direction) {
1279 if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT) 1284 if (trailing_text_direction == base::i18n::LEFT_TO_RIGHT)
1280 new_text += base::i18n::kLeftToRightMark; 1285 new_text += base::i18n::kLeftToRightMark;
1281 else 1286 else
1282 new_text += base::i18n::kRightToLeftMark; 1287 new_text += base::i18n::kRightToLeftMark;
1283 } 1288 }
1284 render_text->SetText(new_text); 1289 render_text->SetText(new_text);
1285 } 1290 }
1286 1291
1287 // We check the width of the whole desired string at once to ensure we 1292 // We check the width of the whole desired string at once to ensure we
1288 // handle kerning/ligatures/etc. correctly. 1293 // handle kerning/ligatures/etc. correctly.
1289 const int guess_width = render_text->GetContentWidth(); 1294 const float guess_width = render_text->GetContentWidth();
1290 if (guess_width == display_rect_.width()) 1295 if (guess_width == available_width)
1291 break; 1296 break;
1292 if (guess_width > display_rect_.width()) { 1297 if (guess_width > available_width) {
1293 hi = guess - 1; 1298 hi = guess - 1;
1294 // Move back if we are on loop terminating condition, and guess is wider 1299 // Move back on the loop terminating condition when the guess is too wide.
1295 // than available.
1296 if (hi < lo) 1300 if (hi < lo)
1297 lo = hi; 1301 lo = hi;
1298 } else { 1302 } else {
1299 lo = guess + 1; 1303 lo = guess + 1;
1300 } 1304 }
1301 } 1305 }
1302 1306
1303 return render_text->text(); 1307 return render_text->text();
1304 } 1308 }
1305 1309
1310 base::string16 RenderText::ElideEmail(const base::string16& email,
1311 float available_width) {
1312 // The returned string will have at least one character besides the ellipsis
1313 // on either side of '@'; if that's impossible, a single ellipsis is returned.
1314 // If possible, only the username is elided. Otherwise, the domain is elided
1315 // in the middle, splitting available width equally with the elided username.
1316 // If the username is short enough that it doesn't need half the available
1317 // width, the elided domain will occupy that extra width.
1318
1319 // Split the email into its local-part (username) and domain-part. The email
1320 // spec allows for @ symbols in the username under some special requirements,
1321 // but not in the domain part, so splitting at the last @ symbol is safe.
1322 const size_t split_index = email.find_last_of('@');
1323 DCHECK_NE(split_index, base::string16::npos);
1324 base::string16 username = email.substr(0, split_index);
1325 base::string16 domain = email.substr(split_index + 1);
1326 DCHECK(!username.empty());
1327 DCHECK(!domain.empty());
1328
1329 // Subtract the @ symbol from the available width as it is mandatory.
1330 const base::string16 kAtSignUTF16 = base::ASCIIToUTF16("@");
1331 available_width -= GetStringWidthF(kAtSignUTF16, font_list());
1332
1333 // Check whether eliding the domain is necessary: if eliding the username
1334 // is sufficient, the domain will not be elided.
1335 const float full_username_width = GetStringWidthF(username, font_list());
1336 const float available_domain_width = available_width -
1337 std::min(full_username_width,
1338 GetStringWidthF(username.substr(0, 1) + kEllipsisUTF16, font_list()));
1339 if (GetStringWidthF(domain, font_list()) > available_domain_width) {
1340 // Elide the domain so that it only takes half of the available width.
1341 // Should the username not need all the width available in its half, the
1342 // domain will occupy the leftover width.
1343 // If |desired_domain_width| is greater than |available_domain_width|: the
1344 // minimal username elision allowed by the specifications will not fit; thus
1345 // |desired_domain_width| must be <= |available_domain_width| at all cost.
1346 const float desired_domain_width =
1347 std::min<float>(available_domain_width,
1348 std::max<float>(available_width - full_username_width,
1349 available_width / 2));
1350 domain = Elide(domain, desired_domain_width, ELIDE_MIDDLE);
1351 // Failing to elide the domain such that at least one character remains
1352 // (other than the ellipsis itself) remains: return a single ellipsis.
1353 if (domain.length() <= 1U)
1354 return base::string16(kEllipsisUTF16);
1355 }
1356
1357 // Fit the username in the remaining width (at this point the elided username
1358 // is guaranteed to fit with at least one character remaining given all the
1359 // precautions taken earlier).
1360 available_width -= GetStringWidthF(domain, font_list());
1361 username = Elide(username, available_width, ELIDE_TAIL);
1362 return username + kAtSignUTF16 + domain;
1363 }
1364
1306 void RenderText::UpdateCachedBoundsAndOffset() { 1365 void RenderText::UpdateCachedBoundsAndOffset() {
1307 if (cached_bounds_and_offset_valid_) 1366 if (cached_bounds_and_offset_valid_)
1308 return; 1367 return;
1309 1368
1310 // TODO(ckocagil): Add support for scrolling multiline text. 1369 // TODO(ckocagil): Add support for scrolling multiline text.
1311 1370
1312 // First, set the valid flag true to calculate the current cursor bounds using 1371 // First, set the valid flag true to calculate the current cursor bounds using
1313 // the stale |display_offset_|. Applying |delta_offset| at the end of this 1372 // the stale |display_offset_|. Applying |delta_offset| at the end of this
1314 // function will set |cursor_bounds_| and |display_offset_| to correct values. 1373 // function will set |cursor_bounds_| and |display_offset_| to correct values.
1315 cached_bounds_and_offset_valid_ = true; 1374 cached_bounds_and_offset_valid_ = true;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 cursor_bounds_ += delta_offset; 1412 cursor_bounds_ += delta_offset;
1354 } 1413 }
1355 1414
1356 void RenderText::DrawSelection(Canvas* canvas) { 1415 void RenderText::DrawSelection(Canvas* canvas) {
1357 const std::vector<Rect> sel = GetSubstringBounds(selection()); 1416 const std::vector<Rect> sel = GetSubstringBounds(selection());
1358 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) 1417 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i)
1359 canvas->FillRect(*i, selection_background_focused_color_); 1418 canvas->FillRect(*i, selection_background_focused_color_);
1360 } 1419 }
1361 1420
1362 } // namespace gfx 1421 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text.h ('k') | ui/gfx/render_text_pango.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698