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.
4
5#include "ui/gfx/display.h"
6
7#include "base/command_line.h"
8#include "base/logging.h"
9#include "base/strings/string_number_conversions.h"
10#include "base/strings/stringprintf.h"
11#include "ui/base/ui_base_switches.h"
12#include "ui/gfx/insets.h"
13#include "ui/gfx/point_conversions.h"
14#include "ui/gfx/point_f.h"
15#include "ui/gfx/size_conversions.h"
16
17namespace gfx {
18namespace {
19
20bool HasForceDeviceScaleFactorImpl() {
21  return CommandLine::ForCurrentProcess()->HasSwitch(
22      switches::kForceDeviceScaleFactor);
23}
24
25float GetForcedDeviceScaleFactorImpl() {
26  double scale_in_double = 1.0;
27  if (HasForceDeviceScaleFactorImpl()) {
28    std::string value = CommandLine::ForCurrentProcess()->
29        GetSwitchValueASCII(switches::kForceDeviceScaleFactor);
30    if (!base::StringToDouble(value, &scale_in_double))
31      LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
32  }
33  return static_cast<float>(scale_in_double);
34}
35
36const int64 kInvalidDisplayIDForCompileTimeInit = -1;
37int64 internal_display_id_ = kInvalidDisplayIDForCompileTimeInit;
38
39}  // namespace
40
41const int64 Display::kInvalidDisplayID = kInvalidDisplayIDForCompileTimeInit;
42
43// static
44float Display::GetForcedDeviceScaleFactor() {
45  static const float kForcedDeviceScaleFactor =
46      GetForcedDeviceScaleFactorImpl();
47  return kForcedDeviceScaleFactor;
48}
49
50//static
51bool Display::HasForceDeviceScaleFactor() {
52  return HasForceDeviceScaleFactorImpl();
53}
54
55Display::Display()
56    : id_(kInvalidDisplayID),
57      device_scale_factor_(GetForcedDeviceScaleFactor()),
58      rotation_(ROTATE_0) {
59}
60
61Display::Display(int64 id)
62    : id_(id),
63      device_scale_factor_(GetForcedDeviceScaleFactor()),
64      rotation_(ROTATE_0) {
65}
66
67Display::Display(int64 id, const gfx::Rect& bounds)
68    : id_(id),
69      bounds_(bounds),
70      work_area_(bounds),
71      device_scale_factor_(GetForcedDeviceScaleFactor()),
72      rotation_(ROTATE_0) {
73#if defined(USE_AURA)
74  SetScaleAndBounds(device_scale_factor_, bounds);
75#endif
76}
77
78Display::~Display() {
79}
80
81Insets Display::GetWorkAreaInsets() const {
82  return gfx::Insets(work_area_.y() - bounds_.y(),
83                     work_area_.x() - bounds_.x(),
84                     bounds_.bottom() - work_area_.bottom(),
85                     bounds_.right() - work_area_.right());
86}
87
88void Display::SetScaleAndBounds(
89    float device_scale_factor,
90    const gfx::Rect& bounds_in_pixel) {
91  Insets insets = bounds_.InsetsFrom(work_area_);
92  if (!HasForceDeviceScaleFactor()) {
93#if defined(OS_MACOSX)
94    // Unless an explicit scale factor was provided for testing, ensure the
95    // scale is integral.
96    device_scale_factor = static_cast<int>(device_scale_factor);
97#endif
98    device_scale_factor_ = device_scale_factor;
99  }
100  device_scale_factor_ = std::max(1.0f, device_scale_factor_);
101  bounds_ = gfx::Rect(
102      gfx::ToFlooredPoint(gfx::ScalePoint(bounds_in_pixel.origin(),
103                                          1.0f / device_scale_factor_)),
104      gfx::ToFlooredSize(gfx::ScaleSize(bounds_in_pixel.size(),
105                                        1.0f / device_scale_factor_)));
106  UpdateWorkAreaFromInsets(insets);
107}
108
109void Display::SetSize(const gfx::Size& size_in_pixel) {
110  gfx::Point origin = bounds_.origin();
111#if defined(USE_AURA)
112  gfx::PointF origin_f = origin;
113  origin_f.Scale(device_scale_factor_);
114  origin.SetPoint(origin_f.x(), origin_f.y());
115#endif
116  SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel));
117}
118
119void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) {
120  work_area_ = bounds_;
121  work_area_.Inset(insets);
122}
123
124gfx::Size Display::GetSizeInPixel() const {
125  return gfx::ToFlooredSize(gfx::ScaleSize(size(), device_scale_factor_));
126}
127
128std::string Display::ToString() const {
129  return base::StringPrintf(
130      "Display[%lld] bounds=%s, workarea=%s, scale=%f, %s",
131      static_cast<long long int>(id_),
132      bounds_.ToString().c_str(),
133      work_area_.ToString().c_str(),
134      device_scale_factor_,
135      IsInternal() ? "internal" : "external");
136}
137
138bool Display::IsInternal() const {
139  return is_valid() && (id_ == internal_display_id_);
140}
141
142int64 Display::InternalDisplayId() {
143  return internal_display_id_;
144}
145
146void Display::SetInternalDisplayId(int64 internal_display_id) {
147  internal_display_id_ = internal_display_id;
148}
149
150}  // namespace gfx
151