OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/display/fake_display_snapshot.h" | 5 #include "ui/display/fake_display_snapshot.h" |
6 | 6 |
7 #include <inttypes.h> | 7 #include <inttypes.h> |
8 | 8 |
9 #include <sstream> | 9 #include <sstream> |
10 #include <utility> | 10 #include <utility> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/string_split.h" |
14 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "third_party/re2/src/re2/re2.h" |
| 18 |
| 19 using base::StringPiece; |
15 | 20 |
16 namespace display { | 21 namespace display { |
17 | 22 |
18 namespace { | 23 namespace { |
19 | 24 |
20 static const float kInchInMm = 25.4f; | 25 static const float kInchInMm = 25.4f; |
21 | 26 |
22 // Get pixel pitch in millimeters from DPI. | 27 // Get pixel pitch in millimeters from DPI. |
23 float PixelPitchMmFromDPI(float dpi) { | 28 float PixelPitchMmFromDPI(float dpi) { |
24 return (1.0f / dpi) * kInchInMm; | 29 return (1.0f / dpi) * kInchInMm; |
(...skipping 30 matching lines...) Expand all Loading... |
55 return "dp"; | 60 return "dp"; |
56 case ui::DISPLAY_CONNECTION_TYPE_NETWORK: | 61 case ui::DISPLAY_CONNECTION_TYPE_NETWORK: |
57 return "network"; | 62 return "network"; |
58 case ui::DISPLAY_CONNECTION_TYPE_VIRTUAL: | 63 case ui::DISPLAY_CONNECTION_TYPE_VIRTUAL: |
59 return "virtual"; | 64 return "virtual"; |
60 } | 65 } |
61 NOTREACHED(); | 66 NOTREACHED(); |
62 return ""; | 67 return ""; |
63 } | 68 } |
64 | 69 |
| 70 // Extracts text after specified delimiter. If the delimiter doesn't appear |
| 71 // exactly once the result will be empty and the input string will be |
| 72 // unmodified. Otherwise, the input string will contain the text before the |
| 73 // delimiter and the result will be the text after the delimiter. |
| 74 StringPiece ExtractSuffix(StringPiece* str, StringPiece delimiter) { |
| 75 std::vector<StringPiece> parts = base::SplitStringPiece( |
| 76 *str, delimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 77 |
| 78 if (parts.size() == 2) { |
| 79 *str = parts[0]; |
| 80 return parts[1]; |
| 81 } |
| 82 |
| 83 return StringPiece(); |
| 84 } |
| 85 |
| 86 // Parses a display mode from |str| in the format HxW[%R], returning null if |
| 87 // |str| is invalid. |
| 88 std::unique_ptr<ui::DisplayMode> ParseDisplayMode(const std::string& str) { |
| 89 int width = 0; |
| 90 int height = 0; |
| 91 std::string refresh_rate_str; |
| 92 |
| 93 // Check against regex and extract values. |
| 94 if (!RE2::FullMatch(str, "(\\d+)x(\\d+)(?:%(\\d+\\.?\\d*))?", &width, &height, |
| 95 &refresh_rate_str)) { |
| 96 LOG(ERROR) << "Invalid display mode string \"" << str << "\""; |
| 97 return nullptr; |
| 98 } |
| 99 |
| 100 // Refresh rate is optional and will be be 60 if not specified. |
| 101 double refresh_rate = 60.0f; |
| 102 if (!refresh_rate_str.empty() && |
| 103 !base::StringToDouble(refresh_rate_str, &refresh_rate)) { |
| 104 LOG(ERROR) << "Unable to parse display mode \"" << str << "\""; |
| 105 return nullptr; |
| 106 } |
| 107 |
| 108 return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), false, |
| 109 static_cast<float>(refresh_rate)); |
| 110 } |
| 111 |
| 112 // Parses a list of alternate display modes, adding each new display mode to |
| 113 // |builder|. Returns false if any of the modes are invalid. |
| 114 bool HandleModes(FakeDisplaySnapshot::Builder* builder, |
| 115 StringPiece resolutions) { |
| 116 for (const std::string& mode_str : |
| 117 base::SplitString(resolutions, ":", base::TRIM_WHITESPACE, |
| 118 base::SPLIT_WANT_NONEMPTY)) { |
| 119 std::unique_ptr<ui::DisplayMode> mode = ParseDisplayMode(mode_str); |
| 120 if (!mode) |
| 121 return false; |
| 122 |
| 123 builder->AddMode(std::move(mode)); |
| 124 } |
| 125 |
| 126 return true; |
| 127 } |
| 128 |
| 129 // Parses device DPI and updates |builder|. Returns false if an invalid DPI |
| 130 // string is provided. |
| 131 bool HandleDPI(FakeDisplaySnapshot::Builder* builder, StringPiece dpi) { |
| 132 if (dpi.empty()) |
| 133 return true; |
| 134 |
| 135 int dpi_value = 0; |
| 136 if (base::StringToInt(dpi, &dpi_value)) { |
| 137 builder->SetDPI(dpi_value); |
| 138 return true; |
| 139 } |
| 140 |
| 141 LOG(ERROR) << "Invalid DPI string \"" << dpi << "\""; |
| 142 return false; |
| 143 } |
| 144 |
| 145 // Parses a list of display options and set each option true on |builder|. |
| 146 // Returns false if any invalid options are provided. If an option appears more |
| 147 // than once it will have no effect the second time. |
| 148 bool HandleOptions(FakeDisplaySnapshot::Builder* builder, StringPiece options) { |
| 149 for (size_t i = 0; i < options.size(); ++i) { |
| 150 switch (options[i]) { |
| 151 case 'o': |
| 152 builder->SetHasOverscan(true); |
| 153 break; |
| 154 case 'c': |
| 155 builder->SetHasColorCorrectionMatrix(true); |
| 156 break; |
| 157 case 'a': |
| 158 builder->SetIsAspectPerservingScaling(true); |
| 159 break; |
| 160 case 'i': |
| 161 builder->SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL); |
| 162 break; |
| 163 default: |
| 164 LOG(ERROR) << "Invalid option specifier \"" << options[i] << "\""; |
| 165 return false; |
| 166 } |
| 167 } |
| 168 |
| 169 return true; |
| 170 } |
| 171 |
65 } // namespace | 172 } // namespace |
66 | 173 |
67 using Builder = FakeDisplaySnapshot::Builder; | 174 using Builder = FakeDisplaySnapshot::Builder; |
68 | 175 |
69 Builder::Builder() {} | 176 Builder::Builder() {} |
70 | 177 |
71 Builder::~Builder() {} | 178 Builder::~Builder() {} |
72 | 179 |
73 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() { | 180 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() { |
74 if (modes_.empty() || id_ == Display::kInvalidDisplayID) { | 181 if (modes_.empty() || id_ == Display::kInvalidDisplayID) { |
75 NOTREACHED() << "Display modes or display ID missing"; | 182 NOTREACHED() << "Display modes or display ID missing"; |
76 return nullptr; | 183 return nullptr; |
77 } | 184 } |
78 | 185 |
79 // If there is no native mode set, use the first display mode. | 186 // If there is no native mode set, use the first display mode. |
80 if (!native_mode_) | 187 if (!native_mode_) |
81 native_mode_ = modes_.back().get(); | 188 native_mode_ = modes_.back().get(); |
82 | 189 |
83 // Calculate physical size to match set DPI. | 190 // Calculate physical size to match set DPI. |
84 gfx::Size physical_size = | 191 gfx::Size physical_size = |
85 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); | 192 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); |
86 | 193 |
87 return base::WrapUnique(new FakeDisplaySnapshot( | 194 return base::MakeUnique<FakeDisplaySnapshot>( |
88 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, | 195 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, |
89 has_overscan_, has_color_correction_matrix_, name_, product_id_, | 196 has_overscan_, has_color_correction_matrix_, name_, product_id_, |
90 std::move(modes_), current_mode_, native_mode_)); | 197 std::move(modes_), current_mode_, native_mode_); |
91 } | 198 } |
92 | 199 |
93 Builder& Builder::SetId(int64_t id) { | 200 Builder& Builder::SetId(int64_t id) { |
94 id_ = id; | 201 id_ = id; |
95 return *this; | 202 return *this; |
96 } | 203 } |
97 | 204 |
98 Builder& Builder::SetNativeMode(const gfx::Size& size) { | 205 Builder& Builder::SetNativeMode(const gfx::Size& size) { |
99 native_mode_ = AddOrFindDisplayMode(size); | 206 native_mode_ = AddOrFindDisplayMode(size); |
100 return *this; | 207 return *this; |
101 } | 208 } |
102 | 209 |
| 210 Builder& Builder::SetNativeMode(std::unique_ptr<ui::DisplayMode> mode) { |
| 211 native_mode_ = AddOrFindDisplayMode(std::move(mode)); |
| 212 return *this; |
| 213 } |
| 214 |
103 Builder& Builder::SetCurrentMode(const gfx::Size& size) { | 215 Builder& Builder::SetCurrentMode(const gfx::Size& size) { |
104 current_mode_ = AddOrFindDisplayMode(size); | 216 current_mode_ = AddOrFindDisplayMode(size); |
105 return *this; | 217 return *this; |
106 } | 218 } |
107 | 219 |
| 220 Builder& Builder::SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode) { |
| 221 current_mode_ = AddOrFindDisplayMode(std::move(mode)); |
| 222 return *this; |
| 223 } |
| 224 |
108 Builder& Builder::AddMode(const gfx::Size& size) { | 225 Builder& Builder::AddMode(const gfx::Size& size) { |
109 AddOrFindDisplayMode(size); | 226 AddOrFindDisplayMode(size); |
110 return *this; | 227 return *this; |
111 } | 228 } |
112 | 229 |
| 230 Builder& Builder::AddMode(std::unique_ptr<ui::DisplayMode> mode) { |
| 231 AddOrFindDisplayMode(std::move(mode)); |
| 232 return *this; |
| 233 } |
| 234 |
113 Builder& Builder::SetOrigin(const gfx::Point& origin) { | 235 Builder& Builder::SetOrigin(const gfx::Point& origin) { |
114 origin_ = origin; | 236 origin_ = origin; |
115 return *this; | 237 return *this; |
116 } | 238 } |
117 | 239 |
118 Builder& Builder::SetType(ui::DisplayConnectionType type) { | 240 Builder& Builder::SetType(ui::DisplayConnectionType type) { |
119 type_ = type; | 241 type_ = type; |
120 return *this; | 242 return *this; |
121 } | 243 } |
122 | 244 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 for (auto& mode : modes_) { | 284 for (auto& mode : modes_) { |
163 if (mode->size() == size) | 285 if (mode->size() == size) |
164 return mode.get(); | 286 return mode.get(); |
165 } | 287 } |
166 | 288 |
167 // Not found, insert a mode with the size and return. | 289 // Not found, insert a mode with the size and return. |
168 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f)); | 290 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f)); |
169 return modes_.back().get(); | 291 return modes_.back().get(); |
170 } | 292 } |
171 | 293 |
172 FakeDisplaySnapshot::FakeDisplaySnapshot( | 294 const ui::DisplayMode* Builder::AddOrFindDisplayMode( |
173 int64_t display_id, | 295 std::unique_ptr<ui::DisplayMode> mode) { |
174 const gfx::Point& origin, | 296 for (auto& existing : modes_) { |
175 const gfx::Size& physical_size, | 297 if (mode->size() == existing->size() && |
176 ui::DisplayConnectionType type, | 298 mode->is_interlaced() == existing->is_interlaced() && |
177 bool is_aspect_preserving_scaling, | 299 mode->refresh_rate() == existing->refresh_rate()) |
178 bool has_overscan, | 300 return existing.get(); |
179 bool has_color_correction_matrix, | 301 } |
180 std::string display_name, | 302 |
181 int64_t product_id, | 303 // Not found, insert mode and return. |
182 std::vector<std::unique_ptr<const ui::DisplayMode>> modes, | 304 modes_.push_back(std::move(mode)); |
183 const ui::DisplayMode* current_mode, | 305 return modes_.back().get(); |
184 const ui::DisplayMode* native_mode) | 306 } |
| 307 |
| 308 FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id, |
| 309 const gfx::Point& origin, |
| 310 const gfx::Size& physical_size, |
| 311 ui::DisplayConnectionType type, |
| 312 bool is_aspect_preserving_scaling, |
| 313 bool has_overscan, |
| 314 bool has_color_correction_matrix, |
| 315 std::string display_name, |
| 316 int64_t product_id, |
| 317 DisplayModeList modes, |
| 318 const ui::DisplayMode* current_mode, |
| 319 const ui::DisplayMode* native_mode) |
185 : DisplaySnapshot(display_id, | 320 : DisplaySnapshot(display_id, |
186 origin, | 321 origin, |
187 physical_size, | 322 physical_size, |
188 type, | 323 type, |
189 is_aspect_preserving_scaling, | 324 is_aspect_preserving_scaling, |
190 has_overscan, | 325 has_overscan, |
191 has_color_correction_matrix, | 326 has_color_correction_matrix, |
192 display_name, | 327 display_name, |
193 base::FilePath(), | 328 base::FilePath(), |
194 std::move(modes), | 329 std::move(modes), |
195 std::vector<uint8_t>(), | 330 std::vector<uint8_t>(), |
196 current_mode, | 331 current_mode, |
197 native_mode) { | 332 native_mode) { |
198 product_id_ = product_id; | 333 product_id_ = product_id; |
199 } | 334 } |
200 | 335 |
201 FakeDisplaySnapshot::~FakeDisplaySnapshot() {} | 336 FakeDisplaySnapshot::~FakeDisplaySnapshot() {} |
202 | 337 |
| 338 // static |
| 339 std::unique_ptr<ui::DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec( |
| 340 int64_t id, |
| 341 const std::string& spec) { |
| 342 StringPiece leftover(spec); |
| 343 |
| 344 // Cut off end of string at each delimiter to split. |
| 345 StringPiece options = ExtractSuffix(&leftover, "/"); |
| 346 StringPiece dpi = ExtractSuffix(&leftover, "^"); |
| 347 StringPiece resolutions = ExtractSuffix(&leftover, "#"); |
| 348 |
| 349 // Leftovers should be just the native mode at this point. |
| 350 std::unique_ptr<ui::DisplayMode> native_mode = |
| 351 ParseDisplayMode(leftover.as_string()); |
| 352 |
| 353 // Fail without valid native mode. |
| 354 if (!native_mode) |
| 355 return nullptr; |
| 356 |
| 357 FakeDisplaySnapshot::Builder builder; |
| 358 builder.SetId(id).SetNativeMode(std::move(native_mode)); |
| 359 builder.SetName(base::StringPrintf("Fake Display %" PRId64, id)); |
| 360 |
| 361 if (!HandleModes(&builder, resolutions) || !HandleDPI(&builder, dpi) || |
| 362 !HandleOptions(&builder, options)) |
| 363 return nullptr; |
| 364 |
| 365 return builder.Build(); |
| 366 } |
| 367 |
203 std::string FakeDisplaySnapshot::ToString() const { | 368 std::string FakeDisplaySnapshot::ToString() const { |
204 return base::StringPrintf( | 369 return base::StringPrintf( |
205 "id=%" PRId64 | 370 "id=%" PRId64 |
206 " current_mode=%s native_mode=%s origin=%s" | 371 " current_mode=%s native_mode=%s origin=%s" |
207 " physical_size=%s, type=%s name=\"%s\" modes=(%s)", | 372 " physical_size=%s, type=%s name=\"%s\" modes=(%s)", |
208 display_id_, | 373 display_id_, |
209 current_mode_ ? current_mode_->ToString().c_str() : "nullptr", | 374 current_mode_ ? current_mode_->ToString().c_str() : "nullptr", |
210 native_mode_ ? native_mode_->ToString().c_str() : "nullptr", | 375 native_mode_ ? native_mode_->ToString().c_str() : "nullptr", |
211 origin_.ToString().c_str(), physical_size_.ToString().c_str(), | 376 origin_.ToString().c_str(), physical_size_.ToString().c_str(), |
212 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), | 377 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), |
213 ModeListString(modes_).c_str()); | 378 ModeListString(modes_).c_str()); |
214 } | 379 } |
215 | 380 |
216 } // namespace display | 381 } // namespace display |
OLD | NEW |