|
|
Chromium Code Reviews|
Created:
7 years ago by Anuj Modified:
6 years, 11 months ago CC:
chromium-reviews, tfarina, James Su, erikwright+watch_chromium.org, jshin+watch_chromium.org Base URL:
svn://svn.chromium.org/chrome/trunk/src Visibility:
Public. |
DescriptionImplement eliding/truncating at end in RenderText
The eliding is determined using binary search similar to the ElideText
in ui/gfx/text_elider.cc.
The mixed LTR-RTL handling for ellipsis is done using LTR/RTL markers.
There is no other way of rendering the ellipsis with the directionality
of preceding strong-directional characters. Previous scheme worked
because it rendered LTR and RTL sub-strings as different RenderText
instances.
Added helper method to be able to determine directionality of the
trailing text.
Made StringSlicer used by text_elider.cc public to be shared by RenderText.
Additional Fix:
- Changed ellipsis width check to use render text (render_Text.cc)
- Modify tests to never have a scenario where the input is less wide than the elided.
BUG=327833
TEST=ui_unittests,base_unittests
R=msw@chromium.org
TBR=jshin@chromium.org,pkasting@chromium.org
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=242828
Patch Set 1 #Patch Set 2 : Fixed patch #Patch Set 3 : Addressed comments from crrev.com/107513011 #
Total comments: 32
Patch Set 4 : Addressed comments from msw #1 #
Total comments: 10
Patch Set 5 : Addressed comments from msw #2 #
Total comments: 2
Patch Set 6 : Ready for commit #Patch Set 7 : Rebase, recompile, retest #Patch Set 8 : Reloading after setting core.autocrlf false #Patch Set 9 : Fixed merge issue #
Messages
Total messages: 24 (0 generated)
Created Revert of Revert of Implement eliding/truncating at end in RenderText
Patch Set 1 was created by "Revert of Revert".
Patch Set 2 has additional changes in
- render_text.cc :
- Use RenderText to determine lone ellipsis width
- Additional checks for loop limits.
- render_text_unittest.cc :
- Modified tests to have input text always cause elision when expected by
appending a long string.
Tested on Windows 8
FYI https://codereview.chromium.org/119813002/diff/4/chrome/browser/ui/views/omni... File chrome/browser/ui/views/omnibox/omnibox_result_view.cc (right): https://codereview.chromium.org/119813002/diff/4/chrome/browser/ui/views/omni... chrome/browser/ui/views/omnibox/omnibox_result_view.cc:397: (remaining_width < render_text->GetContentWidth())) { Will remove this block. https://codereview.chromium.org/119813002/diff/4/chrome/browser/ui/views/omni... chrome/browser/ui/views/omnibox/omnibox_result_view.cc:402: render_text->SetElideBehavior(gfx::ELIDE_AT_END); I haven't made this change, because my next CL needs it.
Awaiting review. PTAL.
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) nit: consider an early return (text or empty) for display_rect_.width() == 0. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1190: nit: remove the second blank line here. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1195: for (size_t guess = (lo + hi) / 2; (lo <= hi) && (guess < text.length()); When would guess reasonably exceed the text length? Can you solve this correctly rather than patching it over as such? A [D]CHECK + TODO inside the loop would be better than this and perhaps sufficient for now. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1231: // This shouldn't happen, but lets be paranoid. nit: let's, but I'd prefer a real fix (or perhaps a [D]CHECK + TODO for now). I'm also confused as to how this occurs, were you able to repro this and the ensuing underflow described at my my comment <https://codereview.chromium.org/107513011/diff/140001/ui/gfx/render_text.cc#n... With guess==0, the string should be empty (or just an ellipsis), and neither of those should be wider than the available width (unless perhaps the cursor_enabled_ is true and possibly when the display rect has 0 width). I wonder if this should return |insert_ellipsis ? ellipsis : base::string16()|, since the check at 1188 should ensure that an ellipsis on its own does not exceed the available width. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.h File ui/gfx/render_text.h (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.h#newcode234 ui/gfx/render_text.h:234: // If both truncate and elide are specified, the shorter of the two will be nit: wrap this above https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:416: { L" . ", L" . " , false }, nit: this case is equivalent to kWeak, right? Remove it. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:453: for (size_t i = 1; i < ARRAYSIZE_UNSAFE(cases); i++) { Why do you skip the first test case of an empty string? https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:459: // Extend input to always be wide enough to be elided. nit: add to this comment ", otherwise the layout text with its ellipsis may be wider than the input text." Really, I wish the test cases were better designed to avoid this workaround, but oh well... https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); Use append, and shouldn't this use characters with no/weak directionality? https://codereview.chromium.org/119813002/diff/4/ui/gfx/text_elider.cc File ui/gfx/text_elider.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/text_elider.cc#newcod... ui/gfx/text_elider.cc:484: hi = guess - 1; Shouldn't this text_elider version of the eliding code get the same fix as your new RenderText version. Though really, I hope this is removed soon...
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) That check exists on line 1137. I think this is fine, although the early return conditions are split in two places. If you feel strongly about it, I will like to move all of them together at one place - here at the beginning of the method, or before the call to this method. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1190: On 2013/12/27 22:54:33, msw wrote: > nit: remove the second blank line here. Done. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1195: for (size_t guess = (lo + hi) / 2; (lo <= hi) && (guess < text.length()); Given guess will be used as an index of text, I think this constraint is a good idea. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1231: // This shouldn't happen, but lets be paranoid. I was able to reproduce the issue you described in your earlier comment. This won't happen anymore because of the check on line 1188 for ellipsis_width. For some reason (likely cursor_enabled_, but I didn't confirm), the width of ellipsis as determined by GetStringSize is different from that determined through a RenderText instance. But now the ellipsis width is determined using RenderText instance. That said, for the completeness and correctness of this binary-search for-loop, I think it is good to have this check. At this point, the guess_width would correspond to a render_text which contains just an ellipsis when guess == 0 and insert_ellipsis is true. So it should return an empty string. I have modified how I check for guess being in correct bounds of the length of text. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.h File ui/gfx/render_text.h (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.h#newcode234 ui/gfx/render_text.h:234: // If both truncate and elide are specified, the shorter of the two will be On 2013/12/27 22:54:33, msw wrote: > nit: wrap this above Done. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:416: { L" . ", L" . " , false }, On 2013/12/27 22:54:33, msw wrote: > nit: this case is equivalent to kWeak, right? Remove it. Done. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:453: for (size_t i = 1; i < ARRAYSIZE_UNSAFE(cases); i++) { Fixed. I was skipping it for testing the testcases. :) https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:459: // Extend input to always be wide enough to be elided. Reworded the comment. I think this is a reasonable implementation of tests given the variables of font metrics. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); I am curious about preference for append? The two are perfectly equivalent (https://code.google.com/p/chromium/codesearch#chromium/usr/include/c%2B%2B/4....) M is better because it is wider (if not the widest). The directionality doesn't matter as it will all be truncated. https://codereview.chromium.org/119813002/diff/4/ui/gfx/text_elider.cc File ui/gfx/text_elider.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/text_elider.cc#newcod... ui/gfx/text_elider.cc:484: hi = guess - 1; Done. I also want to get rid of this soon. Just resisting the temptation to pull that change in this CL to keep scope of this CL small.
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) On 2013/12/30 22:46:58, Anuj wrote: > That check exists on line 1137. I think this is fine, although the early return > conditions are split in two places. If you feel strongly about it, I will like > to move all of them together at one place - here at the beginning of the method, > or before the call to this method. Please don't delete my original comments when replying; it's frustrating to read replies without context, or to dig into each file to revive that context. You can move this check out to UpdateLayoutText. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1231: // This shouldn't happen, but lets be paranoid. On 2013/12/30 22:46:58, Anuj wrote: > I was able to reproduce the issue you described in your earlier comment. This > won't happen anymore because of the check on line 1188 for ellipsis_width. For > some reason (likely cursor_enabled_, but I didn't confirm), the width of > ellipsis as determined by GetStringSize is different from that determined > through a RenderText instance. But now the ellipsis width is determined using > RenderText instance. > > That said, for the completeness and correctness of this binary-search for-loop, > I think it is good to have this check. At this point, the guess_width would > correspond to a render_text which contains just an ellipsis when guess == 0 and > insert_ellipsis is true. So it should return an empty string. > > I have modified how I check for guess being in correct bounds of the length of > text. > I'm glad the revised ellipsis width checking fixed the underflow issue thanks. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); On 2013/12/30 22:46:58, Anuj wrote: > M is better because it is wider (if not the widest). The directionality doesn't > matter as it will all be truncated. Don't you check the trailing directionality of the elided string and make sure that it matches the input string by adding marks? I would avoid modifying the trailing directionality here. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1194: for (size_t guess = (lo + hi) / 2; (lo <= hi); guess = (lo + hi) / 2) { nit: remove the parens around lo <= hi https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1196: if (guess < 0) Guess will *never* be <0, it's unsigned... remove this. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1199: if (guess >= text.length()) Perhaps my previous question was unclear. Under what conditions will |guess| be assigned a value greater than or equal to the text length? Shouldn't that be impossible? I think this should be removed. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text_unit... File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text_unit... ui/gfx/render_text_unittest.cc:458: // Extend the text of testcase to ensure that it is wider than the nit: s/text of testcase/input text/ https://codereview.chromium.org/119813002/diff/210002/ui/gfx/text_elider.cc File ui/gfx/text_elider.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/text_elider.cc#n... ui/gfx/text_elider.cc:475: if (guess < 0) ditto, remove these checks to be consistent with the other impl.
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) On 2013/12/30 23:17:59, msw wrote: > On 2013/12/30 22:46:58, Anuj wrote: > > That check exists on line 1137. I think this is fine, although the early > return > > conditions are split in two places. If you feel strongly about it, I will like > > to move all of them together at one place - here at the beginning of the > method, > > or before the call to this method. > > Please don't delete my original comments when replying; it's frustrating to read > replies without context, or to dig into each file to revive that context. > You can move this check out to UpdateLayoutText. I think that comments are insufficient context, and if you want code in context too, you have to dig into each file. I will try not to remove your comments from context, but no promises because I think they are ugly/redundant. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1231: // This shouldn't happen, but lets be paranoid. On 2013/12/30 23:17:59, msw wrote: > On 2013/12/30 22:46:58, Anuj wrote: > > I was able to reproduce the issue you described in your earlier comment. This > > won't happen anymore because of the check on line 1188 for ellipsis_width. For > > some reason (likely cursor_enabled_, but I didn't confirm), the width of > > ellipsis as determined by GetStringSize is different from that determined > > through a RenderText instance. But now the ellipsis width is determined using > > RenderText instance. > > > > That said, for the completeness and correctness of this binary-search > for-loop, > > I think it is good to have this check. At this point, the guess_width would > > correspond to a render_text which contains just an ellipsis when guess == 0 > and > > insert_ellipsis is true. So it should return an empty string. > > > > I have modified how I check for guess being in correct bounds of the length of > > text. > > > > I'm glad the revised ellipsis width checking fixed the underflow issue thanks. Done. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); On 2013/12/30 23:17:59, msw wrote: > On 2013/12/30 22:46:58, Anuj wrote: > > M is better because it is wider (if not the widest). The directionality > doesn't > > matter as it will all be truncated. > Don't you check the trailing directionality of the elided string and make sure > that it matches the input string by adding marks? I would avoid modifying the > trailing directionality here. I do. But the string which remains matters. This part will be removed, and its directionality doesn't matter. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1194: for (size_t guess = (lo + hi) / 2; (lo <= hi); guess = (lo + hi) / 2) { On 2013/12/30 23:18:00, msw wrote: > nit: remove the parens around lo <= hi Done. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1196: if (guess < 0) On 2013/12/30 23:18:00, msw wrote: > Guess will *never* be <0, it's unsigned... remove this. Done. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1199: if (guess >= text.length()) On 2013/12/30 23:18:00, msw wrote: > Perhaps my previous question was unclear. Under what conditions will |guess| be > assigned a value greater than or equal to the text length? Shouldn't that be > impossible? I think this should be removed. Done. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text_unit... File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/render_text_unit... ui/gfx/render_text_unittest.cc:458: // Extend the text of testcase to ensure that it is wider than the On 2013/12/30 23:18:00, msw wrote: > nit: s/text of testcase/input text/ Done. https://codereview.chromium.org/119813002/diff/210002/ui/gfx/text_elider.cc File ui/gfx/text_elider.cc (right): https://codereview.chromium.org/119813002/diff/210002/ui/gfx/text_elider.cc#n... ui/gfx/text_elider.cc:475: if (guess < 0) On 2013/12/30 23:18:00, msw wrote: > ditto, remove these checks to be consistent with the other impl. Done.
LGTM with a q/nit. https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) ok, lol https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); On 2013/12/31 00:04:03, Anuj wrote: > On 2013/12/30 23:17:59, msw wrote: > > On 2013/12/30 22:46:58, Anuj wrote: > > > M is better because it is wider (if not the widest). The directionality > > doesn't > > > matter as it will all be truncated. > > Don't you check the trailing directionality of the elided string and make sure > > that it matches the input string by adding marks? I would avoid modifying the > > trailing directionality here. > > I do. But the string which remains matters. This part will be removed, and its > directionality doesn't matter. Ah, good point, thanks for clarifying. https://codereview.chromium.org/119813002/diff/360001/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/360001/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1129: base::string16 text = GetLayoutText(); This won't make a string copy will it? Consider just inlining GetLayoutText() as it was plus the one new GetLayoutText().empty().
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text.cc#newcod... ui/gfx/render_text.cc:1151: if (text.empty()) On 2013/12/31 00:04:03, Anuj wrote: > I think that comments are insufficient context, and if you want code in context > too, you have to dig into each file. I will try not to remove your comments from > context, but no promises because I think they are ugly/redundant. FWIW, it also kinda drives me nuts when people remove all previous comments, or reply above them instead of below. It's really hard to recall the discussion properly sometimes. I usually compromise by removing all but one level of previous comments (or sometimes more levels when more context is necessary), as I've done in this case.
https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.cc File ui/gfx/render_text_unittest.cc (right): https://codereview.chromium.org/119813002/diff/4/ui/gfx/render_text_unittest.... ui/gfx/render_text_unittest.cc:461: input += WideToUTF16(L" MMMMMMMMMMM"); On 2013/12/31 00:24:52, msw wrote: > On 2013/12/31 00:04:03, Anuj wrote: > > On 2013/12/30 23:17:59, msw wrote: > > > On 2013/12/30 22:46:58, Anuj wrote: > > > > M is better because it is wider (if not the widest). The directionality > > > doesn't > > > > matter as it will all be truncated. > > > Don't you check the trailing directionality of the elided string and make > sure > > > that it matches the input string by adding marks? I would avoid modifying > the > > > trailing directionality here. > > > > I do. But the string which remains matters. This part will be removed, and its > > directionality doesn't matter. > > Ah, good point, thanks for clarifying. Done. https://codereview.chromium.org/119813002/diff/360001/ui/gfx/render_text.cc File ui/gfx/render_text.cc (right): https://codereview.chromium.org/119813002/diff/360001/ui/gfx/render_text.cc#n... ui/gfx/render_text.cc:1129: base::string16 text = GetLayoutText(); On 2013/12/31 00:24:52, msw wrote: > This won't make a string copy will it? Consider just inlining GetLayoutText() as > it was plus the one new GetLayoutText().empty(). Done.
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/430001
Failed to apply patch for
chrome/browser/ui/views/omnibox/omnibox_result_view.cc:
While running patch -p1 --forward --force --no-backup-if-mismatch;
patching file chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Hunk #1 FAILED at 357.
1 out of 1 hunk FAILED -- saving rejects to file
chrome/browser/ui/views/omnibox/omnibox_result_view.cc.rej
Patch: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index
9938b54774812cc4cf22db8bb0cc4e2fd0506cdc..6eb06903c1db5ad45544ad6956c9aaf3c5b814d6
100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -357,213 +357,59 @@ int OmniboxResultView::DrawString(
}
}
- // Split the text into visual runs. We do this first so that we don't need
to
- // worry about whether our eliding might change the visual display in
- // unintended ways, e.g. by removing directional markings or by adding an
- // ellipsis that's not enclosed in appropriate markings.
- base::i18n::BiDiLineIterator bidi_line;
- if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
- return x;
- const int num_runs = bidi_line.CountRuns();
- ScopedVector<gfx::RenderText> render_texts;
- Runs runs;
- for (int run = 0; run < num_runs; ++run) {
- int run_start_int = 0, run_length_int = 0;
- // The index we pass to GetVisualRun corresponds to the position of the run
- // in the displayed text. For example, the string "Google in HEBREW" (where
- // HEBREW is text in the Hebrew language) has two runs: "Google in " which
- // is an LTR run, and "HEBREW" which is an RTL run. In an LTR context, the
- // run "Google in " has the index 0 (since it is the leftmost run
- // displayed). In an RTL context, the same run has the index 1 because it
- // is the rightmost run. This is why the order in which we traverse the
- // runs is different depending on the locale direction.
- const UBiDiDirection run_direction = bidi_line.GetVisualRun(
- (base::i18n::IsRTL() && !is_url) ? (num_runs - run - 1) : run,
- &run_start_int, &run_length_int);
- DCHECK_GT(run_length_int, 0);
- runs.push_back(RunData());
- RunData* current_run = &runs.back();
- current_run->run_start = run_start_int;
- const size_t run_end = current_run->run_start + run_length_int;
- current_run->visual_order = run;
- current_run->is_rtl = !is_url && (run_direction == UBIDI_RTL);
-
- // Compute classifications for this run.
- for (size_t i = 0; i < classifications.size(); ++i) {
- const size_t text_start =
- std::max(classifications[i].offset, current_run->run_start);
- if (text_start >= run_end)
- break; // We're past the last classification in the run.
-
- const size_t text_end = (i < (classifications.size() - 1)) ?
- std::min(classifications[i + 1].offset, run_end) : run_end;
- if (text_end <= current_run->run_start)
- continue; // We haven't reached the first classification in the run.
-
- render_texts.push_back(gfx::RenderText::CreateInstance());
- gfx::RenderText* render_text = render_texts.back();
- current_run->classifications.push_back(render_text);
- render_text->SetText(text.substr(text_start, text_end - text_start));
- render_text->SetFontList(font_list_);
-
- // Calculate style-related data.
- if (classifications[i].style & ACMatchClassification::MATCH)
- render_text->SetStyle(gfx::BOLD, true);
- const ResultViewState state = GetState();
- if (classifications[i].style & ACMatchClassification::URL)
- render_text->SetColor(GetColor(state, URL));
- else if (classifications[i].style & ACMatchClassification::DIM)
- render_text->SetColor(GetColor(state, DIMMED_TEXT));
- else
- render_text->SetColor(GetColor(state, force_dim ? DIMMED_TEXT : TEXT));
-
- current_run->pixel_width += render_text->GetStringSize().width();
- }
- DCHECK(!current_run->classifications.empty());
- }
- DCHECK(!runs.empty());
-
- // Sort into logical order so we can elide logically.
- std::sort(runs.begin(), runs.end(), &SortRunsLogically);
-
- // Now determine what to elide, if anything. Several subtle points:
- // * Because we have the run data, we can get edge cases correct, like
- // whether to place an ellipsis before or after the end of a run when the
- // text needs to be elided at the run boundary.
- // * The "or one before it" comments below refer to cases where an earlier
- // classification fits completely, but leaves too little space for an
- // ellipsis that turns out to be needed later. These cases are commented
- // more completely in Elide().
- int remaining_width = mirroring_context_->remaining_width(x);
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- if (i->pixel_width > remaining_width) {
- // This run or one before it needs to be elided.
- for (Classifications::iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const int width = (*j)->GetStringSize().width();
- if (width > remaining_width) {
- // This classification or one before it needs to be elided. Erase
all
- // further classifications and runs so Elide() can simply reverse-
- // iterate over everything to find the specific classification to
- // elide.
- i->classifications.erase(++j, i->classifications.end());
- runs.erase(++i, runs.end());
- Elide(&runs, remaining_width);
- break;
- }
- remaining_width -= width;
- }
+ scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance());
+ const size_t text_length = text.length();
+ render_text->SetText(text);
+ render_text->SetFontList(font_list_);
+ render_text->SetMultiline(false);
+ render_text->SetCursorEnabled(false);
+ if (is_url)
+ render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR);
+
+ // Apply classifications.
+ for (size_t i = 0; i < classifications.size(); ++i) {
+ const size_t text_start = classifications[i].offset;
+ if (text_start >= text_length)
break;
- }
- remaining_width -= i->pixel_width;
- }
- // Sort back into visual order so we can display the runs correctly.
- std::sort(runs.begin(), runs.end(), &SortRunsVisually);
-
- // Draw the runs.
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL());
- if (reverse_visible_order)
- std::reverse(i->classifications.begin(), i->classifications.end());
- for (Classifications::const_iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const gfx::Size size = (*j)->GetStringSize();
- // Align the text runs to a common baseline.
- const gfx::Rect rect(
- mirroring_context_->mirrored_left_coord(x, x + size.width()), y,
- size.width(), height());
- (*j)->SetDisplayRect(rect);
- (*j)->Draw(canvas);
- x += size.width();
+ const size_t text_end = (i < (classifications.size() - 1)) ?
+ std::min(classifications[i + 1].offset, text_length) : text_length;
+ const gfx::Range current_range(text_start, text_end);
+
+ // Calculate style-related data.
+ if (classifications[i].style & ACMatchClassification::MATCH)
+ render_text->ApplyStyle(gfx::BOLD, true, current_range);
+
+ ColorKind color_kind = TEXT;
+ if (classifications[i].style & ACMatchClassification::URL) {
+ color_kind = URL;
+ } else if (force_dim ||
+ (classifications[i].style & ACMatchClassification::DIM)) {
+ color_kind = DIMMED_TEXT;
}
+ render_text->ApplyColor(GetColor(GetState(), color_kind), current_range);
}
- return x;
-}
+ int remaining_width = mirroring_context_->remaining_width(x);
-void OmniboxResultView::Elide(Runs* runs, int remaining_width) const {
- // The complexity of this function is due to edge cases like the following:
- // We have 100 px of available space, an initial classification that takes 86
- // px, and a font that has a 15 px wide ellipsis character. Now if the first
- // classification is followed by several very narrow classifications (e.g. 3
- // px wide each), we don't know whether we need to elide or not at the time
we
- // see the first classification -- it depends on how many subsequent
- // classifications follow, and some of those may be in the next run (or
- // several runs!). This is why instead we let our caller move forward until
- // we know we definitely need to elide, and then in this function we move
- // backward again until we find a string that we can successfully do the
- // eliding on.
- bool on_trailing_classification = true;
- for (Runs::reverse_iterator i(runs->rbegin()); i != runs->rend(); ++i) {
- for (Classifications::reverse_iterator j(i->classifications.rbegin());
- j != i->classifications.rend(); ++j) {
- if (!on_trailing_classification) {
- // We also add this classification's width (sans ellipsis) back to the
- // available width since we want to consider the available space we'll
- // have when we draw this classification.
- remaining_width += (*j)->GetStringSize().width();
-
- // If we reached here, we couldn't fit an ellipsis in the space taken
by
- // the previous classifications we looped over (see comments at bottom
- // of loop). Append one here to represent those elided portions.
- (*j)->SetText((*j)->text() + kEllipsis);
- }
- on_trailing_classification = false;
-
- // Can we fit at least an ellipsis?
- gfx::Font font((*j)->GetStyle(gfx:…
(message too large)
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/390002
Failed to apply patch for
chrome/browser/ui/views/omnibox/omnibox_result_view.cc:
While running patch -p1 --forward --force --no-backup-if-mismatch;
patching file chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Hunk #1 FAILED at 357.
1 out of 1 hunk FAILED -- saving rejects to file
chrome/browser/ui/views/omnibox/omnibox_result_view.cc.rej
Patch: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index
9938b54774812cc4cf22db8bb0cc4e2fd0506cdc..6eb06903c1db5ad45544ad6956c9aaf3c5b814d6
100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -357,213 +357,59 @@ int OmniboxResultView::DrawString(
}
}
- // Split the text into visual runs. We do this first so that we don't need
to
- // worry about whether our eliding might change the visual display in
- // unintended ways, e.g. by removing directional markings or by adding an
- // ellipsis that's not enclosed in appropriate markings.
- base::i18n::BiDiLineIterator bidi_line;
- if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
- return x;
- const int num_runs = bidi_line.CountRuns();
- ScopedVector<gfx::RenderText> render_texts;
- Runs runs;
- for (int run = 0; run < num_runs; ++run) {
- int run_start_int = 0, run_length_int = 0;
- // The index we pass to GetVisualRun corresponds to the position of the run
- // in the displayed text. For example, the string "Google in HEBREW" (where
- // HEBREW is text in the Hebrew language) has two runs: "Google in " which
- // is an LTR run, and "HEBREW" which is an RTL run. In an LTR context, the
- // run "Google in " has the index 0 (since it is the leftmost run
- // displayed). In an RTL context, the same run has the index 1 because it
- // is the rightmost run. This is why the order in which we traverse the
- // runs is different depending on the locale direction.
- const UBiDiDirection run_direction = bidi_line.GetVisualRun(
- (base::i18n::IsRTL() && !is_url) ? (num_runs - run - 1) : run,
- &run_start_int, &run_length_int);
- DCHECK_GT(run_length_int, 0);
- runs.push_back(RunData());
- RunData* current_run = &runs.back();
- current_run->run_start = run_start_int;
- const size_t run_end = current_run->run_start + run_length_int;
- current_run->visual_order = run;
- current_run->is_rtl = !is_url && (run_direction == UBIDI_RTL);
-
- // Compute classifications for this run.
- for (size_t i = 0; i < classifications.size(); ++i) {
- const size_t text_start =
- std::max(classifications[i].offset, current_run->run_start);
- if (text_start >= run_end)
- break; // We're past the last classification in the run.
-
- const size_t text_end = (i < (classifications.size() - 1)) ?
- std::min(classifications[i + 1].offset, run_end) : run_end;
- if (text_end <= current_run->run_start)
- continue; // We haven't reached the first classification in the run.
-
- render_texts.push_back(gfx::RenderText::CreateInstance());
- gfx::RenderText* render_text = render_texts.back();
- current_run->classifications.push_back(render_text);
- render_text->SetText(text.substr(text_start, text_end - text_start));
- render_text->SetFontList(font_list_);
-
- // Calculate style-related data.
- if (classifications[i].style & ACMatchClassification::MATCH)
- render_text->SetStyle(gfx::BOLD, true);
- const ResultViewState state = GetState();
- if (classifications[i].style & ACMatchClassification::URL)
- render_text->SetColor(GetColor(state, URL));
- else if (classifications[i].style & ACMatchClassification::DIM)
- render_text->SetColor(GetColor(state, DIMMED_TEXT));
- else
- render_text->SetColor(GetColor(state, force_dim ? DIMMED_TEXT : TEXT));
-
- current_run->pixel_width += render_text->GetStringSize().width();
- }
- DCHECK(!current_run->classifications.empty());
- }
- DCHECK(!runs.empty());
-
- // Sort into logical order so we can elide logically.
- std::sort(runs.begin(), runs.end(), &SortRunsLogically);
-
- // Now determine what to elide, if anything. Several subtle points:
- // * Because we have the run data, we can get edge cases correct, like
- // whether to place an ellipsis before or after the end of a run when the
- // text needs to be elided at the run boundary.
- // * The "or one before it" comments below refer to cases where an earlier
- // classification fits completely, but leaves too little space for an
- // ellipsis that turns out to be needed later. These cases are commented
- // more completely in Elide().
- int remaining_width = mirroring_context_->remaining_width(x);
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- if (i->pixel_width > remaining_width) {
- // This run or one before it needs to be elided.
- for (Classifications::iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const int width = (*j)->GetStringSize().width();
- if (width > remaining_width) {
- // This classification or one before it needs to be elided. Erase
all
- // further classifications and runs so Elide() can simply reverse-
- // iterate over everything to find the specific classification to
- // elide.
- i->classifications.erase(++j, i->classifications.end());
- runs.erase(++i, runs.end());
- Elide(&runs, remaining_width);
- break;
- }
- remaining_width -= width;
- }
+ scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance());
+ const size_t text_length = text.length();
+ render_text->SetText(text);
+ render_text->SetFontList(font_list_);
+ render_text->SetMultiline(false);
+ render_text->SetCursorEnabled(false);
+ if (is_url)
+ render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR);
+
+ // Apply classifications.
+ for (size_t i = 0; i < classifications.size(); ++i) {
+ const size_t text_start = classifications[i].offset;
+ if (text_start >= text_length)
break;
- }
- remaining_width -= i->pixel_width;
- }
- // Sort back into visual order so we can display the runs correctly.
- std::sort(runs.begin(), runs.end(), &SortRunsVisually);
-
- // Draw the runs.
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL());
- if (reverse_visible_order)
- std::reverse(i->classifications.begin(), i->classifications.end());
- for (Classifications::const_iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const gfx::Size size = (*j)->GetStringSize();
- // Align the text runs to a common baseline.
- const gfx::Rect rect(
- mirroring_context_->mirrored_left_coord(x, x + size.width()), y,
- size.width(), height());
- (*j)->SetDisplayRect(rect);
- (*j)->Draw(canvas);
- x += size.width();
+ const size_t text_end = (i < (classifications.size() - 1)) ?
+ std::min(classifications[i + 1].offset, text_length) : text_length;
+ const gfx::Range current_range(text_start, text_end);
+
+ // Calculate style-related data.
+ if (classifications[i].style & ACMatchClassification::MATCH)
+ render_text->ApplyStyle(gfx::BOLD, true, current_range);
+
+ ColorKind color_kind = TEXT;
+ if (classifications[i].style & ACMatchClassification::URL) {
+ color_kind = URL;
+ } else if (force_dim ||
+ (classifications[i].style & ACMatchClassification::DIM)) {
+ color_kind = DIMMED_TEXT;
}
+ render_text->ApplyColor(GetColor(GetState(), color_kind), current_range);
}
- return x;
-}
+ int remaining_width = mirroring_context_->remaining_width(x);
-void OmniboxResultView::Elide(Runs* runs, int remaining_width) const {
- // The complexity of this function is due to edge cases like the following:
- // We have 100 px of available space, an initial classification that takes 86
- // px, and a font that has a 15 px wide ellipsis character. Now if the first
- // classification is followed by several very narrow classifications (e.g. 3
- // px wide each), we don't know whether we need to elide or not at the time
we
- // see the first classification -- it depends on how many subsequent
- // classifications follow, and some of those may be in the next run (or
- // several runs!). This is why instead we let our caller move forward until
- // we know we definitely need to elide, and then in this function we move
- // backward again until we find a string that we can successfully do the
- // eliding on.
- bool on_trailing_classification = true;
- for (Runs::reverse_iterator i(runs->rbegin()); i != runs->rend(); ++i) {
- for (Classifications::reverse_iterator j(i->classifications.rbegin());
- j != i->classifications.rend(); ++j) {
- if (!on_trailing_classification) {
- // We also add this classification's width (sans ellipsis) back to the
- // available width since we want to consider the available space we'll
- // have when we draw this classification.
- remaining_width += (*j)->GetStringSize().width();
-
- // If we reached here, we couldn't fit an ellipsis in the space taken
by
- // the previous classifications we looped over (see comments at bottom
- // of loop). Append one here to represent those elided portions.
- (*j)->SetText((*j)->text() + kEllipsis);
- }
- on_trailing_classification = false;
-
- // Can we fit at least an ellipsis?
- gfx::Font font((*j)->GetStyle(gfx:…
(message too large)
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/520001
Failed to apply patch for
chrome/browser/ui/views/omnibox/omnibox_result_view.cc:
While running patch -p1 --forward --force --no-backup-if-mismatch;
patching file chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Hunk #1 FAILED at 357.
1 out of 1 hunk FAILED -- saving rejects to file
chrome/browser/ui/views/omnibox/omnibox_result_view.cc.rej
Patch: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index
9938b54774812cc4cf22db8bb0cc4e2fd0506cdc..6eb06903c1db5ad45544ad6956c9aaf3c5b814d6
100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -357,213 +357,59 @@ int OmniboxResultView::DrawString(
}
}
- // Split the text into visual runs. We do this first so that we don't need
to
- // worry about whether our eliding might change the visual display in
- // unintended ways, e.g. by removing directional markings or by adding an
- // ellipsis that's not enclosed in appropriate markings.
- base::i18n::BiDiLineIterator bidi_line;
- if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
- return x;
- const int num_runs = bidi_line.CountRuns();
- ScopedVector<gfx::RenderText> render_texts;
- Runs runs;
- for (int run = 0; run < num_runs; ++run) {
- int run_start_int = 0, run_length_int = 0;
- // The index we pass to GetVisualRun corresponds to the position of the run
- // in the displayed text. For example, the string "Google in HEBREW" (where
- // HEBREW is text in the Hebrew language) has two runs: "Google in " which
- // is an LTR run, and "HEBREW" which is an RTL run. In an LTR context, the
- // run "Google in " has the index 0 (since it is the leftmost run
- // displayed). In an RTL context, the same run has the index 1 because it
- // is the rightmost run. This is why the order in which we traverse the
- // runs is different depending on the locale direction.
- const UBiDiDirection run_direction = bidi_line.GetVisualRun(
- (base::i18n::IsRTL() && !is_url) ? (num_runs - run - 1) : run,
- &run_start_int, &run_length_int);
- DCHECK_GT(run_length_int, 0);
- runs.push_back(RunData());
- RunData* current_run = &runs.back();
- current_run->run_start = run_start_int;
- const size_t run_end = current_run->run_start + run_length_int;
- current_run->visual_order = run;
- current_run->is_rtl = !is_url && (run_direction == UBIDI_RTL);
-
- // Compute classifications for this run.
- for (size_t i = 0; i < classifications.size(); ++i) {
- const size_t text_start =
- std::max(classifications[i].offset, current_run->run_start);
- if (text_start >= run_end)
- break; // We're past the last classification in the run.
-
- const size_t text_end = (i < (classifications.size() - 1)) ?
- std::min(classifications[i + 1].offset, run_end) : run_end;
- if (text_end <= current_run->run_start)
- continue; // We haven't reached the first classification in the run.
-
- render_texts.push_back(gfx::RenderText::CreateInstance());
- gfx::RenderText* render_text = render_texts.back();
- current_run->classifications.push_back(render_text);
- render_text->SetText(text.substr(text_start, text_end - text_start));
- render_text->SetFontList(font_list_);
-
- // Calculate style-related data.
- if (classifications[i].style & ACMatchClassification::MATCH)
- render_text->SetStyle(gfx::BOLD, true);
- const ResultViewState state = GetState();
- if (classifications[i].style & ACMatchClassification::URL)
- render_text->SetColor(GetColor(state, URL));
- else if (classifications[i].style & ACMatchClassification::DIM)
- render_text->SetColor(GetColor(state, DIMMED_TEXT));
- else
- render_text->SetColor(GetColor(state, force_dim ? DIMMED_TEXT : TEXT));
-
- current_run->pixel_width += render_text->GetStringSize().width();
- }
- DCHECK(!current_run->classifications.empty());
- }
- DCHECK(!runs.empty());
-
- // Sort into logical order so we can elide logically.
- std::sort(runs.begin(), runs.end(), &SortRunsLogically);
-
- // Now determine what to elide, if anything. Several subtle points:
- // * Because we have the run data, we can get edge cases correct, like
- // whether to place an ellipsis before or after the end of a run when the
- // text needs to be elided at the run boundary.
- // * The "or one before it" comments below refer to cases where an earlier
- // classification fits completely, but leaves too little space for an
- // ellipsis that turns out to be needed later. These cases are commented
- // more completely in Elide().
- int remaining_width = mirroring_context_->remaining_width(x);
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- if (i->pixel_width > remaining_width) {
- // This run or one before it needs to be elided.
- for (Classifications::iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const int width = (*j)->GetStringSize().width();
- if (width > remaining_width) {
- // This classification or one before it needs to be elided. Erase
all
- // further classifications and runs so Elide() can simply reverse-
- // iterate over everything to find the specific classification to
- // elide.
- i->classifications.erase(++j, i->classifications.end());
- runs.erase(++i, runs.end());
- Elide(&runs, remaining_width);
- break;
- }
- remaining_width -= width;
- }
+ scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance());
+ const size_t text_length = text.length();
+ render_text->SetText(text);
+ render_text->SetFontList(font_list_);
+ render_text->SetMultiline(false);
+ render_text->SetCursorEnabled(false);
+ if (is_url)
+ render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR);
+
+ // Apply classifications.
+ for (size_t i = 0; i < classifications.size(); ++i) {
+ const size_t text_start = classifications[i].offset;
+ if (text_start >= text_length)
break;
- }
- remaining_width -= i->pixel_width;
- }
- // Sort back into visual order so we can display the runs correctly.
- std::sort(runs.begin(), runs.end(), &SortRunsVisually);
-
- // Draw the runs.
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL());
- if (reverse_visible_order)
- std::reverse(i->classifications.begin(), i->classifications.end());
- for (Classifications::const_iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const gfx::Size size = (*j)->GetStringSize();
- // Align the text runs to a common baseline.
- const gfx::Rect rect(
- mirroring_context_->mirrored_left_coord(x, x + size.width()), y,
- size.width(), height());
- (*j)->SetDisplayRect(rect);
- (*j)->Draw(canvas);
- x += size.width();
+ const size_t text_end = (i < (classifications.size() - 1)) ?
+ std::min(classifications[i + 1].offset, text_length) : text_length;
+ const gfx::Range current_range(text_start, text_end);
+
+ // Calculate style-related data.
+ if (classifications[i].style & ACMatchClassification::MATCH)
+ render_text->ApplyStyle(gfx::BOLD, true, current_range);
+
+ ColorKind color_kind = TEXT;
+ if (classifications[i].style & ACMatchClassification::URL) {
+ color_kind = URL;
+ } else if (force_dim ||
+ (classifications[i].style & ACMatchClassification::DIM)) {
+ color_kind = DIMMED_TEXT;
}
+ render_text->ApplyColor(GetColor(GetState(), color_kind), current_range);
}
- return x;
-}
+ int remaining_width = mirroring_context_->remaining_width(x);
-void OmniboxResultView::Elide(Runs* runs, int remaining_width) const {
- // The complexity of this function is due to edge cases like the following:
- // We have 100 px of available space, an initial classification that takes 86
- // px, and a font that has a 15 px wide ellipsis character. Now if the first
- // classification is followed by several very narrow classifications (e.g. 3
- // px wide each), we don't know whether we need to elide or not at the time
we
- // see the first classification -- it depends on how many subsequent
- // classifications follow, and some of those may be in the next run (or
- // several runs!). This is why instead we let our caller move forward until
- // we know we definitely need to elide, and then in this function we move
- // backward again until we find a string that we can successfully do the
- // eliding on.
- bool on_trailing_classification = true;
- for (Runs::reverse_iterator i(runs->rbegin()); i != runs->rend(); ++i) {
- for (Classifications::reverse_iterator j(i->classifications.rbegin());
- j != i->classifications.rend(); ++j) {
- if (!on_trailing_classification) {
- // We also add this classification's width (sans ellipsis) back to the
- // available width since we want to consider the available space we'll
- // have when we draw this classification.
- remaining_width += (*j)->GetStringSize().width();
-
- // If we reached here, we couldn't fit an ellipsis in the space taken
by
- // the previous classifications we looped over (see comments at bottom
- // of loop). Append one here to represent those elided portions.
- (*j)->SetText((*j)->text() + kEllipsis);
- }
- on_trailing_classification = false;
-
- // Can we fit at least an ellipsis?
- gfx::Font font((*j)->GetStyle(gfx:…
(message too large)
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/520001
Failed to apply patch for
chrome/browser/ui/views/omnibox/omnibox_result_view.cc:
While running patch -p1 --forward --force --no-backup-if-mismatch;
patching file chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Hunk #1 FAILED at 357.
1 out of 1 hunk FAILED -- saving rejects to file
chrome/browser/ui/views/omnibox/omnibox_result_view.cc.rej
Patch: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
Index: chrome/browser/ui/views/omnibox/omnibox_result_view.cc
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index
9938b54774812cc4cf22db8bb0cc4e2fd0506cdc..6eb06903c1db5ad45544ad6956c9aaf3c5b814d6
100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -357,213 +357,59 @@ int OmniboxResultView::DrawString(
}
}
- // Split the text into visual runs. We do this first so that we don't need
to
- // worry about whether our eliding might change the visual display in
- // unintended ways, e.g. by removing directional markings or by adding an
- // ellipsis that's not enclosed in appropriate markings.
- base::i18n::BiDiLineIterator bidi_line;
- if (!bidi_line.Open(text, base::i18n::IsRTL(), is_url))
- return x;
- const int num_runs = bidi_line.CountRuns();
- ScopedVector<gfx::RenderText> render_texts;
- Runs runs;
- for (int run = 0; run < num_runs; ++run) {
- int run_start_int = 0, run_length_int = 0;
- // The index we pass to GetVisualRun corresponds to the position of the run
- // in the displayed text. For example, the string "Google in HEBREW" (where
- // HEBREW is text in the Hebrew language) has two runs: "Google in " which
- // is an LTR run, and "HEBREW" which is an RTL run. In an LTR context, the
- // run "Google in " has the index 0 (since it is the leftmost run
- // displayed). In an RTL context, the same run has the index 1 because it
- // is the rightmost run. This is why the order in which we traverse the
- // runs is different depending on the locale direction.
- const UBiDiDirection run_direction = bidi_line.GetVisualRun(
- (base::i18n::IsRTL() && !is_url) ? (num_runs - run - 1) : run,
- &run_start_int, &run_length_int);
- DCHECK_GT(run_length_int, 0);
- runs.push_back(RunData());
- RunData* current_run = &runs.back();
- current_run->run_start = run_start_int;
- const size_t run_end = current_run->run_start + run_length_int;
- current_run->visual_order = run;
- current_run->is_rtl = !is_url && (run_direction == UBIDI_RTL);
-
- // Compute classifications for this run.
- for (size_t i = 0; i < classifications.size(); ++i) {
- const size_t text_start =
- std::max(classifications[i].offset, current_run->run_start);
- if (text_start >= run_end)
- break; // We're past the last classification in the run.
-
- const size_t text_end = (i < (classifications.size() - 1)) ?
- std::min(classifications[i + 1].offset, run_end) : run_end;
- if (text_end <= current_run->run_start)
- continue; // We haven't reached the first classification in the run.
-
- render_texts.push_back(gfx::RenderText::CreateInstance());
- gfx::RenderText* render_text = render_texts.back();
- current_run->classifications.push_back(render_text);
- render_text->SetText(text.substr(text_start, text_end - text_start));
- render_text->SetFontList(font_list_);
-
- // Calculate style-related data.
- if (classifications[i].style & ACMatchClassification::MATCH)
- render_text->SetStyle(gfx::BOLD, true);
- const ResultViewState state = GetState();
- if (classifications[i].style & ACMatchClassification::URL)
- render_text->SetColor(GetColor(state, URL));
- else if (classifications[i].style & ACMatchClassification::DIM)
- render_text->SetColor(GetColor(state, DIMMED_TEXT));
- else
- render_text->SetColor(GetColor(state, force_dim ? DIMMED_TEXT : TEXT));
-
- current_run->pixel_width += render_text->GetStringSize().width();
- }
- DCHECK(!current_run->classifications.empty());
- }
- DCHECK(!runs.empty());
-
- // Sort into logical order so we can elide logically.
- std::sort(runs.begin(), runs.end(), &SortRunsLogically);
-
- // Now determine what to elide, if anything. Several subtle points:
- // * Because we have the run data, we can get edge cases correct, like
- // whether to place an ellipsis before or after the end of a run when the
- // text needs to be elided at the run boundary.
- // * The "or one before it" comments below refer to cases where an earlier
- // classification fits completely, but leaves too little space for an
- // ellipsis that turns out to be needed later. These cases are commented
- // more completely in Elide().
- int remaining_width = mirroring_context_->remaining_width(x);
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- if (i->pixel_width > remaining_width) {
- // This run or one before it needs to be elided.
- for (Classifications::iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const int width = (*j)->GetStringSize().width();
- if (width > remaining_width) {
- // This classification or one before it needs to be elided. Erase
all
- // further classifications and runs so Elide() can simply reverse-
- // iterate over everything to find the specific classification to
- // elide.
- i->classifications.erase(++j, i->classifications.end());
- runs.erase(++i, runs.end());
- Elide(&runs, remaining_width);
- break;
- }
- remaining_width -= width;
- }
+ scoped_ptr<gfx::RenderText> render_text(gfx::RenderText::CreateInstance());
+ const size_t text_length = text.length();
+ render_text->SetText(text);
+ render_text->SetFontList(font_list_);
+ render_text->SetMultiline(false);
+ render_text->SetCursorEnabled(false);
+ if (is_url)
+ render_text->SetDirectionalityMode(gfx::DIRECTIONALITY_FORCE_LTR);
+
+ // Apply classifications.
+ for (size_t i = 0; i < classifications.size(); ++i) {
+ const size_t text_start = classifications[i].offset;
+ if (text_start >= text_length)
break;
- }
- remaining_width -= i->pixel_width;
- }
- // Sort back into visual order so we can display the runs correctly.
- std::sort(runs.begin(), runs.end(), &SortRunsVisually);
-
- // Draw the runs.
- for (Runs::iterator i(runs.begin()); i != runs.end(); ++i) {
- const bool reverse_visible_order = (i->is_rtl != base::i18n::IsRTL());
- if (reverse_visible_order)
- std::reverse(i->classifications.begin(), i->classifications.end());
- for (Classifications::const_iterator j(i->classifications.begin());
- j != i->classifications.end(); ++j) {
- const gfx::Size size = (*j)->GetStringSize();
- // Align the text runs to a common baseline.
- const gfx::Rect rect(
- mirroring_context_->mirrored_left_coord(x, x + size.width()), y,
- size.width(), height());
- (*j)->SetDisplayRect(rect);
- (*j)->Draw(canvas);
- x += size.width();
+ const size_t text_end = (i < (classifications.size() - 1)) ?
+ std::min(classifications[i + 1].offset, text_length) : text_length;
+ const gfx::Range current_range(text_start, text_end);
+
+ // Calculate style-related data.
+ if (classifications[i].style & ACMatchClassification::MATCH)
+ render_text->ApplyStyle(gfx::BOLD, true, current_range);
+
+ ColorKind color_kind = TEXT;
+ if (classifications[i].style & ACMatchClassification::URL) {
+ color_kind = URL;
+ } else if (force_dim ||
+ (classifications[i].style & ACMatchClassification::DIM)) {
+ color_kind = DIMMED_TEXT;
}
+ render_text->ApplyColor(GetColor(GetState(), color_kind), current_range);
}
- return x;
-}
+ int remaining_width = mirroring_context_->remaining_width(x);
-void OmniboxResultView::Elide(Runs* runs, int remaining_width) const {
- // The complexity of this function is due to edge cases like the following:
- // We have 100 px of available space, an initial classification that takes 86
- // px, and a font that has a 15 px wide ellipsis character. Now if the first
- // classification is followed by several very narrow classifications (e.g. 3
- // px wide each), we don't know whether we need to elide or not at the time
we
- // see the first classification -- it depends on how many subsequent
- // classifications follow, and some of those may be in the next run (or
- // several runs!). This is why instead we let our caller move forward until
- // we know we definitely need to elide, and then in this function we move
- // backward again until we find a string that we can successfully do the
- // eliding on.
- bool on_trailing_classification = true;
- for (Runs::reverse_iterator i(runs->rbegin()); i != runs->rend(); ++i) {
- for (Classifications::reverse_iterator j(i->classifications.rbegin());
- j != i->classifications.rend(); ++j) {
- if (!on_trailing_classification) {
- // We also add this classification's width (sans ellipsis) back to the
- // available width since we want to consider the available space we'll
- // have when we draw this classification.
- remaining_width += (*j)->GetStringSize().width();
-
- // If we reached here, we couldn't fit an ellipsis in the space taken
by
- // the previous classifications we looped over (see comments at bottom
- // of loop). Append one here to represent those elided portions.
- (*j)->SetText((*j)->text() + kEllipsis);
- }
- on_trailing_classification = false;
-
- // Can we fit at least an ellipsis?
- gfx::Font font((*j)->GetStyle(gfx:…
(message too large)
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/570001
Retried try job too often on chromium_presubmit for step(s) presubmit http://build.chromium.org/p/tryserver.chromium/buildstatus?builder=chromium_p...
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/570001
CQ is trying da patch. Follow status at https://chromium-status.appspot.com/cq/skanuj@chromium.org/119813002/570001
Message was sent while issue was closed.
Change committed as 242828 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
