History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/font/BidiUtils.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/font/BidiUtils.java+386−0
@@ -0,0 +1,386 @@
1/*
2 * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * (C) Copyright IBM Corp. 1999-2000 - All Rights Reserved
28 *
29 * The original version of this source code and documentation is
30 * copyrighted and owned by IBM. These materials are provided
31 * under terms of a License Agreement between IBM and Sun.
32 * This technology is protected by multiple US and International
33 * patents. This notice and attribution to IBM may not be removed.
34 */
35
36package sun.font;
37
38import java.text.Bidi;
39
40public final class BidiUtils {
41
42
43
44 /**
45 * Return the level of each character into the levels array starting at start.
46 * This is a convenience method for clients who prefer to use an explicit levels
47 * array instead of iterating over the runs.
48 *
49 * @param levels the array to receive the character levels
50 * @param start the starting offset into the the array
51 * @throws IndexOutOfBoundsException if <code>start</code> is less than 0 or
52 * <code>start + getLength()</code> is greater than <code>levels.length</code>.
53 */
54 public static void getLevels(Bidi bidi, byte[] levels, int start) {
55 int limit = start + bidi.getLength();
56
57 if (start < 0 || limit > levels.length) {
58 throw new IndexOutOfBoundsException("levels.length = " + levels.length +
59 " start: " + start + " limit: " + limit);
60 }
61
62 int runCount = bidi.getRunCount();
63 int p = start;
64 for (int i = 0; i < runCount; ++i) {
65 int rlimit = start + bidi.getRunLimit(i);
66 byte rlevel = (byte)bidi.getRunLevel(i);
67
68 while (p < rlimit) {
69 levels[p++] = rlevel;
70 }
71 }
72 }
73
74 /**
75 * Return an array containing the resolved bidi level of each character, in logical order.
76 * @return an array containing the level of each character, in logical order.
77 */
78 public static byte[] getLevels(Bidi bidi) {
79 byte[] levels = new byte[bidi.getLength()];
80 getLevels(bidi, levels, 0);
81 return levels;
82 }
83
84 static final char NUMLEVELS = 62;
85
86 /**
87 * Given level data, compute a a visual to logical mapping.
88 * The leftmost (or topmost) character is at visual index zero. The
89 * logical index of the character is derived from the visual index
90 * by the expression <code>li = map[vi];</code>.
91 * @param levels the levels array
92 * @return the mapping array from visual to logical
93 */
94 public static int[] createVisualToLogicalMap(byte[] levels) {
95 int len = levels.length;
96 int[] mapping = new int[len];
97
98 byte lowestOddLevel = (byte)(NUMLEVELS + 1);
99 byte highestLevel = 0;
100
101 // initialize mapping and levels
102
103 for (int i = 0; i < len; i++) {
104 mapping[i] = i;
105
106 byte level = levels[i];
107 if (level > highestLevel) {
108 highestLevel = level;
109 }
110
111 if ((level & 0x01) != 0 && level < lowestOddLevel) {
112 lowestOddLevel = level;
113 }
114 }
115
116 while (highestLevel >= lowestOddLevel) {
117 int i = 0;
118 for (;;) {
119 while (i < len && levels[i] < highestLevel) {
120 i++;
121 }
122 int begin = i++;
123
124 if (begin == levels.length) {
125 break; // no more runs at this level
126 }
127
128 while (i < len && levels[i] >= highestLevel) {
129 i++;
130 }
131 int end = i - 1;
132
133 while (begin < end) {
134 int temp = mapping[begin];
135 mapping[begin] = mapping[end];
136 mapping[end] = temp;
137 ++begin;
138 --end;
139 }
140 }
141
142 --highestLevel;
143 }
144
145 return mapping;
146 }
147
148 /**
149 * Return the inverse position map. The source array must map one-to-one (each value
150 * is distinct and the values run from zero to the length of the array minus one).
151 * For example, if <code>values[i] = j</code>, then <code>inverse[j] = i</code>.
152 * @param values the source ordering array
153 * @return the inverse array
154 */
155 public static int[] createInverseMap(int[] values) {
156 if (values == null) {
157 return null;
158 }
159
160 int[] result = new int[values.length];
161 for (int i = 0; i < values.length; i++) {
162 result[values[i]] = i;
163 }
164
165 return result;
166 }
167
168
169 /**
170 * Return an array containing contiguous values from 0 to length
171 * having the same ordering as the source array. If this would be
172 * a canonical ltr ordering, return null. The data in values[] is NOT
173 * required to be a permutation, but elements in values are required
174 * to be distinct.
175 * @param values an array containing the discontiguous values
176 * @return the contiguous values
177 */
178 public static int[] createContiguousOrder(int[] values) {
179 if (values != null) {
180 return computeContiguousOrder(values, 0, values.length);
181 }
182
183 return null;
184 }
185
186 /**
187 * Compute a contiguous order for the range start, limit.
188 */
189 private static int[] computeContiguousOrder(int[] values, int start,
190 int limit) {
191
192 int[] result = new int[limit-start];
193 for (int i=0; i < result.length; i++) {
194 result[i] = i + start;
195 }
196
197 // now we'll sort result[], with the following comparison:
198 // result[i] lessthan result[j] iff values[result[i]] < values[result[j]]
199
200 // selection sort for now; use more elaborate sorts if desired
201 for (int i=0; i < result.length-1; i++) {
202 int minIndex = i;
203 int currentValue = values[result[minIndex]];
204 for (int j=i; j < result.length; j++) {
205 if (values[result[j]] < currentValue) {
206 minIndex = j;
207 currentValue = values[result[minIndex]];
208 }
209 }
210 int temp = result[i];
211 result[i] = result[minIndex];
212 result[minIndex] = temp;
213 }
214
215 // shift result by start:
216 if (start != 0) {
217 for (int i=0; i < result.length; i++) {
218 result[i] -= start;
219 }
220 }
221
222 // next, check for canonical order:
223 int k;
224 for (k=0; k < result.length; k++) {
225 if (result[k] != k) {
226 break;
227 }
228 }
229
230 if (k == result.length) {
231 return null;
232 }
233
234 // now return inverse of result:
235 return createInverseMap(result);
236 }
237
238 /**
239 * Return an array containing the data in the values array from start up to limit,
240 * normalized to fall within the range from 0 up to limit - start.
241 * If this would be a canonical ltr ordering, return null.
242 * NOTE: This method assumes that values[] is a logical to visual map
243 * generated from levels[].
244 * @param values the source mapping
245 * @param levels the levels corresponding to the values
246 * @param start the starting offset in the values and levels arrays
247 * @param limit the limiting offset in the values and levels arrays
248 * @return the normlized map
249 */
250 public static int[] createNormalizedMap(int[] values, byte[] levels,
251 int start, int limit) {
252
253 if (values != null) {
254 if (start != 0 || limit != values.length) {
255 // levels optimization
256 boolean copyRange, canonical;
257 byte primaryLevel;
258
259 if (levels == null) {
260 primaryLevel = (byte) 0x0;
261 copyRange = true;
262 canonical = true;
263 }
264 else {
265 if (levels[start] == levels[limit-1]) {
266 primaryLevel = levels[start];
267 canonical = (primaryLevel & (byte)0x1) == 0;
268
269 // scan for levels below primary
270 int i;
271 for (i=start; i < limit; i++) {
272 if (levels[i] < primaryLevel) {
273 break;
274 }
275 if (canonical) {
276 canonical = levels[i] == primaryLevel;
277 }
278 }
279
280 copyRange = (i == limit);
281 }
282 else {
283 copyRange = false;
284
285 // these don't matter; but the compiler cares:
286 primaryLevel = (byte) 0x0;
287 canonical = false;
288 }
289 }
290
291 if (copyRange) {
292 if (canonical) {
293 return null;
294 }
295
296 int[] result = new int[limit-start];
297 int baseValue;
298
299 if ((primaryLevel & (byte)0x1) != 0) {
300 baseValue = values[limit-1];
301 } else {
302 baseValue = values[start];
303 }
304
305 if (baseValue == 0) {
306 System.arraycopy(values, start, result, 0, limit-start);
307 }
308 else {
309 for (int j=0; j < result.length; j++) {
310 result[j] = values[j+start] - baseValue;
311 }
312 }
313
314 return result;
315 }
316 else {
317 return computeContiguousOrder(values, start, limit);
318 }
319 }
320 else {
321 return values;
322 }
323 }
324
325 return null;
326 }
327
328 /**
329 * Reorder the objects in the array into visual order based on their levels.
330 * This is a utility function to use when you have a collection of objects
331 * representing runs of text in logical order, each run containing text
332 * at a single level. The elements in the objects array will be reordered
333 * into visual order assuming each run of text has the level provided
334 * by the corresponding element in the levels array.
335 * @param levels an array representing the bidi level of each object
336 * @param objects the array of objects to be reordered into visual order
337 */
338 public static void reorderVisually(byte[] levels, Object[] objects) {
339 int len = levels.length;
340
341 byte lowestOddLevel = (byte)(NUMLEVELS + 1);
342 byte highestLevel = 0;
343
344 // initialize mapping and levels
345
346 for (int i = 0; i < len; i++) {
347 byte level = levels[i];
348 if (level > highestLevel) {
349 highestLevel = level;
350 }
351
352 if ((level & 0x01) != 0 && level < lowestOddLevel) {
353 lowestOddLevel = level;
354 }
355 }
356
357 while (highestLevel >= lowestOddLevel) {
358 int i = 0;
359 for (;;) {
360 while (i < len && levels[i] < highestLevel) {
361 i++;
362 }
363 int begin = i++;
364
365 if (begin == levels.length) {
366 break; // no more runs at this level
367 }
368
369 while (i < len && levels[i] >= highestLevel) {
370 i++;
371 }
372 int end = i - 1;
373
374 while (begin < end) {
375 Object temp = objects[begin];
376 objects[begin] = objects[end];
377 objects[end] = temp;
378 ++begin;
379 --end;
380 }
381 }
382
383 --highestLevel;
384 }
385 }
386}