Chromium Code Reviews| 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 // Temporarily apply composition underlines and selection colors. |
| 180 // which is at most three per style range per the code below. | 183 ApplyCompositionAndSelectionStyles(); |
| 181 attributes_.reset(CFArrayCreateMutable(NULL, 3 * style_ranges().size(), | 184 |
| 185 // Track the current color and style with iterators. | |
| 186 BreakList<SkColor>::const_iterator color = colors().list().begin(); | |
| 187 size_t max_style_count = colors().list().size(); | |
| 188 BreakList<bool>::const_iterator style[NUM_TEXT_STYLES]; | |
| 189 for (size_t i = 0; i < NUM_TEXT_STYLES; ++i) { | |
| 190 style[i] = styles(static_cast<TextStyle>(i)).list().begin(); | |
| 191 max_style_count += styles(static_cast<TextStyle>(i)).list().size(); | |
| 192 } | |
| 193 | |
| 194 // Clear attributes and reserve space to hold the maximum number of entries. | |
| 195 // Note: CFAttributedStringSetAttribute() does not appear to retain the values | |
| 196 // passed in, as can be verified via CFGetRetainCount(). To ensure the | |
| 197 // attribute objects do not leak, they are saved to |attributes_|. | |
| 198 attributes_.reset(CFArrayCreateMutable(NULL, max_style_count, | |
|
Alexei Svitkine (slow)
2013/01/28 20:52:30
Please put the "Note:" comment above the current f
msw
2013/01/29 17:17:25
Done (but potentially reverting in the subsequent
| |
| 182 &kCFTypeArrayCallBacks)); | 199 &kCFTypeArrayCallBacks)); |
| 183 | 200 |
| 184 // https://developer.apple.com/library/mac/#documentation/Carbon/Reference/Cor eText_StringAttributes_Ref/Reference/reference.html | 201 // 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) { | 202 for (size_t i = 0, end = 0; i < text().length(); i = end) { |
| 186 const StyleRange& style = style_ranges()[i]; | 203 end = GetNextBreak(color, style); |
| 187 const CFRange range = CFRangeMake(style.range.start(), | 204 const CFRange range = CFRangeMake(i, end - i); |
| 188 style.range.length()); | |
| 189 | |
| 190 // Note: CFAttributedStringSetAttribute() does not appear to retain the | |
| 191 // values passed in, as can be verified via CFGetRetainCount(). To ensure | |
| 192 // the attribute objects do not leak, they are saved to |attributes_|. | |
| 193 | |
| 194 base::mac::ScopedCFTypeRef<CGColorRef> foreground( | 205 base::mac::ScopedCFTypeRef<CGColorRef> foreground( |
| 195 gfx::CGColorCreateFromSkColor(style.foreground)); | 206 gfx::CGColorCreateFromSkColor(color->second)); |
| 196 CFAttributedStringSetAttribute(attr_string, range, | 207 CFAttributedStringSetAttribute(attr_string, range, |
| 197 kCTForegroundColorAttributeName, | 208 kCTForegroundColorAttributeName, foreground); |
| 198 foreground); | |
| 199 CFArrayAppendValue(attributes_, foreground); | 209 CFArrayAppendValue(attributes_, foreground); |
| 200 | 210 |
| 201 if (style.underline) { | 211 if (style[UNDERLINE]->second) { |
| 202 CTUnderlineStyle value = kCTUnderlineStyleSingle; | 212 CTUnderlineStyle value = kCTUnderlineStyleSingle; |
| 203 base::mac::ScopedCFTypeRef<CFNumberRef> underline( | 213 base::mac::ScopedCFTypeRef<CFNumberRef> underline_value( |
| 204 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); | 214 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); |
| 205 CFAttributedStringSetAttribute(attr_string, range, | 215 CFAttributedStringSetAttribute(attr_string, range, |
| 206 kCTUnderlineStyleAttributeName, | 216 kCTUnderlineStyleAttributeName, underline_value); |
|
Alexei Svitkine (slow)
2013/01/28 20:52:30
Nit:
This is actually against the style guide, se
msw
2013/01/29 17:17:25
Done.
| |
| 207 underline); | 217 CFArrayAppendValue(attributes_, underline_value); |
| 208 CFArrayAppendValue(attributes_, underline); | |
| 209 } | 218 } |
| 210 | 219 |
| 211 if (style.font_style & (Font::BOLD | Font::ITALIC)) { | 220 const int traits = (style[BOLD]->second ? kCTFontBoldTrait : 0) | |
| 212 int traits = 0; | 221 (style[ITALIC]->second ? kCTFontItalicTrait : 0); |
| 213 if (style.font_style & Font::BOLD) | 222 if (traits != 0) { |
| 214 traits |= kCTFontBoldTrait; | |
| 215 if (style.font_style & Font::ITALIC) | |
| 216 traits |= kCTFontItalicTrait; | |
| 217 base::mac::ScopedCFTypeRef<CTFontRef> styled_font( | 223 base::mac::ScopedCFTypeRef<CTFontRef> styled_font( |
| 218 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits)); | 224 CTFontCreateCopyWithSymbolicTraits(font, 0.0, NULL, traits, traits)); |
| 219 // TODO(asvitkine): Handle |styled_font| == NULL case better. | 225 // TODO(asvitkine): Handle |styled_font| == NULL case better. |
| 220 if (styled_font) { | 226 if (styled_font) { |
| 221 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName, | 227 CFAttributedStringSetAttribute(attr_string, range, kCTFontAttributeName, |
| 222 styled_font); | 228 styled_font); |
| 223 CFArrayAppendValue(attributes_, styled_font); | 229 CFArrayAppendValue(attributes_, styled_font); |
| 224 } | 230 } |
| 225 } | 231 } |
| 232 | |
| 233 AdvanceIterators(end, &color, style); | |
| 226 } | 234 } |
| 235 | |
| 236 // Undo the temporarily applied composition underlines and selection colors. | |
| 237 UndoCompositionAndSelectionStyles(); | |
| 227 } | 238 } |
| 228 | 239 |
| 229 void RenderTextMac::ComputeRuns() { | 240 void RenderTextMac::ComputeRuns() { |
| 230 DCHECK(line_); | 241 DCHECK(line_); |
| 231 | 242 |
| 232 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); | 243 CFArrayRef ct_runs = CTLineGetGlyphRuns(line_); |
| 233 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); | 244 const CFIndex ct_runs_count = CFArrayGetCount(ct_runs); |
| 234 | 245 |
| 235 gfx::Vector2d text_offset = GetTextOffset(); | 246 gfx::Vector2d text_offset = GetTextOffset(); |
| 236 // Skia will draw glyphs with respect to the baseline. | 247 // Skia will draw glyphs with respect to the baseline. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 CTRunGetPositions(ct_run, empty_cf_range, &positions[0]); | 287 CTRunGetPositions(ct_run, empty_cf_range, &positions[0]); |
| 277 positions_ptr = &positions[0]; | 288 positions_ptr = &positions[0]; |
| 278 } | 289 } |
| 279 for (size_t glyph = 0; glyph < glyph_count; glyph++) { | 290 for (size_t glyph = 0; glyph < glyph_count; glyph++) { |
| 280 SkPoint* point = &run->glyph_positions[glyph]; | 291 SkPoint* point = &run->glyph_positions[glyph]; |
| 281 point->set(x + SkDoubleToScalar(positions_ptr[glyph].x), | 292 point->set(x + SkDoubleToScalar(positions_ptr[glyph].x), |
| 282 y + SkDoubleToScalar(positions_ptr[glyph].y)); | 293 y + SkDoubleToScalar(positions_ptr[glyph].y)); |
| 283 } | 294 } |
| 284 | 295 |
| 285 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle | 296 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle |
| 286 // this better. | 297 // this better. Also, support strike and diagonal_strike. |
| 287 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); | 298 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); |
| 288 CTFontRef ct_font = | 299 CTFontRef ct_font = |
| 289 base::mac::GetValueFromDictionary<CTFontRef>(attributes, | 300 base::mac::GetValueFromDictionary<CTFontRef>(attributes, |
| 290 kCTFontAttributeName); | 301 kCTFontAttributeName); |
| 291 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( | 302 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( |
| 292 CTFontCopyFamilyName(ct_font)); | 303 CTFontCopyFamilyName(ct_font)); |
| 293 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); | 304 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); |
| 294 run->text_size = CTFontGetSize(ct_font); | 305 run->text_size = CTFontGetSize(ct_font); |
| 295 | 306 |
| 296 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); | 307 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); |
| 297 if (traits & kCTFontBoldTrait) | 308 if (traits & kCTFontBoldTrait) |
| 298 run->font_style |= Font::BOLD; | 309 run->font_style |= Font::BOLD; |
| 299 if (traits & kCTFontItalicTrait) | 310 if (traits & kCTFontItalicTrait) |
| 300 run->font_style |= Font::ITALIC; | 311 run->font_style |= Font::ITALIC; |
| 301 | 312 |
| 302 const CGColorRef foreground = | 313 const CGColorRef foreground = |
| 303 base::mac::GetValueFromDictionary<CGColorRef>( | 314 base::mac::GetValueFromDictionary<CGColorRef>( |
| 304 attributes, kCTForegroundColorAttributeName); | 315 attributes, kCTForegroundColorAttributeName); |
| 305 if (foreground) | 316 if (foreground) |
| 306 run->foreground = gfx::CGColorRefToSkColor(foreground); | 317 run->foreground = gfx::CGColorRefToSkColor(foreground); |
| 307 | 318 |
| 308 const CFNumberRef underline = | 319 const CFNumberRef underline = |
| 309 base::mac::GetValueFromDictionary<CFNumberRef>( | 320 base::mac::GetValueFromDictionary<CFNumberRef>( |
| 310 attributes, kCTUnderlineStyleAttributeName); | 321 attributes, kCTUnderlineStyleAttributeName); |
| 311 CTUnderlineStyle value = kCTUnderlineStyleNone; | 322 CTUnderlineStyle value = kCTUnderlineStyleNone; |
| 312 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value)) | 323 if (underline && CFNumberGetValue(underline, kCFNumberSInt32Type, &value)) |
| 313 run->style.underline = (value == kCTUnderlineStyleSingle); | 324 run->underline = (value == kCTUnderlineStyleSingle); |
| 314 | 325 |
| 315 run_origin.offset(run_width, 0); | 326 run_origin.offset(run_width, 0); |
| 316 } | 327 } |
| 317 runs_valid_ = true; | 328 runs_valid_ = true; |
| 318 } | 329 } |
| 319 | 330 |
| 320 RenderText* RenderText::CreateInstance() { | 331 RenderText* RenderText::CreateInstance() { |
| 321 return new RenderTextMac; | 332 return new RenderTextMac; |
| 322 } | 333 } |
| 323 | 334 |
| 324 } // namespace gfx | 335 } // namespace gfx |
| OLD | NEW |