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