2018-02-06 00:22:30 +01: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 .
*
2018-02-07 01:58:35 +01:00
* Google Author ( s ) : Garret Rieger , Roderick Sheeter
2018-02-06 00:22:30 +01:00
*/
2018-08-31 22:25:19 +02:00
# include "hb-subset-plan.hh"
2018-08-26 07:36:36 +02:00
# include "hb-map.hh"
# include "hb-set.hh"
2018-02-06 00:22:30 +01:00
2018-02-07 19:07:46 +01:00
# include "hb-ot-cmap-table.hh"
2018-02-16 19:27:03 +01:00
# include "hb-ot-glyf-table.hh"
2020-02-26 22:11:42 +01:00
# include "hb-ot-layout-gdef-table.hh"
# include "hb-ot-layout-gpos-table.hh"
2020-06-11 20:27:57 +02:00
# include "hb-ot-layout-gsub-table.hh"
2018-11-14 22:38:03 +01:00
# include "hb-ot-cff1-table.hh"
2020-01-24 14:52:23 +01:00
# include "hb-ot-color-colr-table.hh"
2021-04-01 21:01:19 +02:00
# include "hb-ot-color-colrv1-closure.hh"
2019-05-13 18:38:42 +02:00
# include "hb-ot-var-fvar-table.hh"
# include "hb-ot-stat-table.hh"
2021-09-20 23:42:51 +02:00
# include "hb-ot-math-table.hh"
2018-02-07 19:07:46 +01:00
2022-03-24 00:28:22 +01:00
using OT : : Layout : : GSUB : : GSUB ;
2022-06-29 01:55:32 +02:00
using OT : : Layout : : GPOS ;
2020-02-26 22:11:42 +01:00
2022-06-03 09:17:20 +02:00
typedef hb_hashmap_t < unsigned , hb : : unique_ptr < hb_set_t > > script_langsys_map ;
2019-05-12 20:08:45 +02:00
# ifndef HB_NO_SUBSET_CFF
2019-05-11 08:46:22 +02:00
static inline void
2018-11-14 22:38:03 +01:00
_add_cff_seac_components ( const OT : : cff1 : : accelerator_t & cff ,
2019-10-08 11:54:26 +02:00
hb_codepoint_t gid ,
hb_set_t * gids_to_retain )
2018-11-14 22:38:03 +01:00
{
hb_codepoint_t base_gid , accent_gid ;
if ( cff . get_seac_components ( gid , & base_gid , & accent_gid ) )
{
2019-10-08 11:54:26 +02:00
gids_to_retain - > add ( base_gid ) ;
gids_to_retain - > add ( accent_gid ) ;
2018-11-14 22:38:03 +01:00
}
}
2019-05-12 20:08:45 +02:00
# endif
2018-11-14 22:38:03 +01:00
2021-05-11 20:44:32 +02:00
static void
_remap_palette_indexes ( const hb_set_t * palette_indexes ,
2021-06-09 22:46:35 +02:00
hb_map_t * mapping /* OUT */ )
2021-05-11 20:44:32 +02:00
{
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 + + ;
}
}
2019-10-23 01:00:43 +02:00
static void
2019-10-31 23:59:02 +01:00
_remap_indexes ( const hb_set_t * indexes ,
hb_map_t * mapping /* OUT */ )
2019-10-23 01:00:43 +02:00
{
2019-10-31 23:59:02 +01:00
unsigned count = indexes - > get_population ( ) ;
2019-10-23 01:00:43 +02:00
2019-10-31 23:59:02 +01:00
for ( auto _ : + hb_zip ( indexes - > iter ( ) , hb_range ( count ) ) )
mapping - > set ( _ . first , _ . second ) ;
2019-10-23 01:00:43 +02:00
}
2021-05-18 11:31:14 +02:00
# ifndef HB_NO_SUBSET_LAYOUT
2021-05-20 02:33:46 +02:00
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 */ ) ;
2021-08-25 02:06:14 +02:00
2022-06-30 22:03:33 +02:00
/**
* Removes all tags from ' tags ' that are not in filter . Additionally eliminates any duplicates .
* Returns true if anything was removed ( not including duplicates ) .
*/
static bool _filter_tag_list ( hb_vector_t < hb_tag_t > * tags , /* IN/OUT */
const hb_set_t * filter )
2018-06-07 23:32:34 +02:00
{
2022-06-30 22:03:33 +02:00
hb_vector_t < hb_tag_t > out ;
out . alloc ( tags - > get_size ( ) ) ;
2021-08-25 00:53:32 +02:00
2022-06-30 22:03:33 +02:00
bool removed = false ;
hb_set_t visited ;
for ( hb_tag_t tag : * tags )
2021-08-25 00:53:32 +02:00
{
2021-11-16 04:58:33 +01:00
if ( ! tag ) continue ;
2022-06-30 22:03:33 +02:00
if ( visited . has ( tag ) ) continue ;
if ( ! filter - > has ( tag ) )
2021-11-16 04:58:33 +01:00
{
2022-06-30 22:03:33 +02:00
removed = true ;
2021-11-16 04:58:33 +01:00
continue ;
}
2022-02-11 21:44:58 +01:00
2022-06-30 22:03:33 +02:00
visited . add ( tag ) ;
out . push ( tag ) ;
2021-05-20 02:33:46 +02:00
}
2020-09-29 22:16:01 +02:00
2022-06-30 22:03:33 +02:00
hb_swap ( out , * tags ) ;
return removed ;
}
2021-05-20 02:33:46 +02:00
2022-06-30 22:03:33 +02:00
template < typename T >
2022-06-30 22:14:29 +02:00
static void _collect_layout_indices ( hb_subset_plan_t * plan ,
2022-06-30 22:03:33 +02:00
const T & table ,
layout_collect_func_t layout_collect_func ,
hb_set_t * indices /* OUT */ )
{
unsigned num_features = table . get_feature_count ( ) + 1 ;
hb_vector_t < hb_tag_t > features ;
2022-06-30 22:14:29 +02:00
if ( ! plan - > check_success ( features . resize ( num_features ) ) ) return ;
2022-06-30 22:03:33 +02:00
table . get_feature_tags ( 0 , & num_features , features . arrayZ ) ;
features . resize ( num_features ) ;
2022-06-30 22:14:29 +02:00
bool retain_all_features = ! _filter_tag_list ( & features , plan - > layout_features ) ;
2022-06-30 22:03:33 +02:00
2022-06-30 22:24:42 +02:00
unsigned num_scripts = table . get_script_count ( ) + 1 ;
hb_vector_t < hb_tag_t > scripts ;
if ( ! plan - > check_success ( scripts . resize ( num_scripts ) ) ) return ;
table . get_script_tags ( 0 , & num_scripts , scripts . arrayZ ) ;
scripts . resize ( num_scripts ) ;
bool retain_all_scripts = ! _filter_tag_list ( & scripts , plan - > layout_scripts ) ;
if ( ! plan - > check_success ( ! features . in_error ( ) ) | | ! features
| | ! plan - > check_success ( ! scripts . in_error ( ) ) | | ! scripts )
2022-06-30 22:03:33 +02:00
return ;
2021-05-20 02:33:46 +02:00
2022-06-30 22:03:33 +02:00
// The collect function needs a null element to signal end of the array.
features . push ( 0 ) ;
2022-06-30 22:24:42 +02:00
scripts . push ( 0 ) ;
2022-06-30 22:14:29 +02:00
layout_collect_func ( plan - > source ,
2021-08-25 00:53:32 +02:00
T : : tableTag ,
2022-06-30 22:24:42 +02:00
retain_all_scripts ? nullptr : scripts . arrayZ ,
2021-05-20 02:33:46 +02:00
nullptr ,
2022-06-30 22:24:42 +02:00
retain_all_features ? nullptr : features . arrayZ ,
2021-08-25 07:22:49 +02:00
indices ) ;
2019-10-23 01:00:43 +02:00
}
2021-05-20 02:33:46 +02:00
template < typename T >
2019-10-23 01:00:43 +02:00
static inline void
2022-06-30 22:14:29 +02:00
_closure_glyphs_lookups_features ( hb_subset_plan_t * plan ,
2021-06-09 22:46:35 +02:00
hb_set_t * gids_to_retain ,
hb_map_t * lookups ,
hb_map_t * features ,
2021-05-20 02:33:46 +02:00
script_langsys_map * langsys_map )
2019-10-23 01:00:43 +02:00
{
2022-06-30 22:14:29 +02:00
hb_blob_ptr_t < T > table = hb_sanitize_context_t ( ) . reference_table < T > ( plan - > source ) ;
2021-05-20 02:33:46 +02:00
hb_tag_t table_tag = table - > tableTag ;
2019-10-23 01:00:43 +02:00
hb_set_t lookup_indices ;
2022-06-30 22:14:29 +02:00
_collect_layout_indices < T > ( plan ,
2021-08-25 02:06:14 +02:00
* table ,
hb_ot_layout_collect_lookups ,
& lookup_indices ) ;
2021-05-20 02:33:46 +02:00
if ( table_tag = = HB_OT_TAG_GSUB )
2022-06-30 22:14:29 +02:00
hb_ot_layout_lookups_substitute_closure ( plan - > source ,
& lookup_indices ,
2021-05-20 02:33:46 +02:00
gids_to_retain ) ;
2022-06-30 22:14:29 +02:00
table - > closure_lookups ( plan - > source ,
2021-05-20 02:33:46 +02:00
gids_to_retain ,
2022-06-30 22:14:29 +02:00
& lookup_indices ) ;
2021-05-20 02:33:46 +02:00
_remap_indexes ( & lookup_indices , lookups ) ;
2019-10-31 23:59:02 +01:00
2020-09-29 22:16:01 +02:00
// Collect and prune features
2019-10-31 23:59:02 +01:00
hb_set_t feature_indices ;
2022-06-30 22:14:29 +02:00
_collect_layout_indices < T > ( plan ,
2021-08-25 02:06:14 +02:00
* table ,
hb_ot_layout_collect_features ,
& feature_indices ) ;
2021-05-20 02:33:46 +02:00
table - > prune_features ( lookups , & feature_indices ) ;
2021-01-29 00:21:26 +01:00
hb_map_t duplicate_feature_map ;
2021-05-20 02:33:46 +02:00
table - > find_duplicate_features ( lookups , & feature_indices , & duplicate_feature_map ) ;
2021-01-29 00:21:26 +01:00
feature_indices . clear ( ) ;
2021-05-20 02:33:46 +02:00
table - > prune_langsys ( & duplicate_feature_map , langsys_map , & feature_indices ) ;
_remap_indexes ( & feature_indices , features ) ;
2021-01-29 00:21:26 +01:00
2021-05-20 02:33:46 +02:00
table . destroy ( ) ;
2018-06-07 23:32:34 +02:00
}
2021-05-20 02:33:46 +02:00
2019-05-14 12:26:18 +02:00
# endif
2018-06-07 23:32:34 +02:00
2020-02-26 22:11:42 +01:00
# 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 )
{
2020-02-26 22:11:42 +01:00
hb_blob_ptr_t < OT : : GDEF > gdef = hb_sanitize_context_t ( ) . reference_table < OT : : GDEF > ( face ) ;
2022-06-25 01:14:30 +02:00
hb_blob_ptr_t < GPOS > gpos = hb_sanitize_context_t ( ) . reference_table < GPOS > ( face ) ;
2020-02-26 22:11:42 +01:00
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 ) ;
2020-07-29 06:03:32 +02:00
2020-02-26 22:11:42 +01:00
gdef . destroy ( ) ;
gpos . destroy ( ) ;
2020-02-26 22:11:42 +01:00
}
# endif
2019-08-07 22:17:26 +02:00
static inline void
2021-06-09 22:46:35 +02:00
_cmap_closure ( hb_face_t * face ,
const hb_set_t * unicodes ,
hb_set_t * glyphset )
2019-08-07 22:17:26 +02:00
{
2022-01-20 19:47:17 +01:00
OT : : cmap : : accelerator_t cmap ( face ) ;
2019-10-29 01:12:55 +01:00
cmap . table - > closure_glyphs ( unicodes , glyphset ) ;
2019-08-07 22:17:26 +02:00
}
2021-10-03 05:32:30 +02: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-01-20 20:37:21 +01:00
OT : : COLR : : accelerator_t colr ( face ) ;
2021-10-03 05:32:30 +02: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-02-11 21:44:58 +01:00
2021-10-03 05:32:30 +02:00
glyphs_colred - > union_ ( glyphset_colrv0 ) ;
2022-02-11 21:44:58 +01:00
2021-10-03 05:32:30 +02: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 ) ;
}
2021-09-20 23:42:51 +02:00
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 ( ) ;
}
2019-05-11 08:46:22 +02:00
static inline void
2018-11-16 07:48:26 +01:00
_remove_invalid_gids ( hb_set_t * glyphs ,
unsigned int num_glyphs )
{
2022-05-05 18:19:16 +02:00
glyphs - > del_range ( num_glyphs , HB_SET_VALUE_INVALID ) ;
2018-11-16 07:48:26 +01:00
}
2018-06-07 23:32:34 +02:00
2021-07-15 02:27:14 +02:00
static void
_populate_unicodes_to_retain ( const hb_set_t * unicodes ,
const hb_set_t * glyphs ,
hb_subset_plan_t * plan )
{
2022-01-20 19:47:17 +01:00
OT : : cmap : : accelerator_t cmap ( plan - > source ) ;
2021-07-15 02:27:14 +02:00
2022-05-04 23:22:26 +02:00
unsigned size_threshold = plan - > source - > get_num_glyphs ( ) ;
if ( glyphs - > is_empty ( ) & & unicodes - > get_population ( ) < size_threshold )
2021-07-15 02:27:14 +02:00
{
2022-05-04 00:40:56 +02:00
// This is approach to collection is faster, but can only be used if glyphs
2022-05-04 23:22:26 +02:00
// are not being explicitly added to the subset and the input unicodes set is
// not excessively large (eg. an inverted set).
2022-05-04 00:02:59 +02:00
plan - > unicode_to_new_gid_list . alloc ( unicodes - > get_population ( ) ) ;
2021-08-25 22:34:05 +02:00
for ( hb_codepoint_t cp : * unicodes )
2021-07-15 02:27:14 +02:00
{
2021-08-25 22:34:05 +02:00
hb_codepoint_t gid ;
if ( ! cmap . get_nominal_glyph ( cp , & gid ) )
{
DEBUG_MSG ( SUBSET , nullptr , " Drop U+%04X; no gid " , cp ) ;
continue ;
}
2021-08-25 23:42:00 +02:00
2021-08-25 22:34:05 +02:00
plan - > codepoint_to_glyph - > set ( cp , gid ) ;
2022-05-04 00:02:59 +02:00
plan - > unicode_to_new_gid_list . push ( hb_pair ( cp , gid ) ) ;
2021-07-15 02:27:14 +02:00
}
2021-08-26 00:25:08 +02:00
}
else
{
2022-05-04 00:40:56 +02:00
// This approach is slower, but can handle adding in glyphs to the subset and will match
// them with cmap entries.
2021-08-25 23:42:00 +02:00
hb_map_t unicode_glyphid_map ;
2022-05-04 23:48:18 +02:00
hb_set_t cmap_unicodes ;
cmap . collect_mapping ( & cmap_unicodes , & unicode_glyphid_map ) ;
2022-05-04 23:22:26 +02:00
plan - > unicode_to_new_gid_list . alloc ( hb_min ( unicodes - > get_population ( )
+ glyphs - > get_population ( ) ,
2022-05-04 23:48:18 +02:00
cmap_unicodes . get_population ( ) ) ) ;
2021-07-15 02:27:14 +02:00
2022-05-04 23:48:18 +02:00
for ( hb_codepoint_t cp : cmap_unicodes )
2021-08-25 23:42:00 +02:00
{
2022-05-04 23:48:18 +02:00
hb_codepoint_t gid = unicode_glyphid_map [ cp ] ;
if ( ! unicodes - > has ( cp ) & & ! glyphs - > has ( gid ) )
continue ;
2021-07-15 02:27:14 +02:00
2022-05-04 23:48:18 +02:00
plan - > codepoint_to_glyph - > set ( cp , gid ) ;
plan - > unicode_to_new_gid_list . push ( hb_pair ( cp , gid ) ) ;
2021-08-25 23:42:00 +02:00
}
2021-08-25 22:34:05 +02:00
2021-08-26 00:25:08 +02:00
/* Add gids which where requested, but not mapped in cmap */
2022-05-04 23:48:18 +02:00
for ( hb_codepoint_t gid : * glyphs )
2021-08-25 23:42:00 +02:00
{
if ( gid > = plan - > source - > get_num_glyphs ( ) )
2021-08-26 00:25:08 +02:00
break ;
2021-08-25 23:42:00 +02:00
plan - > _glyphset_gsub - > add ( gid ) ;
}
2021-08-25 22:34:05 +02:00
}
2022-05-05 01:06:18 +02:00
auto & arr = plan - > unicode_to_new_gid_list ;
if ( arr . length )
2022-05-03 00:29:43 +02:00
{
2022-05-05 01:06:18 +02:00
plan - > unicodes - > add_sorted_array ( & arr . arrayZ - > first , arr . length , sizeof ( * arr . arrayZ ) ) ;
plan - > _glyphset_gsub - > add_array ( & arr . arrayZ - > second , arr . length , sizeof ( * arr . arrayZ ) ) ;
2022-05-03 00:29:43 +02:00
}
2021-07-15 02:27:14 +02:00
}
2022-06-26 01:01:11 +02:00
# ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
# define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
2022-06-26 00:54:46 +02:00
# endif
static unsigned
_glyf_add_gid_and_children ( const OT : : glyf_accelerator_t & glyf ,
hb_codepoint_t gid ,
hb_set_t * gids_to_retain ,
2022-06-26 01:01:11 +02:00
int operation_count ,
unsigned depth = 0 )
2022-06-26 00:54:46 +02:00
{
if ( unlikely ( depth + + > HB_MAX_NESTING_LEVEL ) ) return operation_count ;
2022-06-26 01:01:11 +02:00
if ( unlikely ( - - operation_count < 0 ) ) return operation_count ;
2022-06-26 00:54:46 +02:00
/* Check if is already visited */
if ( gids_to_retain - > has ( gid ) ) return operation_count ;
gids_to_retain - > add ( gid ) ;
for ( auto item : glyf . glyph_for_gid ( gid ) . get_composite_iterator ( ) )
operation_count =
_glyf_add_gid_and_children ( glyf ,
2022-06-26 03:06:27 +02:00
item . glyphIndex ,
2022-06-26 00:54:46 +02:00
gids_to_retain ,
2022-06-26 01:01:11 +02:00
operation_count ,
depth ) ;
2022-06-26 00:54:46 +02:00
return operation_count ;
}
2019-05-21 00:04:20 +02:00
static void
_populate_gids_to_retain ( hb_subset_plan_t * plan ,
2019-10-23 01:00:43 +02:00
bool close_over_gsub ,
2020-02-26 22:11:42 +01:00
bool close_over_gpos ,
2020-07-29 06:14:23 +02:00
bool close_over_gdef )
2018-02-06 02:26:25 +01:00
{
2022-06-25 22:38:43 +02:00
OT : : glyf_accelerator_t glyf ( plan - > source ) ;
2019-11-20 05:36:56 +01:00
# ifndef HB_NO_SUBSET_CFF
2022-01-20 19:47:17 +01:00
OT : : cff1 : : accelerator_t cff ( plan - > source ) ;
2019-11-20 05:36:56 +01:00
# endif
2018-02-09 04:22:47 +01:00
2019-05-21 00:04:20 +02:00
plan - > _glyphset_gsub - > add ( 0 ) ; // Not-def
2018-02-09 04:22:47 +01:00
2019-08-07 22:17:26 +02:00
_cmap_closure ( plan - > source , plan - > unicodes , plan - > _glyphset_gsub ) ;
2018-02-07 18:32:36 +01:00
2019-05-11 08:46:22 +02:00
# ifndef HB_NO_SUBSET_LAYOUT
2018-06-07 23:32:34 +02:00
if ( close_over_gsub )
2019-10-31 23:59:02 +01:00
// closure all glyphs/lookups/features needed for GSUB substitutions.
2022-03-24 00:28:22 +01:00
_closure_glyphs_lookups_features < GSUB > (
2022-06-30 22:14:29 +02:00
plan ,
2021-07-30 00:07:13 +02:00
plan - > _glyphset_gsub ,
plan - > gsub_lookups ,
plan - > gsub_features ,
plan - > gsub_langsys ) ;
2019-10-23 01:00:43 +02:00
if ( close_over_gpos )
2022-06-25 01:14:30 +02:00
_closure_glyphs_lookups_features < GPOS > (
2022-06-30 22:14:29 +02:00
plan ,
2021-07-30 00:07:13 +02:00
plan - > _glyphset_gsub ,
plan - > gpos_lookups ,
plan - > gpos_features ,
plan - > gpos_langsys ) ;
2019-05-11 08:46:22 +02:00
# endif
2019-05-21 00:04:20 +02:00
_remove_invalid_gids ( plan - > _glyphset_gsub , plan - > source - > get_num_glyphs ( ) ) ;
2018-06-07 23:32:34 +02:00
2021-09-20 23:42:51 +02: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-10-03 05:32:30 +02: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-06-18 23:14:20 +02:00
2021-12-06 04:27:57 +01:00
hb_set_set ( plan - > _glyphset_colred , & cur_glyphset ) ;
2022-05-05 18:33:50 +02:00
/* Populate a full set of glyphs to retain by adding all referenced
* composite glyphs . */
if ( glyf . has_data ( ) )
for ( hb_codepoint_t gid : cur_glyphset )
2022-06-26 01:01:11 +02:00
_glyf_add_gid_and_children ( glyf , gid , plan - > _glyphset ,
cur_glyphset . get_population ( ) * HB_COMPOSITE_OPERATIONS_PER_GLYPH ) ;
2022-05-05 18:33:50 +02:00
else
plan - > _glyphset - > union_ ( cur_glyphset ) ;
2019-05-11 08:46:22 +02:00
# ifndef HB_NO_SUBSET_CFF
2022-05-05 18:33:50 +02:00
if ( cff . is_valid ( ) )
for ( hb_codepoint_t gid : cur_glyphset )
2019-05-21 00:04:20 +02:00
_add_cff_seac_components ( cff , gid , plan - > _glyphset ) ;
2019-05-11 08:46:22 +02:00
# endif
2018-05-30 21:23:51 +02:00
2019-05-21 00:04:20 +02:00
_remove_invalid_gids ( plan - > _glyphset , plan - > source - > get_num_glyphs ( ) ) ;
2021-05-11 20:44:32 +02:00
2018-11-16 07:48:26 +01:00
2020-02-26 22:11:42 +01:00
# ifndef HB_NO_VAR
if ( close_over_gdef )
2020-10-06 19:26:17 +02:00
_collect_layout_variation_indices ( plan - > source ,
2021-06-09 22:46:35 +02:00
plan - > _glyphset_gsub ,
plan - > gpos_lookups ,
plan - > layout_variation_indices ,
plan - > layout_variation_idx_map ) ;
2020-02-26 22:11:42 +01:00
# endif
2018-02-06 02:26:25 +01:00
}
2018-02-06 00:22:30 +01:00
2022-05-18 23:42:28 +02:00
static void
_create_glyph_map_gsub ( const hb_set_t * glyph_set_gsub ,
const hb_map_t * glyph_map ,
hb_map_t * out )
{
+ hb_iter ( glyph_set_gsub )
| hb_map ( [ & ] ( hb_codepoint_t gid ) {
return hb_pair_t < hb_codepoint_t , hb_codepoint_t > ( gid ,
glyph_map - > get ( gid ) ) ;
} )
| hb_sink ( out )
;
}
2018-05-30 21:23:51 +02:00
static void
2019-05-09 01:33:03 +02:00
_create_old_gid_to_new_gid_map ( const hb_face_t * face ,
2021-06-09 22:46:35 +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 */ )
2018-05-30 21:23:51 +02:00
{
2022-05-18 20:34:27 +02:00
unsigned pop = all_gids_to_retain - > get_population ( ) ;
reverse_glyph_map - > resize ( pop ) ;
glyph_map - > resize ( pop ) ;
2019-05-09 01:33:03 +02:00
if ( ! retain_gids )
2019-01-19 02:49:35 +01:00
{
2019-05-09 01:33:03 +02:00
+ hb_enumerate ( hb_iter ( all_gids_to_retain ) , ( hb_codepoint_t ) 0 )
| hb_sink ( reverse_glyph_map )
;
* num_glyphs = reverse_glyph_map - > get_population ( ) ;
2022-05-18 20:34:27 +02:00
}
else
{
2019-05-09 01:33:03 +02:00
+ hb_iter ( all_gids_to_retain )
2019-05-16 03:15:05 +02:00
| hb_map ( [ ] ( hb_codepoint_t _ ) {
2019-05-09 01:33:03 +02:00
return hb_pair_t < hb_codepoint_t , hb_codepoint_t > ( _ , _ ) ;
} )
2019-05-14 02:35:02 +02:00
| hb_sink ( reverse_glyph_map )
2019-05-09 01:33:03 +02:00
;
2022-05-05 18:48:24 +02:00
hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID ;
hb_set_previous ( all_gids_to_retain , & max_glyph ) ;
2019-05-15 18:42:38 +02:00
* num_glyphs = max_glyph + 1 ;
2019-01-19 02:49:35 +01:00
}
2019-05-09 01:33:03 +02:00
+ reverse_glyph_map - > iter ( )
| hb_map ( & hb_pair_t < hb_codepoint_t , hb_codepoint_t > : : reverse )
| hb_sink ( glyph_map )
;
2018-05-30 21:23:51 +02:00
}
2019-05-13 18:38:42 +02:00
static void
2019-08-24 15:27:14 +02:00
_nameid_closure ( hb_face_t * face ,
hb_set_t * nameids )
2019-05-13 18:38:42 +02:00
{
2019-08-04 09:01:31 +02:00
# ifndef HB_NO_STYLE
2019-06-20 03:42:39 +02:00
face - > table . STAT - > collect_name_ids ( nameids ) ;
2019-06-20 03:36:35 +02:00
# endif
2019-06-20 04:26:22 +02:00
# ifndef HB_NO_VAR
2019-06-20 03:42:39 +02:00
face - > table . fvar - > collect_name_ids ( nameids ) ;
2019-06-20 04:26:22 +02:00
# endif
2019-05-13 18:38:42 +02:00
}
2018-02-06 00:22:30 +01:00
/**
2022-02-12 01:01:33 +01:00
* hb_subset_plan_create_or_fail :
2021-06-28 21:57:39 +02:00
* @ face : font face to create the plan for .
2021-07-26 02:13:49 +02:00
* @ input : a # hb_subset_input_t input .
2021-06-28 21:57:39 +02:00
*
2018-02-06 00:22:30 +01:00
* Computes a plan for subsetting the supplied face according
2018-08-30 03:09:55 +02:00
* to a provided input . The plan describes
2018-02-06 00:22:30 +01:00
* which tables and glyphs should be retained .
*
2021-07-26 02:13:49 +02:00
* Return value : ( transfer full ) : New subset plan . Destroy with
2022-02-12 01:01:33 +01:00
* hb_subset_plan_destroy ( ) . If there is a failure creating the plan
* nullptr will be returned .
2018-02-06 00:22:30 +01:00
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2018-02-06 00:22:30 +01:00
* */
hb_subset_plan_t *
2022-02-12 01:01:33 +01:00
hb_subset_plan_create_or_fail ( hb_face_t * face ,
const hb_subset_input_t * input )
2018-02-06 00:22:30 +01:00
{
2020-07-29 03:31:46 +02:00
hb_subset_plan_t * plan ;
2020-07-29 06:03:32 +02:00
if ( unlikely ( ! ( plan = hb_object_create < hb_subset_plan_t > ( ) ) ) )
2022-02-12 01:01:33 +01:00
return nullptr ;
2018-02-10 21:20:10 +01:00
2020-07-29 03:31:46 +02:00
plan - > successful = true ;
2021-07-30 00:07:13 +02:00
plan - > flags = input - > flags ;
2019-04-05 19:05:55 +02:00
plan - > unicodes = hb_set_create ( ) ;
2022-05-04 00:02:59 +02:00
plan - > unicode_to_new_gid_list . init ( ) ;
2021-08-30 20:16:51 +02:00
plan - > name_ids = hb_set_copy ( input - > sets . name_ids ) ;
2019-05-13 18:38:42 +02:00
_nameid_closure ( face , plan - > name_ids ) ;
2021-08-30 20:16:51 +02:00
plan - > name_languages = hb_set_copy ( input - > sets . name_languages ) ;
plan - > layout_features = hb_set_copy ( input - > sets . layout_features ) ;
2022-06-30 22:03:33 +02:00
plan - > layout_scripts = hb_set_create ( ) ;
hb_set_invert ( plan - > layout_scripts ) ;
2021-08-30 20:16:51 +02:00
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 ) ;
2018-02-15 01:05:39 +01:00
plan - > source = hb_face_reference ( face ) ;
2018-08-25 17:18:53 +02:00
plan - > dest = hb_face_builder_create ( ) ;
2019-05-21 00:04:20 +02:00
plan - > _glyphset = hb_set_create ( ) ;
plan - > _glyphset_gsub = hb_set_create ( ) ;
2021-09-20 23:42:51 +02:00
plan - > _glyphset_mathed = hb_set_create ( ) ;
2021-12-06 04:27:57 +01:00
plan - > _glyphset_colred = hb_set_create ( ) ;
2019-04-05 19:05:55 +02:00
plan - > codepoint_to_glyph = hb_map_create ( ) ;
plan - > glyph_map = hb_map_create ( ) ;
plan - > reverse_glyph_map = hb_map_create ( ) ;
2022-05-18 23:42:28 +02:00
plan - > glyph_map_gsub = hb_map_create ( ) ;
2019-10-23 01:00:43 +02:00
plan - > gsub_lookups = hb_map_create ( ) ;
plan - > gpos_lookups = hb_map_create ( ) ;
2021-01-29 00:21:26 +01:00
2021-03-25 19:39:57 +01: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 ( ) ;
2019-10-31 23:59:02 +01:00
plan - > gsub_features = hb_map_create ( ) ;
plan - > gpos_features = hb_map_create ( ) ;
2021-04-01 21:01:19 +02:00
plan - > colrv1_layers = hb_map_create ( ) ;
2021-05-11 20:44:32 +02:00
plan - > colr_palettes = hb_map_create ( ) ;
2020-02-26 22:11:42 +01:00
plan - > layout_variation_indices = hb_set_create ( ) ;
plan - > layout_variation_idx_map = hb_map_create ( ) ;
2019-05-21 00:04:20 +02:00
2022-02-12 01:01:33 +01:00
if ( unlikely ( plan - > in_error ( ) ) ) {
2022-02-12 01:19:43 +01:00
hb_subset_plan_destroy ( plan ) ;
2022-02-12 01:01:33 +01:00
return nullptr ;
2021-03-25 19:39:57 +01:00
}
2021-08-30 20:16:51 +02:00
_populate_unicodes_to_retain ( input - > sets . unicodes , input - > sets . glyphs , plan ) ;
2021-07-15 02:27:14 +02:00
2019-05-21 00:04:20 +02:00
_populate_gids_to_retain ( plan ,
2021-08-30 20:16:51 +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 ) ) ;
2019-01-18 03:55:56 +01:00
2019-01-29 03:10:56 +01:00
_create_old_gid_to_new_gid_map ( face ,
2021-07-29 20:52:14 +02:00
input - > flags & HB_SUBSET_FLAGS_RETAIN_GIDS ,
2019-03-26 17:15:56 +01:00
plan - > _glyphset ,
2019-01-19 02:49:35 +01:00
plan - > glyph_map ,
2019-08-24 15:27:14 +02:00
plan - > reverse_glyph_map ,
& plan - > _num_output_glyphs ) ;
2018-02-14 23:16:25 +01:00
2022-05-18 23:42:28 +02:00
_create_glyph_map_gsub (
plan - > _glyphset_gsub ,
plan - > glyph_map ,
plan - > glyph_map_gsub ) ;
2022-05-02 23:29:16 +02:00
// Now that we have old to new gid map update the unicode to new gid list.
2022-05-04 00:02:59 +02:00
for ( unsigned i = 0 ; i < plan - > unicode_to_new_gid_list . length ; i + + )
2022-05-02 23:29:16 +02:00
{
2022-05-04 00:02:59 +02:00
// Use raw array access for performance.
plan - > unicode_to_new_gid_list . arrayZ [ i ] . second =
plan - > glyph_map - > get ( plan - > unicode_to_new_gid_list . arrayZ [ i ] . second ) ;
2022-05-02 23:29:16 +02:00
}
2022-02-12 01:01:33 +01:00
if ( unlikely ( plan - > in_error ( ) ) ) {
2022-02-12 01:19:43 +01:00
hb_subset_plan_destroy ( plan ) ;
2022-02-12 01:01:33 +01:00
return nullptr ;
}
2018-02-06 02:26:25 +01:00
return plan ;
2018-02-06 00:22:30 +01:00
}
/**
* hb_subset_plan_destroy :
2021-07-26 02:13:49 +02:00
* @ plan : a # hb_subset_plan_t
*
* Decreases the reference count on @ plan , and if it reaches zero , destroys
* @ plan , freeing all memory .
2018-02-06 00:22:30 +01:00
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2018-02-06 00:22:30 +01:00
* */
void
hb_subset_plan_destroy ( hb_subset_plan_t * plan )
{
if ( ! hb_object_destroy ( plan ) ) return ;
2018-05-30 21:23:51 +02:00
hb_set_destroy ( plan - > unicodes ) ;
2022-05-04 00:02:59 +02:00
plan - > unicode_to_new_gid_list . fini ( ) ;
2019-04-05 19:05:55 +02:00
hb_set_destroy ( plan - > name_ids ) ;
2020-01-21 22:37:28 +01:00
hb_set_destroy ( plan - > name_languages ) ;
2021-05-20 02:33:46 +02:00
hb_set_destroy ( plan - > layout_features ) ;
2022-06-30 22:03:33 +02:00
hb_set_destroy ( plan - > layout_scripts ) ;
2020-04-23 00:58:41 +02:00
hb_set_destroy ( plan - > glyphs_requested ) ;
2019-05-16 20:29:15 +02:00
hb_set_destroy ( plan - > drop_tables ) ;
2021-07-22 22:26:03 +02:00
hb_set_destroy ( plan - > no_subset_tables ) ;
2018-02-15 01:05:39 +01:00
hb_face_destroy ( plan - > source ) ;
hb_face_destroy ( plan - > dest ) ;
2018-05-30 21:23:51 +02:00
hb_map_destroy ( plan - > codepoint_to_glyph ) ;
hb_map_destroy ( plan - > glyph_map ) ;
2019-01-19 03:33:21 +01:00
hb_map_destroy ( plan - > reverse_glyph_map ) ;
2022-05-18 23:42:28 +02:00
hb_map_destroy ( plan - > glyph_map_gsub ) ;
2019-01-29 01:59:15 +01:00
hb_set_destroy ( plan - > _glyphset ) ;
2019-05-21 00:04:20 +02:00
hb_set_destroy ( plan - > _glyphset_gsub ) ;
2021-09-20 23:42:51 +02:00
hb_set_destroy ( plan - > _glyphset_mathed ) ;
2021-12-06 04:27:57 +01:00
hb_set_destroy ( plan - > _glyphset_colred ) ;
2019-10-23 01:00:43 +02:00
hb_map_destroy ( plan - > gsub_lookups ) ;
hb_map_destroy ( plan - > gpos_lookups ) ;
2019-10-31 23:59:02 +01:00
hb_map_destroy ( plan - > gsub_features ) ;
hb_map_destroy ( plan - > gpos_features ) ;
2021-04-01 21:01:19 +02:00
hb_map_destroy ( plan - > colrv1_layers ) ;
2021-05-11 20:44:32 +02:00
hb_map_destroy ( plan - > colr_palettes ) ;
2020-02-26 22:11:42 +01:00
hb_set_destroy ( plan - > layout_variation_indices ) ;
hb_map_destroy ( plan - > layout_variation_idx_map ) ;
2019-10-31 23:59:02 +01:00
2021-03-25 19:39:57 +01:00
if ( plan - > gsub_langsys )
{
hb_object_destroy ( plan - > gsub_langsys ) ;
plan - > gsub_langsys - > fini_shallow ( ) ;
2021-07-08 18:58:50 +02:00
hb_free ( plan - > gsub_langsys ) ;
2021-03-25 19:39:57 +01:00
}
if ( plan - > gpos_langsys )
{
hb_object_destroy ( plan - > gpos_langsys ) ;
plan - > gpos_langsys - > fini_shallow ( ) ;
2021-07-08 18:58:50 +02:00
hb_free ( plan - > gpos_langsys ) ;
2021-03-25 19:39:57 +01:00
}
2018-02-15 01:05:39 +01:00
2021-07-08 18:58:50 +02:00
hb_free ( plan ) ;
2018-02-06 00:22:30 +01:00
}
2022-02-11 21:44:58 +01:00
/**
* hb_subset_plan_old_to_new_glyph_mapping :
* @ plan : a subsetting plan .
*
2022-02-25 03:22:33 +01:00
* 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 .
2022-02-11 21:44:58 +01:00
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 21:44:58 +01:00
* */
const hb_map_t *
hb_subset_plan_old_to_new_glyph_mapping ( const hb_subset_plan_t * plan )
{
return plan - > glyph_map ;
}
/**
2022-02-25 03:22:33 +01:00
* hb_subset_plan_new_to_old_glyph_mapping :
2022-02-11 21:44:58 +01:00
* @ 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 .
*
2022-02-25 03:22:33 +01:00
* Return value : ( transfer none ) :
* A pointer to the # hb_map_t of the mapping .
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 21:44:58 +01:00
* */
const hb_map_t *
hb_subset_plan_new_to_old_glyph_mapping ( const hb_subset_plan_t * plan )
{
return plan - > reverse_glyph_map ;
}
/**
2022-03-01 11:01:18 +01:00
* hb_subset_plan_unicode_to_old_glyph_mapping :
2022-02-11 21:44:58 +01:00
* @ plan : a subsetting plan .
*
* Returns the mapping between codepoints in the original font and the
* associated glyph id in the original font .
*
2022-02-25 03:22:33 +01:00
* Return value : ( transfer none ) :
* A pointer to the # hb_map_t of the mapping .
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 21:44:58 +01:00
* */
const hb_map_t *
2022-02-28 22:45:40 +01:00
hb_subset_plan_unicode_to_old_glyph_mapping ( const hb_subset_plan_t * plan )
2022-02-11 21:44:58 +01:00
{
return plan - > codepoint_to_glyph ;
}
2022-02-11 23:54:23 +01:00
/**
* hb_subset_plan_reference : ( skip )
* @ plan : a # hb_subset_plan_t object .
*
* Increases the reference count on @ plan .
*
* Return value : @ plan .
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 23:54:23 +01:00
* */
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
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 23:54:23 +01:00
* */
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
*
2022-03-01 20:27:32 +01:00
* Since : 4.0 .0
2022-02-11 23:54:23 +01:00
* */
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 ) ;
}