81 lines
3.1 KiB
Diff
81 lines
3.1 KiB
Diff
# UNDF: UNDF-2026-000001208
|
|
# UNDF: UNDF-2026-XXXXXXXXX
|
|
--- a/libview/ev-page-accessible.c
|
|
+++ b/libview/ev-page-accessible.c
|
|
@@ -95,6 +95,8 @@ static void
|
|
ev_page_accessible_get_children (EvPageAccessible *self)
|
|
{
|
|
EvView *view;
|
|
+ GHashTable *link_set = NULL;
|
|
+ GHashTable *image_set = NULL;
|
|
+ GHashTable *field_set = NULL;
|
|
EvMappingList *images;
|
|
EvMappingList *links;
|
|
EvMappingList *fields;
|
|
@@ -121,20 +123,56 @@ ev_page_accessible_get_children (EvPageAccessible *self)
|
|
children = g_list_concat (children, g_list_copy (ev_mapping_list_get_list (images)));
|
|
children = g_list_concat (children, g_list_copy (ev_mapping_list_get_list (fields)));
|
|
|
|
+ /* Build O(1) pointer-keyed lookup tables so our per-element
|
|
+ * classification below is O(1) rather than O(N) per call.
|
|
+ * Previously ev_mapping_list_find() was called up to 3 times per
|
|
+ * element, each doing a full GList scan: O(N^2) total.
|
|
+ */
|
|
+ if (links) {
|
|
+ GList *l;
|
|
+ link_set = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
+ for (l = ev_mapping_list_get_list (links); l; l = l->next) {
|
|
+ EvMapping *m = (EvMapping *)l->data;
|
|
+ g_hash_table_insert (link_set, m->data, m);
|
|
+ }
|
|
+ }
|
|
+ if (images) {
|
|
+ GList *l;
|
|
+ image_set = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
+ for (l = ev_mapping_list_get_list (images); l; l = l->next) {
|
|
+ EvMapping *m = (EvMapping *)l->data;
|
|
+ g_hash_table_insert (image_set, m->data, m);
|
|
+ }
|
|
+ }
|
|
+ if (fields) {
|
|
+ GList *l;
|
|
+ field_set = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
+ for (l = ev_mapping_list_get_list (fields); l; l = l->next) {
|
|
+ EvMapping *m = (EvMapping *)l->data;
|
|
+ g_hash_table_insert (field_set, m->data, m);
|
|
+ }
|
|
+ }
|
|
+
|
|
children = g_list_sort (children, (GCompareFunc) compare_mappings);
|
|
self->priv->children = g_ptr_array_new_full (g_list_length (children), (GDestroyNotify) g_object_unref);
|
|
|
|
for (list = children; list && list->data; list = list->next) {
|
|
EvMapping *mapping = list->data;
|
|
AtkObject *child = NULL;
|
|
|
|
- if (links && ev_mapping_list_find (links, mapping->data)) {
|
|
+ if (link_set && g_hash_table_lookup (link_set, mapping->data)) {
|
|
EvLinkAccessible *link = ev_link_accessible_new (self, EV_LINK (mapping->data), &mapping->area);
|
|
AtkHyperlink *atk_link = atk_hyperlink_impl_get_hyperlink (ATK_HYPERLINK_IMPL (link));
|
|
|
|
child = atk_hyperlink_get_object (atk_link, 0);
|
|
- } else if (images && ev_mapping_list_find (images, mapping->data))
|
|
+ } else if (image_set && g_hash_table_lookup (image_set, mapping->data))
|
|
child = ATK_OBJECT (ev_image_accessible_new (self, EV_IMAGE (mapping->data), &mapping->area));
|
|
- else if (fields && ev_mapping_list_find (fields, mapping->data))
|
|
+ else if (field_set && g_hash_table_lookup (field_set, mapping->data))
|
|
child = ATK_OBJECT (ev_form_field_accessible_new (self, EV_FORM_FIELD (mapping->data), &mapping->area));
|
|
|
|
if (child)
|
|
g_ptr_array_add (self->priv->children, child);
|
|
}
|
|
|
|
g_list_free (children);
|
|
+
|
|
+ if (link_set)
|
|
+ g_hash_table_destroy (link_set);
|
|
+ if (image_set)
|
|
+ g_hash_table_destroy (image_set);
|
|
+ if (field_set)
|
|
+ g_hash_table_destroy (field_set);
|
|
}
|