1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "font/ui_font_allocator.h"
17
18 #include "draw/draw_utils.h"
19 #include "engines/gfx/gfx_engine_manager.h"
20 #include "font/ui_font.h"
21 #include "font/ui_font_cache_manager.h"
22 #include "gfx_utils/graphic_buffer.h"
23
24 namespace OHOS {
UIFontAllocator()25 UIFontAllocator::UIFontAllocator()
26 : ram_(nullptr), ramSize_(0), freeSize_(0), minSize_(0), end_(nullptr), free_(nullptr)
27 {
28 }
29
~UIFontAllocator()30 UIFontAllocator::~UIFontAllocator() {}
31
SetRamAddr(uint8_t * ram,uint32_t size)32 void UIFontAllocator::SetRamAddr(uint8_t* ram, uint32_t size)
33 {
34 if (size <= sizeof(struct Chunk) * 2) { // 2 : head and tail two chunk
35 ramSize_ = 0;
36 return;
37 }
38 if (ram == nullptr) {
39 ramSize_ = 0;
40 return;
41 }
42
43 UI_ADDR_ALIGN(ram, size);
44 ram_ = ram;
45
46 struct Chunk* chunk = nullptr;
47 ramSize_ = size - sizeof(struct Chunk) * 2; // head and tail two chunk
48 chunk = reinterpret_cast<struct Chunk*>(ram_);
49 chunk->next = size - sizeof(struct Chunk);
50 chunk->prev = 0;
51 chunk->used = false;
52
53 end_ = reinterpret_cast<struct Chunk*>(ram_ + size - sizeof(struct Chunk));
54 end_->next = size - sizeof(struct Chunk);
55 end_->prev = size - sizeof(struct Chunk);
56 end_->used = true;
57
58 free_ = chunk;
59 freeSize_ = size - sizeof(struct Chunk);
60 }
61
GetSize(void * addr)62 uint32_t UIFontAllocator::GetSize(void* addr)
63 {
64 struct Chunk* chunk = reinterpret_cast<struct Chunk*>(static_cast<uint8_t*>(addr) - sizeof(struct Chunk));
65 return chunk->next - (reinterpret_cast<uint8_t*>(addr) - reinterpret_cast<uint8_t*>(ram_));
66 }
67
SetMinChunkSize(uint32_t size)68 void UIFontAllocator::SetMinChunkSize(uint32_t size)
69 {
70 minSize_ = UI_ALIGN_UP(size);
71 }
72
Allocate(uint32_t size)73 void* UIFontAllocator::Allocate(uint32_t size)
74 {
75 uint32_t free;
76 uint32_t left;
77 struct Chunk* chunk = nullptr;
78 struct Chunk* chunk2 = nullptr;
79 struct Chunk* chunk3 = nullptr;
80
81 size = UI_ALIGN_UP(size);
82 if (size < minSize_) {
83 size = minSize_;
84 }
85
86 for (uint32_t ptr = reinterpret_cast<uint8_t*>(free_) - ram_; ptr < ramSize_;
87 ptr = reinterpret_cast<struct Chunk*>(ram_ + ptr)->next) {
88 chunk = reinterpret_cast<struct Chunk*>(ram_ + ptr);
89 if (chunk->used) {
90 continue;
91 }
92 free = chunk->next - ptr;
93 if (free < sizeof(struct Chunk) + size) {
94 continue;
95 }
96 left = free - sizeof(struct Chunk) - size;
97 if (left >= sizeof(struct Chunk) + minSize_) {
98 uint32_t ptr2 = ptr + sizeof(struct Chunk) + size;
99 chunk2 = reinterpret_cast<struct Chunk*>(ram_ + ptr2);
100 chunk2->used = false;
101 chunk2->next = chunk->next;
102 chunk2->prev = ptr;
103 chunk->next = ptr2;
104 chunk->used = true;
105 if (chunk2->next != end_->next) {
106 chunk3 = reinterpret_cast<struct Chunk*>(ram_ + chunk2->next);
107 chunk3->prev = ptr2;
108 }
109 freeSize_ -= size + sizeof(struct Chunk);
110 } else {
111 chunk->used = true;
112 freeSize_ -= chunk->next - ptr;
113 }
114
115 if (chunk == free_) {
116 struct Chunk* cur = free_;
117 while (cur->used && (cur != end_)) {
118 cur = reinterpret_cast<struct Chunk*>(ram_ + cur->next);
119 }
120 free_ = cur;
121 }
122
123 return reinterpret_cast<uint8_t*>(chunk) + sizeof(struct Chunk);
124 }
125
126 return nullptr;
127 }
128
CombineFree(struct Chunk * chunk)129 void UIFontAllocator::CombineFree(struct Chunk* chunk)
130 {
131 if (chunk == nullptr) {
132 return;
133 }
134 struct Chunk* nextChunk = nullptr;
135 struct Chunk* prevChunk = nullptr;
136
137 nextChunk = reinterpret_cast<struct Chunk*>(ram_ + chunk->next);
138 if (((nextChunk != chunk) && !(nextChunk->used)) && (nextChunk != end_)) {
139 if (free_ == nextChunk) {
140 free_ = chunk;
141 }
142 chunk->next = nextChunk->next;
143 reinterpret_cast<struct Chunk*>(ram_ + nextChunk->next)->prev = reinterpret_cast<uint8_t*>(chunk) - ram_;
144 }
145
146 prevChunk = reinterpret_cast<struct Chunk*>(ram_ + chunk->prev);
147 if ((prevChunk != chunk) && !(prevChunk->used)) {
148 if (free_ == chunk) {
149 free_ = prevChunk;
150 }
151 prevChunk->next = chunk->next;
152 reinterpret_cast<struct Chunk*>(ram_ + chunk->next)->prev = reinterpret_cast<uint8_t*>(prevChunk) - ram_;
153 }
154 }
155
Free(void * addr)156 void UIFontAllocator::Free(void* addr)
157 {
158 struct Chunk* chunk = nullptr;
159
160 if (addr == nullptr) {
161 return;
162 }
163
164 if ((reinterpret_cast<uint8_t*>(addr) < ram_) ||
165 (reinterpret_cast<uint8_t*>(addr) > reinterpret_cast<uint8_t*>(end_))) {
166 return;
167 }
168
169 chunk = reinterpret_cast<struct Chunk*>(static_cast<uint8_t*>(addr) - sizeof(struct Chunk));
170 chunk->used = false;
171 if (chunk < free_) {
172 free_ = chunk;
173 }
174
175 freeSize_ += chunk->next - (reinterpret_cast<uint8_t*>(chunk) - ram_);
176 CombineFree(chunk);
177 }
178
GetCacheBuffer(uint16_t fontId,uint32_t unicode,ColorMode mode,GlyphNode & glyphNode,bool hasMetric,TextStyle textStyle)179 BufferInfo UIFontAllocator::GetCacheBuffer(uint16_t fontId,
180 uint32_t unicode,
181 ColorMode mode,
182 GlyphNode& glyphNode,
183 bool hasMetric,
184 TextStyle textStyle)
185 {
186 BufferInfo bufInfo{Rect(), 0, nullptr, nullptr, glyphNode.cols, glyphNode.rows, mode, 0};
187 bufInfo.stride = BIT_TO_BYTE(bufInfo.width * DrawUtils::GetPxSizeByColorMode(bufInfo.mode));
188
189 BaseGfxEngine::GetInstance()->AdjustLineStride(bufInfo);
190 uint32_t bitmapSize = bufInfo.stride * bufInfo.height;
191 if (hasMetric) {
192 bitmapSize += sizeof(Metric);
193 }
194 bufInfo.virAddr =
195 reinterpret_cast<void*>(UIFontCacheManager::GetInstance()->GetSpace(fontId, unicode, bitmapSize, textStyle));
196 return bufInfo;
197 }
198
RearrangeBitmap(BufferInfo & bufInfo,uint32_t fileSz,bool hasMetric)199 void UIFontAllocator::RearrangeBitmap(BufferInfo& bufInfo, uint32_t fileSz, bool hasMetric)
200 {
201 uint32_t word = bufInfo.width;
202 word = BIT_TO_BYTE(word * DrawUtils::GetPxSizeByColorMode(bufInfo.mode));
203 if (bufInfo.stride <= word) {
204 return;
205 }
206
207 uint8_t* bitmap = reinterpret_cast<uint8_t*>(bufInfo.virAddr);
208 if (hasMetric) {
209 bitmap += sizeof(Metric);
210 }
211 uint32_t suffixLen = bufInfo.stride - word;
212 uint8_t* rdestBuf = bitmap + bufInfo.stride * bufInfo.height;
213 uint8_t* rsrcBuf = bitmap + fileSz;
214
215 /* Rearrange bitmap in local buffer */
216 for (uint32_t row = 0; row < bufInfo.height; row++) {
217 rdestBuf -= suffixLen;
218 (void)memset_s(rdestBuf, suffixLen, 0, suffixLen);
219 for (uint32_t i = 0; i < word; i++) {
220 *(--rdestBuf) = *(--rsrcBuf);
221 }
222 }
223 BaseGfxEngine::GetInstance()->MemoryBarrier();
224 }
225 } // namespace OHOS
226