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

Side by Side Diff: ui/gfx/platform_font_win.cc

Issue 853553002: Relanding this with font test fixes for gdi. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: DeriveFontWithHeight starts with a font matching the minimum size Created 5 years, 11 months 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
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698