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 <algorithm> 8 9 #include "base/command_line.h" 10 #include "base/logging.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/stringprintf.h" 13 #include "ui/gfx/insets.h" 14 #include "ui/gfx/point_conversions.h" 15 #include "ui/gfx/point_f.h" 16 #include "ui/gfx/size_conversions.h" 17 #include "ui/gfx/switches.h" 18 19 namespace gfx { 20 namespace { 21 22 bool HasForceDeviceScaleFactorImpl() { 23 return CommandLine::ForCurrentProcess()->HasSwitch( 24 switches::kForceDeviceScaleFactor); 25 } 26 27 float GetForcedDeviceScaleFactorImpl() { 28 double scale_in_double = 1.0; 29 if (HasForceDeviceScaleFactorImpl()) { 30 std::string value = CommandLine::ForCurrentProcess()-> 31 GetSwitchValueASCII(switches::kForceDeviceScaleFactor); 32 if (!base::StringToDouble(value, &scale_in_double)) 33 LOG(ERROR) << "Failed to parse the default device scale factor:" << value; 34 } 35 return static_cast<float>(scale_in_double); 36 } 37 38 int64 internal_display_id_ = -1; 39 40 } // namespace 41 42 const int64 Display::kInvalidDisplayID = -1; 43 44 // static 45 float Display::GetForcedDeviceScaleFactor() { 46 static const float kForcedDeviceScaleFactor = 47 GetForcedDeviceScaleFactorImpl(); 48 return kForcedDeviceScaleFactor; 49 } 50 51 //static 52 bool Display::HasForceDeviceScaleFactor() { 53 static const bool kHasForceDeviceScaleFactor = 54 HasForceDeviceScaleFactorImpl(); 55 return kHasForceDeviceScaleFactor; 56 } 57 58 Display::Display() 59 : id_(kInvalidDisplayID), 60 device_scale_factor_(GetForcedDeviceScaleFactor()), 61 rotation_(ROTATE_0), 62 touch_support_(TOUCH_SUPPORT_UNKNOWN) { 63 } 64 65 Display::Display(int64 id) 66 : id_(id), 67 device_scale_factor_(GetForcedDeviceScaleFactor()), 68 rotation_(ROTATE_0), 69 touch_support_(TOUCH_SUPPORT_UNKNOWN) { 70 } 71 72 Display::Display(int64 id, const gfx::Rect& bounds) 73 : id_(id), 74 bounds_(bounds), 75 work_area_(bounds), 76 device_scale_factor_(GetForcedDeviceScaleFactor()), 77 rotation_(ROTATE_0), 78 touch_support_(TOUCH_SUPPORT_UNKNOWN) { 79 #if defined(USE_AURA) 80 SetScaleAndBounds(device_scale_factor_, bounds); 81 #endif 82 } 83 84 Display::~Display() { 85 } 86 87 int Display::RotationAsDegree() const { 88 switch (rotation_) { 89 case ROTATE_0: 90 return 0; 91 case ROTATE_90: 92 return 90; 93 case ROTATE_180: 94 return 180; 95 case ROTATE_270: 96 return 270; 97 } 98 99 NOTREACHED(); 100 return 0; 101 } 102 103 void Display::SetRotationAsDegree(int rotation) { 104 switch (rotation) { 105 case 0: 106 rotation_ = ROTATE_0; 107 break; 108 case 90: 109 rotation_ = ROTATE_90; 110 break; 111 case 180: 112 rotation_ = ROTATE_180; 113 break; 114 case 270: 115 rotation_ = ROTATE_270; 116 break; 117 default: 118 // We should not reach that but we will just ignore the call if we do. 119 NOTREACHED(); 120 } 121 } 122 123 Insets Display::GetWorkAreaInsets() const { 124 return gfx::Insets(work_area_.y() - bounds_.y(), 125 work_area_.x() - bounds_.x(), 126 bounds_.bottom() - work_area_.bottom(), 127 bounds_.right() - work_area_.right()); 128 } 129 130 void Display::SetScaleAndBounds( 131 float device_scale_factor, 132 const gfx::Rect& bounds_in_pixel) { 133 Insets insets = bounds_.InsetsFrom(work_area_); 134 if (!HasForceDeviceScaleFactor()) { 135 #if defined(OS_MACOSX) 136 // Unless an explicit scale factor was provided for testing, ensure the 137 // scale is integral. 138 device_scale_factor = static_cast<int>(device_scale_factor); 139 #endif 140 device_scale_factor_ = device_scale_factor; 141 } 142 device_scale_factor_ = std::max(1.0f, device_scale_factor_); 143 bounds_ = gfx::Rect( 144 gfx::ToFlooredPoint(gfx::ScalePoint(bounds_in_pixel.origin(), 145 1.0f / device_scale_factor_)), 146 gfx::ToFlooredSize(gfx::ScaleSize(bounds_in_pixel.size(), 147 1.0f / device_scale_factor_))); 148 UpdateWorkAreaFromInsets(insets); 149 } 150 151 void Display::SetSize(const gfx::Size& size_in_pixel) { 152 gfx::Point origin = bounds_.origin(); 153 #if defined(USE_AURA) 154 gfx::PointF origin_f = origin; 155 origin_f.Scale(device_scale_factor_); 156 origin.SetPoint(origin_f.x(), origin_f.y()); 157 #endif 158 SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel)); 159 } 160 161 void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) { 162 work_area_ = bounds_; 163 work_area_.Inset(insets); 164 } 165 166 gfx::Size Display::GetSizeInPixel() const { 167 return gfx::ToFlooredSize(gfx::ScaleSize(size(), device_scale_factor_)); 168 } 169 170 std::string Display::ToString() const { 171 return base::StringPrintf( 172 "Display[%lld] bounds=%s, workarea=%s, scale=%f, %s", 173 static_cast<long long int>(id_), 174 bounds_.ToString().c_str(), 175 work_area_.ToString().c_str(), 176 device_scale_factor_, 177 IsInternal() ? "internal" : "external"); 178 } 179 180 bool Display::IsInternal() const { 181 return is_valid() && (id_ == internal_display_id_); 182 } 183 184 int64 Display::InternalDisplayId() { 185 return internal_display_id_; 186 } 187 188 void Display::SetInternalDisplayId(int64 internal_display_id) { 189 internal_display_id_ = internal_display_id; 190 } 191 192 } // namespace gfx 193