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/platform_font_win.h" | 5 #include "ui/gfx/platform_font_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <dwrite.h> | 8 #include <dwrite.h> |
9 #include <math.h> | 9 #include <math.h> |
10 #include <windows.h> | 10 #include <windows.h> |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 InitWithCopyOfHFONT(native_font); | 204 InitWithCopyOfHFONT(native_font); |
205 } | 205 } |
206 | 206 |
207 PlatformFontWin::PlatformFontWin(const std::string& font_name, | 207 PlatformFontWin::PlatformFontWin(const std::string& font_name, |
208 int font_size) { | 208 int font_size) { |
209 InitWithFontNameAndSize(font_name, font_size); | 209 InitWithFontNameAndSize(font_name, font_size); |
210 } | 210 } |
211 | 211 |
212 Font PlatformFontWin::DeriveFontWithHeight(int height, int style) { | 212 Font PlatformFontWin::DeriveFontWithHeight(int height, int style) { |
213 DCHECK_GE(height, 0); | 213 DCHECK_GE(height, 0); |
| 214 if (GetHeight() == height && GetStyle() == style) |
| 215 return Font(this); |
214 | 216 |
215 // Create a font with a height near that of the target height. | 217 // CreateFontIndirect() doesn't return the largest size for the given height |
| 218 // when decreasing the height. Iterate to find it. |
| 219 if (GetHeight() > height) { |
| 220 const int min_font_size = GetMinimumFontSize(); |
| 221 Font font = DeriveFont(-1, style); |
| 222 int font_height = font.GetHeight(); |
| 223 int font_size = font.GetFontSize(); |
| 224 while (font_height > height && font_size != min_font_size) { |
| 225 font = font.Derive(-1, style); |
| 226 if (font_height == font.GetHeight() && font_size == font.GetFontSize()) |
| 227 break; |
| 228 font_height = font.GetHeight(); |
| 229 font_size = font.GetFontSize(); |
| 230 } |
| 231 return font; |
| 232 } |
| 233 |
216 LOGFONT font_info; | 234 LOGFONT font_info; |
217 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); | 235 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); |
218 font_info.lfHeight = height; | 236 font_info.lfHeight = height; |
219 SetLogFontStyle(style, &font_info); | 237 SetLogFontStyle(style, &font_info); |
220 | 238 |
221 HFONT hfont = CreateFontIndirect(&font_info); | 239 HFONT hfont = CreateFontIndirect(&font_info); |
222 Font font(new PlatformFontWin(CreateHFontRef(hfont))); | 240 return DeriveWithCorrectedSize(hfont); |
223 | |
224 // Respect the minimum font size constraint. | |
225 const int min_font_size = GetMinimumFontSize(); | |
226 | |
227 // Used to avoid shrinking the font and expanding it. | |
228 bool ran_shrink_loop = false; | |
229 | |
230 // CreateFontIndirect() doesn't return the largest size for the given height | |
231 // when decreasing the height. Iterate to find it. | |
232 while ((font.GetHeight() > height) && | |
233 (font.GetFontSize() >= min_font_size)) { | |
234 ran_shrink_loop = true; | |
235 Font derived_font = font.Derive(-1, style); | |
236 if ((derived_font.GetFontSize() < min_font_size) || | |
237 (derived_font.GetFontSize() == font.GetFontSize())) | |
238 break; | |
239 DCHECK_LT(derived_font.GetFontSize(), font.GetFontSize()); | |
240 font = derived_font; | |
241 } | |
242 | |
243 while ((!ran_shrink_loop && font.GetHeight() <= height) || | |
244 (font.GetFontSize() < min_font_size)) { | |
245 Font derived_font = font.Derive(1, style); | |
246 if ((derived_font.GetHeight() > height) && | |
247 (font.GetFontSize() >= min_font_size)) | |
248 break; | |
249 DCHECK_GT(derived_font.GetFontSize(), font.GetFontSize()); | |
250 font = derived_font; | |
251 } | |
252 return font; | |
253 } | 241 } |
254 | 242 |
255 //////////////////////////////////////////////////////////////////////////////// | 243 //////////////////////////////////////////////////////////////////////////////// |
256 // PlatformFontWin, PlatformFont implementation: | 244 // PlatformFontWin, PlatformFont implementation: |
257 | 245 |
258 Font PlatformFontWin::DeriveFont(int size_delta, int style) const { | 246 Font PlatformFontWin::DeriveFont(int size_delta, int style) const { |
259 LOGFONT font_info; | 247 LOGFONT font_info; |
260 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); | 248 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); |
261 const int requested_font_size = font_ref_->requested_font_size(); | 249 const int requested_font_size = font_ref_->requested_font_size(); |
262 font_info.lfHeight = AdjustFontSize(-requested_font_size, size_delta); | 250 font_info.lfHeight = AdjustFontSize(-requested_font_size, size_delta); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 style |= Font::ITALIC; | 416 style |= Font::ITALIC; |
429 if (font_metrics.tmUnderlined) | 417 if (font_metrics.tmUnderlined) |
430 style |= Font::UNDERLINE; | 418 style |= Font::UNDERLINE; |
431 if (font_metrics.tmWeight >= kTextMetricWeightBold) | 419 if (font_metrics.tmWeight >= kTextMetricWeightBold) |
432 style |= Font::BOLD; | 420 style |= Font::BOLD; |
433 | 421 |
434 return new HFontRef(font, font_size, height, baseline, cap_height, | 422 return new HFontRef(font, font_size, height, baseline, cap_height, |
435 ave_char_width, style); | 423 ave_char_width, style); |
436 } | 424 } |
437 | 425 |
| 426 Font PlatformFontWin::DeriveWithCorrectedSize(HFONT base_font) { |
| 427 base::win::ScopedGetDC screen_dc(NULL); |
| 428 gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); |
| 429 |
| 430 base::win::ScopedGDIObject<HFONT> best_font(base_font); |
| 431 TEXTMETRIC best_font_metrics; |
| 432 GetTextMetricsForFont(screen_dc, best_font, &best_font_metrics); |
| 433 |
| 434 LOGFONT font_info; |
| 435 GetObject(base_font, sizeof(LOGFONT), &font_info); |
| 436 |
| 437 // Set |lfHeight| to negative value to indicate it's the size, not the height. |
| 438 font_info.lfHeight = |
| 439 -(best_font_metrics.tmHeight - best_font_metrics.tmInternalLeading); |
| 440 |
| 441 do { |
| 442 // Increment font size. Prefer font with greater size if its height isn't |
| 443 // greater than height of base font. |
| 444 font_info.lfHeight = AdjustFontSize(font_info.lfHeight, 1); |
| 445 base::win::ScopedGDIObject<HFONT> font(CreateFontIndirect(&font_info)); |
| 446 TEXTMETRIC font_metrics; |
| 447 GetTextMetricsForFont(screen_dc, font, &font_metrics); |
| 448 if (font_metrics.tmHeight > best_font_metrics.tmHeight) |
| 449 break; |
| 450 best_font.Set(font.release()); |
| 451 best_font_metrics = font_metrics; |
| 452 } while (true); |
| 453 |
| 454 return Font(new PlatformFontWin(CreateHFontRef(best_font.release()))); |
| 455 } |
| 456 |
438 // static | 457 // static |
439 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( | 458 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( |
440 HFONT gdi_font, | 459 HFONT gdi_font, |
441 const TEXTMETRIC& font_metrics) { | 460 const TEXTMETRIC& font_metrics) { |
442 LOGFONT font_info = {0}; | 461 LOGFONT font_info = {0}; |
443 GetObject(gdi_font, sizeof(LOGFONT), &font_info); | 462 GetObject(gdi_font, sizeof(LOGFONT), &font_info); |
444 | 463 |
445 // If the font height is passed in as 0, assume the height to be -1 to ensure | 464 // If the font height is passed in as 0, assume the height to be -1 to ensure |
446 // that we return the metrics for a 1 point font. | 465 // that we return the metrics for a 1 point font. |
447 // If the font height is positive it represents the rasterized font's cell | 466 // If the font height is positive it represents the rasterized font's cell |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 SkPaint paint; | 511 SkPaint paint; |
493 paint.setAntiAlias(!!antialiasing); | 512 paint.setAntiAlias(!!antialiasing); |
494 paint.setTypeface(skia_face.get()); | 513 paint.setTypeface(skia_face.get()); |
495 paint.setTextSize(-font_info.lfHeight); | 514 paint.setTextSize(-font_info.lfHeight); |
496 SkPaint::FontMetrics skia_metrics; | 515 SkPaint::FontMetrics skia_metrics; |
497 paint.getFontMetrics(&skia_metrics); | 516 paint.getFontMetrics(&skia_metrics); |
498 | 517 |
499 // The calculations below are similar to those in the CreateHFontRef | 518 // The calculations below are similar to those in the CreateHFontRef |
500 // function. The height, baseline and cap height are rounded up to ensure | 519 // function. The height, baseline and cap height are rounded up to ensure |
501 // that they match up closely with GDI. | 520 // that they match up closely with GDI. |
502 const int height = std::ceil(skia_metrics.fDescent - skia_metrics.fAscent); | 521 const int height = std::ceil( |
| 522 skia_metrics.fDescent - skia_metrics.fAscent + skia_metrics.fLeading); |
503 const int baseline = std::max<int>(1, std::ceil(-skia_metrics.fAscent)); | 523 const int baseline = std::max<int>(1, std::ceil(-skia_metrics.fAscent)); |
504 const int cap_height = std::ceil(paint.getTextSize() * | 524 const int cap_height = std::ceil(paint.getTextSize() * |
505 static_cast<double>(dwrite_font_metrics.capHeight) / | 525 static_cast<double>(dwrite_font_metrics.capHeight) / |
506 dwrite_font_metrics.designUnitsPerEm); | 526 dwrite_font_metrics.designUnitsPerEm); |
507 | 527 |
508 // The metrics retrieved from skia don't have the average character width. In | 528 // The metrics retrieved from skia don't have the average character width. In |
509 // any case if we get the average character width from skia then use that or | 529 // any case if we get the average character width from skia then use that or |
510 // use the text extent technique as documented by microsoft. See | 530 // use the text extent technique as documented by microsoft. See |
511 // GetAverageCharWidthInDialogUnits for details. | 531 // GetAverageCharWidthInDialogUnits for details. |
512 const int ave_char_width = | 532 const int ave_char_width = |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 return new PlatformFontWin(native_font); | 620 return new PlatformFontWin(native_font); |
601 } | 621 } |
602 | 622 |
603 // static | 623 // static |
604 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 624 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
605 int font_size) { | 625 int font_size) { |
606 return new PlatformFontWin(font_name, font_size); | 626 return new PlatformFontWin(font_name, font_size); |
607 } | 627 } |
608 | 628 |
609 } // namespace gfx | 629 } // namespace gfx |
OLD | NEW |