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

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

Issue 968923004: Use GetDisplayText() instead of text() for rendering text. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 5 years, 9 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 (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_mac.h" 5 #include "ui/gfx/render_text_mac.h"
6 6
7 #include <ApplicationServices/ApplicationServices.h> 7 #include <ApplicationServices/ApplicationServices.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 15 matching lines...) Expand all
26 26
27 scoped_ptr<RenderText> RenderTextMac::CreateInstanceOfSameType() const { 27 scoped_ptr<RenderText> RenderTextMac::CreateInstanceOfSameType() const {
28 return make_scoped_ptr(new RenderTextMac); 28 return make_scoped_ptr(new RenderTextMac);
29 } 29 }
30 30
31 const base::string16& RenderTextMac::GetDisplayText() { 31 const base::string16& RenderTextMac::GetDisplayText() {
32 return text_elided() ? display_text() : layout_text(); 32 return text_elided() ? display_text() : layout_text();
33 } 33 }
34 34
35 Size RenderTextMac::GetStringSize() { 35 Size RenderTextMac::GetStringSize() {
36 EnsureLayout(); 36 EnsureStringSize();
oshima 2015/03/05 18:14:20 I believe this should return the size of display t
Jun Mukai 2015/03/05 18:41:38 Reverted back to the original.
37 return Size(std::ceil(string_size_.width()), string_size_.height()); 37 return Size(std::ceil(string_size_->width()), string_size_->height());
38 } 38 }
39 39
40 SizeF RenderTextMac::GetStringSizeF() { 40 SizeF RenderTextMac::GetStringSizeF() {
41 EnsureLayout(); 41 EnsureStringSize();
42 return string_size_; 42 return *string_size_;
43 } 43 }
44 44
45 SelectionModel RenderTextMac::FindCursorPosition(const Point& point) { 45 SelectionModel RenderTextMac::FindCursorPosition(const Point& point) {
46 // TODO(asvitkine): Implement this. http://crbug.com/131618 46 // TODO(asvitkine): Implement this. http://crbug.com/131618
47 return SelectionModel(); 47 return SelectionModel();
48 } 48 }
49 49
50 std::vector<RenderText::FontSpan> RenderTextMac::GetFontSpansForTesting() { 50 std::vector<RenderText::FontSpan> RenderTextMac::GetFontSpansForTesting() {
51 EnsureLayout(); 51 EnsureLayout();
52 if (!runs_valid_) 52 if (!runs_valid_)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 return index; 102 return index;
103 } 103 }
104 104
105 bool RenderTextMac::IsValidCursorIndex(size_t index) { 105 bool RenderTextMac::IsValidCursorIndex(size_t index) {
106 // TODO(asvitkine): Implement this. http://crbug.com/131618 106 // TODO(asvitkine): Implement this. http://crbug.com/131618
107 return IsValidLogicalIndex(index); 107 return IsValidLogicalIndex(index);
108 } 108 }
109 109
110 void RenderTextMac::OnLayoutTextAttributeChanged(bool text_changed) { 110 void RenderTextMac::OnLayoutTextAttributeChanged(bool text_changed) {
111 DCHECK(!multiline()) << "RenderTextMac does not support multi line"; 111 DCHECK(!multiline()) << "RenderTextMac does not support multi line";
112 string_size_.reset();
112 if (text_changed) { 113 if (text_changed) {
113 if (elide_behavior() != NO_ELIDE && 114 if (elide_behavior() != NO_ELIDE &&
114 elide_behavior() != FADE_TAIL && 115 elide_behavior() != FADE_TAIL &&
115 !layout_text().empty()) { 116 !layout_text().empty()) {
116 UpdateDisplayText(GetContentWidth()); 117 UpdateDisplayText(GetContentWidth());
117 } else { 118 } else {
118 UpdateDisplayText(0); 119 UpdateDisplayText(0);
119 } 120 }
120 } 121 }
121 line_.reset(); 122 line_.reset();
122 attributes_.reset(); 123 attributes_.reset();
123 runs_.clear(); 124 runs_.clear();
124 runs_valid_ = false; 125 runs_valid_ = false;
125 } 126 }
126 127
127 void RenderTextMac::OnDisplayTextAttributeChanged() { 128 void RenderTextMac::OnDisplayTextAttributeChanged() {
128 OnLayoutTextAttributeChanged(true); 129 OnLayoutTextAttributeChanged(true);
129 } 130 }
130 131
131 void RenderTextMac::EnsureLayout() { 132 void RenderTextMac::EnsureLayout() {
132 if (line_.get()) 133 if (line_.get())
133 return; 134 return;
134 runs_.clear(); 135 runs_.clear();
135 runs_valid_ = false; 136 runs_valid_ = false;
136 137
137 CTFontRef ct_font = base::mac::NSToCFCast( 138 EnsureStringSize();
138 font_list().GetPrimaryFont().GetNativeFont()); 139 line_ = EnsureLayoutInternal(GetDisplayText(), &attributes_);
139
140 const void* keys[] = { kCTFontAttributeName };
141 const void* values[] = { ct_font };
142 base::ScopedCFTypeRef<CFDictionaryRef> attributes(
143 CFDictionaryCreate(NULL,
144 keys,
145 values,
146 arraysize(keys),
147 NULL,
148 &kCFTypeDictionaryValueCallBacks));
149
150 base::ScopedCFTypeRef<CFStringRef> cf_text(
151 base::SysUTF16ToCFStringRef(text()));
152 base::ScopedCFTypeRef<CFAttributedStringRef> attr_text(
153 CFAttributedStringCreate(NULL, cf_text, attributes));
154 base::ScopedCFTypeRef<CFMutableAttributedStringRef> attr_text_mutable(
155 CFAttributedStringCreateMutableCopy(NULL, 0, attr_text));
156
157 // TODO(asvitkine|msw): Respect GetTextDirection(), which may not match the
158 // natural text direction. See kCTTypesetterOptionForcedEmbeddingLevel, etc.
159
160 ApplyStyles(attr_text_mutable, ct_font);
161 line_.reset(CTLineCreateWithAttributedString(attr_text_mutable));
162
163 CGFloat ascent = 0;
164 CGFloat descent = 0;
165 CGFloat leading = 0;
166 // TODO(asvitkine): Consider using CTLineGetBoundsWithOptions() on 10.8+.
167 double width = CTLineGetTypographicBounds(line_, &ascent, &descent, &leading);
168 // Ensure ascent and descent are not smaller than ones of the font list.
169 // Keep them tall enough to draw often-used characters.
170 // For example, if a text field contains a Japanese character, which is
171 // smaller than Latin ones, and then later a Latin one is inserted, this
172 // ensures that the text baseline does not shift.
173 CGFloat font_list_height = font_list().GetHeight();
174 CGFloat font_list_baseline = font_list().GetBaseline();
175 ascent = std::max(ascent, font_list_baseline);
176 descent = std::max(descent, font_list_height - font_list_baseline);
177 string_size_ =
178 SizeF(width, std::max(ascent + descent + leading,
179 static_cast<CGFloat>(min_line_height())));
180 common_baseline_ = ascent;
181 } 140 }
182 141
183 void RenderTextMac::DrawVisualText(Canvas* canvas) { 142 void RenderTextMac::DrawVisualText(Canvas* canvas) {
184 DCHECK(line_); 143 DCHECK(line_);
185 if (!runs_valid_) 144 if (!runs_valid_)
186 ComputeRuns(); 145 ComputeRuns();
187 146
188 internal::SkiaTextRenderer renderer(canvas); 147 internal::SkiaTextRenderer renderer(canvas);
189 ApplyFadeEffects(&renderer); 148 ApplyFadeEffects(&renderer);
190 ApplyTextShadows(&renderer); 149 ApplyTextShadows(&renderer);
(...skipping 20 matching lines...) Expand all
211 text_size(0), 170 text_size(0),
212 foreground(SK_ColorBLACK), 171 foreground(SK_ColorBLACK),
213 underline(false), 172 underline(false),
214 strike(false), 173 strike(false),
215 diagonal_strike(false) { 174 diagonal_strike(false) {
216 } 175 }
217 176
218 RenderTextMac::TextRun::~TextRun() { 177 RenderTextMac::TextRun::~TextRun() {
219 } 178 }
220 179
221 void RenderTextMac::ApplyStyles(CFMutableAttributedStringRef attr_string, 180 void RenderTextMac::EnsureStringSize() {
222 CTFontRef font) { 181 if (string_size_)
182 return;
183
184 base::ScopedCFTypeRef<CFMutableArrayRef> attributes_owner;
185 base::ScopedCFTypeRef<CTLineRef> line(
186 EnsureLayoutInternal(layout_text(), &attributes_owner));
187
188 CGFloat ascent = 0;
189 CGFloat descent = 0;
190 CGFloat leading = 0;
191 // TODO(asvitkine): Consider using CTLineGetBoundsWithOptions() on 10.8+.
192 double width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
193 // Ensure ascent and descent are not smaller than ones of the font list.
194 // Keep them tall enough to draw often-used characters.
195 // For example, if a text field contains a Japanese character, which is
196 // smaller than Latin ones, and then later a Latin one is inserted, this
197 // ensures that the text baseline does not shift.
198 CGFloat font_list_height = font_list().GetHeight();
199 CGFloat font_list_baseline = font_list().GetBaseline();
200 ascent = std::max(ascent, font_list_baseline);
201 descent = std::max(descent, font_list_height - font_list_baseline);
202 string_size_.reset(new SizeF(
203 width, std::max(ascent + descent + leading,
204 static_cast<CGFloat>(min_line_height()))));
205 common_baseline_ = ascent;
206 }
207
208 base::ScopedCFTypeRef<CTLineRef> RenderTextMac::EnsureLayoutInternal(
209 const base::string16& text,
210 base::ScopedCFTypeRef<CFMutableArrayRef>* attributes_owner) const {
211 CTFontRef ct_font = base::mac::NSToCFCast(
212 font_list().GetPrimaryFont().GetNativeFont());
213
214 const void* keys[] = { kCTFontAttributeName };
215 const void* values[] = { ct_font };
216 base::ScopedCFTypeRef<CFDictionaryRef> attributes(
217 CFDictionaryCreate(NULL,
218 keys,
219 values,
220 arraysize(keys),
221 NULL,
222 &kCFTypeDictionaryValueCallBacks));
223
224 base::ScopedCFTypeRef<CFStringRef> cf_text(
225 base::SysUTF16ToCFStringRef(text));
226 base::ScopedCFTypeRef<CFAttributedStringRef> attr_text(
227 CFAttributedStringCreate(NULL, cf_text, attributes));
228 base::ScopedCFTypeRef<CFMutableAttributedStringRef> attr_text_mutable(
229 CFAttributedStringCreateMutableCopy(NULL, 0, attr_text));
230
231 // TODO(asvitkine|msw): Respect GetTextDirection(), which may not match the
232 // natural text direction. See kCTTypesetterOptionForcedEmbeddingLevel, etc.
233
234 *attributes_owner = ApplyStyles(attr_text_mutable, ct_font);
235 return base::ScopedCFTypeRef<CTLineRef>(
236 CTLineCreateWithAttributedString(attr_text_mutable));
237 }
238
239 base::ScopedCFTypeRef<CFMutableArrayRef> RenderTextMac::ApplyStyles(
240 CFMutableAttributedStringRef attr_string,
241 CTFontRef font) const {
223 // Temporarily apply composition underlines and selection colors. 242 // Temporarily apply composition underlines and selection colors.
224 ApplyCompositionAndSelectionStyles(); 243 ApplyCompositionAndSelectionStyles();
225 244
226 // Note: CFAttributedStringSetAttribute() does not appear to retain the values 245 // Note: CFAttributedStringSetAttribute() does not appear to retain the values
227 // passed in, as can be verified via CFGetRetainCount(). To ensure the 246 // passed in, as can be verified via CFGetRetainCount(). To ensure the
228 // attribute objects do not leak, they are saved to |attributes_|. 247 // attribute objects do not leak, they are saved to |attributes_|.
229 // Clear the attributes storage. 248 // Clear the attributes storage.
230 attributes_.reset(CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); 249 base::ScopedCFTypeRef<CFMutableArrayRef> attributes(
250 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
231 251
232 // https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Cor eText_StringAttributes_Ref/Reference/reference.html 252 // https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Cor eText_StringAttributes_Ref/Reference/reference.html
233 internal::StyleIterator style(colors(), styles()); 253 internal::StyleIterator style(colors(), styles());
234 const size_t layout_text_length = GetDisplayText().length(); 254 const size_t layout_text_length = CFAttributedStringGetLength(attr_string);
235 for (size_t i = 0, end = 0; i < layout_text_length; i = end) { 255 for (size_t i = 0, end = 0; i < layout_text_length; i = end) {
236 end = TextIndexToDisplayIndex(style.GetRange().end()); 256 end = std::min(style.GetRange().end(), layout_text_length);
237 const CFRange range = CFRangeMake(i, end - i); 257 const CFRange range = CFRangeMake(i, end - i);
238 base::ScopedCFTypeRef<CGColorRef> foreground( 258 base::ScopedCFTypeRef<CGColorRef> foreground(
239 CGColorCreateFromSkColor(style.color())); 259 CGColorCreateFromSkColor(style.color()));
240 CFAttributedStringSetAttribute(attr_string, range, 260 CFAttributedStringSetAttribute(attr_string, range,
241 kCTForegroundColorAttributeName, foreground); 261 kCTForegroundColorAttributeName, foreground);
242 CFArrayAppendValue(attributes_, foreground); 262 CFArrayAppendValue(attributes, foreground);
243 263
244 if (style.style(UNDERLINE)) { 264 if (style.style(UNDERLINE)) {
245 CTUnderlineStyle value = kCTUnderlineStyleSingle; 265 CTUnderlineStyle value = kCTUnderlineStyleSingle;
246 base::ScopedCFTypeRef<CFNumberRef> underline_value( 266 base::ScopedCFTypeRef<CFNumberRef> underline_value(
247 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); 267 CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
248 CFAttributedStringSetAttribute(attr_string, range, 268 CFAttributedStringSetAttribute(attr_string, range,
249 kCTUnderlineStyleAttributeName, 269 kCTUnderlineStyleAttributeName,
250 underline_value); 270 underline_value);
251 CFArrayAppendValue(attributes_, underline_value); 271 CFArrayAppendValue(attributes, underline_value);
252 } 272 }
253 273
254 const int traits = (style.style(BOLD) ? kCTFontBoldTrait : 0) | 274 const int traits = (style.style(BOLD) ? kCTFontBoldTrait : 0) |
255 (style.style(ITALIC) ? kCTFontItalicTrait : 0); 275 (style.style(ITALIC) ? kCTFontItalicTrait : 0);
256 if (traits != 0) { 276 if (traits != 0) {
257 base::ScopedCFTypeRef<CTFontRef> styled_font( 277 base::ScopedCFTypeRef<CTFontRef> styled_font(
258 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits)); 278 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits));
259 // TODO(asvitkine): Handle |styled_font| == NULL case better. 279 // TODO(asvitkine): Handle |styled_font| == NULL case better.
260 if (styled_font) { 280 if (styled_font) {
261 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName, 281 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName,
262 styled_font); 282 styled_font);
263 CFArrayAppendValue(attributes_, styled_font); 283 CFArrayAppendValue(attributes, styled_font);
264 } 284 }
265 } 285 }
266 286
267 style.UpdatePosition(DisplayIndexToTextIndex(end)); 287 style.UpdatePosition(DisplayIndexToTextIndex(end));
268 } 288 }
269 289
270 // Undo the temporarily applied composition underlines and selection colors. 290 // Undo the temporarily applied composition underlines and selection colors.
271 UndoCompositionAndSelectionStyles(); 291 UndoCompositionAndSelectionStyles();
292
293 return attributes;
272 } 294 }
273 295
274 void RenderTextMac::ComputeRuns() { 296 void RenderTextMac::ComputeRuns() {
275 DCHECK(line_); 297 DCHECK(line_);
276 298
277 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); 299 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_);
278 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); 300 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs);
279 301
280 // TODO(asvitkine): Don't use GetLineOffset() until draw time, since it may be 302 // TODO(asvitkine): Don't use GetLineOffset() until draw time, since it may be
281 // updated based on alignment changes without resetting the layout. 303 // updated based on alignment changes without resetting the layout.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 CTUnderlineStyle value = kCTUnderlineStyleNone; 380 CTUnderlineStyle value = kCTUnderlineStyleNone;
359 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value)) 381 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value))
360 run->underline = (value == kCTUnderlineStyleSingle); 382 run->underline = (value == kCTUnderlineStyleSingle);
361 383
362 run_origin.offset(run_width, 0); 384 run_origin.offset(run_width, 0);
363 } 385 }
364 runs_valid_ = true; 386 runs_valid_ = true;
365 } 387 }
366 388
367 } // namespace gfx 389 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698