fontface.cpp (12968B)
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 "glyphbuffer_p.h" 9 #include "filesystem.h" 10 #include "fontface_p.h" 11 #include "matrix.h" 12 #include "object_p.h" 13 #include "path.h" 14 #include "runtime_p.h" 15 #include "string_p.h" 16 #include "opentype/otcore_p.h" 17 #include "opentype/otface_p.h" 18 #include "support/intops_p.h" 19 #include "support/ptrops_p.h" 20 #include "support/scopedbuffer_p.h" 21 #include "threading/uniqueidgenerator_p.h" 22 #include "unicode/unicode_p.h" 23 24 // bl::FontFace - Globals 25 // ====================== 26 27 BLFontFacePrivateFuncs bl_null_font_face_funcs; 28 static BLObjectEternalVirtualImpl<BLFontFacePrivateImpl, BLFontFaceVirt> bl_font_face_default_impl; 29 30 // bl::FontFace - Default Impl 31 // =========================== 32 33 BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS) 34 35 static BLResult BL_CDECL bl_null_font_face_impl_destroy(BLObjectImpl* impl) noexcept { 36 return BL_SUCCESS; 37 } 38 39 static BLResult BL_CDECL bl_null_font_face_map_text_to_glyphs( 40 const BLFontFaceImpl* impl, 41 uint32_t* content, 42 size_t count, 43 BLGlyphMappingState* state) noexcept { 44 45 state->reset(); 46 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 47 } 48 49 static BLResult BL_CDECL bl_null_font_face_get_glyph_bounds( 50 const BLFontFaceImpl* impl, 51 const uint32_t* glyph_data, 52 intptr_t glyph_advance, 53 BLBoxI* boxes, 54 size_t count) noexcept { 55 56 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 57 } 58 59 static BLResult BL_CDECL bl_null_font_face_get_glyph_advances( 60 const BLFontFaceImpl* impl, 61 const uint32_t* glyph_data, 62 intptr_t glyph_advance, 63 BLGlyphPlacement* placement_data, 64 size_t count) noexcept { 65 66 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 67 } 68 69 static BLResult BL_CDECL bl_null_font_face_get_glyph_outlines( 70 const BLFontFaceImpl* impl, 71 BLGlyphId glyph_id, 72 const BLMatrix2D* user_transform, 73 BLPath* out, 74 size_t* contour_count_out, 75 bl::ScopedBuffer* tmp_buffer) noexcept { 76 77 *contour_count_out = 0; 78 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 79 } 80 81 static BLResult BL_CDECL bl_null_font_face_apply_kern( 82 const BLFontFaceImpl* face_impl, 83 uint32_t* glyph_data, 84 BLGlyphPlacement* placement_data, 85 size_t count) noexcept { 86 87 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 88 } 89 90 static BLResult BL_CDECL bl_null_font_face_apply_gsub( 91 const BLFontFaceImpl* impl, 92 BLGlyphBuffer* gb, 93 const uint32_t* bit_words, 94 size_t bit_word_count) noexcept { 95 96 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 97 } 98 99 static BLResult BL_CDECL bl_null_font_face_apply_gpos( 100 const BLFontFaceImpl* impl, 101 BLGlyphBuffer* gb, 102 const uint32_t* bit_words, 103 size_t bit_word_count) noexcept { 104 105 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 106 } 107 108 static BLResult BL_CDECL bl_null_font_face_position_glyphs( 109 const BLFontFaceImpl* impl, 110 uint32_t* glyph_data, 111 BLGlyphPlacement* placement_data, 112 size_t count) noexcept { 113 114 return bl_make_error(BL_ERROR_FONT_NOT_INITIALIZED); 115 } 116 117 BL_DIAGNOSTIC_POP 118 119 // bl::FontFace - Init & Destroy 120 // ============================= 121 122 BLResult bl_font_face_init(BLFontFaceCore* self) noexcept { 123 self->_d = bl_object_defaults[BL_OBJECT_TYPE_FONT_FACE]._d; 124 return BL_SUCCESS; 125 } 126 127 BLResult bl_font_face_init_move(BLFontFaceCore* self, BLFontFaceCore* other) noexcept { 128 BL_ASSERT(self != other); 129 BL_ASSERT(other->_d.is_font_face()); 130 131 self->_d = other->_d; 132 other->_d = bl_object_defaults[BL_OBJECT_TYPE_FONT_FACE]._d; 133 134 return BL_SUCCESS; 135 } 136 137 BLResult bl_font_face_init_weak(BLFontFaceCore* self, const BLFontFaceCore* other) noexcept { 138 BL_ASSERT(self != other); 139 BL_ASSERT(other->_d.is_font_face()); 140 141 return bl_object_private_init_weak_tagged(self, other); 142 } 143 144 BLResult bl_font_face_destroy(BLFontFaceCore* self) noexcept { 145 BL_ASSERT(self->_d.is_font_face()); 146 147 return bl::ObjectInternal::release_virtual_instance(self); 148 } 149 150 // bl::FontFace - Reset 151 // ==================== 152 153 BLResult bl_font_face_reset(BLFontFaceCore* self) noexcept { 154 BL_ASSERT(self->_d.is_font_face()); 155 156 return bl::ObjectInternal::replace_virtual_instance(self, static_cast<BLFontFaceCore*>(&bl_object_defaults[BL_OBJECT_TYPE_FONT_FACE])); 157 } 158 159 // bl::FontFace - Assign 160 // ===================== 161 162 BLResult bl_font_face_assign_move(BLFontFaceCore* self, BLFontFaceCore* other) noexcept { 163 BL_ASSERT(self->_d.is_font_face()); 164 BL_ASSERT(other->_d.is_font_face()); 165 166 BLFontFaceCore tmp = *other; 167 other->_d = bl_object_defaults[BL_OBJECT_TYPE_FONT_FACE]._d; 168 return bl::ObjectInternal::replace_virtual_instance(self, &tmp); 169 } 170 171 BLResult bl_font_face_assign_weak(BLFontFaceCore* self, const BLFontFaceCore* other) noexcept { 172 BL_ASSERT(self->_d.is_font_face()); 173 BL_ASSERT(other->_d.is_font_face()); 174 175 return bl::ObjectInternal::assign_virtual_instance(self, other); 176 } 177 178 // bl::FontFace - Equality & Comparison 179 // ==================================== 180 181 bool bl_font_face_equals(const BLFontFaceCore* a, const BLFontFaceCore* b) noexcept { 182 BL_ASSERT(a->_d.is_font_face()); 183 BL_ASSERT(b->_d.is_font_face()); 184 185 return a->_d.impl == b->_d.impl; 186 } 187 188 // bl::FontFace - Create 189 // ===================== 190 191 BLResult bl_font_face_create_from_file(BLFontFaceCore* self, const char* file_name, BLFileReadFlags read_flags) noexcept { 192 BL_ASSERT(self->_d.is_font_face()); 193 194 BLFontData font_data; 195 BL_PROPAGATE(font_data.create_from_file(file_name, read_flags)); 196 return bl_font_face_create_from_data(self, &font_data, 0); 197 } 198 199 BLResult bl_font_face_create_from_data(BLFontFaceCore* self, const BLFontDataCore* font_data, uint32_t face_index) noexcept { 200 using namespace bl::FontFaceInternal; 201 202 BL_ASSERT(self->_d.is_font_face()); 203 BL_ASSERT(font_data->_d.is_font_data()); 204 205 if (BL_UNLIKELY(!font_data->dcast().is_valid())) 206 return bl_make_error(BL_ERROR_NOT_INITIALIZED); 207 208 if (face_index >= font_data->dcast().face_count()) 209 return bl_make_error(BL_ERROR_INVALID_VALUE); 210 211 BLFontFaceCore newO; 212 BL_PROPAGATE(bl::OpenType::create_open_type_face(&newO, static_cast<const BLFontData*>(font_data), face_index)); 213 214 // TODO: Move to OTFace? 215 get_impl<bl::OpenType::OTFaceImpl>(&newO)->unique_id = BLUniqueIdGenerator::generate_id(BLUniqueIdGenerator::Domain::kAny); 216 217 return bl::ObjectInternal::replace_virtual_instance(self, &newO); 218 } 219 220 // bl::FontFace - Accessors 221 // ======================== 222 223 BLResult bl_font_face_get_full_name(const BLFontFaceCore* self, BLStringCore* out) noexcept { 224 using namespace bl::FontFaceInternal; 225 226 BL_ASSERT(self->_d.is_font_face()); 227 BL_ASSERT(out->_d.is_string()); 228 229 BLFontFacePrivateImpl* self_impl = get_impl(self); 230 return bl_string_assign_weak(out, &self_impl->full_name); 231 } 232 233 BLResult bl_font_face_get_family_name(const BLFontFaceCore* self, BLStringCore* out) noexcept { 234 using namespace bl::FontFaceInternal; 235 236 BL_ASSERT(self->_d.is_font_face()); 237 BL_ASSERT(out->_d.is_string()); 238 239 BLFontFacePrivateImpl* self_impl = get_impl(self); 240 return bl_string_assign_weak(out, &self_impl->family_name); 241 } 242 243 BLResult bl_font_face_get_subfamily_name(const BLFontFaceCore* self, BLStringCore* out) noexcept { 244 using namespace bl::FontFaceInternal; 245 246 BL_ASSERT(self->_d.is_font_face()); 247 BL_ASSERT(out->_d.is_string()); 248 249 BLFontFacePrivateImpl* self_impl = get_impl(self); 250 return bl_string_assign_weak(out, &self_impl->subfamily_name); 251 } 252 253 BLResult bl_font_face_get_post_script_name(const BLFontFaceCore* self, BLStringCore* out) noexcept { 254 using namespace bl::FontFaceInternal; 255 256 BL_ASSERT(self->_d.is_font_face()); 257 BL_ASSERT(out->_d.is_string()); 258 259 BLFontFacePrivateImpl* self_impl = get_impl(self); 260 return bl_string_assign_weak(out, &self_impl->post_script_name); 261 } 262 263 BLResult bl_font_face_get_face_info(const BLFontFaceCore* self, BLFontFaceInfo* out) noexcept { 264 BL_ASSERT(self->_d.is_font_face()); 265 266 *out = self->dcast().face_info(); 267 return BL_SUCCESS; 268 } 269 270 BLResult bl_font_face_get_design_metrics(const BLFontFaceCore* self, BLFontDesignMetrics* out) noexcept { 271 BL_ASSERT(self->_d.is_font_face()); 272 273 *out = self->dcast().design_metrics(); 274 return BL_SUCCESS; 275 } 276 277 BLResult bl_font_face_get_coverage_info(const BLFontFaceCore* self, BLFontCoverageInfo* out) noexcept { 278 BL_ASSERT(self->_d.is_font_face()); 279 280 *out = self->dcast().coverage_info(); 281 return BL_SUCCESS; 282 } 283 284 BLResult bl_font_face_get_panose_info(const BLFontFaceCore* self, BLFontPanoseInfo* out) noexcept { 285 BL_ASSERT(self->_d.is_font_face()); 286 287 *out = self->dcast().panose_info(); 288 return BL_SUCCESS; 289 } 290 291 BLResult bl_font_face_get_character_coverage(const BLFontFaceCore* self, BLBitSetCore* out) noexcept { 292 using namespace bl::FontFaceInternal; 293 294 BL_ASSERT(self->_d.is_font_face()); 295 296 // Don't calculate the `character_coverage` again if it was already calculated. We don't need atomics here as it 297 // is set only once, atomics will be used only if it hasn't been calculated yet or if there is a race (already 298 // calculated by another thread, but nullptr at this exact moment here). 299 BLFontFacePrivateImpl* self_impl = get_impl(self); 300 if (!bl_object_atomic_content_test(&self_impl->character_coverage)) { 301 if (self_impl->face_info.face_type != BL_FONT_FACE_TYPE_OPENTYPE) 302 return bl_make_error(BL_ERROR_NOT_IMPLEMENTED); 303 304 BLBitSet tmp_bit_set; 305 BL_PROPAGATE(bl::OpenType::CMapImpl::populate_character_coverage(static_cast<bl::OpenType::OTFaceImpl*>(self_impl), &tmp_bit_set.dcast())); 306 307 tmp_bit_set.shrink(); 308 if (!bl_object_atomic_content_move(&self_impl->character_coverage, &tmp_bit_set)) 309 return bl_bit_set_assign_move(out, &tmp_bit_set); 310 } 311 312 return bl_bit_set_assign_weak(out, &self_impl->character_coverage); 313 } 314 315 bool bl_font_face_has_script_tag(const BLFontFaceCore* self, BLTag script_tag) noexcept { 316 using namespace bl::FontFaceInternal; 317 BL_ASSERT(self->_d.is_font_face()); 318 319 const BLFontFacePrivateImpl* self_impl = get_impl(self); 320 return self_impl->script_tag_set.has_tag(script_tag); 321 } 322 323 bool bl_font_face_has_feature_tag(const BLFontFaceCore* self, BLTag feature_tag) noexcept { 324 using namespace bl::FontFaceInternal; 325 BL_ASSERT(self->_d.is_font_face()); 326 327 const BLFontFacePrivateImpl* self_impl = get_impl(self); 328 return self_impl->feature_tag_set.has_tag(feature_tag); 329 } 330 331 bool bl_font_face_has_variation_tag(const BLFontFaceCore* self, BLTag variation_tag) noexcept { 332 using namespace bl::FontFaceInternal; 333 BL_ASSERT(self->_d.is_font_face()); 334 335 const BLFontFacePrivateImpl* self_impl = get_impl(self); 336 return self_impl->variation_tag_set.has_tag(variation_tag); 337 } 338 339 BLResult bl_font_face_get_script_tags(const BLFontFaceCore* self, BLArrayCore* out) noexcept { 340 using namespace bl::FontFaceInternal; 341 342 BL_ASSERT(self->_d.is_font_face()); 343 BL_ASSERT(out->_d.is_array()); 344 345 const BLFontFacePrivateImpl* self_impl = get_impl(self); 346 return self_impl->script_tag_set.flatten_to(out->dcast<BLArray<BLTag>>()); 347 } 348 349 BLResult bl_font_face_get_feature_tags(const BLFontFaceCore* self, BLArrayCore* out) noexcept { 350 using namespace bl::FontFaceInternal; 351 352 BL_ASSERT(self->_d.is_font_face()); 353 BL_ASSERT(out->_d.is_array()); 354 355 const BLFontFacePrivateImpl* self_impl = get_impl(self); 356 return self_impl->feature_tag_set.flatten_to(out->dcast<BLArray<BLTag>>()); 357 } 358 359 BLResult bl_font_face_get_variation_tags(const BLFontFaceCore* self, BLArrayCore* out) noexcept { 360 using namespace bl::FontFaceInternal; 361 362 BL_ASSERT(self->_d.is_font_face()); 363 BL_ASSERT(out->_d.is_array()); 364 365 const BLFontFacePrivateImpl* self_impl = get_impl(self); 366 return self_impl->variation_tag_set.flatten_to(out->dcast<BLArray<BLTag>>()); 367 } 368 369 // bl::FontFace - Runtime Registration 370 // =================================== 371 372 void bl_font_face_rt_init(BLRuntimeContext* rt) noexcept { 373 bl_unused(rt); 374 375 // Initialize BLFontFace built-ins. 376 bl_null_font_face_funcs.map_text_to_glyphs = bl_null_font_face_map_text_to_glyphs; 377 bl_null_font_face_funcs.get_glyph_bounds = bl_null_font_face_get_glyph_bounds; 378 bl_null_font_face_funcs.get_glyph_advances = bl_null_font_face_get_glyph_advances; 379 bl_null_font_face_funcs.get_glyph_outlines = bl_null_font_face_get_glyph_outlines; 380 bl_null_font_face_funcs.apply_kern = bl_null_font_face_apply_kern; 381 bl_null_font_face_funcs.apply_gsub = bl_null_font_face_apply_gsub; 382 bl_null_font_face_funcs.apply_gpos = bl_null_font_face_apply_gpos; 383 bl_null_font_face_funcs.position_glyphs = bl_null_font_face_position_glyphs; 384 385 bl_font_face_default_impl.virt.base.destroy = bl_null_font_face_impl_destroy; 386 bl_font_face_default_impl.virt.base.get_property = bl_object_impl_get_property; 387 bl_font_face_default_impl.virt.base.set_property = bl_object_impl_set_property; 388 bl_font_face_impl_ctor(&bl_font_face_default_impl.impl, &bl_font_face_default_impl.virt, bl_null_font_face_funcs); 389 390 bl_object_defaults[BL_OBJECT_TYPE_FONT_FACE]._d.init_dynamic(BLObjectInfo::from_type_with_marker(BL_OBJECT_TYPE_FONT_FACE), &bl_font_face_default_impl.impl); 391 }