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

Side by Side Diff: third_party/WebKit/Source/platform/fonts/shaping/ShapingLineBreaker.cpp

Issue 2871173002: Add LazyLineBreakIterator::Next/PreviousBreakOpportunity() (Closed)
Patch Set: Created 3 years, 7 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
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "platform/fonts/shaping/ShapingLineBreaker.h" 5 #include "platform/fonts/shaping/ShapingLineBreaker.h"
6 6
7 #include "platform/fonts/Font.h" 7 #include "platform/fonts/Font.h"
8 #include "platform/fonts/shaping/HarfBuzzShaper.h" 8 #include "platform/fonts/shaping/HarfBuzzShaper.h"
9 #include "platform/fonts/shaping/ShapeResult.h" 9 #include "platform/fonts/shaping/ShapeResult.h"
10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h" 10 #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 // HarfBuzzHarfBuzz safe to break info when available. 46 // HarfBuzzHarfBuzz safe to break info when available.
47 for (; offset < end; offset++) { 47 for (; offset < end; offset++) {
48 if (text[offset] == kSpaceCharacter) 48 if (text[offset] == kSpaceCharacter)
49 break; 49 break;
50 } 50 }
51 return offset; 51 return offset;
52 } 52 }
53 53
54 } // namespace 54 } // namespace
55 55
56 // TODO(eae); Should take a const LazyLineBreakIterator& but that requires the
57 // LazyLineBreakIterator::isBreakable method to be updated to be const.
58 unsigned ShapingLineBreaker::PreviousBreakOpportunity(
59 LazyLineBreakIterator* break_iterator,
60 unsigned start,
61 unsigned offset) {
62 DCHECK(break_iterator);
63 unsigned pos = std::min(start + offset, shaper_->TextLength());
64 for (; pos > start; pos--) {
65 int next_break = 0;
66 if (break_iterator->IsBreakable(pos, next_break, break_type_))
67 return pos;
68 }
69 return start;
70 }
71
72 unsigned ShapingLineBreaker::NextBreakOpportunity(
73 LazyLineBreakIterator* break_iterator,
74 unsigned offset) {
75 DCHECK(break_iterator);
76 int next_break = 0;
77 break_iterator->IsBreakable(offset, next_break, break_type_);
78 return next_break;
79 }
80
81 // Shapes a line of text by finding a valid and appropriate break opportunity 56 // Shapes a line of text by finding a valid and appropriate break opportunity
82 // based on the shaping results for the entire paragraph. Re-shapes the start 57 // based on the shaping results for the entire paragraph. Re-shapes the start
83 // and end of the line as needed. 58 // and end of the line as needed.
84 // 59 //
85 // Definitions: 60 // Definitions:
86 // Candidate break opportunity: Ideal point to break, disregarding line 61 // Candidate break opportunity: Ideal point to break, disregarding line
87 // breaking rules. May be in the middle of a word 62 // breaking rules. May be in the middle of a word
88 // or inside a ligature. 63 // or inside a ligature.
89 // Valid break opportunity: A point where a break is allowed according to 64 // Valid break opportunity: A point where a break is allowed according to
90 // the relevant breaking rules. 65 // the relevant breaking rules.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 if (first_safe != start) { 99 if (first_safe != start) {
125 LayoutUnit original_width = 100 LayoutUnit original_width =
126 result_->SnappedEndPositionForOffset(first_safe) - start_position; 101 result_->SnappedEndPositionForOffset(first_safe) - start_position;
127 line_start_result = shaper_->Shape(font_, direction, start, first_safe); 102 line_start_result = shaper_->Shape(font_, direction, start, first_safe);
128 available_space += line_start_result->SnappedWidth() - original_width; 103 available_space += line_start_result->SnappedWidth() - original_width;
129 } 104 }
130 105
131 // Find a candidate break opportunity by identifying the last offset before 106 // Find a candidate break opportunity by identifying the last offset before
132 // exceeding the available space and the determine the closest valid break 107 // exceeding the available space and the determine the closest valid break
133 // preceding the candidate. 108 // preceding the candidate.
134 LazyLineBreakIterator break_iterator(text_, locale_); 109 LazyLineBreakIterator break_iterator(text_, locale_, break_type_);
135 LayoutUnit end_position = start_position + available_space; 110 LayoutUnit end_position = start_position + available_space;
136 unsigned candidate_break = result_->OffsetForPosition(end_position, false); 111 unsigned candidate_break = result_->OffsetForPosition(end_position, false);
137 unsigned break_opportunity = 112 unsigned break_opportunity =
138 PreviousBreakOpportunity(&break_iterator, start, candidate_break); 113 break_iterator.PreviousBreakOpportunity(candidate_break, start);
139 if (break_opportunity <= start) { 114 if (break_opportunity <= start) {
140 break_opportunity = NextBreakOpportunity(&break_iterator, candidate_break); 115 break_opportunity = break_iterator.NextBreakOpportunity(candidate_break);
141 } 116 }
142 117
143 RefPtr<ShapeResult> line_end_result; 118 RefPtr<ShapeResult> line_end_result;
144 unsigned last_safe = break_opportunity; 119 unsigned last_safe = break_opportunity;
145 while (break_opportunity > start) { 120 while (break_opportunity > start) {
146 // If the previous valid break opportunity is not at a safe-to-break 121 // If the previous valid break opportunity is not at a safe-to-break
147 // boundary reshape between the safe-to-break offset and the valid break 122 // boundary reshape between the safe-to-break offset and the valid break
148 // offset. If the resulting width exceeds the available space the 123 // offset. If the resulting width exceeds the available space the
149 // preceding boundary is tried until the available space is sufficient. 124 // preceding boundary is tried until the available space is sufficient.
150 unsigned previous_safe = std::max( 125 unsigned previous_safe = std::max(
151 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity), 126 PreviousSafeToBreakAfter(shaper_->GetText(), start, break_opportunity),
152 start); 127 start);
153 if (previous_safe != break_opportunity) { 128 if (previous_safe != break_opportunity) {
154 LayoutUnit safe_position = 129 LayoutUnit safe_position =
155 result_->SnappedStartPositionForOffset(previous_safe); 130 result_->SnappedStartPositionForOffset(previous_safe);
156 while (break_opportunity > previous_safe && previous_safe > start) { 131 while (break_opportunity > previous_safe && previous_safe > start) {
157 line_end_result = 132 line_end_result =
158 shaper_->Shape(font_, direction, previous_safe, break_opportunity); 133 shaper_->Shape(font_, direction, previous_safe, break_opportunity);
159 if (safe_position + line_end_result->SnappedWidth() <= end_position) 134 if (safe_position + line_end_result->SnappedWidth() <= end_position)
160 break; 135 break;
161 line_end_result = nullptr; 136 line_end_result = nullptr;
162 break_opportunity = PreviousBreakOpportunity(&break_iterator, start, 137 break_opportunity = break_iterator.PreviousBreakOpportunity(
163 break_opportunity - 1); 138 break_opportunity - 1, start);
164 } 139 }
165 } 140 }
166 141
167 if (break_opportunity > start) { 142 if (break_opportunity > start) {
168 last_safe = previous_safe; 143 last_safe = previous_safe;
169 break; 144 break;
170 } 145 }
171 146
172 // No suitable break opportunity, not exceeding the available space, 147 // No suitable break opportunity, not exceeding the available space,
173 // found. Choose the next valid one even though it will overflow. 148 // found. Choose the next valid one even though it will overflow.
174 break_opportunity = NextBreakOpportunity(&break_iterator, candidate_break); 149 break_opportunity = break_iterator.NextBreakOpportunity(candidate_break);
175 } 150 }
176 151
177 // Create shape results for the line by copying from the re-shaped result (if 152 // Create shape results for the line by copying from the re-shaped result (if
178 // reshaping was needed) and the original shape results. 153 // reshaping was needed) and the original shape results.
179 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction); 154 RefPtr<ShapeResult> line_result = ShapeResult::Create(font_, 0, direction);
180 unsigned max_length = std::numeric_limits<unsigned>::max(); 155 unsigned max_length = std::numeric_limits<unsigned>::max();
181 if (line_start_result) 156 if (line_start_result)
182 line_start_result->CopyRange(0, max_length, line_result.Get()); 157 line_start_result->CopyRange(0, max_length, line_result.Get());
183 if (last_safe > first_safe) 158 if (last_safe > first_safe)
184 result_->CopyRange(first_safe, last_safe, line_result.Get()); 159 result_->CopyRange(first_safe, last_safe, line_result.Get());
185 if (line_end_result) 160 if (line_end_result)
186 line_end_result->CopyRange(last_safe, max_length, line_result.Get()); 161 line_end_result->CopyRange(last_safe, max_length, line_result.Get());
187 162
188 *break_offset = break_opportunity; 163 *break_offset = break_opportunity;
189 return line_result.Release(); 164 return line_result.Release();
190 } 165 }
191 166
192 } // namespace blink 167 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698