Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/gfx/color_profile.h" | 5 #include "ui/gfx/color_profile.h" |
| 6 | 6 |
| 7 #include <stddef.h> | |
| 7 #include <windows.h> | 8 #include <windows.h> |
|
Avi (use Gerrit)
2016/03/15 16:20:38
It's probably OK here, but in general leave the wi
| |
| 8 #include <stddef.h> | |
| 9 #include <map> | 9 #include <map> |
| 10 | 10 |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
| 15 | 15 |
| 16 namespace gfx { | 16 namespace gfx { |
| 17 | 17 |
| 18 namespace { | |
| 19 | |
| 18 class ColorProfileCache { | 20 class ColorProfileCache { |
| 19 public: | 21 public: |
| 20 // A thread-safe cache of color profiles keyed by windows device name. | 22 // A thread-safe cache of color profiles keyed by windows device name. |
| 21 ColorProfileCache() {} | 23 ColorProfileCache() {} |
| 22 | 24 |
| 23 bool Find(const std::wstring& device, std::vector<char>* profile) { | 25 bool Find(const std::wstring& device, std::vector<char>* profile) { |
| 24 base::AutoLock lock(lock_); | 26 base::AutoLock lock(lock_); |
| 25 DeviceColorProfile::const_iterator it = cache_.find(device); | 27 DeviceColorProfile::const_iterator it = cache_.find(device); |
| 26 if (it == cache_.end()) | 28 if (it == cache_.end()) |
| 27 return false; | 29 return false; |
| 28 *profile = it->second; | 30 *profile = it->second; |
| 29 return true; | 31 return true; |
| 30 } | 32 } |
| 31 | 33 |
| 32 void Insert(const std::wstring& device, const std::vector<char>& profile) { | 34 void Insert(const std::wstring& device) { |
| 33 base::AutoLock lock(lock_); | 35 std::vector<char> profile; |
| 34 cache_[device] = profile; | 36 |
| 37 { | |
| 38 base::AutoLock lock(lock_); | |
| 39 if (cache_.find(device) != cache_.end()) | |
| 40 return; | |
| 41 } | |
| 42 | |
| 43 HDC hdc = ::CreateDC(device.c_str(), NULL, NULL, NULL); | |
| 44 DWORD path_length = MAX_PATH; | |
| 45 WCHAR path[MAX_PATH + 1]; | |
| 46 BOOL get_icm_result = ::GetICMProfile(hdc, &path_length, path); | |
| 47 ::DeleteDC(hdc); | |
| 48 if (get_icm_result) { | |
| 49 base::FilePath file_name = base::FilePath(path).BaseName(); | |
| 50 if (file_name != base::FilePath(L"sRGB Color Space Profile.icm")) { | |
| 51 std::string data; | |
| 52 if (base::ReadFileToString(base::FilePath(path), &data)) | |
| 53 profile.assign(data.data(), data.data() + data.size()); | |
| 54 size_t length = profile.size(); | |
| 55 if (gfx::InvalidColorProfileLength(length)) | |
| 56 profile.clear(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 { | |
| 61 base::AutoLock lock(lock_); | |
| 62 cache_[device] = profile; | |
| 63 } | |
| 35 } | 64 } |
| 36 | 65 |
| 37 bool Erase(const std::wstring& device) { | 66 bool Erase(const std::wstring& device) { |
| 38 base::AutoLock lock(lock_); | 67 base::AutoLock lock(lock_); |
| 39 DeviceColorProfile::iterator it = cache_.find(device); | 68 DeviceColorProfile::iterator it = cache_.find(device); |
| 40 if (it == cache_.end()) | 69 if (it == cache_.end()) |
| 41 return false; | 70 return false; |
| 42 cache_.erase(device); | 71 cache_.erase(device); |
| 43 return true; | 72 return true; |
| 44 } | 73 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 57 DISALLOW_COPY_AND_ASSIGN(ColorProfileCache); | 86 DISALLOW_COPY_AND_ASSIGN(ColorProfileCache); |
| 58 }; | 87 }; |
| 59 | 88 |
| 60 base::LazyInstance<ColorProfileCache>::Leaky g_color_profile_cache = | 89 base::LazyInstance<ColorProfileCache>::Leaky g_color_profile_cache = |
| 61 LAZY_INSTANCE_INITIALIZER; | 90 LAZY_INSTANCE_INITIALIZER; |
| 62 | 91 |
| 63 inline ColorProfileCache& GetColorProfileCache() { | 92 inline ColorProfileCache& GetColorProfileCache() { |
| 64 return g_color_profile_cache.Get(); | 93 return g_color_profile_cache.Get(); |
| 65 } | 94 } |
| 66 | 95 |
| 96 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, | |
| 97 HDC hdc, | |
| 98 LPRECT rect, | |
| 99 LPARAM data) { | |
| 100 | |
| 101 MONITORINFOEX monitor_info; | |
| 102 monitor_info.cbSize = sizeof(MONITORINFOEX); | |
| 103 if (::GetMonitorInfo(monitor, &monitor_info)) | |
| 104 GetColorProfileCache().Insert(monitor_info.szDevice); | |
| 105 return TRUE; | |
| 106 } | |
| 107 | |
| 108 } // namespace | |
| 109 | |
| 110 void UpdateDisplayColorProfileCache() { | |
| 111 EnumDisplayMonitors(nullptr, nullptr, EnumMonitorCallback, 0); | |
| 112 } | |
| 113 | |
| 67 bool GetDisplayColorProfile(const gfx::Rect& bounds, | 114 bool GetDisplayColorProfile(const gfx::Rect& bounds, |
| 68 std::vector<char>* profile) { | 115 std::vector<char>* profile) { |
| 69 DCHECK(profile->empty()); | 116 DCHECK(profile->empty()); |
| 70 | 117 |
| 71 RECT rect = bounds.ToRECT(); | 118 RECT rect = bounds.ToRECT(); |
| 72 HMONITOR handle = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); | 119 HMONITOR handle = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONULL); |
| 73 if (bounds.IsEmpty() || !handle) | 120 if (bounds.IsEmpty() || !handle) |
| 74 return false; | 121 return false; |
| 75 | 122 |
| 76 MONITORINFOEX monitor; | 123 MONITORINFOEX monitor; |
| 77 monitor.cbSize = sizeof(MONITORINFOEX); | 124 monitor.cbSize = sizeof(MONITORINFOEX); |
| 78 CHECK(::GetMonitorInfo(handle, &monitor)); | 125 if (::GetMonitorInfo(handle, &monitor)) |
| 79 if (GetColorProfileCache().Find(monitor.szDevice, profile)) | 126 return GetColorProfileCache().Find(monitor.szDevice, profile); |
| 80 return true; | 127 return false; |
| 81 | |
| 82 HDC hdc = ::CreateDC(monitor.szDevice, NULL, NULL, NULL); | |
| 83 DWORD path_length = MAX_PATH; | |
| 84 WCHAR path[MAX_PATH + 1]; | |
| 85 BOOL result = ::GetICMProfile(hdc, &path_length, path); | |
| 86 ::DeleteDC(hdc); | |
| 87 if (!result) | |
| 88 return false; | |
| 89 | |
| 90 base::FilePath file_name = base::FilePath(path).BaseName(); | |
| 91 if (file_name != base::FilePath(L"sRGB Color Space Profile.icm")) { | |
| 92 std::string data; | |
| 93 if (base::ReadFileToString(base::FilePath(path), &data)) | |
| 94 profile->assign(data.data(), data.data() + data.size()); | |
| 95 size_t length = profile->size(); | |
| 96 if (gfx::InvalidColorProfileLength(length)) | |
| 97 profile->clear(); | |
| 98 } | |
| 99 | |
| 100 GetColorProfileCache().Insert(monitor.szDevice, *profile); | |
| 101 return true; | |
| 102 } | 128 } |
| 103 | 129 |
| 104 void ReadColorProfile(std::vector<char>* profile) { | 130 void ReadColorProfile(std::vector<char>* profile) { |
| 105 // TODO: support multiple monitors. | 131 // TODO: This function should be named to reflect that it is querying the |
| 106 HDC screen_dc = GetDC(NULL); | 132 // primary monitor. |
| 107 DWORD path_len = MAX_PATH; | 133 POINT point = {0, 0}; |
| 108 WCHAR path[MAX_PATH + 1]; | 134 HMONITOR handle = ::MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY); |
| 135 if (!handle) | |
| 136 return; | |
| 109 | 137 |
| 110 BOOL result = GetICMProfile(screen_dc, &path_len, path); | 138 MONITORINFOEX monitor; |
| 111 ReleaseDC(NULL, screen_dc); | 139 monitor.cbSize = sizeof(MONITORINFOEX); |
| 112 if (!result) | 140 if (::GetMonitorInfo(handle, &monitor)) |
| 113 return; | 141 GetColorProfileCache().Find(monitor.szDevice, profile); |
| 114 std::string profileData; | |
| 115 if (!base::ReadFileToString(base::FilePath(path), &profileData)) | |
| 116 return; | |
| 117 size_t length = profileData.size(); | |
| 118 if (gfx::InvalidColorProfileLength(length)) | |
| 119 return; | |
| 120 profile->assign(profileData.data(), profileData.data() + length); | |
| 121 } | 142 } |
| 122 | 143 |
| 123 } // namespace gfx | 144 } // namespace gfx |
| OLD | NEW |