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
3 // found in the LICENSE file.
5 #include "ui/gfx/win/dpi.h"
8 #include "base/win/scoped_hdc.h"
9 #include "ui/gfx/display.h"
10 #include "ui/gfx/geometry/point_conversions.h"
11 #include "ui/gfx/geometry/rect_conversions.h"
12 #include "ui/gfx/geometry/size_conversions.h"
18 float g_device_scale_factor
= 0.0f
;
20 float GetUnforcedDeviceScaleFactor() {
21 // If the global device scale factor is initialized use it. This is to ensure
22 // we use the same scale factor across all callsites.
23 if (g_device_scale_factor
)
24 return g_device_scale_factor
;
25 return static_cast<float>(gfx::GetDPI().width()) /
26 static_cast<float>(kDefaultDPI
);
33 void InitDeviceScaleFactor(float scale
) {
34 DCHECK_NE(0.0f
, scale
);
35 g_device_scale_factor
= scale
;
41 static bool should_initialize
= true;
43 if (should_initialize
) {
44 should_initialize
= false;
45 base::win::ScopedGetDC
screen_dc(NULL
);
46 // This value is safe to cache for the life time of the app since the
47 // user must logout to change the DPI setting. This value also applies
49 dpi_x
= GetDeviceCaps(screen_dc
, LOGPIXELSX
);
50 dpi_y
= GetDeviceCaps(screen_dc
, LOGPIXELSY
);
52 return Size(dpi_x
, dpi_y
);
56 if (gfx::Display::HasForceDeviceScaleFactor())
57 return gfx::Display::GetForcedDeviceScaleFactor();
58 float dpi_scale
= GetUnforcedDeviceScaleFactor();
59 if (dpi_scale
<= 1.25) {
60 // Force 125% and below to 100% scale. We do this to maintain previous
61 // (non-DPI-aware) behavior where only the font size was boosted.
69 Point
ScreenToDIPPoint(const Point
& pixel_point
) {
70 return ToFlooredPoint(ScalePoint(pixel_point
, 1.0f
/ GetDPIScale()));
73 Point
DIPToScreenPoint(const Point
& dip_point
) {
74 return ToFlooredPoint(ScalePoint(dip_point
, GetDPIScale()));
77 Rect
ScreenToDIPRect(const Rect
& pixel_bounds
) {
78 // It's important we scale the origin and size separately. If we instead
79 // calculated the size from the floored origin and ceiled right the size could
80 // vary depending upon where the two points land. That would cause problems
81 // for the places this code is used (in particular mapping from native window
83 return Rect(ScreenToDIPPoint(pixel_bounds
.origin()),
84 ScreenToDIPSize(pixel_bounds
.size()));
87 Rect
DIPToScreenRect(const Rect
& dip_bounds
) {
88 // See comment in ScreenToDIPRect for why we calculate size like this.
89 return Rect(DIPToScreenPoint(dip_bounds
.origin()),
90 DIPToScreenSize(dip_bounds
.size()));
93 Size
ScreenToDIPSize(const Size
& size_in_pixels
) {
94 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
95 return ToCeiledSize(ScaleSize(size_in_pixels
, 1.0f
/ GetDPIScale()));
98 Size
DIPToScreenSize(const Size
& dip_size
) {
99 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
100 return ToCeiledSize(ScaleSize(dip_size
, GetDPIScale()));
103 int GetSystemMetricsInDIP(int metric
) {
104 return static_cast<int>(GetSystemMetrics(metric
) / GetDPIScale() + 0.5);