OLD | NEW |
---|---|
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 <cmath> | 9 #include <cmath> |
10 #include <utility> | 10 #include <utility> |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
151 ApplyTextShadows(&renderer); | 151 ApplyTextShadows(&renderer); |
152 | 152 |
153 for (size_t i = 0; i < runs_.size(); ++i) { | 153 for (size_t i = 0; i < runs_.size(); ++i) { |
154 const TextRun& run = runs_[i]; | 154 const TextRun& run = runs_[i]; |
155 renderer.SetForegroundColor(run.foreground); | 155 renderer.SetForegroundColor(run.foreground); |
156 renderer.SetTextSize(run.text_size); | 156 renderer.SetTextSize(run.text_size); |
157 renderer.SetFontFamilyWithStyle(run.font_name, run.font_style); | 157 renderer.SetFontFamilyWithStyle(run.font_name, run.font_style); |
158 renderer.DrawPosText(&run.glyph_positions[0], &run.glyphs[0], | 158 renderer.DrawPosText(&run.glyph_positions[0], &run.glyphs[0], |
159 run.glyphs.size()); | 159 run.glyphs.size()); |
160 renderer.DrawDecorations(run.origin.x(), run.origin.y(), run.width, | 160 renderer.DrawDecorations(run.origin.x(), run.origin.y(), run.width, |
161 run.style); | 161 run.underline, run.strike, run.diagonal_strike); |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
165 RenderTextMac::TextRun::TextRun() | 165 RenderTextMac::TextRun::TextRun() |
166 : ct_run(NULL), | 166 : ct_run(NULL), |
167 origin(SkPoint::Make(0, 0)), | 167 origin(SkPoint::Make(0, 0)), |
168 width(0), | 168 width(0), |
169 font_style(Font::NORMAL), | 169 font_style(Font::NORMAL), |
170 text_size(0), | 170 text_size(0), |
171 foreground(SK_ColorBLACK) { | 171 foreground(SK_ColorBLACK), |
172 underline(false), | |
173 strike(false), | |
174 diagonal_strike(false) { | |
172 } | 175 } |
173 | 176 |
174 RenderTextMac::TextRun::~TextRun() { | 177 RenderTextMac::TextRun::~TextRun() { |
175 } | 178 } |
176 | 179 |
177 void RenderTextMac::ApplyStyles(CFMutableAttributedStringRef attr_string, | 180 void RenderTextMac::ApplyStyles(CFMutableAttributedStringRef attr_string, |
178 CTFontRef font) { | 181 CTFontRef font) { |
179 // Clear attributes and reserve space to hold the maximum number of entries, | 182 // Adjust the text colors to reflect the selection range. |
180 // which is at most three per style range per the code below. | 183 ColorBreaks adjusted_colors(colors()); |
181 attributes_.reset(CFArrayCreateMutable(NULL, 3 * style_ranges().size(), | 184 ApplySelectionColor(&adjusted_colors); |
185 | |
186 // Adjust the underline styling to reflect composition ranges. | |
187 const StyleBreaks* adjusted_styles[NUM_TEXT_STYLES]; | |
188 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | |
189 adjusted_styles[i] = &styles(static_cast<TextStyle>(i)); | |
190 StyleBreaks adjusted_underlines(styles(UNDERLINE)); | |
191 ApplyCompositionStyle(&adjusted_underlines); | |
192 adjusted_styles[UNDERLINE] = &adjusted_underlines; | |
193 | |
194 // Track the current color and style with iterators; get the max style count. | |
195 ColorBreaks::const_iterator color = adjusted_colors.begin(); | |
196 StyleBreaks::const_iterator style[NUM_TEXT_STYLES]; | |
197 size_t max_style_count = adjusted_colors.size(); | |
198 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) { | |
199 style[i] = adjusted_styles[i]->begin(); | |
200 max_style_count += adjusted_styles[i]->size(); | |
201 } | |
202 size_t style_end[NUM_TEXT_STYLES]; | |
203 | |
204 // Clear attributes and reserve space to hold the maximum number of entries. | |
205 attributes_.reset(CFArrayCreateMutable(NULL, max_style_count, | |
182 &kCFTypeArrayCallBacks)); | 206 &kCFTypeArrayCallBacks)); |
183 | 207 |
184 // https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Cor eText_StringAttributes_Ref/Reference/reference.html | 208 // https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Cor eText_StringAttributes_Ref/Reference/reference.html |
185 for (size_t i = 0; i < style_ranges().size(); ++i) { | 209 for (size_t i = 0, end = 0; i < text().length(); i = end) { |
186 const StyleRange& style = style_ranges()[i]; | 210 // Find the end of this ranged style. |
187 const CFRange range = CFRangeMake(style.range.start(), | 211 const size_t color_end = TextIndexToLayoutIndex( |
188 style.range.length()); | 212 GetBreakEnd(adjusted_colors, color)); |
213 end = color_end; | |
214 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) { | |
215 style_end[i] = TextIndexToLayoutIndex( | |
216 GetBreakEnd(*adjusted_styles[i], style[i])); | |
217 end = std::min(end, style_end[i]); | |
Alexei Svitkine (slow)
2013/01/22 19:41:03
I find requiring this logic to RenderText subclass
msw
2013/01/22 22:27:24
I agree, and have a TODO in the CL description for
| |
218 } | |
189 | 219 |
190 // Note: CFAttributedStringSetAttribute() does not appear to retain the | 220 // Note: CFAttributedStringSetAttribute() does not appear to retain the |
191 // values passed in, as can be verified via CFGetRetainCount(). To ensure | 221 // values passed in, as can be verified via CFGetRetainCount(). To ensure |
192 // the attribute objects do not leak, they are saved to |attributes_|. | 222 // the attribute objects do not leak, they are saved to |attributes_|. |
193 | 223 |
224 const CFRange range = CFRangeMake(i, end - i); | |
194 base::mac::ScopedCFTypeRef<CGColorRef> foreground( | 225 base::mac::ScopedCFTypeRef<CGColorRef> foreground( |
195 gfx::CGColorCreateFromSkColor(style.foreground)); | 226 gfx::CGColorCreateFromSkColor(color->second)); |
196 CFAttributedStringSetAttribute(attr_string, range, | 227 CFAttributedStringSetAttribute(attr_string, range, |
197 kCTForegroundColorAttributeName, | 228 kCTForegroundColorAttributeName, |
198 foreground); | 229 foreground); |
199 CFArrayAppendValue(attributes_, foreground); | 230 CFArrayAppendValue(attributes_, foreground); |
200 | 231 |
201 if (style.underline) { | 232 if (style[UNDERLINE]->second) { |
202 CTUnderlineStyle value = kCTUnderlineStyleSingle; | 233 CTUnderlineStyle value = kCTUnderlineStyleSingle; |
203 base::mac::ScopedCFTypeRef<CFNumberRef> underline( | 234 base::mac::ScopedCFTypeRef<CFNumberRef> underline_value( |
204 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); | 235 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); |
205 CFAttributedStringSetAttribute(attr_string, range, | 236 CFAttributedStringSetAttribute(attr_string, range, |
206 kCTUnderlineStyleAttributeName, | 237 kCTUnderlineStyleAttributeName, |
207 underline); | 238 underline_value); |
208 CFArrayAppendValue(attributes_, underline); | 239 CFArrayAppendValue(attributes_, underline_value); |
209 } | 240 } |
210 | 241 |
211 if (style.font_style & (Font::BOLD | Font::ITALIC)) { | 242 const int traits = (style[BOLD]->second ? kCTFontBoldTrait : 0) | |
212 int traits = 0; | 243 (style[ITALIC]->second ? kCTFontItalicTrait : 0); |
213 if (style.font_style & Font::BOLD) | 244 if (traits != 0) { |
214 traits |= kCTFontBoldTrait; | |
215 if (style.font_style & Font::ITALIC) | |
216 traits |= kCTFontItalicTrait; | |
217 base::mac::ScopedCFTypeRef<CTFontRef> styled_font( | 245 base::mac::ScopedCFTypeRef<CTFontRef> styled_font( |
218 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits)); | 246 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits)); |
219 // TODO(asvitkine): Handle |styled_font| == NULL case better. | 247 // TODO(asvitkine): Handle |styled_font| == NULL case better. |
220 if (styled_font) { | 248 if (styled_font) { |
221 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName, | 249 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName, |
222 styled_font); | 250 styled_font); |
223 CFArrayAppendValue(attributes_, styled_font); | 251 CFArrayAppendValue(attributes_, styled_font); |
224 } | 252 } |
225 } | 253 } |
254 | |
255 // Advance the color and style iterators as needed. | |
256 color += color_end == end ? 1 : 0; | |
257 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) | |
258 style[i] += style_end[i] == end ? 1 : 0; | |
226 } | 259 } |
227 } | 260 } |
228 | 261 |
229 void RenderTextMac::ComputeRuns() { | 262 void RenderTextMac::ComputeRuns() { |
230 DCHECK(line_); | 263 DCHECK(line_); |
231 | 264 |
232 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); | 265 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); |
233 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); | 266 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); |
234 | 267 |
235 gfx::Vector2d text_offset = GetTextOffset(); | 268 gfx::Vector2d text_offset = GetTextOffset(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 CTRunGetPositions(ct_run, empty_cf_range, &positions[0]); | 309 CTRunGetPositions(ct_run, empty_cf_range, &positions[0]); |
277 positions_ptr = &positions[0]; | 310 positions_ptr = &positions[0]; |
278 } | 311 } |
279 for (size_t glyph = 0; glyph < glyph_count; glyph++) { | 312 for (size_t glyph = 0; glyph < glyph_count; glyph++) { |
280 SkPoint* point = &run->glyph_positions[glyph]; | 313 SkPoint* point = &run->glyph_positions[glyph]; |
281 point->set(x + SkDoubleToScalar(positions_ptr[glyph].x), | 314 point->set(x + SkDoubleToScalar(positions_ptr[glyph].x), |
282 y + SkDoubleToScalar(positions_ptr[glyph].y)); | 315 y + SkDoubleToScalar(positions_ptr[glyph].y)); |
283 } | 316 } |
284 | 317 |
285 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle | 318 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle |
286 // this better. | 319 // this better. Also, support strike and diagonal_strike. |
287 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); | 320 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); |
288 CTFontRef ct_font = | 321 CTFontRef ct_font = |
289 base::mac::GetValueFromDictionary<CTFontRef>(attributes, | 322 base::mac::GetValueFromDictionary<CTFontRef>(attributes, |
290 kCTFontAttributeName); | 323 kCTFontAttributeName); |
291 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( | 324 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( |
292 CTFontCopyFamilyName(ct_font)); | 325 CTFontCopyFamilyName(ct_font)); |
293 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); | 326 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); |
294 run->text_size = CTFontGetSize(ct_font); | 327 run->text_size = CTFontGetSize(ct_font); |
295 | 328 |
296 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); | 329 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); |
297 if (traits & kCTFontBoldTrait) | 330 if (traits & kCTFontBoldTrait) |
298 run->font_style |= Font::BOLD; | 331 run->font_style |= Font::BOLD; |
299 if (traits & kCTFontItalicTrait) | 332 if (traits & kCTFontItalicTrait) |
300 run->font_style |= Font::ITALIC; | 333 run->font_style |= Font::ITALIC; |
301 | 334 |
302 const CGColorRef foreground = | 335 const CGColorRef foreground = |
303 base::mac::GetValueFromDictionary<CGColorRef>( | 336 base::mac::GetValueFromDictionary<CGColorRef>( |
304 attributes, kCTForegroundColorAttributeName); | 337 attributes, kCTForegroundColorAttributeName); |
305 if (foreground) | 338 if (foreground) |
306 run->foreground = gfx::CGColorRefToSkColor(foreground); | 339 run->foreground = gfx::CGColorRefToSkColor(foreground); |
307 | 340 |
308 const CFNumberRef underline = | 341 const CFNumberRef underline = |
309 base::mac::GetValueFromDictionary<CFNumberRef>( | 342 base::mac::GetValueFromDictionary<CFNumberRef>( |
310 attributes, kCTUnderlineStyleAttributeName); | 343 attributes, kCTUnderlineStyleAttributeName); |
311 CTUnderlineStyle value = kCTUnderlineStyleNone; | 344 CTUnderlineStyle value = kCTUnderlineStyleNone; |
312 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value)) | 345 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value)) |
313 run->style.underline = (value == kCTUnderlineStyleSingle); | 346 run->underline = (value == kCTUnderlineStyleSingle); |
314 | 347 |
315 run_origin.offset(run_width, 0); | 348 run_origin.offset(run_width, 0); |
316 } | 349 } |
317 runs_valid_ = true; | 350 runs_valid_ = true; |
318 } | 351 } |
319 | 352 |
320 RenderText* RenderText::CreateInstance() { | 353 RenderText* RenderText::CreateInstance() { |
321 return new RenderTextMac; | 354 return new RenderTextMac; |
322 } | 355 } |
323 | 356 |
324 } // namespace gfx | 357 } // namespace gfx |
OLD | NEW |