glyphbuffer.cpp (11052B)
1 // This file is part of Blend2D project <https://blend2d.com> 2 // 3 // See blend2d.h or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #include "api-build_p.h" 7 #include "array_p.h" 8 #include "font_p.h" 9 #include "glyphbuffer_p.h" 10 #include "runtime_p.h" 11 #include "string_p.h" 12 #include "support/intops_p.h" 13 #include "support/ptrops_p.h" 14 #include "support/stringops_p.h" 15 #include "unicode/unicode_p.h" 16 17 // bl::GlyphBuffer - Internals 18 // =========================== 19 20 static const constexpr BLGlyphBufferPrivateImpl bl_glyph_buffer_internal_impl_none {}; 21 22 static BL_INLINE BLResult bl_glyph_buffer_ensure_data(BLGlyphBufferCore* self, BLGlyphBufferPrivateImpl** impl) noexcept { 23 *impl = bl_glyph_buffer_get_impl(self); 24 if (*impl != &bl_glyph_buffer_internal_impl_none) 25 return BL_SUCCESS; 26 27 *impl = BLGlyphBufferPrivateImpl::create(); 28 if (BL_UNLIKELY(!*impl)) 29 return bl_make_error(BL_ERROR_OUT_OF_MEMORY); 30 31 self->impl = *impl; 32 return BL_SUCCESS; 33 } 34 35 // bl::GlyphBuffer - Private API 36 // ============================= 37 38 BLResult BLGlyphBufferPrivateImpl::ensure_buffer(size_t buffer_id, size_t copy_size, size_t min_capacity) noexcept { 39 size_t old_capacity = capacity[buffer_id]; 40 BL_ASSERT(copy_size <= old_capacity); 41 42 if (min_capacity <= old_capacity) 43 return BL_SUCCESS; 44 45 size_t new_capacity = min_capacity; 46 if (new_capacity < BL_GLYPH_BUFFER_INITIAL_CAPACITY) 47 new_capacity = BL_GLYPH_BUFFER_INITIAL_CAPACITY; 48 else if (new_capacity < SIZE_MAX - 256) 49 new_capacity = bl::IntOps::align_up(min_capacity, 64); 50 51 bl::OverflowFlag of = 0; 52 size_t data_size = bl::IntOps::mul_overflow<size_t>(new_capacity, BL_GLYPH_BUFFER_ANY_ITEM_SIZE, &of); 53 54 if (BL_UNLIKELY(of)) 55 return BL_ERROR_OUT_OF_MEMORY; 56 57 uint8_t* new_data = static_cast<uint8_t*>(malloc(data_size)); 58 if (BL_UNLIKELY(!new_data)) 59 return BL_ERROR_OUT_OF_MEMORY; 60 61 uint8_t* old_data = static_cast<uint8_t*>(buffer[buffer_id]); 62 if (copy_size) { 63 memcpy(new_data, 64 old_data, 65 copy_size * sizeof(BLGlyphId)); 66 67 memcpy(new_data + new_capacity * sizeof(BLGlyphId), 68 old_data + old_capacity * sizeof(BLGlyphId), 69 copy_size * sizeof(BLGlyphInfo)); 70 } 71 72 free(old_data); 73 buffer[buffer_id] = new_data; 74 capacity[buffer_id] = new_capacity; 75 76 if (buffer_id == 0) 77 get_glyph_data_ptrs(0, &content, &info_data); 78 79 return BL_SUCCESS; 80 } 81 82 template<typename T> 83 static BL_INLINE BLGlyphInfo bl_glyph_info_from_cluster(const T& cluster) noexcept { 84 return BLGlyphInfo { uint32_t(cluster), 0 }; 85 } 86 87 template<typename T> 88 static BL_INLINE BLResult bl_internal_glyph_buffer_data_set_glyph_ids(BLGlyphBufferPrivateImpl* d, const T* src, size_t size, intptr_t advance) noexcept { 89 uint32_t* glyph_data = d->content; 90 BLGlyphInfo* info_data = d->info_data; 91 92 for (size_t i = 0; i < size; i++) { 93 glyph_data[i] = uint32_t(src[0]); 94 info_data[i] = bl_glyph_info_from_cluster(i); 95 src = bl::PtrOps::offset(src, advance); 96 } 97 98 d->size = size; 99 d->flags = 0; 100 return BL_SUCCESS; 101 } 102 103 static BL_INLINE BLResult bl_internal_glyph_buffer_data_set_latin1_text(BLGlyphBufferPrivateImpl* d, const char* src, size_t size) noexcept { 104 uint32_t* text_data = d->content; 105 BLGlyphInfo* info_data = d->info_data; 106 107 for (size_t i = 0; i < size; i++) { 108 text_data[i] = uint8_t(src[i]); 109 info_data[i] = bl_glyph_info_from_cluster(i); 110 } 111 112 d->size = size; 113 d->flags = 0; 114 115 if (d->size) 116 d->flags |= BL_GLYPH_RUN_FLAG_UCS4_CONTENT; 117 118 return BL_SUCCESS; 119 } 120 121 template<typename Reader, typename CharType> 122 static BL_INLINE BLResult bl_internal_glyph_buffer_data_set_unicode_text(BLGlyphBufferPrivateImpl* d, const CharType* src, size_t size) noexcept { 123 Reader reader(src, size); 124 125 uint32_t* text_data = d->content; 126 BLGlyphInfo* info_data = d->info_data; 127 128 while (reader.has_next()) { 129 uint32_t uc; 130 uint32_t cluster = uint32_t(reader.native_index(src)); 131 BLResult result = reader.next(uc); 132 133 *text_data++ = uc; 134 *info_data++ = bl_glyph_info_from_cluster(cluster); 135 136 if (BL_LIKELY(result == BL_SUCCESS)) 137 continue; 138 139 text_data[-1] = bl::Unicode::kCharReplacement; 140 d->flags |= BL_GLYPH_RUN_FLAG_INVALID_TEXT; 141 reader.skip_one_unit(); 142 } 143 144 d->size = (size_t)(text_data - d->content); 145 d->flags = 0; 146 147 if (d->size) 148 d->flags |= BL_GLYPH_RUN_FLAG_UCS4_CONTENT; 149 150 return BL_SUCCESS; 151 } 152 153 // bl::GlyphBuffer - Init & Destroy 154 // ================================ 155 156 BL_API_IMPL BLResult bl_glyph_buffer_init(BLGlyphBufferCore* self) noexcept { 157 self->impl = const_cast<BLGlyphBufferPrivateImpl*>(&bl_glyph_buffer_internal_impl_none); 158 return BL_SUCCESS; 159 } 160 161 BL_API_IMPL BLResult bl_glyph_buffer_init_move(BLGlyphBufferCore* self, BLGlyphBufferCore* other) noexcept { 162 BLGlyphBufferPrivateImpl* impl = bl_glyph_buffer_get_impl(other); 163 other->impl = const_cast<BLGlyphBufferPrivateImpl*>(&bl_glyph_buffer_internal_impl_none); 164 self->impl = impl; 165 return BL_SUCCESS; 166 } 167 168 BL_API_IMPL BLResult bl_glyph_buffer_destroy(BLGlyphBufferCore* self) noexcept { 169 BLGlyphBufferPrivateImpl* impl = bl_glyph_buffer_get_impl(self); 170 self->impl = nullptr; 171 172 if (impl != &bl_glyph_buffer_internal_impl_none) 173 impl->destroy(); 174 return BL_SUCCESS; 175 } 176 177 // bl::GlyphBuffer - Reset 178 // ======================= 179 180 BL_API_IMPL BLResult bl_glyph_buffer_reset(BLGlyphBufferCore* self) noexcept { 181 BLGlyphBufferPrivateImpl* impl = bl_glyph_buffer_get_impl(self); 182 self->impl = const_cast<BLGlyphBufferPrivateImpl*>(&bl_glyph_buffer_internal_impl_none); 183 184 if (impl != &bl_glyph_buffer_internal_impl_none) 185 impl->destroy(); 186 return BL_SUCCESS; 187 } 188 189 // bl::GlyphBuffer - Content 190 // ========================= 191 192 BL_API_IMPL BLResult bl_glyph_buffer_clear(BLGlyphBufferCore* self) noexcept { 193 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 194 195 // Would be true if the glyph-buffer is built-in 'none' instance or the data 196 // is allocated, but empty. 197 if (self_impl->size == 0) 198 return BL_SUCCESS; 199 200 self_impl->clear(); 201 return BL_SUCCESS; 202 } 203 204 BL_API_IMPL size_t bl_glyph_buffer_get_size(const BLGlyphBufferCore* self) noexcept { 205 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 206 return self_impl->size; 207 } 208 209 BL_API_IMPL uint32_t bl_glyph_buffer_get_flags(const BLGlyphBufferCore* self) noexcept { 210 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 211 return self_impl->flags; 212 } 213 214 BL_API_IMPL const BLGlyphRun* bl_glyph_buffer_get_glyph_run(const BLGlyphBufferCore* self) noexcept { 215 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 216 return &self_impl->glyph_run; 217 } 218 219 BL_API_IMPL const uint32_t* bl_glyph_buffer_get_content(const BLGlyphBufferCore* self) noexcept { 220 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 221 return self_impl->content; 222 } 223 224 BL_API_IMPL const BLGlyphInfo* bl_glyph_buffer_get_info_data(const BLGlyphBufferCore* self) noexcept { 225 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 226 return self_impl->info_data; 227 } 228 229 BL_API_IMPL const BLGlyphPlacement* bl_glyph_buffer_get_placement_data(const BLGlyphBufferCore* self) noexcept { 230 BLGlyphBufferPrivateImpl* self_impl = bl_glyph_buffer_get_impl(self); 231 return self_impl->placement_data; 232 } 233 234 BL_API_IMPL BLResult bl_glyph_buffer_set_text(BLGlyphBufferCore* self, const void* text_data, size_t size, BLTextEncoding encoding) noexcept { 235 if (BL_UNLIKELY(uint32_t(encoding) > BL_TEXT_ENCODING_MAX_VALUE)) 236 return bl_make_error(BL_ERROR_INVALID_VALUE); 237 238 BLGlyphBufferPrivateImpl* d; 239 BL_PROPAGATE(bl_glyph_buffer_ensure_data(self, &d)); 240 241 switch (encoding) { 242 case BL_TEXT_ENCODING_LATIN1: 243 if (size == SIZE_MAX) 244 size = strlen(static_cast<const char*>(text_data)); 245 246 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 247 return bl_internal_glyph_buffer_data_set_latin1_text(d, static_cast<const char*>(text_data), size); 248 249 case BL_TEXT_ENCODING_UTF8: 250 if (size == SIZE_MAX) 251 size = strlen(static_cast<const char*>(text_data)); 252 253 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 254 return bl_internal_glyph_buffer_data_set_unicode_text<bl::Unicode::Utf8Reader>(d, static_cast<const uint8_t*>(text_data), size); 255 256 case BL_TEXT_ENCODING_UTF16: 257 if (size == SIZE_MAX) 258 size = bl::StringOps::length(static_cast<const uint16_t*>(text_data)); 259 260 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 261 return bl_internal_glyph_buffer_data_set_unicode_text<bl::Unicode::Utf16Reader>(d, static_cast<const uint16_t*>(text_data), size * 2u); 262 263 case BL_TEXT_ENCODING_UTF32: 264 if (size == SIZE_MAX) 265 size = bl::StringOps::length(static_cast<const uint32_t*>(text_data)); 266 267 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 268 return bl_internal_glyph_buffer_data_set_unicode_text<bl::Unicode::Utf32Reader>(d, static_cast<const uint32_t*>(text_data), size * 4u); 269 270 default: 271 // Avoids a compile-time warning, should never be reached. 272 return bl_make_error(BL_ERROR_INVALID_VALUE); 273 } 274 } 275 276 BL_API_IMPL BLResult bl_glyph_buffer_set_glyphs(BLGlyphBufferCore* self, const uint32_t* glyph_data, size_t size) noexcept { 277 if (BL_UNLIKELY(sizeof(size_t) > 4 && size > 0xFFFFFFFFu)) 278 return bl_make_error(BL_ERROR_DATA_TOO_LARGE); 279 280 BLGlyphBufferPrivateImpl* d; 281 282 BL_PROPAGATE(bl_glyph_buffer_ensure_data(self, &d)); 283 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 284 285 return bl_internal_glyph_buffer_data_set_glyph_ids(d, glyph_data, size, intptr_t(sizeof(uint16_t))); 286 } 287 288 BL_API_IMPL BLResult bl_glyph_buffer_set_glyphs_from_struct(BLGlyphBufferCore* self, const void* glyph_data, size_t size, size_t glyph_id_size, intptr_t glyph_id_advance) noexcept { 289 if (BL_UNLIKELY(glyph_id_size != 2 && glyph_id_size != 4)) 290 return bl_make_error(BL_ERROR_INVALID_VALUE); 291 292 if (BL_UNLIKELY(sizeof(size_t) > 4 && size > 0xFFFFFFFFu)) 293 return bl_make_error(BL_ERROR_DATA_TOO_LARGE); 294 295 BLGlyphBufferPrivateImpl* d; 296 297 BL_PROPAGATE(bl_glyph_buffer_ensure_data(self, &d)); 298 BL_PROPAGATE(d->ensure_buffer(0, 0, size)); 299 300 if (glyph_id_size == 2) 301 return bl_internal_glyph_buffer_data_set_glyph_ids(d, static_cast<const uint16_t*>(glyph_data), size, glyph_id_advance); 302 else 303 return bl_internal_glyph_buffer_data_set_glyph_ids(d, static_cast<const uint32_t*>(glyph_data), size, glyph_id_advance); 304 } 305 306 BL_API_IMPL BLResult bl_glyph_buffer_set_debug_sink(BLGlyphBufferCore* self, BLDebugMessageSinkFunc sink, void* user_data) noexcept { 307 if (!sink) 308 return bl_glyph_buffer_reset_debug_sink(self); 309 310 BLGlyphBufferPrivateImpl* d; 311 BL_PROPAGATE(bl_glyph_buffer_ensure_data(self, &d)); 312 313 d->debug_sink = sink; 314 d->debug_sink_user_data = user_data; 315 316 return BL_SUCCESS; 317 } 318 319 BL_API_IMPL BLResult bl_glyph_buffer_reset_debug_sink(BLGlyphBufferCore* self) noexcept { 320 if (!bl_glyph_buffer_get_impl(self)->debug_sink) 321 return BL_SUCCESS; 322 323 BLGlyphBufferPrivateImpl* d; 324 BL_PROPAGATE(bl_glyph_buffer_ensure_data(self, &d)); 325 326 d->debug_sink = nullptr; 327 d->debug_sink_user_data = nullptr; 328 329 return BL_SUCCESS; 330 }