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) | 214 |
215 return Font(this); | 215 // Create a font with a height near that of the target height. |
216 HFONT hfont = CreateFontWithHeight(height, style); | |
217 Font font(new PlatformFontWin(CreateHFontRef(hfont))); | |
218 | |
219 // Respect the minimum font size constraint. | |
220 const int min_font_size = GetMinimumFontSize(); | |
216 | 221 |
217 // CreateFontIndirect() doesn't return the largest size for the given height | 222 // CreateFontIndirect() doesn't return the largest size for the given height |
218 // when decreasing the height. Iterate to find it. | 223 // when decreasing the height. Iterate to find it. |
219 if (GetHeight() > height) { | 224 if (font.GetHeight() > height) { |
220 const int min_font_size = GetMinimumFontSize(); | 225 while ((font.GetHeight() > height) && |
221 Font font = DeriveFont(-1, style); | 226 (font.GetFontSize() >= min_font_size)) { |
222 int font_height = font.GetHeight(); | 227 Font derived_font = font.Derive(-1, style); |
223 int font_size = font.GetFontSize(); | 228 if ((derived_font.GetFontSize() < min_font_size) || |
224 while (font_height > height && font_size != min_font_size) { | 229 (derived_font.GetFontSize() == font.GetFontSize())) |
225 font = font.Derive(-1, style); | |
226 if (font_height == font.GetHeight() && font_size == font.GetFontSize()) | |
227 break; | 230 break; |
228 font_height = font.GetHeight(); | 231 DCHECK_LT(derived_font.GetFontSize(), font.GetFontSize()); |
229 font_size = font.GetFontSize(); | 232 font = derived_font; |
230 } | 233 } |
231 return font; | 234 return font; |
232 } | 235 } |
233 | 236 |
234 LOGFONT font_info; | 237 while (font.GetHeight() <= height) { |
235 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); | 238 Font derived_font = font.Derive(1, style); |
236 font_info.lfHeight = height; | 239 if ((derived_font.GetHeight() > height) && |
237 SetLogFontStyle(style, &font_info); | 240 (font.GetFontSize() >= min_font_size)) |
238 | 241 break; |
239 HFONT hfont = CreateFontIndirect(&font_info); | 242 DCHECK_GT(derived_font.GetFontSize(), font.GetFontSize()); |
240 return DeriveWithCorrectedSize(hfont); | 243 font = derived_font; |
244 } | |
245 return font; | |
241 } | 246 } |
242 | 247 |
243 //////////////////////////////////////////////////////////////////////////////// | 248 //////////////////////////////////////////////////////////////////////////////// |
244 // PlatformFontWin, PlatformFont implementation: | 249 // PlatformFontWin, PlatformFont implementation: |
245 | 250 |
246 Font PlatformFontWin::DeriveFont(int size_delta, int style) const { | 251 Font PlatformFontWin::DeriveFont(int size_delta, int style) const { |
247 LOGFONT font_info; | 252 LOGFONT font_info; |
248 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); | 253 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); |
249 const int requested_font_size = font_ref_->requested_font_size(); | 254 const int requested_font_size = font_ref_->requested_font_size(); |
250 font_info.lfHeight = AdjustFontSize(-requested_font_size, size_delta); | 255 font_info.lfHeight = AdjustFontSize(-requested_font_size, size_delta); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 style |= Font::ITALIC; | 421 style |= Font::ITALIC; |
417 if (font_metrics.tmUnderlined) | 422 if (font_metrics.tmUnderlined) |
418 style |= Font::UNDERLINE; | 423 style |= Font::UNDERLINE; |
419 if (font_metrics.tmWeight >= kTextMetricWeightBold) | 424 if (font_metrics.tmWeight >= kTextMetricWeightBold) |
420 style |= Font::BOLD; | 425 style |= Font::BOLD; |
421 | 426 |
422 return new HFontRef(font, font_size, height, baseline, cap_height, | 427 return new HFontRef(font, font_size, height, baseline, cap_height, |
423 ave_char_width, style); | 428 ave_char_width, style); |
424 } | 429 } |
425 | 430 |
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 | |
457 // static | 431 // static |
458 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( | 432 PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia( |
459 HFONT gdi_font, | 433 HFONT gdi_font, |
460 const TEXTMETRIC& font_metrics) { | 434 const TEXTMETRIC& font_metrics) { |
461 LOGFONT font_info = {0}; | 435 LOGFONT font_info = {0}; |
462 GetObject(gdi_font, sizeof(LOGFONT), &font_info); | 436 GetObject(gdi_font, sizeof(LOGFONT), &font_info); |
463 | 437 |
464 // If the font height is passed in as 0, assume the height to be -1 to ensure | 438 // If the font height is passed in as 0, assume the height to be -1 to ensure |
465 // that we return the metrics for a 1 point font. | 439 // that we return the metrics for a 1 point font. |
466 // If the font height is positive it represents the rasterized font's cell | 440 // 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... | |
511 SkPaint paint; | 485 SkPaint paint; |
512 paint.setAntiAlias(!!antialiasing); | 486 paint.setAntiAlias(!!antialiasing); |
513 paint.setTypeface(skia_face.get()); | 487 paint.setTypeface(skia_face.get()); |
514 paint.setTextSize(-font_info.lfHeight); | 488 paint.setTextSize(-font_info.lfHeight); |
515 SkPaint::FontMetrics skia_metrics; | 489 SkPaint::FontMetrics skia_metrics; |
516 paint.getFontMetrics(&skia_metrics); | 490 paint.getFontMetrics(&skia_metrics); |
517 | 491 |
518 // The calculations below are similar to those in the CreateHFontRef | 492 // The calculations below are similar to those in the CreateHFontRef |
519 // function. The height, baseline and cap height are rounded up to ensure | 493 // function. The height, baseline and cap height are rounded up to ensure |
520 // that they match up closely with GDI. | 494 // that they match up closely with GDI. |
521 const int height = std::ceil( | 495 const int height = std::ceil(skia_metrics.fDescent - skia_metrics.fAscent); |
522 skia_metrics.fDescent - skia_metrics.fAscent + skia_metrics.fLeading); | |
523 const int baseline = std::max<int>(1, std::ceil(-skia_metrics.fAscent)); | 496 const int baseline = std::max<int>(1, std::ceil(-skia_metrics.fAscent)); |
524 const int cap_height = std::ceil(paint.getTextSize() * | 497 const int cap_height = std::ceil(paint.getTextSize() * |
525 static_cast<double>(dwrite_font_metrics.capHeight) / | 498 static_cast<double>(dwrite_font_metrics.capHeight) / |
526 dwrite_font_metrics.designUnitsPerEm); | 499 dwrite_font_metrics.designUnitsPerEm); |
527 | 500 |
528 // The metrics retrieved from skia don't have the average character width. In | 501 // The metrics retrieved from skia don't have the average character width. In |
529 // any case if we get the average character width from skia then use that or | 502 // any case if we get the average character width from skia then use that or |
530 // use the text extent technique as documented by microsoft. See | 503 // use the text extent technique as documented by microsoft. See |
531 // GetAverageCharWidthInDialogUnits for details. | 504 // GetAverageCharWidthInDialogUnits for details. |
532 const int ave_char_width = | 505 const int ave_char_width = |
533 skia_metrics.fAvgCharWidth == 0 ? | 506 skia_metrics.fAvgCharWidth == 0 ? |
534 HFontRef::GetAverageCharWidthInDialogUnits(gdi_font) | 507 HFontRef::GetAverageCharWidthInDialogUnits(gdi_font) |
535 : skia_metrics.fAvgCharWidth; | 508 : skia_metrics.fAvgCharWidth; |
536 | 509 |
537 int style = 0; | 510 int style = 0; |
538 if (skia_style & SkTypeface::kItalic) | 511 if (skia_style & SkTypeface::kItalic) |
539 style |= Font::ITALIC; | 512 style |= Font::ITALIC; |
540 if (font_info.lfUnderline) | 513 if (font_info.lfUnderline) |
541 style |= Font::UNDERLINE; | 514 style |= Font::UNDERLINE; |
542 if (font_info.lfWeight >= kTextMetricWeightBold) | 515 if (font_info.lfWeight >= kTextMetricWeightBold) |
543 style |= Font::BOLD; | 516 style |= Font::BOLD; |
544 return new HFontRef(gdi_font, -font_info.lfHeight, height, baseline, | 517 return new HFontRef(gdi_font, -font_info.lfHeight, height, baseline, |
545 cap_height, ave_char_width, style); | 518 cap_height, ave_char_width, style); |
546 } | 519 } |
547 | 520 |
548 PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) { | 521 PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) { |
549 } | 522 } |
550 | 523 |
524 HFONT PlatformFontWin::CreateFontWithHeight(int height, int style) { | |
msw
2015/01/13 23:54:59
I don't think that this simplifies the code as you
ananta
2015/01/14 00:17:23
Reverted this part of the change. This was an expe
| |
525 LOGFONT font_info; | |
526 GetObject(GetNativeFont(), sizeof(LOGFONT), &font_info); | |
527 font_info.lfHeight = height; | |
528 SetLogFontStyle(style, &font_info); | |
529 | |
530 base::win::ScopedGetDC screen_dc(NULL); | |
531 gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT); | |
532 | |
533 base::win::ScopedGDIObject<HFONT> best_font(CreateFontIndirect(&font_info)); | |
534 | |
535 TEXTMETRIC best_font_metrics = {0}; | |
536 GetTextMetricsForFont(screen_dc, best_font, &best_font_metrics); | |
537 | |
538 // Set |lfHeight| to negative value to indicate it's the size, not the height. | |
539 font_info.lfHeight = | |
540 -(best_font_metrics.tmHeight - best_font_metrics.tmInternalLeading); | |
541 | |
542 // Respect the minimum font size constraint. | |
543 const int min_font_size = GetMinimumFontSize(); | |
544 | |
545 do { | |
546 // Increment font size. Prefer font with greater size if its height isn't | |
547 // greater than height of base font. Exception being the case where we have | |
548 // a minimum font size being enforced. | |
549 font_info.lfHeight = AdjustFontSize(font_info.lfHeight, 1); | |
550 base::win::ScopedGDIObject<HFONT> font(CreateFontIndirect(&font_info)); | |
551 TEXTMETRIC font_metrics = {0}; | |
552 GetTextMetricsForFont(screen_dc, font, &font_metrics); | |
553 if ((font_metrics.tmHeight > best_font_metrics.tmHeight) && | |
554 ((best_font_metrics.tmHeight - best_font_metrics.tmInternalLeading) >= | |
555 min_font_size)) { | |
556 break; | |
557 } | |
558 best_font.Set(font.release()); | |
559 best_font_metrics = font_metrics; | |
560 } while (true); | |
561 | |
562 return best_font.release(); | |
563 } | |
564 | |
565 | |
551 //////////////////////////////////////////////////////////////////////////////// | 566 //////////////////////////////////////////////////////////////////////////////// |
552 // PlatformFontWin::HFontRef: | 567 // PlatformFontWin::HFontRef: |
553 | 568 |
554 PlatformFontWin::HFontRef::HFontRef(HFONT hfont, | 569 PlatformFontWin::HFontRef::HFontRef(HFONT hfont, |
555 int font_size, | 570 int font_size, |
556 int height, | 571 int height, |
557 int baseline, | 572 int baseline, |
558 int cap_height, | 573 int cap_height, |
559 int ave_char_width, | 574 int ave_char_width, |
560 int style) | 575 int style) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
620 return new PlatformFontWin(native_font); | 635 return new PlatformFontWin(native_font); |
621 } | 636 } |
622 | 637 |
623 // static | 638 // static |
624 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, | 639 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, |
625 int font_size) { | 640 int font_size) { |
626 return new PlatformFontWin(font_name, font_size); | 641 return new PlatformFontWin(font_name, font_size); |
627 } | 642 } |
628 | 643 |
629 } // namespace gfx | 644 } // namespace gfx |
OLD | NEW |