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+
36+package sun.font;
37+
38+import java.text.Bidi;
39+
40+public 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+}