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 namespace OHOS {
UIFontAllocator()19 UIFontAllocator::UIFontAllocator() : ram_(nullptr), ramSize_(0), freeSize_(0),
20 minSize_(0), end_(nullptr), free_(nullptr) {}
21
~UIFontAllocator()22 UIFontAllocator::~UIFontAllocator() {}
23
SetRamAddr(uint8_t * ram,uint32_t size)24 void UIFontAllocator::SetRamAddr(uint8_t* ram, uint32_t size)
25 {
26 struct Chunk* chunk = nullptr;
27
28 ram_ = ram;
29 ramSize_ = size - sizeof(struct Chunk) * 2; // head and tail two chunk
30 chunk = reinterpret_cast<struct Chunk*>(ram_);
31 chunk->next = size - sizeof(struct Chunk);
32 chunk->prev = 0;
33 chunk->used = false;
34
35 end_ = reinterpret_cast<struct Chunk*>(ram_ + size - sizeof(struct Chunk));
36 end_->next = size - sizeof(struct Chunk);
37 end_->prev = size - sizeof(struct Chunk);
38 end_->used = true;
39
40 free_ = chunk;
41 freeSize_ = size - sizeof(struct Chunk);
42 }
43
GetSize(void * addr)44 uint32_t UIFontAllocator::GetSize(void *addr)
45 {
46 struct Chunk *chunk = reinterpret_cast<struct Chunk*>(static_cast<uint8_t*>(addr) - sizeof(struct Chunk));
47 return chunk->next - (reinterpret_cast<uint8_t*>(addr) - reinterpret_cast<uint8_t*>(ram_));
48 }
49
SetMinChunkSize(uint32_t size)50 void UIFontAllocator::SetMinChunkSize(uint32_t size)
51 {
52 minSize_ = AlignSize(size);
53 }
54
Allocate(uint32_t size)55 void* UIFontAllocator::Allocate(uint32_t size)
56 {
57 uint32_t free, left;
58 uint32_t ptr, ptr2;
59 struct Chunk* chunk = nullptr;
60 struct Chunk* chunk2 = nullptr;
61 struct Chunk* chunk3 = nullptr;
62
63 size = AlignSize(size);
64 if (size < minSize_) {
65 size = minSize_;
66 }
67
68 for (ptr = reinterpret_cast<uint8_t*>(free_) - ram_; ptr < ramSize_;
69 ptr = reinterpret_cast<struct Chunk*>(ram_ + ptr)->next) {
70 chunk = reinterpret_cast<struct Chunk*>(ram_ + ptr);
71 if (chunk->used) {
72 continue;
73 }
74 free = chunk->next - ptr;
75 if (free < sizeof(struct Chunk) + size) {
76 continue;
77 }
78 left = free - sizeof(struct Chunk) - size;
79 if (left >= sizeof(struct Chunk) + minSize_) {
80 ptr2 = ptr + sizeof(struct Chunk) + size;
81 chunk2 = reinterpret_cast<struct Chunk*>(ram_ + ptr2);
82 chunk2->used = false;
83 chunk2->next = chunk->next;
84 chunk2->prev = ptr;
85 chunk->next = ptr2;
86 chunk->used = true;
87 if (chunk2->next != end_->next) {
88 chunk3 = reinterpret_cast<struct Chunk*>(ram_ + chunk2->next);
89 chunk3->prev = ptr2;
90 }
91 freeSize_ -= size + sizeof(struct Chunk);
92 } else {
93 chunk->used = true;
94 freeSize_ -= chunk->next - ptr;
95 }
96
97 if (chunk == free_) {
98 struct Chunk* cur = free_;
99 while (cur->used && (cur != end_)) {
100 cur = reinterpret_cast<struct Chunk*>(ram_ + cur->next);
101 }
102 free_ = cur;
103 }
104
105 return reinterpret_cast<uint8_t*>(chunk) + sizeof(struct Chunk);
106 }
107
108 return nullptr;
109 }
110
CombineFree(struct Chunk * chunk)111 void UIFontAllocator::CombineFree(struct Chunk* chunk)
112 {
113 if (chunk == nullptr) {
114 return;
115 }
116 struct Chunk* nextChunk = nullptr;
117 struct Chunk* prevChunk = nullptr;
118
119 nextChunk = reinterpret_cast<struct Chunk*>(ram_ + chunk->next);
120 if (((nextChunk != chunk) && !(nextChunk->used)) && (nextChunk != end_)) {
121 if (free_ == nextChunk) {
122 free_ = chunk;
123 }
124 chunk->next = nextChunk->next;
125 reinterpret_cast<struct Chunk*>(ram_ + nextChunk->next)->prev = reinterpret_cast<uint8_t*>(chunk) - ram_;
126 }
127
128 prevChunk = reinterpret_cast<struct Chunk*>(ram_ + chunk->prev);
129 if ((prevChunk != chunk) && !(prevChunk->used)) {
130 if (free_ == chunk) {
131 free_ = prevChunk;
132 }
133 prevChunk->next = chunk->next;
134 reinterpret_cast<struct Chunk*>(ram_ + chunk->next)->prev = reinterpret_cast<uint8_t*>(prevChunk) - ram_;
135 }
136 }
137
Free(void * addr)138 void UIFontAllocator::Free(void* addr)
139 {
140 struct Chunk* chunk = nullptr;
141
142 if (addr == nullptr) {
143 return;
144 }
145
146 if ((reinterpret_cast<uint8_t*>(addr) < ram_) ||
147 (reinterpret_cast<uint8_t*>(addr) > reinterpret_cast<uint8_t*>(end_))) {
148 return;
149 }
150
151 chunk = reinterpret_cast<struct Chunk*>(static_cast<uint8_t*>(addr) - sizeof(struct Chunk));
152 chunk->used = false;
153 if (chunk < free_) {
154 free_ = chunk;
155 }
156
157 freeSize_ += chunk->next - (reinterpret_cast<uint8_t*>(chunk) - ram_);
158 CombineFree(chunk);
159 }
160 } // namespace OHOS
161