Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "imageStore.h"
24 :
25 : #include "io/path.h"
26 :
27 : #include "image.h"
28 : #include "score.h"
29 :
30 : #include "log.h"
31 :
32 : using namespace mu;
33 : using namespace muse;
34 : using namespace muse::io;
35 :
36 : namespace mu::engraving {
37 : ImageStore imageStore; // the global image store
38 :
39 : //---------------------------------------------------------
40 : // ImageStoreItem
41 : //---------------------------------------------------------
42 :
43 2 : ImageStoreItem::ImageStoreItem(const std::string& type)
44 2 : : m_type(type)
45 : {
46 2 : }
47 :
48 : //---------------------------------------------------------
49 : // dereference
50 : // decrement usage count of image in score
51 : //---------------------------------------------------------
52 :
53 24 : void ImageStoreItem::dereference(Image* image)
54 : {
55 24 : m_references.remove(image);
56 24 : }
57 :
58 : //---------------------------------------------------------
59 : // reference
60 : // increment usage count of image in score
61 : //---------------------------------------------------------
62 :
63 24 : void ImageStoreItem::reference(Image* image)
64 : {
65 24 : m_references.push_back(image);
66 24 : }
67 :
68 : //---------------------------------------------------------
69 : // isUsed
70 : // check if item is used in score
71 : //---------------------------------------------------------
72 :
73 0 : bool ImageStoreItem::isUsed(Score* score) const
74 : {
75 0 : for (Image* image : m_references) {
76 0 : if (image->score() == score && image->ownershipParent()) {
77 0 : return true;
78 : }
79 : }
80 0 : return false;
81 : }
82 :
83 : //---------------------------------------------------------
84 : // hashName
85 : //---------------------------------------------------------
86 :
87 19 : std::string ImageStoreItem::hashName() const
88 : {
89 19 : const char hex[17] = "0123456789abcdef";
90 : char p[33];
91 323 : for (int i = 0; i < 16; ++i) {
92 304 : p[i * 2] = hex[(m_hash[i] >> 4) & 0xf];
93 304 : p[i * 2 + 1] = hex[m_hash[i] & 0xf];
94 : }
95 19 : p[32] = 0;
96 76 : return std::string(p) + "." + m_type;
97 : }
98 :
99 : //---------------------------------------------------------
100 : // toInt
101 : //---------------------------------------------------------
102 :
103 672 : inline static int toInt(char c)
104 : {
105 672 : if (c >= '0' && c <= '9') {
106 441 : return c - '0';
107 : }
108 231 : return c - 'a' + 10;
109 : }
110 :
111 : //---------------------------------------------------------
112 : // ~ImageStore
113 : //---------------------------------------------------------
114 :
115 19 : ImageStore::~ImageStore()
116 : {
117 19 : muse::DeleteAll(m_items);
118 19 : }
119 :
120 : //---------------------------------------------------------
121 : // getImage
122 : //---------------------------------------------------------
123 :
124 21 : ImageStoreItem* ImageStore::getImage(std::string name) const
125 : {
126 21 : name = muse::io::completeBasename(name).toStdString();
127 21 : if (name.size() != 32) {
128 0 : return nullptr;
129 : }
130 21 : ByteArray hash(16);
131 357 : for (int i = 0; i < 16; ++i) {
132 336 : hash[i] = toInt(name.at(i * 2)) * 16 + toInt(name.at(i * 2 + 1));
133 : }
134 21 : for (ImageStoreItem* item : m_items) {
135 19 : if (item->hash() == hash) {
136 19 : return item;
137 : }
138 : }
139 2 : LOGW() << "image not found: " << name;
140 2 : return nullptr;
141 21 : }
142 :
143 : //---------------------------------------------------------
144 : // add
145 : //---------------------------------------------------------
146 :
147 2 : ImageStoreItem* ImageStore::add(const std::string& name, const ByteArray& ba)
148 : {
149 2 : ByteArray hash = cryptographicHash()->hash(ba, ICryptographicHash::Algorithm::Md4);
150 2 : for (ImageStoreItem* item : m_items) {
151 0 : if (item->hash() == hash) {
152 0 : return item;
153 : }
154 : }
155 2 : ImageStoreItem* item = new ImageStoreItem(muse::io::suffix(name));
156 2 : item->set(ba, hash);
157 2 : m_items.push_back(item);
158 2 : return item;
159 2 : }
160 :
161 : //---------------------------------------------------------
162 : // clearUnused
163 : //---------------------------------------------------------
164 :
165 2095 : void ImageStore::clearUnused()
166 : {
167 4190 : m_items.erase(
168 2095 : std::remove_if(m_items.begin(), m_items.end(), [](ImageStoreItem* i) {
169 14 : const bool remove = !i->isUsed();
170 14 : if (remove) {
171 2 : delete i;
172 : }
173 14 : return remove;
174 : }),
175 2095 : m_items.end()
176 : );
177 2095 : }
178 : }
|