Chromium Code Reviews| 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 exist then | |
|
Daniel Erat
2016/10/07 17:17:22
nit: "If the delimiter doesn't appear exactly once
kylechar
2016/10/11 13:56:49
Done.
| |
| 71 // the result will be empty and the input string will be unmodified. Otherwise, | |
| 72 // the input string will contain the text before the delimiter and the result | |
| 73 // 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 float refresh_rate = 60.0f; | |
| 92 | |
| 93 // With sscanf() it will happily ignore characters at the end of the string, | |
| 94 // so check |str| is valid using a regex. | |
| 95 if (!RE2::FullMatch(str, "\\d+x\\d+(?:%\\d+(?:\\.\\d*)?)?")) { | |
|
Daniel Erat
2016/10/07 17:17:22
since you're already using a regexp, why not extra
kylechar
2016/10/11 13:56:49
For the caveat I don't think it applies to the reg
| |
| 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 if (sscanf(str.c_str(), "%dx%d%%%f", &width, &height, &refresh_rate) < 2) { | |
| 102 LOG(ERROR) << "Unable to parse display mode \"" << str << "\""; | |
| 103 return nullptr; | |
| 104 } | |
| 105 | |
| 106 return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), false, | |
| 107 refresh_rate); | |
| 108 } | |
| 109 | |
| 110 // Parses a list of alternate display modes, adding each new display mode to | |
| 111 // |builder|. Returns false if any of the modes are invalid. | |
| 112 bool HandleModes(FakeDisplaySnapshot::Builder* builder, | |
| 113 StringPiece resolutions) { | |
| 114 for (const std::string& mode_str : | |
| 115 base::SplitString(resolutions, ":", base::TRIM_WHITESPACE, | |
| 116 base::SPLIT_WANT_NONEMPTY)) { | |
| 117 std::unique_ptr<ui::DisplayMode> mode = ParseDisplayMode(mode_str); | |
| 118 if (!mode) | |
| 119 return false; | |
| 120 | |
| 121 builder->AddMode(std::move(mode)); | |
| 122 } | |
| 123 | |
| 124 return true; | |
| 125 } | |
| 126 | |
| 127 // Parses device DPI and updates |builder|. Returns false if an invalid DPI | |
| 128 // string is provided. | |
| 129 bool HandleDPI(FakeDisplaySnapshot::Builder* builder, StringPiece dpi) { | |
| 130 if (dpi.empty()) | |
| 131 return true; | |
| 132 | |
| 133 int dpi_value = 0; | |
| 134 if (base::StringToInt(dpi, &dpi_value)) { | |
| 135 builder->SetDPI(dpi_value); | |
| 136 return true; | |
| 137 } | |
| 138 | |
| 139 LOG(ERROR) << "Invalid DPI string \"" << dpi << "\""; | |
| 140 return false; | |
| 141 } | |
| 142 | |
| 143 // Parses a list of display options and set each option true on |builder|. | |
| 144 // Returns false if any invalid options are provided. If an option appears more | |
| 145 // than once it will have no effect the second time. | |
| 146 bool HandleOptions(FakeDisplaySnapshot::Builder* builder, StringPiece options) { | |
| 147 for (size_t i = 0; i < options.size(); ++i) { | |
| 148 switch (options[i]) { | |
| 149 case 'o': | |
| 150 builder->SetHasOverscan(true); | |
| 151 break; | |
| 152 case 'c': | |
| 153 builder->SetHasColorCorrectionMatrix(true); | |
| 154 break; | |
| 155 case 'a': | |
| 156 builder->SetIsAspectPerservingScaling(true); | |
| 157 break; | |
| 158 case 'i': | |
| 159 builder->SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL); | |
| 160 break; | |
| 161 default: | |
| 162 LOG(ERROR) << "Invalid option specifier \"" << options[i] << "\""; | |
| 163 return false; | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 return true; | |
| 168 } | |
| 169 | |
| 65 } // namespace | 170 } // namespace |
| 66 | 171 |
| 67 using Builder = FakeDisplaySnapshot::Builder; | 172 using Builder = FakeDisplaySnapshot::Builder; |
| 68 | 173 |
| 69 Builder::Builder() {} | 174 Builder::Builder() {} |
| 70 | 175 |
| 71 Builder::~Builder() {} | 176 Builder::~Builder() {} |
| 72 | 177 |
| 73 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() { | 178 std::unique_ptr<FakeDisplaySnapshot> Builder::Build() { |
| 74 if (modes_.empty() || id_ == Display::kInvalidDisplayID) { | 179 if (modes_.empty() || id_ == Display::kInvalidDisplayID) { |
| 75 NOTREACHED() << "Display modes or display ID missing"; | 180 NOTREACHED() << "Display modes or display ID missing"; |
| 76 return nullptr; | 181 return nullptr; |
| 77 } | 182 } |
| 78 | 183 |
| 79 // If there is no native mode set, use the first display mode. | 184 // If there is no native mode set, use the first display mode. |
| 80 if (!native_mode_) | 185 if (!native_mode_) |
| 81 native_mode_ = modes_.back().get(); | 186 native_mode_ = modes_.back().get(); |
| 82 | 187 |
| 83 // Calculate physical size to match set DPI. | 188 // Calculate physical size to match set DPI. |
| 84 gfx::Size physical_size = | 189 gfx::Size physical_size = |
| 85 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); | 190 gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); |
| 86 | 191 |
| 87 return base::WrapUnique(new FakeDisplaySnapshot( | 192 return base::MakeUnique<FakeDisplaySnapshot>( |
| 88 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, | 193 id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, |
| 89 has_overscan_, has_color_correction_matrix_, name_, product_id_, | 194 has_overscan_, has_color_correction_matrix_, name_, product_id_, |
| 90 std::move(modes_), current_mode_, native_mode_)); | 195 std::move(modes_), current_mode_, native_mode_); |
| 91 } | 196 } |
| 92 | 197 |
| 93 Builder& Builder::SetId(int64_t id) { | 198 Builder& Builder::SetId(int64_t id) { |
| 94 id_ = id; | 199 id_ = id; |
| 95 return *this; | 200 return *this; |
| 96 } | 201 } |
| 97 | 202 |
| 98 Builder& Builder::SetNativeMode(const gfx::Size& size) { | 203 Builder& Builder::SetNativeMode(const gfx::Size& size) { |
| 99 native_mode_ = AddOrFindDisplayMode(size); | 204 native_mode_ = AddOrFindDisplayMode(size); |
| 100 return *this; | 205 return *this; |
| 101 } | 206 } |
| 102 | 207 |
| 208 Builder& Builder::SetNativeMode(std::unique_ptr<ui::DisplayMode> mode) { | |
| 209 native_mode_ = AddOrFindDisplayMode(std::move(mode)); | |
| 210 return *this; | |
| 211 } | |
| 212 | |
| 103 Builder& Builder::SetCurrentMode(const gfx::Size& size) { | 213 Builder& Builder::SetCurrentMode(const gfx::Size& size) { |
| 104 current_mode_ = AddOrFindDisplayMode(size); | 214 current_mode_ = AddOrFindDisplayMode(size); |
| 105 return *this; | 215 return *this; |
| 106 } | 216 } |
| 107 | 217 |
| 218 Builder& Builder::SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode) { | |
| 219 current_mode_ = AddOrFindDisplayMode(std::move(mode)); | |
| 220 return *this; | |
| 221 } | |
| 222 | |
| 108 Builder& Builder::AddMode(const gfx::Size& size) { | 223 Builder& Builder::AddMode(const gfx::Size& size) { |
| 109 AddOrFindDisplayMode(size); | 224 AddOrFindDisplayMode(size); |
| 110 return *this; | 225 return *this; |
| 111 } | 226 } |
| 112 | 227 |
| 228 Builder& Builder::AddMode(std::unique_ptr<ui::DisplayMode> mode) { | |
| 229 AddOrFindDisplayMode(std::move(mode)); | |
| 230 return *this; | |
| 231 } | |
| 232 | |
| 113 Builder& Builder::SetOrigin(const gfx::Point& origin) { | 233 Builder& Builder::SetOrigin(const gfx::Point& origin) { |
| 114 origin_ = origin; | 234 origin_ = origin; |
| 115 return *this; | 235 return *this; |
| 116 } | 236 } |
| 117 | 237 |
| 118 Builder& Builder::SetType(ui::DisplayConnectionType type) { | 238 Builder& Builder::SetType(ui::DisplayConnectionType type) { |
| 119 type_ = type; | 239 type_ = type; |
| 120 return *this; | 240 return *this; |
| 121 } | 241 } |
| 122 | 242 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 for (auto& mode : modes_) { | 282 for (auto& mode : modes_) { |
| 163 if (mode->size() == size) | 283 if (mode->size() == size) |
| 164 return mode.get(); | 284 return mode.get(); |
| 165 } | 285 } |
| 166 | 286 |
| 167 // Not found, insert a mode with the size and return. | 287 // Not found, insert a mode with the size and return. |
| 168 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f)); | 288 modes_.push_back(base::MakeUnique<ui::DisplayMode>(size, false, 60.0f)); |
| 169 return modes_.back().get(); | 289 return modes_.back().get(); |
| 170 } | 290 } |
| 171 | 291 |
| 172 FakeDisplaySnapshot::FakeDisplaySnapshot( | 292 const ui::DisplayMode* Builder::AddOrFindDisplayMode( |
| 173 int64_t display_id, | 293 std::unique_ptr<ui::DisplayMode> mode) { |
| 174 const gfx::Point& origin, | 294 for (auto& existing : modes_) { |
| 175 const gfx::Size& physical_size, | 295 if (mode->size() == existing->size() && |
| 176 ui::DisplayConnectionType type, | 296 mode->is_interlaced() == existing->is_interlaced() && |
| 177 bool is_aspect_preserving_scaling, | 297 mode->refresh_rate() == existing->refresh_rate()) |
| 178 bool has_overscan, | 298 return existing.get(); |
| 179 bool has_color_correction_matrix, | 299 } |
| 180 std::string display_name, | 300 |
| 181 int64_t product_id, | 301 // Not found, insert mode and return. |
| 182 std::vector<std::unique_ptr<const ui::DisplayMode>> modes, | 302 modes_.push_back(std::move(mode)); |
| 183 const ui::DisplayMode* current_mode, | 303 return modes_.back().get(); |
| 184 const ui::DisplayMode* native_mode) | 304 } |
| 305 | |
| 306 FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id, | |
| 307 const gfx::Point& origin, | |
| 308 const gfx::Size& physical_size, | |
| 309 ui::DisplayConnectionType type, | |
| 310 bool is_aspect_preserving_scaling, | |
| 311 bool has_overscan, | |
| 312 bool has_color_correction_matrix, | |
| 313 std::string display_name, | |
| 314 int64_t product_id, | |
| 315 DisplayModeList modes, | |
| 316 const ui::DisplayMode* current_mode, | |
| 317 const ui::DisplayMode* native_mode) | |
| 185 : DisplaySnapshot(display_id, | 318 : DisplaySnapshot(display_id, |
| 186 origin, | 319 origin, |
| 187 physical_size, | 320 physical_size, |
| 188 type, | 321 type, |
| 189 is_aspect_preserving_scaling, | 322 is_aspect_preserving_scaling, |
| 190 has_overscan, | 323 has_overscan, |
| 191 has_color_correction_matrix, | 324 has_color_correction_matrix, |
| 192 display_name, | 325 display_name, |
| 193 base::FilePath(), | 326 base::FilePath(), |
| 194 std::move(modes), | 327 std::move(modes), |
| 195 std::vector<uint8_t>(), | 328 std::vector<uint8_t>(), |
| 196 current_mode, | 329 current_mode, |
| 197 native_mode) { | 330 native_mode) { |
| 198 product_id_ = product_id; | 331 product_id_ = product_id; |
| 199 } | 332 } |
| 200 | 333 |
| 201 FakeDisplaySnapshot::~FakeDisplaySnapshot() {} | 334 FakeDisplaySnapshot::~FakeDisplaySnapshot() {} |
| 202 | 335 |
| 336 // static | |
| 337 std::unique_ptr<ui::DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec( | |
| 338 int64_t id, | |
| 339 const std::string& spec) { | |
| 340 StringPiece leftover(spec); | |
| 341 | |
| 342 // Cut off end of string at each delimiter to split. | |
| 343 StringPiece options = ExtractSuffix(&leftover, "/"); | |
| 344 StringPiece dpi = ExtractSuffix(&leftover, "^"); | |
| 345 StringPiece resolutions = ExtractSuffix(&leftover, "#"); | |
| 346 | |
| 347 // Leftovers should be just the native mode at this point. | |
| 348 std::unique_ptr<ui::DisplayMode> native_mode = | |
| 349 ParseDisplayMode(leftover.as_string()); | |
| 350 | |
| 351 // Fail without valid native mode. | |
| 352 if (!native_mode) | |
| 353 return nullptr; | |
| 354 | |
| 355 FakeDisplaySnapshot::Builder builder; | |
| 356 builder.SetId(id).SetNativeMode(std::move(native_mode)); | |
| 357 builder.SetName(base::StringPrintf("Fake Display %" PRId64, id)); | |
| 358 | |
| 359 if (!HandleModes(&builder, resolutions) || !HandleDPI(&builder, dpi) || | |
| 360 !HandleOptions(&builder, options)) | |
| 361 return nullptr; | |
| 362 | |
| 363 return builder.Build(); | |
| 364 } | |
| 365 | |
| 203 std::string FakeDisplaySnapshot::ToString() const { | 366 std::string FakeDisplaySnapshot::ToString() const { |
| 204 return base::StringPrintf( | 367 return base::StringPrintf( |
| 205 "id=%" PRId64 | 368 "id=%" PRId64 |
| 206 " current_mode=%s native_mode=%s origin=%s" | 369 " current_mode=%s native_mode=%s origin=%s" |
| 207 " physical_size=%s, type=%s name=\"%s\" modes=(%s)", | 370 " physical_size=%s, type=%s name=\"%s\" modes=(%s)", |
| 208 display_id_, | 371 display_id_, |
| 209 current_mode_ ? current_mode_->ToString().c_str() : "nullptr", | 372 current_mode_ ? current_mode_->ToString().c_str() : "nullptr", |
| 210 native_mode_ ? native_mode_->ToString().c_str() : "nullptr", | 373 native_mode_ ? native_mode_->ToString().c_str() : "nullptr", |
| 211 origin_.ToString().c_str(), physical_size_.ToString().c_str(), | 374 origin_.ToString().c_str(), physical_size_.ToString().c_str(), |
| 212 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), | 375 DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(), |
| 213 ModeListString(modes_).c_str()); | 376 ModeListString(modes_).c_str()); |
| 214 } | 377 } |
| 215 | 378 |
| 216 } // namespace display | 379 } // namespace display |
| OLD | NEW |