odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

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 }