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> |
11 | 11 |
12 #include "base/mac/foundation_util.h" | 12 #include "base/mac/foundation_util.h" |
13 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
14 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
15 #include "skia/ext/skia_utils_mac.h" | 15 #include "skia/ext/skia_utils_mac.h" |
16 | 16 |
17 namespace { | |
18 | |
19 // Returns the pixel height of |ct_font|. | |
20 CGFloat GetCTFontPixelSize(CTFontRef ct_font) { | |
21 return CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font); | |
22 } | |
23 | |
24 // Creates a CTFont with the given font name and pixel size. Ownership is | |
25 // transferred to the caller. | |
26 // | |
27 // Note: This code makes use of pixel sizes (rather than view coordinate sizes) | |
28 // because it draws to an underlying Skia canvas, which is normally pixel based. | |
29 CTFontRef CreateCTFontWithPixelSize(const std::string& font_name, | |
30 const int target_pixel_size) { | |
31 // Epsilon value used for comparing font sizes. | |
32 const CGFloat kEpsilon = 0.001; | |
33 // The observed pixel to points ratio for Lucida Grande on 10.6. Other fonts | |
34 // have other ratios and the documentation doesn't provide a guarantee that | |
35 // the relation is linear. So this ratio is used as a first try before | |
36 // falling back to the bisection method. | |
37 const CGFloat kPixelsToPointsRatio = 0.849088; | |
38 | |
39 base::mac::ScopedCFTypeRef<CFStringRef> font_name_cf_string( | |
40 base::SysUTF8ToCFStringRef(font_name)); | |
41 | |
42 // First, try using |kPixelsToPointsRatio|. | |
43 CGFloat point_size = target_pixel_size * kPixelsToPointsRatio; | |
44 base::mac::ScopedCFTypeRef<CTFontRef> ct_font( | |
45 CTFontCreateWithName(font_name_cf_string, point_size, NULL)); | |
46 CGFloat actual_pixel_size = GetCTFontPixelSize(ct_font); | |
47 if (std::fabs(actual_pixel_size - target_pixel_size) < kEpsilon) | |
48 return ct_font.release(); | |
49 | |
50 // |kPixelsToPointsRatio| wasn't correct. Use the bisection method to find the | |
51 // right size. | |
52 | |
53 // First, find the initial bisection range, so that the point size that | |
54 // corresponds to |target_pixel_size| is between |lo| and |hi|. | |
55 CGFloat lo = 0; | |
56 CGFloat hi = point_size; | |
57 while (actual_pixel_size < target_pixel_size) { | |
58 lo = hi; | |
59 hi *= 2; | |
60 ct_font.reset(CTFontCreateWithName(font_name_cf_string, hi, NULL)); | |
61 actual_pixel_size = GetCTFontPixelSize(ct_font); | |
62 } | |
63 | |
64 // Now, bisect to find the right size. | |
65 while (lo < hi) { | |
66 point_size = (hi - lo) * 0.5 + lo; | |
67 ct_font.reset(CTFontCreateWithName(font_name_cf_string, point_size, NULL)); | |
68 actual_pixel_size = GetCTFontPixelSize(ct_font); | |
69 if (std::fabs(actual_pixel_size - target_pixel_size) < kEpsilon) | |
70 break; | |
71 if (target_pixel_size > actual_pixel_size) | |
72 lo = point_size; | |
73 else | |
74 hi = point_size; | |
75 } | |
76 | |
77 return ct_font.release(); | |
78 } | |
79 | |
80 } // namespace | |
81 | |
82 namespace gfx { | 17 namespace gfx { |
83 | 18 |
84 RenderTextMac::RenderTextMac() : common_baseline_(0), runs_valid_(false) { | 19 RenderTextMac::RenderTextMac() : common_baseline_(0), runs_valid_(false) { |
85 } | 20 } |
86 | 21 |
87 RenderTextMac::~RenderTextMac() { | 22 RenderTextMac::~RenderTextMac() { |
88 } | 23 } |
89 | 24 |
90 Size RenderTextMac::GetStringSize() { | 25 Size RenderTextMac::GetStringSize() { |
91 EnsureLayout(); | 26 EnsureLayout(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 runs_valid_ = false; | 91 runs_valid_ = false; |
157 } | 92 } |
158 | 93 |
159 void RenderTextMac::EnsureLayout() { | 94 void RenderTextMac::EnsureLayout() { |
160 if (line_.get()) | 95 if (line_.get()) |
161 return; | 96 return; |
162 runs_.clear(); | 97 runs_.clear(); |
163 runs_valid_ = false; | 98 runs_valid_ = false; |
164 | 99 |
165 const Font& font = GetFont(); | 100 const Font& font = GetFont(); |
| 101 base::mac::ScopedCFTypeRef<CFStringRef> font_name_cf_string( |
| 102 base::SysUTF8ToCFStringRef(font.GetFontName())); |
166 base::mac::ScopedCFTypeRef<CTFontRef> ct_font( | 103 base::mac::ScopedCFTypeRef<CTFontRef> ct_font( |
167 CreateCTFontWithPixelSize(font.GetFontName(), font.GetFontSize())); | 104 CTFontCreateWithName(font_name_cf_string, font.GetFontSize(), NULL)); |
168 | 105 |
169 const void* keys[] = { kCTFontAttributeName }; | 106 const void* keys[] = { kCTFontAttributeName }; |
170 const void* values[] = { ct_font }; | 107 const void* values[] = { ct_font }; |
171 base::mac::ScopedCFTypeRef<CFDictionaryRef> attributes( | 108 base::mac::ScopedCFTypeRef<CFDictionaryRef> attributes( |
172 CFDictionaryCreate(NULL, keys, values, arraysize(keys), NULL, | 109 CFDictionaryCreate(NULL, keys, values, arraysize(keys), NULL, |
173 &kCFTypeDictionaryValueCallBacks)); | 110 &kCFTypeDictionaryValueCallBacks)); |
174 | 111 |
175 base::mac::ScopedCFTypeRef<CFStringRef> cf_text( | 112 base::mac::ScopedCFTypeRef<CFStringRef> cf_text( |
176 base::SysUTF16ToCFStringRef(text())); | 113 base::SysUTF16ToCFStringRef(text())); |
177 base::mac::ScopedCFTypeRef<CFAttributedStringRef> attr_text( | 114 base::mac::ScopedCFTypeRef<CFAttributedStringRef> attr_text( |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 | 274 |
338 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle | 275 // TODO(asvitkine): Style boundaries are not necessarily per-run. Handle |
339 // this better. | 276 // this better. |
340 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); | 277 CFDictionaryRef attributes = CTRunGetAttributes(ct_run); |
341 CTFontRef ct_font = | 278 CTFontRef ct_font = |
342 base::mac::GetValueFromDictionary<CTFontRef>(attributes, | 279 base::mac::GetValueFromDictionary<CTFontRef>(attributes, |
343 kCTFontAttributeName); | 280 kCTFontAttributeName); |
344 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( | 281 base::mac::ScopedCFTypeRef<CFStringRef> font_name_ref( |
345 CTFontCopyFamilyName(ct_font)); | 282 CTFontCopyFamilyName(ct_font)); |
346 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); | 283 run->font_name = base::SysCFStringRefToUTF8(font_name_ref); |
347 run->text_size = GetCTFontPixelSize(ct_font); | 284 run->text_size = CTFontGetSize(ct_font); |
348 | 285 |
349 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); | 286 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ct_font); |
350 if (traits & kCTFontBoldTrait) | 287 if (traits & kCTFontBoldTrait) |
351 run->font_style |= Font::BOLD; | 288 run->font_style |= Font::BOLD; |
352 if (traits & kCTFontItalicTrait) | 289 if (traits & kCTFontItalicTrait) |
353 run->font_style |= Font::ITALIC; | 290 run->font_style |= Font::ITALIC; |
354 | 291 |
355 const CGColorRef foreground = | 292 const CGColorRef foreground = |
356 base::mac::GetValueFromDictionary<CGColorRef>( | 293 base::mac::GetValueFromDictionary<CGColorRef>( |
357 attributes, kCTForegroundColorAttributeName); | 294 attributes, kCTForegroundColorAttributeName); |
(...skipping 10 matching lines...) Expand all Loading... |
368 run_origin.offset(run_width, 0); | 305 run_origin.offset(run_width, 0); |
369 } | 306 } |
370 runs_valid_ = true; | 307 runs_valid_ = true; |
371 } | 308 } |
372 | 309 |
373 RenderText* RenderText::CreateInstance() { | 310 RenderText* RenderText::CreateInstance() { |
374 return new RenderTextMac; | 311 return new RenderTextMac; |
375 } | 312 } |
376 | 313 |
377 } // namespace gfx | 314 } // namespace gfx |
OLD | NEW |