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