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