Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(550)

Side by Side Diff: app/gfx/font_skia.cc

Issue 338029: Got the about panel to have its text lined up correctly.
Patch Set: Added pango font metrics cache Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « app/gfx/font.h ('k') | chrome/browser/views/about_chrome_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "app/gfx/font.h" 5 #include "app/gfx/font.h"
6 6
7 #include <gdk/gdk.h> 7 #include <gdk/gdk.h>
8 #include <map>
8 #include <pango/pango.h> 9 #include <pango/pango.h>
9 10
10 #include "app/gfx/canvas.h" 11 #include "app/gfx/canvas.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/string_piece.h" 13 #include "base/string_piece.h"
13 #include "base/sys_string_conversions.h" 14 #include "base/sys_string_conversions.h"
14 #include "third_party/skia/include/core/SkTypeface.h" 15 #include "third_party/skia/include/core/SkTypeface.h"
15 #include "third_party/skia/include/core/SkPaint.h" 16 #include "third_party/skia/include/core/SkPaint.h"
16 17
17 namespace { 18 namespace {
(...skipping 17 matching lines...) Expand all
35 scale_factor = pango_cairo_context_get_resolution(context); 36 scale_factor = pango_cairo_context_get_resolution(context);
36 g_object_unref(context); 37 g_object_unref(context);
37 if (scale_factor <= 0) 38 if (scale_factor <= 0)
38 scale_factor = 1; 39 scale_factor = 1;
39 else 40 else
40 scale_factor /= 72.0; 41 scale_factor /= 72.0;
41 } 42 }
42 return scale_factor; 43 return scale_factor;
43 } 44 }
44 45
46 // Retrieves the pango metrics for a pango font description. Caches the metrics
47 // and never frees them. The metrics objects are relatively small and
48 // very expensive to look up.
49 static PangoFontMetrics* GetPangoFontMetrics(PangoFontDescription* desc) {
50 static std::map<int, PangoFontMetrics*>* desc_to_metrics = NULL;
51 static PangoContext* context = NULL;
52
53 if (!context) {
54 context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
55 pango_context_set_language(context, pango_language_get_default());
56 }
57
58 if (!desc_to_metrics) {
59 desc_to_metrics = new std::map<int, PangoFontMetrics*>();
60 }
61
62 int desc_hash = pango_font_description_hash(desc);
63 std::map<int, PangoFontMetrics*>::iterator i =
64 desc_to_metrics->find(desc_hash);
65
66 if (i == desc_to_metrics->end()) {
67 PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL);
68 (*desc_to_metrics)[desc_hash] = metrics;
69 return metrics;
70 } else {
71 return i->second;
72 }
73 }
74
45 } // namespace 75 } // namespace
46 76
47 namespace gfx { 77 namespace gfx {
48 78
49 Font::Font(const Font& other) { 79 Font::Font(const Font& other) {
50 CopyFont(other); 80 CopyFont(other);
51 } 81 }
52 82
53 Font& Font::operator=(const Font& other) { 83 Font& Font::operator=(const Font& other) {
54 CopyFont(other); 84 CopyFont(other);
55 return *this; 85 return *this;
56 } 86 }
57 87
58 Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size, 88 Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size,
59 int style) 89 int style)
60 : typeface_helper_(new SkAutoUnref(tf)), 90 : typeface_helper_(new SkAutoUnref(tf)),
61 typeface_(tf), 91 typeface_(tf),
62 font_family_(font_family), 92 font_family_(font_family),
63 font_size_(font_size), 93 font_size_(font_size),
64 style_(style) { 94 style_(style),
95 pango_metrics_inited_(false),
96 avg_width_(0.0),
97 underline_position_(0.0),
98 underline_thickness_(0.0) {
65 tf->ref(); 99 tf->ref();
66 calculateMetrics(); 100 calculateMetrics();
67 } 101 }
68 102
69 void Font::calculateMetrics() { 103 void Font::calculateMetrics() {
70 SkPaint paint; 104 SkPaint paint;
71 SkPaint::FontMetrics metrics; 105 SkPaint::FontMetrics metrics;
72 PaintSetup(&paint); 106 PaintSetup(&paint);
73 paint.getFontMetrics(&metrics); 107 paint.getFontMetrics(&metrics);
74 108
75 ascent_ = SkScalarCeil(-metrics.fAscent); 109 ascent_ = SkScalarCeil(-metrics.fAscent);
76 height_ = ascent_ + SkScalarCeil(metrics.fDescent); 110 height_ = ascent_ + SkScalarCeil(metrics.fDescent);
77 // avg_width_ is calculated lazily, as it's expensive and not used often.
78 avg_width_ = -1.0;
79 111
80 } 112 }
81 113
82 void Font::CopyFont(const Font& other) { 114 void Font::CopyFont(const Font& other) {
83 typeface_helper_.reset(new SkAutoUnref(other.typeface_)); 115 typeface_helper_.reset(new SkAutoUnref(other.typeface_));
84 typeface_ = other.typeface_; 116 typeface_ = other.typeface_;
85 typeface_->ref(); 117 typeface_->ref();
86 font_family_ = other.font_family_; 118 font_family_ = other.font_family_;
87 font_size_ = other.font_size_; 119 font_size_ = other.font_size_;
88 style_ = other.style_; 120 style_ = other.style_;
89 height_ = other.height_; 121 height_ = other.height_;
90 ascent_ = other.ascent_; 122 ascent_ = other.ascent_;
123 pango_metrics_inited_ = other.pango_metrics_inited_;
91 avg_width_ = other.avg_width_; 124 avg_width_ = other.avg_width_;
125 underline_position_ = other.underline_position_;
126 underline_thickness_ = other.underline_thickness_;
92 } 127 }
93 128
94 int Font::height() const { 129 int Font::height() const {
95 return height_; 130 return height_;
96 } 131 }
97 132
98 int Font::baseline() const { 133 int Font::baseline() const {
99 return ascent_; 134 return ascent_;
100 } 135 }
101 136
102 int Font::ave_char_width() const { 137 int Font::ave_char_width() const {
103 return SkScalarRound(const_cast<Font*>(this)->avg_width()); 138 return SkScalarRound(avg_width());
104 } 139 }
105 140
106 Font Font::CreateFont(const std::wstring& font_family, int font_size) { 141 Font Font::CreateFont(const std::wstring& font_family, int font_size) {
107 DCHECK_GT(font_size, 0); 142 DCHECK_GT(font_size, 0);
108 std::wstring fallback; 143 std::wstring fallback;
109 144
110 SkTypeface* tf = SkTypeface::CreateFromName( 145 SkTypeface* tf = SkTypeface::CreateFromName(
111 base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal); 146 base::SysWideToUTF8(font_family).c_str(), SkTypeface::kNormal);
112 if (!tf) { 147 if (!tf) {
113 // A non-scalable font such as .pcf is specified. Falls back to a default 148 // A non-scalable font such as .pcf is specified. Falls back to a default
(...skipping 27 matching lines...) Expand all
141 if (BOLD & style) 176 if (BOLD & style)
142 skstyle |= SkTypeface::kBold; 177 skstyle |= SkTypeface::kBold;
143 if (ITALIC & style) 178 if (ITALIC & style)
144 skstyle |= SkTypeface::kItalic; 179 skstyle |= SkTypeface::kItalic;
145 180
146 SkTypeface* tf = SkTypeface::CreateFromName( 181 SkTypeface* tf = SkTypeface::CreateFromName(
147 base::SysWideToUTF8(font_family_).c_str(), 182 base::SysWideToUTF8(font_family_).c_str(),
148 static_cast<SkTypeface::Style>(skstyle)); 183 static_cast<SkTypeface::Style>(skstyle));
149 SkAutoUnref tf_helper(tf); 184 SkAutoUnref tf_helper(tf);
150 185
151 return Font(tf, font_family_, font_size_ + size_delta, skstyle); 186 return Font(tf, font_family_, font_size_ + size_delta, style);
152 } 187 }
153 188
154 void Font::PaintSetup(SkPaint* paint) const { 189 void Font::PaintSetup(SkPaint* paint) const {
155 paint->setAntiAlias(false); 190 paint->setAntiAlias(false);
156 paint->setSubpixelText(false); 191 paint->setSubpixelText(false);
157 paint->setTextSize(SkFloatToScalar(font_size_ * GetPangoScaleFactor())); 192 paint->setTextSize(SkFloatToScalar(font_size_ * GetPangoScaleFactor()));
158 paint->setTypeface(typeface_); 193 paint->setTypeface(typeface_);
159 paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold()); 194 paint->setFakeBoldText((BOLD & style_) && !typeface_->isBold());
160 paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ? 195 paint->setTextSkewX((ITALIC & style_) && !typeface_->isItalic() ?
161 -SK_Scalar1/4 : 0); 196 -SK_Scalar1/4 : 0);
162 } 197 }
163 198
164 int Font::GetStringWidth(const std::wstring& text) const { 199 int Font::GetStringWidth(const std::wstring& text) const {
165 int width = 0, height = 0; 200 int width = 0, height = 0;
166 201
167 Canvas::SizeStringInt(text, *this, &width, &height, 0); 202 Canvas::SizeStringInt(text, *this, &width, &height, 0);
168 return width; 203 return width;
169 } 204 }
170 205
171 double Font::avg_width() { 206 void Font::InitPangoMetrics() {
172 if (avg_width_ < 0) { 207 if (!pango_metrics_inited_) {
208 pango_metrics_inited_ = true;
209 PangoFontDescription* pango_desc = PangoFontFromGfxFont(*this);
210 PangoFontMetrics* pango_metrics = GetPangoFontMetrics(pango_desc);
211
212 underline_position_ =
213 pango_font_metrics_get_underline_position(pango_metrics);
214 underline_position_ /= PANGO_SCALE;
215
216 // todo(davemoore) Come up with a better solution.
217 // This is a hack, but without doing this the underlines
218 // we get end up fuzzy. So we align to the midpoint of a pixel.
219 underline_position_ /= 2;
220
221 underline_thickness_ =
222 pango_font_metrics_get_underline_thickness(pango_metrics);
223 underline_thickness_ /= PANGO_SCALE;
224
173 // First get the pango based width 225 // First get the pango based width
174 PangoFontDescription* pango_desc = PangoFontFromGfxFont(*this);
175 PangoContext* context =
176 gdk_pango_context_get_for_screen(gdk_screen_get_default());
177 PangoFontMetrics* pango_metrics =
178 pango_context_get_metrics(context,
179 pango_desc,
180 pango_language_get_default());
181 double pango_width = 226 double pango_width =
182 pango_font_metrics_get_approximate_char_width(pango_metrics); 227 pango_font_metrics_get_approximate_char_width(pango_metrics);
183 pango_width /= PANGO_SCALE; 228 pango_width /= PANGO_SCALE;
184 229
185 // Yes, this is how Microsoft recommends calculating the dialog unit 230 // Yes, this is how Microsoft recommends calculating the dialog unit
186 // conversions. 231 // conversions.
187 int text_width = GetStringWidth( 232 int text_width = GetStringWidth(
188 L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); 233 L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
189 double dialog_units = (text_width / 26 + 1) / 2; 234 double dialog_units = (text_width / 26 + 1) / 2;
190 avg_width_ = std::min(pango_width, dialog_units); 235 avg_width_ = std::min(pango_width, dialog_units);
191 pango_font_metrics_unref(pango_metrics);
192 pango_font_description_free(pango_desc); 236 pango_font_description_free(pango_desc);
193 } 237 }
238 }
239
240 double Font::avg_width() const {
241 const_cast<Font*>(this)->InitPangoMetrics();
194 return avg_width_; 242 return avg_width_;
195 } 243 }
196 244
245 double Font::underline_position() const {
246 const_cast<Font*>(this)->InitPangoMetrics();
247 return underline_position_;
248 }
249
250 double Font::underline_thickness() const {
251 const_cast<Font*>(this)->InitPangoMetrics();
252 return underline_thickness_;
253 }
254
197 int Font::GetExpectedTextWidth(int length) const { 255 int Font::GetExpectedTextWidth(int length) const {
198 double char_width = const_cast<Font*>(this)->avg_width(); 256 double char_width = const_cast<Font*>(this)->avg_width();
199 return round(static_cast<float>(length) * char_width); 257 return round(static_cast<float>(length) * char_width);
200 } 258 }
201 259
202 int Font::style() const { 260 int Font::style() const {
203 return style_; 261 return style_;
204 } 262 }
205 263
206 std::wstring Font::FontName() { 264 std::wstring Font::FontName() {
207 return font_family_; 265 return font_family_;
208 } 266 }
209 267
210 int Font::FontSize() { 268 int Font::FontSize() {
211 return font_size_; 269 return font_size_;
212 } 270 }
213 271
214 NativeFont Font::nativeFont() const { 272 NativeFont Font::nativeFont() const {
215 return typeface_; 273 return typeface_;
216 } 274 }
217 275
218 } // namespace gfx 276 } // namespace gfx
OLDNEW
« no previous file with comments | « app/gfx/font.h ('k') | chrome/browser/views/about_chrome_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698