Commit f2d0aaeb authored by ananta's avatar ananta Committed by Commit bot

Retrieve font metrics from skia if DirectWrite is enabled for font metrics...

Retrieve font metrics from skia if DirectWrite is enabled for font metrics calculations in the chrome browser UI.

The previous patch for getting the correct font metrics from DirectWrite https://codereview.chromium.org/692633003/
was wrong as it did not return the correct font metrics in all cases.

Getting the metrics from skia ensures that we get the same font metrics which would be used by skia for rendering.

Changes in this patch are as below:-
1. Removed DirectWrite factory code from PlatformFontWin. The PlatformFontWin::ConvertGDIFontToDirectWriteFont
   function has been replaced by the CreateHFontRefFromSkia function. This function is called if DirectWrite is
   enabled in the browser which sets a static bool on the PlatformFontWin class.

BUG=428645,427804,427802

Review URL: https://codereview.chromium.org/696913002

Cr-Commit-Position: refs/heads/master@{#302547}
parent fe89e5a5
......@@ -20,6 +20,7 @@
#include "ui/base/ime/input_method_initializer.h"
#if defined(OS_WIN)
#include <dwrite.h>
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "net/cert/sha256_legacy_support_win.h"
......@@ -140,7 +141,7 @@ void MaybeEnableDirectWriteFontRendering() {
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&factory))));
SetDefaultSkiaFactory(SkFontMgr_New_DirectWrite(factory));
gfx::PlatformFontWin::set_direct_write_factory(factory);
gfx::PlatformFontWin::set_use_skia_for_font_metrics(true);
}
}
......
......@@ -20,6 +20,7 @@
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "base/win/win_util.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_render_params.h"
......@@ -82,7 +83,7 @@ PlatformFontWin::AdjustFontCallback
PlatformFontWin::GetMinimumFontSizeCallback
PlatformFontWin::get_minimum_font_size_callback = NULL;
IDWriteFactory* PlatformFontWin::direct_write_factory_ = NULL;
bool PlatformFontWin::use_skia_for_font_metrics_ = false;
////////////////////////////////////////////////////////////////////////////////
// PlatformFontWin, public
......@@ -250,10 +251,8 @@ PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
TEXTMETRIC font_metrics;
if (direct_write_factory_) {
base::win::ScopedGDIObject<HFONT> gdi_font(font);
font = ConvertGDIFontToDirectWriteFont(gdi_font);
}
if (use_skia_for_font_metrics_)
return CreateHFontRefFromSkia(font);
{
base::win::ScopedGetDC screen_dc(NULL);
......@@ -318,40 +317,52 @@ Font PlatformFontWin::DeriveWithCorrectedSize(HFONT base_font) {
}
// static
HFONT PlatformFontWin::ConvertGDIFontToDirectWriteFont(HFONT gdi_font) {
// This function uses the DirectWrite Gdi interop interfaces to convert the
// gdi font passed in to a HFONT which is compatible with DirectWrite font
// metrics which could be different from GDI font metrics. This ensures that
// widgets like labels which use font metrics to calculate bounds have the
// same calculations as skia which uses DirectWrite.
DCHECK(direct_write_factory_);
base::win::ScopedComPtr<IDWriteGdiInterop> gdi_interop;
HRESULT hr = direct_write_factory_->GetGdiInterop(gdi_interop.Receive());
if (FAILED(hr)) {
CHECK(false);
return NULL;
}
base::win::ScopedGetDC screen_dc(NULL);
gfx::ScopedSetMapMode mode(screen_dc, MM_TEXT);
base::win::ScopedSelectObject scoped_font(screen_dc, gdi_font);
base::win::ScopedComPtr<IDWriteFontFace> font_face_gdi;
hr = gdi_interop->CreateFontFaceFromHdc(screen_dc, font_face_gdi.Receive());
if (FAILED(hr)) {
CHECK(false);
return NULL;
PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
HFONT gdi_font) {
LOGFONT font_info = {0};
GetObject(gdi_font, sizeof(LOGFONT), &font_info);
int skia_style = SkTypeface::kNormal;
if (font_info.lfWeight >= FW_SEMIBOLD &&
font_info.lfWeight <= FW_ULTRABOLD) {
skia_style |= SkTypeface::kBold;
}
if (font_info.lfItalic)
skia_style |= SkTypeface::kItalic;
skia::RefPtr<SkTypeface> skia_face = skia::AdoptRef(
SkTypeface::CreateFromName(
base::SysWideToUTF8(font_info.lfFaceName).c_str(),
static_cast<SkTypeface::Style>(skia_style)));
BOOL antialiasing = TRUE;
SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &antialiasing, 0);
SkPaint paint;
paint.setAntiAlias(!!antialiasing);
paint.setTypeface(skia_face.get());
SkPaint::FontMetrics skia_metrics;
paint.getFontMetrics(&skia_metrics);
// 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 ave_char_width = std::max<int>(1, skia_metrics.fAvgCharWidth);
const int font_size = std::max<int>(1, height - skia_metrics.fLeading);
LOGFONT dwrite_to_gdi_log_font = {0};
hr = gdi_interop->ConvertFontFaceToLOGFONT(font_face_gdi,
&dwrite_to_gdi_log_font);
if (FAILED(hr)) {
CHECK(false);
return NULL;
}
return CreateFontIndirect(&dwrite_to_gdi_log_font);
int style = 0;
if (skia_style & SkTypeface::kItalic)
style |= Font::ITALIC;
if (font_info.lfUnderline)
style |= Font::UNDERLINE;
if (font_info.lfWeight >= kTextMetricWeightBold)
style |= Font::BOLD;
return new HFontRef(gdi_font, font_size, height, baseline, cap_height,
ave_char_width, style);
}
PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
......
......@@ -5,7 +5,6 @@
#ifndef UI_GFX_PLATFORM_FONT_WIN_H_
#define UI_GFX_PLATFORM_FONT_WIN_H_
#include <dwrite.h>
#include <string>
#include "base/compiler_specific.h"
......@@ -68,9 +67,10 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
virtual const FontRenderParams& GetFontRenderParams() const override;
virtual NativeFont GetNativeFont() const override;
// Called once during initialization if we are using DirectWrite for fonts.
static void set_direct_write_factory(IDWriteFactory* factory) {
direct_write_factory_ = factory;
// 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;
}
private:
......@@ -150,10 +150,10 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// UI thread.
static HFontRef* GetBaseFontRef();
// Creates and returns a new HFONTRef from the specified HFONT.
// Creates and returns a new HFontRef from the specified HFONT.
static HFontRef* CreateHFontRef(HFONT font);
// Creates and returns a new HFONTRef from the specified HFONT. Uses provided
// Creates and returns a new HFontRef from the specified HFONT. Uses provided
// |font_metrics| instead of calculating new one.
static HFontRef* CreateHFontRef(HFONT font, const TEXTMETRIC& font_metrics);
......@@ -161,12 +161,11 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// |base_font|.
static Font DeriveWithCorrectedSize(HFONT base_font);
// Converts the GDI font identified by the |gdi_font| parameter to a
// DirectWrite compatible HFONT, i.e with metrics compatible with
// DirectWrite.
// Returns the HFONT which is created from DirectWrite compatible font
// 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 HFONT ConvertGDIFontToDirectWriteFont(HFONT gdi_font);
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.
......@@ -178,9 +177,9 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Indirect reference to the HFontRef, which references the underlying HFONT.
scoped_refptr<HFontRef> font_ref_;
// Pointer to the global IDWriteFactory interface. This is only set if we are
// using DirectWrite for fonts. Defaults to NULL.
static IDWriteFactory* direct_write_factory_;
// Set to true if font metrics are to be retrieved from skia. Defaults to
// false.
static bool use_skia_for_font_metrics_;
DISALLOW_COPY_AND_ASSIGN(PlatformFontWin);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment