summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorananta <ananta@chromium.org>2014-11-14 15:30:31 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-14 23:30:56 +0000
commit420c045db8d79e2b114ef6339e1adc4d614ec96e (patch)
treea5b8a208bb16e18e65d2a8f23f648078113a352c
parentdcaa24e38a7d9b62b0449d1a025d5b9d2a9e3c8a (diff)
downloadchromium_src-420c045db8d79e2b114ef6339e1adc4d614ec96e.zip
chromium_src-420c045db8d79e2b114ef6339e1adc4d614ec96e.tar.gz
chromium_src-420c045db8d79e2b114ef6339e1adc4d614ec96e.tar.bz2
Fixed font metrics calculations if DirectWrite font rendering is enabled in the browser.
Fixes as below:- 1. The current code in the PlatformFontWin::CreateHFontRefFromSkia function was ceiling the ascent and descent before calculating the height of the font. We now use std::round(Descent - ascent) to mirror the logic in skia and RenderTextHarfBuzz. 2. Skia does not return all metrics we need like the capHeight which indicates the height of capital letters. This information is returned by DirectWrite. I added code to retrieve the font metrics from DirectWrite in the CreateFontRefFromSkia function and used this to calculate the cap height. The rest of the metrics are retrieved from skia as before. 3. We use the capHeight calculated in step 2 to calculate the internal leading value which is the leading space in the bounds for the glyph. The internal leading value is not returned by DirectWrite. We use this to calculate the font size which ensures that characters now show up in the desired size instead of giant size as seen today. 4. I removed the set_use_skia_for_font_metrics function from PlatformFontWin and added a new function SetDirectWriteFactory which is used to pass in the global directwrite factory by content. We use the factory to retrieve metrics from DirectWrite. BUG=432086, 431377, 432105 Review URL: https://codereview.chromium.org/721163003 Cr-Commit-Position: refs/heads/master@{#304293}
-rw-r--r--content/browser/browser_main_runner.cc2
-rw-r--r--ui/gfx/platform_font_win.cc66
-rw-r--r--ui/gfx/platform_font_win.h19
3 files changed, 60 insertions, 27 deletions
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index 4a74b6e..39a8706 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -141,7 +141,7 @@ void MaybeEnableDirectWriteFontRendering() {
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&factory))));
SetDefaultSkiaFactory(SkFontMgr_New_DirectWrite(factory));
- gfx::PlatformFontWin::set_use_skia_for_font_metrics(true);
+ gfx::PlatformFontWin::SetDirectWriteFactory(factory);
}
}
diff --git a/ui/gfx/platform_font_win.cc b/ui/gfx/platform_font_win.cc
index 40fa24f..58876dd 100644
--- a/ui/gfx/platform_font_win.cc
+++ b/ui/gfx/platform_font_win.cc
@@ -4,11 +4,10 @@
#include "ui/gfx/platform_font_win.h"
-#include <windows.h>
-#include <math.h>
-
#include <algorithm>
-#include <string>
+#include <dwrite.h>
+#include <math.h>
+#include <windows.h>
#include "base/logging.h"
#include "base/macros.h"
@@ -79,11 +78,11 @@ PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_;
// static
PlatformFontWin::AdjustFontCallback
- PlatformFontWin::adjust_font_callback = NULL;
+ PlatformFontWin::adjust_font_callback = nullptr;
PlatformFontWin::GetMinimumFontSizeCallback
PlatformFontWin::get_minimum_font_size_callback = NULL;
-bool PlatformFontWin::use_skia_for_font_metrics_ = false;
+IDWriteFactory* PlatformFontWin::direct_write_factory_ = NULL;
////////////////////////////////////////////////////////////////////////////////
// PlatformFontWin, public
@@ -207,6 +206,13 @@ NativeFont PlatformFontWin::GetNativeFont() const {
return font_ref_->hfont();
}
+void PlatformFontWin::SetDirectWriteFactory(IDWriteFactory* factory) {
+ // We grab a reference on the DirectWrite factory. This reference is
+ // leaked, which is ok because skia leaks it as well.
+ factory->AddRef();
+ direct_write_factory_ = factory;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Font, private:
@@ -249,11 +255,11 @@ PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
}
PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
- TEXTMETRIC font_metrics;
-
- if (use_skia_for_font_metrics_)
+ if (direct_write_factory_)
return CreateHFontRefFromSkia(font);
+ TEXTMETRIC font_metrics;
+
{
base::win::ScopedGetDC screen_dc(NULL);
gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT);
@@ -322,6 +328,30 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
LOGFONT font_info = {0};
GetObject(gdi_font, sizeof(LOGFONT), &font_info);
+ // Skia does not return all values we need for font metrics. For e.g.
+ // the cap height which indicates the height of capital letters is not
+ // returned even though it is returned by DirectWrite.
+ // TODO(ananta)
+ // Fix SkScalerContext_win_dw.cpp to return all metrics we need from
+ // DirectWrite and remove the code here which retrieves metrics from
+ // DirectWrite to calculate the cap height.
+ base::win::ScopedComPtr<IDWriteGdiInterop> gdi_interop;
+ HRESULT hr = direct_write_factory_->GetGdiInterop(gdi_interop.Receive());
+ if (FAILED(hr)) {
+ CHECK(false);
+ return NULL;
+ }
+
+ base::win::ScopedComPtr<IDWriteFont> dwrite_font;
+ hr = gdi_interop->CreateFontFromLOGFONT(&font_info, dwrite_font.Receive());
+ if (FAILED(hr)) {
+ CHECK(false);
+ return NULL;
+ }
+
+ DWRITE_FONT_METRICS dwrite_font_metrics = {0};
+ dwrite_font->GetMetrics(&dwrite_font_metrics);
+
int skia_style = SkTypeface::kNormal;
if (font_info.lfWeight >= FW_SEMIBOLD &&
font_info.lfWeight <= FW_ULTRABOLD) {
@@ -346,12 +376,11 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
// The calculations below are similar to those in the CreateHFontRef
// function.
- const int height =
- std::max<int>(1, std::ceil(fabs(skia_metrics.fAscent)) +
- std::ceil(skia_metrics.fDescent));
- const int baseline = std::max<int>(1, std::ceil(fabs(skia_metrics.fAscent)));
- const int cap_height = std::max<int>(1,
- std::ceil(fabs(skia_metrics.fAscent)) - skia_metrics.fLeading);
+ const int height = std::round(skia_metrics.fDescent - skia_metrics.fAscent);
+ const int baseline = std::max<int>(1, std::round(-skia_metrics.fAscent));
+ const int cap_height = std::round(-font_info.lfHeight *
+ dwrite_font_metrics.capHeight / dwrite_font_metrics.designUnitsPerEm);
+
// The metrics retrieved from skia don't have the average character width. In
// any case if we get the average character width from skia then use that or
// use the text extent technique as documented by microsoft. See
@@ -360,7 +389,12 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
skia_metrics.fAvgCharWidth == 0 ?
HFontRef::GetAverageCharWidthInDialogUnits(gdi_font)
: skia_metrics.fAvgCharWidth;
- const int font_size = std::max<int>(1, height - skia_metrics.fLeading);
+
+ // tmAscent - tmInternalLeading in gdi font land gives us the cap height.
+ // We can use fAscent - cap_height in DirectWrite land to get the internal
+ // leading value.
+ const int internal_leading = -skia_metrics.fAscent - cap_height;
+ const int font_size = std::max<int>(1, height - internal_leading);
int style = 0;
if (skia_style & SkTypeface::kItalic)
diff --git a/ui/gfx/platform_font_win.h b/ui/gfx/platform_font_win.h
index 483dc89..f327978 100644
--- a/ui/gfx/platform_font_win.h
+++ b/ui/gfx/platform_font_win.h
@@ -13,6 +13,8 @@
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/platform_font.h"
+__interface IDWriteFactory;
+
namespace gfx {
class GFX_EXPORT PlatformFontWin : public PlatformFont {
@@ -67,11 +69,9 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
virtual const FontRenderParams& GetFontRenderParams() const override;
virtual NativeFont GetNativeFont() const override;
- // Called once during initialization if should be retrieving font metrics
- // from skia.
- static void set_use_skia_for_font_metrics(bool use_skia_for_font_metrics) {
- use_skia_for_font_metrics_ = use_skia_for_font_metrics;
- }
+ // Called once during initialization if we should be retrieving font metrics
+ // from skia and DirectWrite.
+ static void SetDirectWriteFactory(IDWriteFactory* factory);
private:
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback);
@@ -168,8 +168,8 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Creates and returns a new HFontRef from the specified HFONT using metrics
// from skia. Currently this is only used if we use DirectWrite for font
// metrics.
- static PlatformFontWin::HFontRef* CreateHFontRefFromSkia(
- HFONT gdi_font);
+ // |gdi_font| : Handle to the GDI font created via CreateFontIndirect.
+ static PlatformFontWin::HFontRef* CreateHFontRefFromSkia(HFONT gdi_font);
// Creates a new PlatformFontWin with the specified HFontRef. Used when
// constructing a Font from a HFONT we don't want to copy.
@@ -181,9 +181,8 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Indirect reference to the HFontRef, which references the underlying HFONT.
scoped_refptr<HFontRef> font_ref_;
- // Set to true if font metrics are to be retrieved from skia. Defaults to
- // false.
- static bool use_skia_for_font_metrics_;
+ // Pointer to the global IDWriteFactory interface.
+ static IDWriteFactory* direct_write_factory_;
DISALLOW_COPY_AND_ASSIGN(PlatformFontWin);
};