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"
16 int kDefaultDPIX
= 96;
17 int kDefaultDPIY
= 96;
19 bool force_highdpi_for_testing
= false;
21 float g_device_scale_factor
= 0.0f
;
23 float GetUnforcedDeviceScaleFactor() {
24 // If the global device scale factor is initialized use it. This is to ensure
25 // we use the same scale factor across all callsites.
26 if (g_device_scale_factor
)
27 return g_device_scale_factor
;
28 return static_cast<float>(gfx::GetDPI().width()) /
29 static_cast<float>(kDefaultDPIX
);
36 void InitDeviceScaleFactor(float scale
) {
37 DCHECK_NE(0.0f
, scale
);
38 g_device_scale_factor
= scale
;
44 static bool should_initialize
= true;
46 if (should_initialize
) {
47 should_initialize
= false;
48 base::win::ScopedGetDC
screen_dc(NULL
);
49 // This value is safe to cache for the life time of the app since the
50 // user must logout to change the DPI setting. This value also applies
52 dpi_x
= GetDeviceCaps(screen_dc
, LOGPIXELSX
);
53 dpi_y
= GetDeviceCaps(screen_dc
, LOGPIXELSY
);
55 return Size(dpi_x
, dpi_y
);
59 if (gfx::Display::HasForceDeviceScaleFactor())
60 return gfx::Display::GetForcedDeviceScaleFactor();
61 float dpi_scale
= GetUnforcedDeviceScaleFactor();
62 if (dpi_scale
<= 1.25) {
63 // Force 125% and below to 100% scale. We do this to maintain previous
64 // (non-DPI-aware) behavior where only the font size was boosted.
72 Point
ScreenToDIPPoint(const Point
& pixel_point
) {
73 return ToFlooredPoint(ScalePoint(pixel_point
, 1.0f
/ GetDPIScale()));
76 Point
DIPToScreenPoint(const Point
& dip_point
) {
77 return ToFlooredPoint(ScalePoint(dip_point
, GetDPIScale()));
80 Rect
ScreenToDIPRect(const Rect
& pixel_bounds
) {
81 // It's important we scale the origin and size separately. If we instead
82 // calculated the size from the floored origin and ceiled right the size could
83 // vary depending upon where the two points land. That would cause problems
84 // for the places this code is used (in particular mapping from native window
86 return Rect(ScreenToDIPPoint(pixel_bounds
.origin()),
87 ScreenToDIPSize(pixel_bounds
.size()));
90 Rect
DIPToScreenRect(const Rect
& dip_bounds
) {
91 // See comment in ScreenToDIPRect for why we calculate size like this.
92 return Rect(DIPToScreenPoint(dip_bounds
.origin()),
93 DIPToScreenSize(dip_bounds
.size()));
96 Size
ScreenToDIPSize(const Size
& size_in_pixels
) {
97 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
98 return ToCeiledSize(ScaleSize(size_in_pixels
, 1.0f
/ GetDPIScale()));
101 Size
DIPToScreenSize(const Size
& dip_size
) {
102 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
103 return ToCeiledSize(ScaleSize(dip_size
, GetDPIScale()));
106 int GetSystemMetricsInDIP(int metric
) {
107 return static_cast<int>(GetSystemMetrics(metric
) / GetDPIScale() + 0.5);