1 | /* Pango |
2 | * reorder-items.c: |
3 | * |
4 | * Copyright (C) 1999 Red Hat Software |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public |
17 | * License along with this library; if not, write to the |
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | * Boston, MA 02111-1307, USA. |
20 | */ |
21 | |
22 | #include "config.h" |
23 | #include "pango-item.h" |
24 | |
25 | /* |
26 | * NB: The contents of the file implement the exact same algorithm |
27 | * pango-layout.c:pango_layout_line_reorder(). |
28 | */ |
29 | |
30 | static GList *reorder_items_recurse (GList *items, int n_items); |
31 | |
32 | /** |
33 | * pango_reorder_items: |
34 | * @items: (element-type Pango.Item): a `GList` of `PangoItem` |
35 | * in logical order. |
36 | * |
37 | * Reorder items from logical order to visual order. |
38 | * |
39 | * The visual order is determined from the associated directional |
40 | * levels of the items. The original list is unmodified. |
41 | * |
42 | * (Please open a bug if you use this function. |
43 | * It is not a particularly convenient interface, and the code |
44 | * is duplicated elsewhere in Pango for that reason.) |
45 | * |
46 | * Returns: (transfer full) (element-type Pango.Item): a `GList` |
47 | * of `PangoItem` structures in visual order. |
48 | */ |
49 | GList * |
50 | pango_reorder_items (GList *items) |
51 | { |
52 | return reorder_items_recurse (items, n_items: g_list_length (list: items)); |
53 | } |
54 | |
55 | static GList * |
56 | reorder_items_recurse (GList *items, |
57 | int n_items) |
58 | { |
59 | GList *tmp_list, *level_start_node; |
60 | int i, level_start_i; |
61 | int min_level = G_MAXINT; |
62 | GList *result = NULL; |
63 | |
64 | if (n_items == 0) |
65 | return NULL; |
66 | |
67 | tmp_list = items; |
68 | for (i=0; i<n_items; i++) |
69 | { |
70 | PangoItem *item = tmp_list->data; |
71 | |
72 | min_level = MIN (min_level, item->analysis.level); |
73 | |
74 | tmp_list = tmp_list->next; |
75 | } |
76 | |
77 | level_start_i = 0; |
78 | level_start_node = items; |
79 | tmp_list = items; |
80 | for (i=0; i<n_items; i++) |
81 | { |
82 | PangoItem *item = tmp_list->data; |
83 | |
84 | if (item->analysis.level == min_level) |
85 | { |
86 | if (min_level % 2) |
87 | { |
88 | if (i > level_start_i) |
89 | result = g_list_concat (list1: reorder_items_recurse (items: level_start_node, n_items: i - level_start_i), list2: result); |
90 | result = g_list_prepend (list: result, data: item); |
91 | } |
92 | else |
93 | { |
94 | if (i > level_start_i) |
95 | result = g_list_concat (list1: result, list2: reorder_items_recurse (items: level_start_node, n_items: i - level_start_i)); |
96 | result = g_list_append (list: result, data: item); |
97 | } |
98 | |
99 | level_start_i = i + 1; |
100 | level_start_node = tmp_list->next; |
101 | } |
102 | |
103 | tmp_list = tmp_list->next; |
104 | } |
105 | |
106 | if (min_level % 2) |
107 | { |
108 | if (i > level_start_i) |
109 | result = g_list_concat (list1: reorder_items_recurse (items: level_start_node, n_items: i - level_start_i), list2: result); |
110 | } |
111 | else |
112 | { |
113 | if (i > level_start_i) |
114 | result = g_list_concat (list1: result, list2: reorder_items_recurse (items: level_start_node, n_items: i - level_start_i)); |
115 | } |
116 | |
117 | return result; |
118 | } |
119 | |