| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/gfx/icc_profile.h" |
| 6 |
| 7 #include <list> |
| 8 |
| 9 #include "base/containers/mru_cache.h" |
| 10 #include "base/lazy_instance.h" |
| 11 #include "base/synchronization/lock.h" |
| 12 |
| 13 namespace gfx { |
| 14 |
| 15 namespace { |
| 16 const size_t kMinProfileLength = 128; |
| 17 const size_t kMaxProfileLength = 4 * 1024 * 1024; |
| 18 |
| 19 // Allow keeping around a maximum of 8 cached ICC profiles. Beware that |
| 20 // we will do a linear search thorugh currently-cached ICC profiles, |
| 21 // when creating a new ICC profile. |
| 22 const size_t kMaxCachedICCProfiles = 8; |
| 23 |
| 24 struct Cache { |
| 25 Cache() : id_to_icc_profile_mru(kMaxCachedICCProfiles) {} |
| 26 ~Cache() {} |
| 27 |
| 28 // Start from-ICC-data IDs at the end of the hard-coded list. |
| 29 uint64_t next_unused_id = 5; |
| 30 base::MRUCache<uint64_t, ICCProfile> id_to_icc_profile_mru; |
| 31 base::Lock lock; |
| 32 }; |
| 33 static base::LazyInstance<Cache> g_cache; |
| 34 |
| 35 } // namespace |
| 36 |
| 37 ICCProfile::ICCProfile() = default; |
| 38 ICCProfile::ICCProfile(ICCProfile&& other) = default; |
| 39 ICCProfile::ICCProfile(const ICCProfile& other) = default; |
| 40 ICCProfile& ICCProfile::operator=(ICCProfile&& other) = default; |
| 41 ICCProfile& ICCProfile::operator=(const ICCProfile& other) = default; |
| 42 ICCProfile::~ICCProfile() = default; |
| 43 |
| 44 bool ICCProfile::operator==(const ICCProfile& other) const { |
| 45 return valid_ == other.valid_ && data_ == other.data_; |
| 46 } |
| 47 |
| 48 // static |
| 49 ICCProfile ICCProfile::FromData(const std::vector<char>& icc_profile_data) { |
| 50 ICCProfile icc_profile; |
| 51 if (IsValidProfileLength(icc_profile_data.size())) { |
| 52 icc_profile.valid_ = true; |
| 53 icc_profile.data_ = icc_profile_data; |
| 54 } |
| 55 if (!icc_profile.valid_) |
| 56 return icc_profile; |
| 57 |
| 58 Cache& cache = g_cache.Get(); |
| 59 base::AutoLock lock(cache.lock); |
| 60 |
| 61 // Linearly search the cached ICC profiles to find one with the same data. |
| 62 // If it exists, re-use its id and touch it in the cache. |
| 63 for (auto iter = cache.id_to_icc_profile_mru.begin(); |
| 64 iter != cache.id_to_icc_profile_mru.end(); ++iter) { |
| 65 if (icc_profile.data_ == iter->second.data_) { |
| 66 icc_profile.id_ = iter->second.id_; |
| 67 cache.id_to_icc_profile_mru.Get(icc_profile.id_); |
| 68 return icc_profile; |
| 69 } |
| 70 } |
| 71 |
| 72 // Create a new cached id and add it to the cache. |
| 73 icc_profile.id_ = cache.next_unused_id++; |
| 74 cache.id_to_icc_profile_mru.Put(icc_profile.id_, icc_profile); |
| 75 return icc_profile; |
| 76 } |
| 77 |
| 78 #if !defined(OS_WIN) && !defined(OS_MACOSX) |
| 79 // static |
| 80 ICCProfile ICCProfile::FromBestMonitor() { |
| 81 return ICCProfile(); |
| 82 } |
| 83 #endif |
| 84 |
| 85 // static |
| 86 ICCProfile ICCProfile::FromColorSpace(const gfx::ColorSpace& color_space) { |
| 87 // Retrieve ICC profiles from the cache. |
| 88 if (color_space.icc_profile_id_) { |
| 89 Cache& cache = g_cache.Get(); |
| 90 base::AutoLock lock(cache.lock); |
| 91 |
| 92 auto found = cache.id_to_icc_profile_mru.Get(color_space.icc_profile_id_); |
| 93 if (found != cache.id_to_icc_profile_mru.end()) |
| 94 return found->second; |
| 95 } |
| 96 // TODO(ccameron): Support constructing ICC profiles from arbitrary ColorSpace |
| 97 // objects. |
| 98 return ICCProfile(); |
| 99 } |
| 100 |
| 101 const std::vector<char>& ICCProfile::GetData() const { |
| 102 return data_; |
| 103 } |
| 104 |
| 105 ColorSpace ICCProfile::GetColorSpace() const { |
| 106 ColorSpace color_space; |
| 107 color_space.valid_ = true; |
| 108 color_space.icc_profile_id_ = id_; |
| 109 |
| 110 // Move this ICC profile to the most recently used end of the cache. |
| 111 { |
| 112 Cache& cache = g_cache.Get(); |
| 113 base::AutoLock lock(cache.lock); |
| 114 |
| 115 auto found = cache.id_to_icc_profile_mru.Get(id_); |
| 116 if (found == cache.id_to_icc_profile_mru.end()) |
| 117 cache.id_to_icc_profile_mru.Put(id_, *this); |
| 118 } |
| 119 return color_space; |
| 120 } |
| 121 |
| 122 // static |
| 123 bool ICCProfile::IsValidProfileLength(size_t length) { |
| 124 return length >= kMinProfileLength && length <= kMaxProfileLength; |
| 125 } |
| 126 |
| 127 } // namespace gfx |
| OLD | NEW |