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