Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
Characters
Commits
1de951ff
Commit
1de951ff
authored
Aug 17, 2015
by
Daiki Ueno
Browse files
Respect OpenType font features
parent
2befc65d
Changes
8
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
1de951ff
...
...
@@ -40,7 +40,8 @@ PKG_CHECK_MODULES([DEPS], [gdk-3.0
glib-2.0
gobject-2.0
gtk+-3.0
gjs-1.0 >= $GJS_MIN_VERSION])
gjs-1.0 >= $GJS_MIN_VERSION
harfbuzz >= 1.0.0])
AC_PATH_PROG([GJS],[gjs])
...
...
data/application.css
View file @
1de951ff
...
...
@@ -14,6 +14,10 @@ Gjs_MenuPopover .list-row {
padding
:
5px
6px
;
}
.toolbar.osd
{
padding
:
1px
;
}
.banner
{
color
:
@
insensitive_fg_color
;
}
...
...
data/character.ui
View file @
1de951ff
...
...
@@ -4,28 +4,109 @@
<template
class=
"Gjs_CharacterDialog"
parent=
"GtkDialog"
>
<child
internal-child=
"vbox"
>
<object
class=
"GtkBox"
id=
"vbox1"
>
<property
name=
"halign"
>
fill
</property>
<property
name=
"hexpand"
>
True
</property>
<child>
<object
class=
"GtkStack"
id=
"main-stack"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"halign"
>
fill
</property>
<property
name=
"hexpand"
>
True
</property>
<child>
<object
class=
"GtkGrid"
id=
"character-grid"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"halign"
>
center
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"valign"
>
fill
</property>
<property
name=
"border_width"
>
5
</property>
<property
name=
"orientation"
>
vertical
</property>
<property
name=
"row_spacing"
>
50
</property>
<child>
<object
class=
"GtkLabel"
id=
"character-label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"ellipsize"
>
end
</property>
<property
name=
"halign"
>
center
</property>
<property
name=
"valign"
>
center
</property>
<style>
<class
name=
"character-label"
/>
</style>
<object
class=
"GtkEventBox"
id=
"eventbox"
>
<child>
<object
class=
"GtkOverlay"
id=
"character-overlay"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<child>
<object
class=
"GtkLabel"
id=
"character-label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"margin-top"
>
34
</property>
<style>
<class
name=
"character-label"
/>
</style>
</object>
</child>
<child
type=
"overlay"
>
<object
class=
"GtkRevealer"
id=
"revealer"
>
<property
name=
"valign"
>
start
</property>
<child>
<object
class=
"GtkToolbar"
id=
"toolbar"
>
<property
name=
"opacity"
>
0.4
</property>
<property
name=
"margin"
>
2
</property>
<property
name=
"halign"
>
center
</property>
<property
name=
"valign"
>
end
</property>
<property
name=
"hexpand"
>
False
</property>
<property
name=
"receives_default"
>
True
</property>
<style>
<class
name=
"osd"
/>
</style>
<child>
<object
class=
"GtkToolItem"
>
<property
name=
"visible"
>
True
</property>
<child>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<style>
<class
name=
"linked"
/>
</style>
<child>
<object
class=
"GtkButton"
id=
"previous-button"
>
<property
name=
"visible"
>
True
</property>
<style>
<class
name=
"image-button"
/>
</style>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"icon-name"
>
pan-start-symbolic
</property>
<property
name=
"icon-size"
>
1
</property>
</object>
</child>
</object>
</child>
<child>
<object
class=
"GtkButton"
id=
"next-button"
>
<property
name=
"visible"
>
True
</property>
<style>
<class
name=
"image-button"
/>
</style>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"icon-name"
>
pan-end-symbolic
</property>
<property
name=
"icon-size"
>
1
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property
name=
"pass-through"
>
True
</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property
name=
"left_attach"
>
0
</property>
...
...
@@ -38,6 +119,8 @@
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
False
</property>
<property
name=
"hexpand"
>
False
</property>
<property
name=
"halign"
>
center
</property>
</object>
<packing>
<property
name=
"left_attach"
>
0
</property>
...
...
@@ -49,7 +132,9 @@
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"halign"
>
center
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"selectable"
>
True
</property>
<property
name=
"justify"
>
center
</property>
<style>
<class
name=
"detail-label"
/>
</style>
...
...
@@ -65,39 +150,39 @@
</packing>
</child>
<child>
<object
class=
"GtkScrolledWindow"
id=
"related-scrolled"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"margin_start"
>
6
</property>
<property
name=
"margin_end"
>
6
</property>
<property
name=
"margin_top"
>
6
</property>
<property
name=
"margin_bottom"
>
6
</property>
<property
name=
"hscrollbar_policy"
>
never
</property>
<property
name=
"vexpand"
>
True
</property>
<style>
<class
name=
"related"
/>
</style>
<object
class=
"GtkScrolledWindow"
id=
"related-scrolled"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"margin_start"
>
6
</property>
<property
name=
"margin_end"
>
6
</property>
<property
name=
"margin_top"
>
6
</property>
<property
name=
"margin_bottom"
>
6
</property>
<property
name=
"hscrollbar_policy"
>
never
</property>
<property
name=
"vexpand"
>
True
</property>
<style>
<class
name=
"related"
/>
</style>
<child>
<object
class=
"GtkViewport"
id=
"related-viewport"
>
<child>
<object
class=
"GtkViewport"
id=
"related-viewport"
>
<object
class=
"GtkListBox"
id=
"related-listbox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<child>
<object
class=
"GtkListBox"
id=
"related-listbox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<child>
<placeholder/>
</child>
</object>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
<property
name=
"name"
>
related
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"name"
>
related
</property>
</packing>
</child>
</object>
</child>
</template>
</object>
</child>
</template>
</interface>
lib/gc.c
View file @
1de951ff
...
...
@@ -17,6 +17,8 @@
#define PANGO_ENABLE_ENGINE 1
#include
<pango/pangofc-font.h>
#include
<harfbuzz/hb-ft.h>
#include
<harfbuzz/hb-ot.h>
static
const
uc_block_t
*
all_blocks
;
static
size_t
all_block_count
;
...
...
@@ -926,6 +928,177 @@ gc_pango_context_font_has_glyph (PangoContext *context,
return
retval
==
0
;
}
void
gc_pango_layout_set_font_features
(
PangoLayout
*
layout
,
gchar
*
features
)
{
PangoAttrList
*
attr_list
;
attr_list
=
pango_layout_get_attributes
(
layout
);
if
(
!
attr_list
)
{
attr_list
=
pango_attr_list_new
();
pango_layout_set_attributes
(
layout
,
attr_list
);
}
pango_attr_list_change
(
attr_list
,
pango_attr_font_features_new
(
features
));
}
/**
* gc_pango_list_font_features:
* @font: a #PangoFont
*
* Returns: (transfer full) (nullable) (array zero-terminated=1): A
* list of OpenType feature tags.
*/
gchar
**
gc_pango_list_font_features
(
PangoFont
*
font
)
{
#ifdef HAVE_PANGOFT2
if
(
PANGO_IS_FC_FONT
(
font
))
{
FT_Face
ftface
=
pango_fc_font_lock_face
(
PANGO_FC_FONT
(
font
));
hb_face_t
*
hbface
=
hb_ft_face_create_cached
(
ftface
);
unsigned
int
count
,
i
;
hb_tag_t
*
features
;
gchar
buf
[
5
];
gchar
**
result
;
count
=
hb_ot_layout_table_get_feature_tags
(
hbface
,
HB_OT_TAG_GSUB
,
0
,
NULL
,
NULL
);
features
=
g_new
(
hb_tag_t
,
count
+
1
);
hb_ot_layout_table_get_feature_tags
(
hbface
,
HB_OT_TAG_GSUB
,
0
,
&
count
,
features
);
result
=
g_new0
(
gchar
*
,
count
+
1
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
buf
[
4
]
=
'\0'
;
hb_tag_to_string
(
features
[
i
],
buf
);
result
[
i
]
=
g_strdup
(
buf
);
}
g_free
(
features
);
pango_fc_font_unlock_face
(
PANGO_FC_FONT
(
font
));
return
result
;
}
#endif
return
NULL
;
}
static
void
collect_features
(
gpointer
key
,
gpointer
value
,
gpointer
user_data
)
{
GArray
*
result
=
user_data
;
g_array_append_val
(
result
,
value
);
}
/**
* gc_pango_list_effective_font_features:
* @font: a #PangoFont
* @font_features: (array zero-terminated=1) (element-type utf8): a
* list of font features
* @uc: a #gunichar
*
* Returns: (transfer full) (nullable) (array zero-terminated=1): A
* list of OpenType feature tags followed by a space and the index.
*/
gchar
**
gc_pango_list_effective_font_features
(
PangoFont
*
font
,
gchar
**
font_features
,
gunichar
uc
)
{
GHashTable
*
table
=
g_hash_table_new
(
g_direct_hash
,
g_direct_equal
);
GArray
*
result
=
g_array_sized_new
(
TRUE
,
FALSE
,
sizeof
(
gchar
*
),
g_strv_length
(
font_features
));
#ifdef HAVE_PANGOFT2
if
(
PANGO_IS_FC_FONT
(
font
))
{
FT_Face
ftface
=
pango_fc_font_lock_face
(
PANGO_FC_FONT
(
font
));
hb_face_t
*
hbface
=
hb_ft_face_create_cached
(
ftface
);
hb_buffer_t
*
buffer
;
hb_font_t
*
hbfont
=
NULL
;
hb_glyph_info_t
*
infos
;
unsigned
int
length
;
hb_feature_t
features
[
1
];
hb_codepoint_t
base_gid
=
0
;
gchar
**
p
,
*
last
;
gint
index
;
uint8_t
utf8
[
6
];
size_t
utf8_length
=
G_N_ELEMENTS
(
utf8
);
u32_to_u8
(
&
uc
,
1
,
utf8
,
&
utf8_length
);
hbfont
=
hb_font_create
(
hbface
);
hb_ft_font_set_funcs
(
hbfont
);
hb_font_set_scale
(
hbfont
,
10
,
10
);
buffer
=
hb_buffer_create
();
hb_buffer_set_direction
(
buffer
,
HB_DIRECTION_LTR
);
hb_buffer_add_utf8
(
buffer
,
(
const
char
*
)
utf8
,
utf8_length
,
0
,
1
);
hb_shape
(
hbfont
,
buffer
,
NULL
,
0
);
infos
=
hb_buffer_get_glyph_infos
(
buffer
,
&
length
);
if
(
length
>
0
)
base_gid
=
infos
[
0
].
codepoint
;
hb_buffer_destroy
(
buffer
);
last
=
NULL
;
index
=
0
;
for
(
p
=
font_features
;
*
p
;
p
++
)
{
gchar
*
feature_string
;
hb_codepoint_t
gid
=
0
;
/* OpenType features which could produce alternative glyphs:
calt, cv00-99, jp04, jp78, jp83, jp90, salt, ss00-20 */
if
(
!
(
strlen
(
*
p
)
==
4
&&
(
strcmp
(
*
p
,
"calt"
)
==
0
||
(
strcmp
(
*
p
,
"cv00"
)
>=
0
&&
strcmp
(
*
p
,
"cv99"
)
<=
0
)
||
strcmp
(
*
p
,
"jp78"
)
==
0
||
strcmp
(
*
p
,
"jp83"
)
==
0
||
strcmp
(
*
p
,
"jp90"
)
==
0
||
strcmp
(
*
p
,
"jp04"
)
==
0
||
strcmp
(
*
p
,
"salt"
)
==
0
||
(
strcmp
(
*
p
,
"ss00"
)
>=
0
&&
strcmp
(
*
p
,
"ss20"
)
<=
0
))))
continue
;
if
(
last
!=
NULL
&&
strcmp
(
*
p
,
last
)
==
0
)
index
++
;
else
index
=
0
;
last
=
*
p
;
feature_string
=
g_strdup_printf
(
"%s %d"
,
*
p
,
index
);
hb_feature_from_string
(
feature_string
,
6
,
&
features
[
0
]);
buffer
=
hb_buffer_create
();
hb_buffer_set_direction
(
buffer
,
HB_DIRECTION_LTR
);
hb_buffer_add_utf8
(
buffer
,
(
const
char
*
)
utf8
,
utf8_length
,
0
,
1
);
hb_shape
(
hbfont
,
buffer
,
features
,
1
);
infos
=
hb_buffer_get_glyph_infos
(
buffer
,
&
length
);
if
(
length
>
0
)
gid
=
infos
[
0
].
codepoint
;
hb_buffer_destroy
(
buffer
);
if
(
gid
!=
base_gid
&&
!
g_hash_table_contains
(
table
,
GINT_TO_POINTER
(
gid
)))
g_hash_table_insert
(
table
,
GINT_TO_POINTER
(
gid
),
feature_string
);
else
g_free
(
feature_string
);
}
hb_font_destroy
(
hbfont
);
pango_fc_font_unlock_face
(
PANGO_FC_FONT
(
font
));
}
#endif
g_hash_table_foreach
(
table
,
collect_features
,
result
);
g_hash_table_unref
(
table
);
return
(
gchar
**
)
g_array_free
(
result
,
FALSE
);
}
/**
* gc_get_current_language:
*
...
...
lib/gc.h
View file @
1de951ff
...
...
@@ -72,6 +72,15 @@ GtkClipboard *gc_gtk_clipboard_get (void);
/* Pango support. PangoAttrFallback is not accessible from GI. */
void
gc_pango_layout_disable_fallback
(
PangoLayout
*
layout
);
void
gc_pango_layout_set_font_features
(
PangoLayout
*
layout
,
gchar
*
features
);
gchar
**
gc_pango_list_font_features
(
PangoFont
*
font
);
gchar
**
gc_pango_list_effective_font_features
(
PangoFont
*
font
,
gchar
**
font_features
,
gunichar
uc
);
gboolean
gc_pango_context_font_has_glyph
(
PangoContext
*
context
,
...
...
src/character.js
View file @
1de951ff
...
...
@@ -21,22 +21,27 @@ const Params = imports.params;
const
Gio
=
imports
.
gi
.
Gio
;
const
GLib
=
imports
.
gi
.
GLib
;
const
GObject
=
imports
.
gi
.
GObject
;
const
Gdk
=
imports
.
gi
.
Gdk
;
const
Gtk
=
imports
.
gi
.
Gtk
;
const
Pango
=
imports
.
gi
.
Pango
;
const
Gc
=
imports
.
gi
.
Gc
;
const
Main
=
imports
.
main
;
const
Util
=
imports
.
util
;
const
Mainloop
=
imports
.
mainloop
;
const
_AUTO_HIDE_TIMEOUT
=
1
;
const
CharacterDialog
=
new
Lang
.
Class
({
Name
:
'
CharacterDialog
'
,
Extends
:
Gtk
.
Dialog
,
Template
:
'
resource:///org/gnome/Characters/character.ui
'
,
InternalChildren
:
[
'
main-stack
'
,
'
character-label
'
,
'
detail-label
'
,
'
copy-button
'
,
'
related-listbox
'
],
InternalChildren
:
[
'
main-stack
'
,
'
eventbox
'
,
'
revealer
'
,
'
toolbar
'
,
'
previous-button
'
,
'
next-button
'
,
'
character-label
'
,
'
detail-label
'
,
'
copy-button
'
,
'
related-listbox
'
],
_init
:
function
(
params
)
{
let
filtered
=
Params
.
filter
(
params
,
{
character
:
null
,
fontDescription
:
null
});
fontDescription
:
null
,
fontFeatures
:
null
});
params
=
Params
.
fill
(
params
,
{
use_header_bar
:
true
,
width_request
:
400
,
height_request
:
400
});
...
...
@@ -64,6 +69,122 @@ const CharacterDialog = new Lang.Class({
this
.
_character_label
.
override_font
(
filtered
.
fontDescription
);
this
.
_setCharacter
(
filtered
.
character
);
this
.
_fontFeaturesIndex
=
0
;
this
.
_fontFeatures
=
[];
if
(
filtered
.
fontFeatures
.
length
>
0
)
{
let
context
=
this
.
get_pango_context
();
let
font
=
context
.
load_font
(
filtered
.
fontDescription
);
let
effective
=
Gc
.
pango_list_effective_font_features
(
font
,
filtered
.
fontFeatures
,
filtered
.
character
);
if
(
effective
.
length
>
0
)
{
this
.
_eventbox
.
connect
(
'
enter-notify-event
'
,
Lang
.
bind
(
this
,
this
.
_handleInitialEnterNotify
));
this
.
_eventbox
.
connect
(
'
leave-notify-event
'
,
Lang
.
bind
(
this
,
this
.
_handleLeaveNotify
));
this
.
_previous_button
.
connect
(
'
clicked
'
,
Lang
.
bind
(
this
,
this
.
_previousButtonClicked
));
this
.
_next_button
.
connect
(
'
clicked
'
,
Lang
.
bind
(
this
,
this
.
_nextButtonClicked
));
let
widgets
=
[
this
.
_toolbar
,
this
.
_previous_button
,
this
.
_next_button
];
for
(
let
index
in
widgets
)
{
widgets
[
index
].
connect
(
'
enter-notify-event
'
,
Lang
.
bind
(
this
,
this
.
_handleEnterNotify
));
widgets
[
index
].
connect
(
'
leave-notify-event
'
,
Lang
.
bind
(
this
,
this
.
_handleLeaveNotify
));
}
this
.
_fontFeatures
=
this
.
_fontFeatures
.
concat
(
effective
);
this
.
_fontFeatures
.
unshift
(
''
);
}
}
this
.
_autoHideId
=
0
;
this
.
_previous_button
.
set_sensitive
(
false
);
if
(
this
.
_fontFeatures
.
length
>
0
)
this
.
_next_button
.
set_sensitive
(
true
);
},
_autoHide
:
function
()
{
this
.
_autoHideId
=
0
;
this
.
_revealer
.
set_reveal_child
(
false
);
return
false
;
},
_unqueueAutoHide
:
function
()
{
if
(
this
.
_autoHideId
==
0
)
return
;
Mainloop
.
source_remove
(
this
.
_autoHideId
);
this
.
_autoHideId
=
0
;
},
_queueAutoHide
:
function
()
{
this
.
_unqueueAutoHide
();
this
.
_autoHideId
=
Mainloop
.
timeout_add_seconds
(
_AUTO_HIDE_TIMEOUT
,
Lang
.
bind
(
this
,
this
.
_autoHide
));
},
_handleInitialEnterNotify
:
function
(
box
,
event
)
{
if
(
this
.
_revealer
.
get_child_revealed
())
return
false
;
this
.
_revealer
.
set_reveal_child
(
true
);
return
true
;
},
_handleEnterNotify
:
function
(
widget
,
event
)
{
this
.
_unqueueAutoHide
();
return
false
;
},
_handleLeaveNotify
:
function
(
widget
,
event
)
{
this
.
_queueAutoHide
();
return
false
;
},
_changeFeature
:
function
(
feature
)
{
this
.
_character_label
.
set_attributes
(
null
);
let
layout
=
this
.
_character_label
.
get_layout
();
Gc
.
pango_layout_set_font_features
(
layout
,
feature
);
if
(
feature
==
''
)
this
.
_detail_label
.
label
=
this
.
_codePointLabel
+
"
\n
"
;
else
this
.
_detail_label
.
label
=
this
.
_codePointLabel
+
"
\n
"
+
_
(
"
OpenType feature: %s
"
).
format
(
feature
);
},
_previousButtonClicked
:
function
(
event
)
{
if
(
this
.
_fontFeaturesIndex
==
0
)
return
;
this
.
_fontFeaturesIndex
--
;
if
(
this
.
_fontFeaturesIndex
==
0
)
{
this
.
_previous_button
.
set_sensitive
(
false
);
// Making the button insensitive causes leave-notify and
// then auto-hide of the toolbar. Cancel it manually.
this
.
_unqueueAutoHide
();
}
this
.
_next_button
.
set_sensitive
(
true
);
this
.
_changeFeature
(
this
.
_fontFeatures
[
this
.
_fontFeaturesIndex
]);
},
_nextButtonClicked
:
function
(
event
)
{
if
(
this
.
_fontFeaturesIndex
==
this
.
_fontFeatures
.
length
-
1
)
return
;
this
.
_fontFeaturesIndex
++
;
if
(
this
.
_fontFeaturesIndex
==
this
.
_fontFeatures
.
length
-
1
)
{
this
.
_next_button
.
set_sensitive
(
false
);
// Making the button insensitive causes leave-notify and
// then auto-hide of the toolbar. Cancel it manually.
this
.
_unqueueAutoHide
();
}
this
.
_previous_button
.
set_sensitive
(
true
);
this
.
_changeFeature
(
this
.
_fontFeatures
[
this
.
_fontFeaturesIndex
]);
},
_finishSearch
:
function
(
result
)
{
...
...
@@ -111,7 +232,8 @@ const CharacterDialog = new Lang.Class({
let
codePoint
=
Util
.
toCodePoint
(
this
.
_character
);
let
codePointHex
=
codePoint
.
toString
(
16
).
toUpperCase
();
this
.
_detail_label
.
label
=
_
(
"
Unicode U+%04s
"
).
format
(
codePointHex
);
this
.
_codePointLabel
=
_
(
"
Unicode U+%04s
"
).
format
(
codePointHex
)
this
.
_detail_label
.
label
=
this
.
_codePointLabel
+
"
\n
"
;
this
.
_cancellable
.
cancel
();
this
.
_cancellable
.
reset
();
...
...
src/characterList.js
View file @
1de951ff
...
...
@@ -317,20 +317,27 @@ const CharacterListView = new Lang.Class({
return
this
.
_fontDescription
;
},
getFontFeatures
:
function
()
{
return
this
.
_fontFeatures
;
},
updateCharacterList
:
function
()
{
let
characters
=
this
.
_characters
;
let
fontDescription
=
this
.
_fontDescription
;
let
fontDescription
=
this
.
_filterFontDescription
?
this
.
_filterFontDescription
:
this
.
_fontDescription
;
let
context
=
this
.
get_pango_context
();
let
font
=
context
.
load_font
(
fontDescription
);
this
.
_fontFeatures
=
Gc
.
pango_list_font_features
(
font
);
if
(
this
.
_filterFontDescription
)
{
let
context
=
this
.
get_pango_context
();
let
filterFont
=
context
.
load_font
(
this
.
_filterFontDescription
);
let
filteredCharacters
=
[];
for
(
let
index
=
0
;
index
<
characters
.
length
;
index
++
)
{
let
uc
=
characters
[
index
];
if
(
Gc
.
pango_context_font_has_glyph
(
context
,
f
ilterF
ont
,
uc
))
if
(
Gc
.
pango_context_font_has_glyph
(
context
,
font
,
uc
))
filteredCharacters
.
push
(
uc
);