2020-08-11 11:10:23 +02:00
/*
* Copyright © 2018 Google , Inc .
*
* This is part of HarfBuzz , a text shaping library .
*
* Permission is hereby granted , without written agreement and without
* license or royalty fees , to use , copy , modify , and distribute this
* software and its documentation for any purpose , provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software .
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT , INDIRECT , SPECIAL , INCIDENTAL , OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION , EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE .
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES , INCLUDING ,
* BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE . THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN " AS IS " BASIS , AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE , SUPPORT , UPDATES , ENHANCEMENTS , OR MODIFICATIONS .
*
* Google Author ( s ) : Garret Rieger , Roderick Sheeter
*/
# include "hb-subset-plan.hh"
# include "hb-map.hh"
# include "hb-set.hh"
# include "hb-ot-cmap-table.hh"
# include "hb-ot-glyf-table.hh"
# include "hb-ot-layout-gdef-table.hh"
# include "hb-ot-layout-gpos-table.hh"
# include "hb-ot-layout-gsub-table.hh"
# include "hb-ot-cff1-table.hh"
# include "hb-ot-color-colr-table.hh"
2021-09-19 22:31:36 +02:00
# include "hb-ot-color-colrv1-closure.hh"
2020-08-11 11:10:23 +02:00
# include "hb-ot-var-fvar-table.hh"
# include "hb-ot-stat-table.hh"
2021-11-04 09:01:30 +01:00
# include "hb-ot-math-table.hh"
2020-08-11 11:10:23 +02:00
2021-11-30 11:14:06 +01:00
typedef hb_hashmap_t < unsigned , hb_set_t * > script_langsys_map ;
2020-08-11 11:10:23 +02:00
# ifndef HB_NO_SUBSET_CFF
static inline void
_add_cff_seac_components ( const OT : : cff1 : : accelerator_t & cff ,
hb_codepoint_t gid ,
hb_set_t * gids_to_retain )
{
hb_codepoint_t base_gid , accent_gid ;
if ( cff . get_seac_components ( gid , & base_gid , & accent_gid ) )
{
gids_to_retain - > add ( base_gid ) ;
gids_to_retain - > add ( accent_gid ) ;
}
}
# endif
2021-09-19 22:31:36 +02:00
static void
_remap_palette_indexes ( const hb_set_t * palette_indexes ,
hb_map_t * mapping /* OUT */ )
{
unsigned new_idx = 0 ;
for ( unsigned palette_index : palette_indexes - > iter ( ) )
{
if ( palette_index = = 0xFFFF )
{
mapping - > set ( palette_index , palette_index ) ;
continue ;
}
mapping - > set ( palette_index , new_idx ) ;
new_idx + + ;
}
}
2020-08-11 11:10:23 +02:00
static void
_remap_indexes ( const hb_set_t * indexes ,
hb_map_t * mapping /* OUT */ )
{
unsigned count = indexes - > get_population ( ) ;
for ( auto _ : + hb_zip ( indexes - > iter ( ) , hb_range ( count ) ) )
mapping - > set ( _ . first , _ . second ) ;
}
2021-09-19 22:31:36 +02:00
# ifndef HB_NO_SUBSET_LAYOUT
typedef void ( * layout_collect_func_t ) ( hb_face_t * face , hb_tag_t table_tag , const hb_tag_t * scripts , const hb_tag_t * languages , const hb_tag_t * features , hb_set_t * lookup_indexes /* OUT */ ) ;
template < typename T >
static void _collect_layout_indices ( hb_face_t * face ,
const T & table ,
const hb_set_t * layout_features_to_retain ,
layout_collect_func_t layout_collect_func ,
hb_set_t * indices /* OUT */ )
2020-08-11 11:10:23 +02:00
{
2021-09-19 22:31:36 +02:00
hb_vector_t < hb_tag_t > features ;
if ( ! features . alloc ( table . get_feature_count ( ) + 1 ) )
return ;
2020-08-11 11:10:23 +02:00
2021-11-30 11:14:06 +01:00
hb_set_t visited_features ;
bool retain_all_features = true ;
2021-09-19 22:31:36 +02:00
for ( unsigned i = 0 ; i < table . get_feature_count ( ) ; i + + )
{
hb_tag_t tag = table . get_feature_tag ( i ) ;
2021-11-30 11:14:06 +01:00
if ( ! tag ) continue ;
if ( ! layout_features_to_retain - > has ( tag ) )
{
retain_all_features = false ;
continue ;
}
2022-03-02 09:48:37 +01:00
2021-11-30 11:14:06 +01:00
if ( visited_features . has ( tag ) )
continue ;
features . push ( tag ) ;
visited_features . add ( tag ) ;
2021-09-19 22:31:36 +02:00
}
if ( ! features )
return ;
// The collect function needs a null element to signal end of the array.
features . push ( 0 ) ;
2021-11-30 11:14:06 +01:00
if ( retain_all_features )
2021-09-19 22:31:36 +02:00
{
// Looking for all features, trigger the faster collection method.
layout_collect_func ( face ,
T : : tableTag ,
nullptr ,
nullptr ,
nullptr ,
indices ) ;
return ;
}
layout_collect_func ( face ,
T : : tableTag ,
nullptr ,
nullptr ,
features . arrayZ ,
indices ) ;
2020-08-11 11:10:23 +02:00
}
2021-09-19 22:31:36 +02:00
template < typename T >
2020-08-11 11:10:23 +02:00
static inline void
2021-09-19 22:31:36 +02:00
_closure_glyphs_lookups_features ( hb_face_t * face ,
hb_set_t * gids_to_retain ,
const hb_set_t * layout_features_to_retain ,
hb_map_t * lookups ,
hb_map_t * features ,
script_langsys_map * langsys_map )
2020-08-11 11:10:23 +02:00
{
2021-09-19 22:31:36 +02:00
hb_blob_ptr_t < T > table = hb_sanitize_context_t ( ) . reference_table < T > ( face ) ;
hb_tag_t table_tag = table - > tableTag ;
2020-08-11 11:10:23 +02:00
hb_set_t lookup_indices ;
2021-09-19 22:31:36 +02:00
_collect_layout_indices < T > ( face ,
* table ,
layout_features_to_retain ,
hb_ot_layout_collect_lookups ,
& lookup_indices ) ;
if ( table_tag = = HB_OT_TAG_GSUB )
hb_ot_layout_lookups_substitute_closure ( face ,
& lookup_indices ,
gids_to_retain ) ;
table - > closure_lookups ( face ,
gids_to_retain ,
2020-08-11 11:10:23 +02:00
& lookup_indices ) ;
2021-09-19 22:31:36 +02:00
_remap_indexes ( & lookup_indices , lookups ) ;
2020-08-11 11:10:23 +02:00
2021-03-16 18:56:39 +01:00
// Collect and prune features
2020-08-11 11:10:23 +02:00
hb_set_t feature_indices ;
2021-09-19 22:31:36 +02:00
_collect_layout_indices < T > ( face ,
* table ,
layout_features_to_retain ,
hb_ot_layout_collect_features ,
& feature_indices ) ;
table - > prune_features ( lookups , & feature_indices ) ;
hb_map_t duplicate_feature_map ;
table - > find_duplicate_features ( lookups , & feature_indices , & duplicate_feature_map ) ;
feature_indices . clear ( ) ;
table - > prune_langsys ( & duplicate_feature_map , langsys_map , & feature_indices ) ;
_remap_indexes ( & feature_indices , features ) ;
table . destroy ( ) ;
2020-08-11 11:10:23 +02:00
}
2021-09-19 22:31:36 +02:00
2020-08-11 11:10:23 +02:00
# endif
# ifndef HB_NO_VAR
static inline void
_collect_layout_variation_indices ( hb_face_t * face ,
const hb_set_t * glyphset ,
const hb_map_t * gpos_lookups ,
hb_set_t * layout_variation_indices ,
hb_map_t * layout_variation_idx_map )
{
hb_blob_ptr_t < OT : : GDEF > gdef = hb_sanitize_context_t ( ) . reference_table < OT : : GDEF > ( face ) ;
hb_blob_ptr_t < OT : : GPOS > gpos = hb_sanitize_context_t ( ) . reference_table < OT : : GPOS > ( face ) ;
if ( ! gdef - > has_data ( ) )
{
gdef . destroy ( ) ;
gpos . destroy ( ) ;
return ;
}
OT : : hb_collect_variation_indices_context_t c ( layout_variation_indices , glyphset , gpos_lookups ) ;
gdef - > collect_variation_indices ( & c ) ;
if ( hb_ot_layout_has_positioning ( face ) )
gpos - > collect_variation_indices ( & c ) ;
gdef - > remap_layout_variation_indices ( layout_variation_indices , layout_variation_idx_map ) ;
gdef . destroy ( ) ;
gpos . destroy ( ) ;
}
# endif
static inline void
2021-09-19 22:31:36 +02:00
_cmap_closure ( hb_face_t * face ,
const hb_set_t * unicodes ,
hb_set_t * glyphset )
2020-08-11 11:10:23 +02:00
{
2022-02-02 15:04:28 +01:00
OT : : cmap : : accelerator_t cmap ( face ) ;
2020-08-11 11:10:23 +02:00
cmap . table - > closure_glyphs ( unicodes , glyphset ) ;
}
2021-11-04 09:01:30 +01:00
static void _colr_closure ( hb_face_t * face ,
hb_map_t * layers_map ,
hb_map_t * palettes_map ,
hb_set_t * glyphs_colred )
{
2022-02-02 15:04:28 +01:00
OT : : COLR : : accelerator_t colr ( face ) ;
2021-11-04 09:01:30 +01:00
if ( ! colr . is_valid ( ) ) return ;
unsigned iteration_count = 0 ;
hb_set_t palette_indices , layer_indices ;
unsigned glyphs_num ;
{
glyphs_num = glyphs_colred - > get_population ( ) ;
// Collect all glyphs referenced by COLRv0
hb_set_t glyphset_colrv0 ;
for ( hb_codepoint_t gid : glyphs_colred - > iter ( ) )
colr . closure_glyphs ( gid , & glyphset_colrv0 ) ;
2022-03-02 09:48:37 +01:00
2021-11-04 09:01:30 +01:00
glyphs_colred - > union_ ( glyphset_colrv0 ) ;
2022-03-02 09:48:37 +01:00
2021-11-04 09:01:30 +01:00
//closure for COLRv1
colr . closure_forV1 ( glyphs_colred , & layer_indices , & palette_indices ) ;
} while ( iteration_count + + < = HB_CLOSURE_MAX_STAGES & &
glyphs_num ! = glyphs_colred - > get_population ( ) ) ;
colr . closure_V0palette_indices ( glyphs_colred , & palette_indices ) ;
_remap_indexes ( & layer_indices , layers_map ) ;
_remap_palette_indexes ( & palette_indices , palettes_map ) ;
}
static inline void
_math_closure ( hb_face_t * face ,
hb_set_t * glyphset )
{
hb_blob_ptr_t < OT : : MATH > math = hb_sanitize_context_t ( ) . reference_table < OT : : MATH > ( face ) ;
if ( math - > has_data ( ) )
math - > closure_glyphs ( glyphset ) ;
math . destroy ( ) ;
}
2020-08-11 11:10:23 +02:00
static inline void
_remove_invalid_gids ( hb_set_t * glyphs ,
unsigned int num_glyphs )
{
hb_codepoint_t gid = HB_SET_VALUE_INVALID ;
while ( glyphs - > next ( & gid ) )
{
if ( gid > = num_glyphs )
glyphs - > del ( gid ) ;
}
}
2021-09-19 22:31:36 +02:00
static void
_populate_unicodes_to_retain ( const hb_set_t * unicodes ,
const hb_set_t * glyphs ,
hb_subset_plan_t * plan )
{
2022-02-02 15:04:28 +01:00
OT : : cmap : : accelerator_t cmap ( plan - > source ) ;
2021-09-19 22:31:36 +02:00
constexpr static const int size_threshold = 4096 ;
if ( glyphs - > is_empty ( ) & & unicodes - > get_population ( ) < size_threshold )
{
/* This is the fast path if it's anticipated that size of unicodes
* is < < than the number of codepoints in the font . */
for ( hb_codepoint_t cp : * unicodes )
{
hb_codepoint_t gid ;
if ( ! cmap . get_nominal_glyph ( cp , & gid ) )
{
DEBUG_MSG ( SUBSET , nullptr , " Drop U+%04X; no gid " , cp ) ;
continue ;
}
plan - > codepoint_to_glyph - > set ( cp , gid ) ;
}
}
else
{
hb_map_t unicode_glyphid_map ;
cmap . collect_mapping ( hb_set_get_empty ( ) , & unicode_glyphid_map ) ;
for ( hb_pair_t < hb_codepoint_t , hb_codepoint_t > cp_gid :
+ unicode_glyphid_map . iter ( ) )
{
if ( ! unicodes - > has ( cp_gid . first ) & & ! glyphs - > has ( cp_gid . second ) )
continue ;
plan - > codepoint_to_glyph - > set ( cp_gid . first , cp_gid . second ) ;
}
/* Add gids which where requested, but not mapped in cmap */
// TODO(garretrieger):
// Once https://github.com/harfbuzz/harfbuzz/issues/3169
// is implemented, this can be done with union and del_range
for ( hb_codepoint_t gid : glyphs - > iter ( ) )
{
if ( gid > = plan - > source - > get_num_glyphs ( ) )
break ;
plan - > _glyphset_gsub - > add ( gid ) ;
}
}
+ plan - > codepoint_to_glyph - > keys ( ) | hb_sink ( plan - > unicodes ) ;
+ plan - > codepoint_to_glyph - > values ( ) | hb_sink ( plan - > _glyphset_gsub ) ;
}
2020-08-11 11:10:23 +02:00
static void
_populate_gids_to_retain ( hb_subset_plan_t * plan ,
bool close_over_gsub ,
bool close_over_gpos ,
bool close_over_gdef )
{
2022-02-02 15:04:28 +01:00
OT : : glyf : : accelerator_t glyf ( plan - > source ) ;
2020-08-11 11:10:23 +02:00
# ifndef HB_NO_SUBSET_CFF
2022-02-02 15:04:28 +01:00
OT : : cff1 : : accelerator_t cff ( plan - > source ) ;
2020-08-11 11:10:23 +02:00
# endif
plan - > _glyphset_gsub - > add ( 0 ) ; // Not-def
_cmap_closure ( plan - > source , plan - > unicodes , plan - > _glyphset_gsub ) ;
# ifndef HB_NO_SUBSET_LAYOUT
if ( close_over_gsub )
// closure all glyphs/lookups/features needed for GSUB substitutions.
2021-09-19 22:31:36 +02:00
_closure_glyphs_lookups_features < OT : : GSUB > (
plan - > source ,
plan - > _glyphset_gsub ,
plan - > layout_features ,
plan - > gsub_lookups ,
plan - > gsub_features ,
plan - > gsub_langsys ) ;
2020-08-11 11:10:23 +02:00
if ( close_over_gpos )
2021-09-19 22:31:36 +02:00
_closure_glyphs_lookups_features < OT : : GPOS > (
plan - > source ,
plan - > _glyphset_gsub ,
plan - > layout_features ,
plan - > gpos_lookups ,
plan - > gpos_features ,
plan - > gpos_langsys ) ;
2020-08-11 11:10:23 +02:00
# endif
_remove_invalid_gids ( plan - > _glyphset_gsub , plan - > source - > get_num_glyphs ( ) ) ;
2021-11-04 09:01:30 +01:00
hb_set_set ( plan - > _glyphset_mathed , plan - > _glyphset_gsub ) ;
_math_closure ( plan - > source , plan - > _glyphset_mathed ) ;
_remove_invalid_gids ( plan - > _glyphset_mathed , plan - > source - > get_num_glyphs ( ) ) ;
2021-09-19 22:31:36 +02:00
2021-11-04 09:01:30 +01:00
hb_set_t cur_glyphset = * plan - > _glyphset_mathed ;
_colr_closure ( plan - > source , plan - > colrv1_layers , plan - > colr_palettes , & cur_glyphset ) ;
_remove_invalid_gids ( & cur_glyphset , plan - > source - > get_num_glyphs ( ) ) ;
2021-09-19 22:31:36 +02:00
2021-12-15 13:56:47 +01:00
hb_set_set ( plan - > _glyphset_colred , & cur_glyphset ) ;
2020-08-11 11:10:23 +02:00
// Populate a full set of glyphs to retain by adding all referenced
// composite glyphs.
2021-11-04 09:01:30 +01:00
for ( hb_codepoint_t gid : cur_glyphset . iter ( ) )
2020-08-11 11:10:23 +02:00
{
glyf . add_gid_and_children ( gid , plan - > _glyphset ) ;
# ifndef HB_NO_SUBSET_CFF
if ( cff . is_valid ( ) )
_add_cff_seac_components ( cff , gid , plan - > _glyphset ) ;
# endif
}
_remove_invalid_gids ( plan - > _glyphset , plan - > source - > get_num_glyphs ( ) ) ;
2021-09-19 22:31:36 +02:00
2020-08-11 11:10:23 +02:00
# ifndef HB_NO_VAR
if ( close_over_gdef )
2021-03-16 18:56:39 +01:00
_collect_layout_variation_indices ( plan - > source ,
2021-09-19 22:31:36 +02:00
plan - > _glyphset_gsub ,
plan - > gpos_lookups ,
plan - > layout_variation_indices ,
plan - > layout_variation_idx_map ) ;
2020-08-11 11:10:23 +02:00
# endif
}
static void
_create_old_gid_to_new_gid_map ( const hb_face_t * face ,
2021-09-19 22:31:36 +02:00
bool retain_gids ,
const hb_set_t * all_gids_to_retain ,
hb_map_t * glyph_map , /* OUT */
hb_map_t * reverse_glyph_map , /* OUT */
unsigned int * num_glyphs /* OUT */ )
2020-08-11 11:10:23 +02:00
{
if ( ! retain_gids )
{
+ hb_enumerate ( hb_iter ( all_gids_to_retain ) , ( hb_codepoint_t ) 0 )
| hb_sink ( reverse_glyph_map )
;
* num_glyphs = reverse_glyph_map - > get_population ( ) ;
} else {
+ hb_iter ( all_gids_to_retain )
| hb_map ( [ ] ( hb_codepoint_t _ ) {
return hb_pair_t < hb_codepoint_t , hb_codepoint_t > ( _ , _ ) ;
} )
| hb_sink ( reverse_glyph_map )
;
unsigned max_glyph =
+ hb_iter ( all_gids_to_retain )
| hb_reduce ( hb_max , 0u )
;
* num_glyphs = max_glyph + 1 ;
}
+ reverse_glyph_map - > iter ( )
| hb_map ( & hb_pair_t < hb_codepoint_t , hb_codepoint_t > : : reverse )
| hb_sink ( glyph_map )
;
}
static void
_nameid_closure ( hb_face_t * face ,
hb_set_t * nameids )
{
# ifndef HB_NO_STYLE
face - > table . STAT - > collect_name_ids ( nameids ) ;
# endif
# ifndef HB_NO_VAR
face - > table . fvar - > collect_name_ids ( nameids ) ;
# endif
}
/**
2022-03-02 09:48:37 +01:00
* hb_subset_plan_create_or_fail :
2021-09-19 22:31:36 +02:00
* @ face : font face to create the plan for .
* @ input : a # hb_subset_input_t input .
*
2020-08-11 11:10:23 +02:00
* Computes a plan for subsetting the supplied face according
* to a provided input . The plan describes
* which tables and glyphs should be retained .
*
2021-09-19 22:31:36 +02:00
* Return value : ( transfer full ) : New subset plan . Destroy with
2022-03-02 09:48:37 +01:00
* hb_subset_plan_destroy ( ) . If there is a failure creating the plan
* nullptr will be returned .
2020-08-11 11:10:23 +02:00
*
2022-03-02 09:48:37 +01:00
* Since : 4.0 .0
2020-08-11 11:10:23 +02:00
* */
hb_subset_plan_t *
2022-03-02 09:48:37 +01:00
hb_subset_plan_create_or_fail ( hb_face_t * face ,
const hb_subset_input_t * input )
2020-08-11 11:10:23 +02:00
{
hb_subset_plan_t * plan ;
if ( unlikely ( ! ( plan = hb_object_create < hb_subset_plan_t > ( ) ) ) )
2022-03-02 09:48:37 +01:00
return nullptr ;
2020-08-11 11:10:23 +02:00
plan - > successful = true ;
2021-09-19 22:31:36 +02:00
plan - > flags = input - > flags ;
2020-08-11 11:10:23 +02:00
plan - > unicodes = hb_set_create ( ) ;
2021-09-19 22:31:36 +02:00
plan - > name_ids = hb_set_copy ( input - > sets . name_ids ) ;
2020-08-11 11:10:23 +02:00
_nameid_closure ( face , plan - > name_ids ) ;
2021-09-19 22:31:36 +02:00
plan - > name_languages = hb_set_copy ( input - > sets . name_languages ) ;
plan - > layout_features = hb_set_copy ( input - > sets . layout_features ) ;
plan - > glyphs_requested = hb_set_copy ( input - > sets . glyphs ) ;
plan - > drop_tables = hb_set_copy ( input - > sets . drop_tables ) ;
plan - > no_subset_tables = hb_set_copy ( input - > sets . no_subset_tables ) ;
2020-08-11 11:10:23 +02:00
plan - > source = hb_face_reference ( face ) ;
plan - > dest = hb_face_builder_create ( ) ;
plan - > _glyphset = hb_set_create ( ) ;
plan - > _glyphset_gsub = hb_set_create ( ) ;
2021-11-04 09:01:30 +01:00
plan - > _glyphset_mathed = hb_set_create ( ) ;
2021-12-15 13:56:47 +01:00
plan - > _glyphset_colred = hb_set_create ( ) ;
2020-08-11 11:10:23 +02:00
plan - > codepoint_to_glyph = hb_map_create ( ) ;
plan - > glyph_map = hb_map_create ( ) ;
plan - > reverse_glyph_map = hb_map_create ( ) ;
plan - > gsub_lookups = hb_map_create ( ) ;
plan - > gpos_lookups = hb_map_create ( ) ;
2021-09-19 22:31:36 +02:00
if ( plan - > check_success ( plan - > gsub_langsys = hb_object_create < script_langsys_map > ( ) ) )
plan - > gsub_langsys - > init_shallow ( ) ;
if ( plan - > check_success ( plan - > gpos_langsys = hb_object_create < script_langsys_map > ( ) ) )
plan - > gpos_langsys - > init_shallow ( ) ;
2020-08-11 11:10:23 +02:00
plan - > gsub_features = hb_map_create ( ) ;
plan - > gpos_features = hb_map_create ( ) ;
2021-09-19 22:31:36 +02:00
plan - > colrv1_layers = hb_map_create ( ) ;
plan - > colr_palettes = hb_map_create ( ) ;
2020-08-11 11:10:23 +02:00
plan - > layout_variation_indices = hb_set_create ( ) ;
plan - > layout_variation_idx_map = hb_map_create ( ) ;
2022-03-02 09:48:37 +01:00
if ( unlikely ( plan - > in_error ( ) ) ) {
hb_subset_plan_destroy ( plan ) ;
return nullptr ;
2021-09-19 22:31:36 +02:00
}
_populate_unicodes_to_retain ( input - > sets . unicodes , input - > sets . glyphs , plan ) ;
2020-08-11 11:10:23 +02:00
_populate_gids_to_retain ( plan ,
2021-09-19 22:31:36 +02:00
! input - > sets . drop_tables - > has ( HB_OT_TAG_GSUB ) ,
! input - > sets . drop_tables - > has ( HB_OT_TAG_GPOS ) ,
! input - > sets . drop_tables - > has ( HB_OT_TAG_GDEF ) ) ;
2020-08-11 11:10:23 +02:00
_create_old_gid_to_new_gid_map ( face ,
2021-09-19 22:31:36 +02:00
input - > flags & HB_SUBSET_FLAGS_RETAIN_GIDS ,
2020-08-11 11:10:23 +02:00
plan - > _glyphset ,
plan - > glyph_map ,
plan - > reverse_glyph_map ,
& plan - > _num_output_glyphs ) ;
2022-03-02 09:48:37 +01:00
if ( unlikely ( plan - > in_error ( ) ) ) {
hb_subset_plan_destroy ( plan ) ;
return nullptr ;
}
2020-08-11 11:10:23 +02:00
return plan ;
}
/**
* hb_subset_plan_destroy :
2021-09-19 22:31:36 +02:00
* @ plan : a # hb_subset_plan_t
*
* Decreases the reference count on @ plan , and if it reaches zero , destroys
* @ plan , freeing all memory .
2020-08-11 11:10:23 +02:00
*
2022-03-02 09:48:37 +01:00
* Since : 4.0 .0
2020-08-11 11:10:23 +02:00
* */
void
hb_subset_plan_destroy ( hb_subset_plan_t * plan )
{
if ( ! hb_object_destroy ( plan ) ) return ;
hb_set_destroy ( plan - > unicodes ) ;
hb_set_destroy ( plan - > name_ids ) ;
hb_set_destroy ( plan - > name_languages ) ;
2021-09-19 22:31:36 +02:00
hb_set_destroy ( plan - > layout_features ) ;
2020-08-11 11:10:23 +02:00
hb_set_destroy ( plan - > glyphs_requested ) ;
hb_set_destroy ( plan - > drop_tables ) ;
2021-09-19 22:31:36 +02:00
hb_set_destroy ( plan - > no_subset_tables ) ;
2020-08-11 11:10:23 +02:00
hb_face_destroy ( plan - > source ) ;
hb_face_destroy ( plan - > dest ) ;
hb_map_destroy ( plan - > codepoint_to_glyph ) ;
hb_map_destroy ( plan - > glyph_map ) ;
hb_map_destroy ( plan - > reverse_glyph_map ) ;
hb_set_destroy ( plan - > _glyphset ) ;
hb_set_destroy ( plan - > _glyphset_gsub ) ;
2021-11-04 09:01:30 +01:00
hb_set_destroy ( plan - > _glyphset_mathed ) ;
2021-12-15 13:56:47 +01:00
hb_set_destroy ( plan - > _glyphset_colred ) ;
2020-08-11 11:10:23 +02:00
hb_map_destroy ( plan - > gsub_lookups ) ;
hb_map_destroy ( plan - > gpos_lookups ) ;
hb_map_destroy ( plan - > gsub_features ) ;
hb_map_destroy ( plan - > gpos_features ) ;
2021-09-19 22:31:36 +02:00
hb_map_destroy ( plan - > colrv1_layers ) ;
hb_map_destroy ( plan - > colr_palettes ) ;
2020-08-11 11:10:23 +02:00
hb_set_destroy ( plan - > layout_variation_indices ) ;
hb_map_destroy ( plan - > layout_variation_idx_map ) ;
2021-09-19 22:31:36 +02:00
if ( plan - > gsub_langsys )
{
for ( auto _ : plan - > gsub_langsys - > iter ( ) )
hb_set_destroy ( _ . second ) ;
hb_object_destroy ( plan - > gsub_langsys ) ;
plan - > gsub_langsys - > fini_shallow ( ) ;
hb_free ( plan - > gsub_langsys ) ;
}
if ( plan - > gpos_langsys )
{
for ( auto _ : plan - > gpos_langsys - > iter ( ) )
hb_set_destroy ( _ . second ) ;
hb_object_destroy ( plan - > gpos_langsys ) ;
plan - > gpos_langsys - > fini_shallow ( ) ;
hb_free ( plan - > gpos_langsys ) ;
}
2020-08-11 11:10:23 +02:00
2021-09-19 22:31:36 +02:00
hb_free ( plan ) ;
2020-08-11 11:10:23 +02:00
}
2022-03-02 09:48:37 +01:00
/**
* hb_subset_plan_old_to_new_glyph_mapping :
* @ plan : a subsetting plan .
*
* Returns the mapping between glyphs in the original font to glyphs in the
* subset that will be produced by @ plan
*
* Return value : ( transfer none ) :
* A pointer to the # hb_map_t of the mapping .
*
* Since : 4.0 .0
* */
const hb_map_t *
hb_subset_plan_old_to_new_glyph_mapping ( const hb_subset_plan_t * plan )
{
return plan - > glyph_map ;
}
/**
* hb_subset_plan_new_to_old_glyph_mapping :
* @ plan : a subsetting plan .
*
* Returns the mapping between glyphs in the subset that will be produced by
* @ plan and the glyph in the original font .
*
* Return value : ( transfer none ) :
* A pointer to the # hb_map_t of the mapping .
*
* Since : 4.0 .0
* */
const hb_map_t *
hb_subset_plan_new_to_old_glyph_mapping ( const hb_subset_plan_t * plan )
{
return plan - > reverse_glyph_map ;
}
/**
* hb_subset_plan_unicode_to_old_glyph_mapping :
* @ plan : a subsetting plan .
*
* Returns the mapping between codepoints in the original font and the
* associated glyph id in the original font .
*
* Return value : ( transfer none ) :
* A pointer to the # hb_map_t of the mapping .
*
* Since : 4.0 .0
* */
const hb_map_t *
hb_subset_plan_unicode_to_old_glyph_mapping ( const hb_subset_plan_t * plan )
{
return plan - > codepoint_to_glyph ;
}
/**
* hb_subset_plan_reference : ( skip )
* @ plan : a # hb_subset_plan_t object .
*
* Increases the reference count on @ plan .
*
* Return value : @ plan .
*
* Since : 4.0 .0
* */
hb_subset_plan_t *
hb_subset_plan_reference ( hb_subset_plan_t * plan )
{
return hb_object_reference ( plan ) ;
}
/**
* hb_subset_plan_set_user_data : ( skip )
* @ plan : a # hb_subset_plan_t object .
* @ key : The user - data key to set
* @ data : A pointer to the user data
* @ destroy : ( nullable ) : A callback to call when @ data is not needed anymore
* @ replace : Whether to replace an existing data with the same key
*
* Attaches a user - data key / data pair to the given subset plan object .
*
* Return value : % true if success , % false otherwise
*
* Since : 4.0 .0
* */
hb_bool_t
hb_subset_plan_set_user_data ( hb_subset_plan_t * plan ,
hb_user_data_key_t * key ,
void * data ,
hb_destroy_func_t destroy ,
hb_bool_t replace )
{
return hb_object_set_user_data ( plan , key , data , destroy , replace ) ;
}
/**
* hb_subset_plan_get_user_data : ( skip )
* @ plan : a # hb_subset_plan_t object .
* @ key : The user - data key to query
*
* Fetches the user data associated with the specified key ,
* attached to the specified subset plan object .
*
* Return value : ( transfer none ) : A pointer to the user data
*
* Since : 4.0 .0
* */
void *
hb_subset_plan_get_user_data ( const hb_subset_plan_t * plan ,
hb_user_data_key_t * key )
{
return hb_object_get_user_data ( plan , key ) ;
}