frameworks/base
修訂 | f9c66107fab4e0e4fdebc63924f5fb85c0cd1551 (tree) |
---|---|
時間 | 2018-07-20 08:35:40 |
作者 | JP Sugarbroad <jpsugar@goog...> |
Commiter | JP Sugarbroad |
Revert "Optimise the hit test algorithm"
This reverts commit 9dceb027701a1f638484bfeee3749d8399d38918.
@@ -824,32 +824,6 @@ public abstract class Layout { | ||
824 | 824 | return TextUtils.packRangeInLong(0, getLineEnd(line)); |
825 | 825 | } |
826 | 826 | |
827 | - /** | |
828 | - * Checks if the trailing BiDi level should be used for an offset | |
829 | - * | |
830 | - * This method is useful when the offset is at the BiDi level transition point and determine | |
831 | - * which run need to be used. For example, let's think about following input: (L* denotes | |
832 | - * Left-to-Right characters, R* denotes Right-to-Left characters.) | |
833 | - * Input (Logical Order): L1 L2 L3 R1 R2 R3 L4 L5 L6 | |
834 | - * Input (Display Order): L1 L2 L3 R3 R2 R1 L4 L5 L6 | |
835 | - * | |
836 | - * Then, think about selecting the range (3, 6). The offset=3 and offset=6 are ambiguous here | |
837 | - * since they are at the BiDi transition point. In Android, the offset is considered to be | |
838 | - * associated with the trailing run if the BiDi level of the trailing run is higher than of the | |
839 | - * previous run. In this case, the BiDi level of the input text is as follows: | |
840 | - * | |
841 | - * Input (Logical Order): L1 L2 L3 R1 R2 R3 L4 L5 L6 | |
842 | - * BiDi Run: [ Run 0 ][ Run 1 ][ Run 2 ] | |
843 | - * BiDi Level: 0 0 0 1 1 1 0 0 0 | |
844 | - * | |
845 | - * Thus, offset = 3 is part of Run 1 and this method returns true for offset = 3, since the BiDi | |
846 | - * level of Run 1 is higher than the level of Run 0. Similarly, the offset = 6 is a part of Run | |
847 | - * 1 and this method returns false for the offset = 6 since the BiDi level of Run 1 is higher | |
848 | - * than the level of Run 2. | |
849 | - * | |
850 | - * @returns true if offset is at the BiDi level transition point and trailing BiDi level is | |
851 | - * higher than previous BiDi level. See above for the detail. | |
852 | - */ | |
853 | 827 | private boolean primaryIsTrailingPrevious(int offset) { |
854 | 828 | int line = getLineForOffset(offset); |
855 | 829 | int lineStart = getLineStart(line); |
@@ -900,41 +874,6 @@ public abstract class Layout { | ||
900 | 874 | } |
901 | 875 | |
902 | 876 | /** |
903 | - * Computes in linear time the results of calling | |
904 | - * #primaryIsTrailingPrevious for all offsets on a line. | |
905 | - * @param line The line giving the offsets we compute the information for | |
906 | - * @return The array of results, indexed from 0, where 0 corresponds to the line start offset | |
907 | - */ | |
908 | - private boolean[] primaryIsTrailingPreviousAllLineOffsets(int line) { | |
909 | - int lineStart = getLineStart(line); | |
910 | - int lineEnd = getLineEnd(line); | |
911 | - int[] runs = getLineDirections(line).mDirections; | |
912 | - | |
913 | - boolean[] trailing = new boolean[lineEnd - lineStart + 1]; | |
914 | - | |
915 | - byte[] level = new byte[lineEnd - lineStart + 1]; | |
916 | - for (int i = 0; i < runs.length; i += 2) { | |
917 | - int start = lineStart + runs[i]; | |
918 | - int limit = start + (runs[i + 1] & RUN_LENGTH_MASK); | |
919 | - if (limit > lineEnd) { | |
920 | - limit = lineEnd; | |
921 | - } | |
922 | - level[limit - lineStart - 1] = | |
923 | - (byte) ((runs[i + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK); | |
924 | - } | |
925 | - | |
926 | - for (int i = 0; i < runs.length; i += 2) { | |
927 | - int start = lineStart + runs[i]; | |
928 | - byte currentLevel = (byte) ((runs[i + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK); | |
929 | - trailing[start - lineStart] = currentLevel > (start == lineStart | |
930 | - ? (getParagraphDirection(line) == 1 ? 0 : 1) | |
931 | - : level[start - lineStart - 1]); | |
932 | - } | |
933 | - | |
934 | - return trailing; | |
935 | - } | |
936 | - | |
937 | - /** | |
938 | 877 | * Get the primary horizontal position for the specified text offset. |
939 | 878 | * This is the location where a new character would be inserted in |
940 | 879 | * the paragraph's primary direction. |
@@ -1014,60 +953,6 @@ public abstract class Layout { | ||
1014 | 953 | } |
1015 | 954 | |
1016 | 955 | /** |
1017 | - * Computes in linear time the results of calling | |
1018 | - * #getHorizontal for all offsets on a line. | |
1019 | - * @param line The line giving the offsets we compute information for | |
1020 | - * @param clamped Whether to clamp the results to the width of the layout | |
1021 | - * @param primary Whether the results should be the primary or the secondary horizontal | |
1022 | - * @return The array of results, indexed from 0, where 0 corresponds to the line start offset | |
1023 | - */ | |
1024 | - private float[] getLineHorizontals(int line, boolean clamped, boolean primary) { | |
1025 | - int start = getLineStart(line); | |
1026 | - int end = getLineEnd(line); | |
1027 | - int dir = getParagraphDirection(line); | |
1028 | - boolean hasTab = getLineContainsTab(line); | |
1029 | - Directions directions = getLineDirections(line); | |
1030 | - | |
1031 | - TabStops tabStops = null; | |
1032 | - if (hasTab && mText instanceof Spanned) { | |
1033 | - // Just checking this line should be good enough, tabs should be | |
1034 | - // consistent across all lines in a paragraph. | |
1035 | - TabStopSpan[] tabs = getParagraphSpans((Spanned) mText, start, end, TabStopSpan.class); | |
1036 | - if (tabs.length > 0) { | |
1037 | - tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse | |
1038 | - } | |
1039 | - } | |
1040 | - | |
1041 | - TextLine tl = TextLine.obtain(); | |
1042 | - tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops); | |
1043 | - boolean[] trailings = primaryIsTrailingPreviousAllLineOffsets(line); | |
1044 | - if (!primary) { | |
1045 | - for (int offset = 0; offset < trailings.length; ++offset) { | |
1046 | - trailings[offset] = !trailings[offset]; | |
1047 | - } | |
1048 | - } | |
1049 | - float[] wid = tl.measureAllOffsets(trailings, null); | |
1050 | - TextLine.recycle(tl); | |
1051 | - | |
1052 | - if (clamped) { | |
1053 | - for (int offset = 0; offset <= wid.length; ++offset) { | |
1054 | - if (wid[offset] > mWidth) { | |
1055 | - wid[offset] = mWidth; | |
1056 | - } | |
1057 | - } | |
1058 | - } | |
1059 | - int left = getParagraphLeft(line); | |
1060 | - int right = getParagraphRight(line); | |
1061 | - | |
1062 | - int lineStartPos = getLineStartPos(line, left, right); | |
1063 | - float[] horizontal = new float[end - start + 1]; | |
1064 | - for (int offset = 0; offset < horizontal.length; ++offset) { | |
1065 | - horizontal[offset] = lineStartPos + wid[offset]; | |
1066 | - } | |
1067 | - return horizontal; | |
1068 | - } | |
1069 | - | |
1070 | - /** | |
1071 | 956 | * Get the leftmost position that should be exposed for horizontal |
1072 | 957 | * scrolling on the specified line. |
1073 | 958 | */ |
@@ -1282,8 +1167,6 @@ public abstract class Layout { | ||
1282 | 1167 | // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here. |
1283 | 1168 | tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs, |
1284 | 1169 | false, null); |
1285 | - final HorizontalMeasurementProvider horizontal = | |
1286 | - new HorizontalMeasurementProvider(line, primary); | |
1287 | 1170 | |
1288 | 1171 | final int max; |
1289 | 1172 | if (line == getLineCount() - 1) { |
@@ -1293,7 +1176,7 @@ public abstract class Layout { | ||
1293 | 1176 | !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset; |
1294 | 1177 | } |
1295 | 1178 | int best = lineStartOffset; |
1296 | - float bestdist = Math.abs(horizontal.get(lineStartOffset) - horiz); | |
1179 | + float bestdist = Math.abs(getHorizontal(best, primary) - horiz); | |
1297 | 1180 | |
1298 | 1181 | for (int i = 0; i < dirs.mDirections.length; i += 2) { |
1299 | 1182 | int here = lineStartOffset + dirs.mDirections[i]; |
@@ -1309,7 +1192,7 @@ public abstract class Layout { | ||
1309 | 1192 | guess = (high + low) / 2; |
1310 | 1193 | int adguess = getOffsetAtStartOf(guess); |
1311 | 1194 | |
1312 | - if (horizontal.get(adguess) * swap >= horiz * swap) | |
1195 | + if (getHorizontal(adguess, primary) * swap >= horiz * swap) | |
1313 | 1196 | high = guess; |
1314 | 1197 | else |
1315 | 1198 | low = guess; |
@@ -1322,9 +1205,9 @@ public abstract class Layout { | ||
1322 | 1205 | int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset; |
1323 | 1206 | low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset; |
1324 | 1207 | if (low >= here && low < there) { |
1325 | - float dist = Math.abs(horizontal.get(low) - horiz); | |
1208 | + float dist = Math.abs(getHorizontal(low, primary) - horiz); | |
1326 | 1209 | if (aft < there) { |
1327 | - float other = Math.abs(horizontal.get(aft) - horiz); | |
1210 | + float other = Math.abs(getHorizontal(aft, primary) - horiz); | |
1328 | 1211 | |
1329 | 1212 | if (other < dist) { |
1330 | 1213 | dist = other; |
@@ -1339,7 +1222,7 @@ public abstract class Layout { | ||
1339 | 1222 | } |
1340 | 1223 | } |
1341 | 1224 | |
1342 | - float dist = Math.abs(horizontal.get(here) - horiz); | |
1225 | + float dist = Math.abs(getHorizontal(here, primary) - horiz); | |
1343 | 1226 | |
1344 | 1227 | if (dist < bestdist) { |
1345 | 1228 | bestdist = dist; |
@@ -1347,7 +1230,7 @@ public abstract class Layout { | ||
1347 | 1230 | } |
1348 | 1231 | } |
1349 | 1232 | |
1350 | - float dist = Math.abs(horizontal.get(max) - horiz); | |
1233 | + float dist = Math.abs(getHorizontal(max, primary) - horiz); | |
1351 | 1234 | |
1352 | 1235 | if (dist <= bestdist) { |
1353 | 1236 | bestdist = dist; |
@@ -1359,46 +1242,6 @@ public abstract class Layout { | ||
1359 | 1242 | } |
1360 | 1243 | |
1361 | 1244 | /** |
1362 | - * Responds to #getHorizontal queries, by selecting the better strategy between: | |
1363 | - * - calling #getHorizontal explicitly for each query | |
1364 | - * - precomputing all #getHorizontal measurements, and responding to any query in constant time | |
1365 | - * The first strategy is used for LTR-only text, while the second is used for all other cases. | |
1366 | - * The class is currently only used in #getOffsetForHorizontal, so reuse with care in other | |
1367 | - * contexts. | |
1368 | - */ | |
1369 | - private class HorizontalMeasurementProvider { | |
1370 | - private final int mLine; | |
1371 | - private final boolean mPrimary; | |
1372 | - | |
1373 | - private float[] mHorizontals; | |
1374 | - private int mLineStartOffset; | |
1375 | - | |
1376 | - HorizontalMeasurementProvider(final int line, final boolean primary) { | |
1377 | - mLine = line; | |
1378 | - mPrimary = primary; | |
1379 | - init(); | |
1380 | - } | |
1381 | - | |
1382 | - private void init() { | |
1383 | - final Directions dirs = getLineDirections(mLine); | |
1384 | - if (dirs == DIRS_ALL_LEFT_TO_RIGHT) { | |
1385 | - return; | |
1386 | - } | |
1387 | - | |
1388 | - mHorizontals = getLineHorizontals(mLine, false, mPrimary); | |
1389 | - mLineStartOffset = getLineStart(mLine); | |
1390 | - } | |
1391 | - | |
1392 | - float get(final int offset) { | |
1393 | - if (mHorizontals == null) { | |
1394 | - return getHorizontal(offset, mPrimary); | |
1395 | - } else { | |
1396 | - return mHorizontals[offset - mLineStartOffset]; | |
1397 | - } | |
1398 | - } | |
1399 | - } | |
1400 | - | |
1401 | - /** | |
1402 | 1245 | * Return the text offset after the last character on the specified line. |
1403 | 1246 | */ |
1404 | 1247 | public final int getLineEnd(int line) { |
@@ -339,98 +339,6 @@ class TextLine { | ||
339 | 339 | } |
340 | 340 | |
341 | 341 | /** |
342 | - * @see #measure(int, boolean, FontMetricsInt) | |
343 | - * @return The measure results for all possible offsets | |
344 | - */ | |
345 | - float[] measureAllOffsets(boolean[] trailing, FontMetricsInt fmi) { | |
346 | - float[] measurement = new float[mLen + 1]; | |
347 | - | |
348 | - int[] target = new int[mLen + 1]; | |
349 | - for (int offset = 0; offset < target.length; ++offset) { | |
350 | - target[offset] = trailing[offset] ? offset - 1 : offset; | |
351 | - } | |
352 | - if (target[0] < 0) { | |
353 | - measurement[0] = 0; | |
354 | - } | |
355 | - | |
356 | - float h = 0; | |
357 | - | |
358 | - if (!mHasTabs) { | |
359 | - if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { | |
360 | - for (int offset = 0; offset <= mLen; ++offset) { | |
361 | - measurement[offset] = measureRun(0, offset, mLen, false, fmi); | |
362 | - } | |
363 | - return measurement; | |
364 | - } | |
365 | - if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { | |
366 | - for (int offset = 0; offset <= mLen; ++offset) { | |
367 | - measurement[offset] = measureRun(0, offset, mLen, true, fmi); | |
368 | - } | |
369 | - return measurement; | |
370 | - } | |
371 | - } | |
372 | - | |
373 | - char[] chars = mChars; | |
374 | - int[] runs = mDirections.mDirections; | |
375 | - for (int i = 0; i < runs.length; i += 2) { | |
376 | - int runStart = runs[i]; | |
377 | - int runLimit = runStart + (runs[i + 1] & Layout.RUN_LENGTH_MASK); | |
378 | - if (runLimit > mLen) { | |
379 | - runLimit = mLen; | |
380 | - } | |
381 | - boolean runIsRtl = (runs[i + 1] & Layout.RUN_RTL_FLAG) != 0; | |
382 | - | |
383 | - int segstart = runStart; | |
384 | - for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) { | |
385 | - int codept = 0; | |
386 | - if (mHasTabs && j < runLimit) { | |
387 | - codept = chars[j]; | |
388 | - if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { | |
389 | - codept = Character.codePointAt(chars, j); | |
390 | - if (codept > 0xFFFF) { | |
391 | - ++j; | |
392 | - continue; | |
393 | - } | |
394 | - } | |
395 | - } | |
396 | - | |
397 | - if (j == runLimit || codept == '\t') { | |
398 | - float oldh = h; | |
399 | - boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; | |
400 | - float w = measureRun(segstart, j, j, runIsRtl, fmi); | |
401 | - h += advance ? w : -w; | |
402 | - | |
403 | - float baseh = advance ? oldh : h; | |
404 | - FontMetricsInt crtfmi = advance ? fmi : null; | |
405 | - for (int offset = segstart; offset <= j && offset <= mLen; ++offset) { | |
406 | - if (target[offset] >= segstart && target[offset] < j) { | |
407 | - measurement[offset] = | |
408 | - baseh + measureRun(segstart, offset, j, runIsRtl, crtfmi); | |
409 | - } | |
410 | - } | |
411 | - | |
412 | - if (codept == '\t') { | |
413 | - if (target[j] == j) { | |
414 | - measurement[j] = h; | |
415 | - } | |
416 | - h = mDir * nextTab(h * mDir); | |
417 | - if (target[j + 1] == j) { | |
418 | - measurement[j + 1] = h; | |
419 | - } | |
420 | - } | |
421 | - | |
422 | - segstart = j + 1; | |
423 | - } | |
424 | - } | |
425 | - } | |
426 | - if (target[mLen] == mLen) { | |
427 | - measurement[mLen] = h; | |
428 | - } | |
429 | - | |
430 | - return measurement; | |
431 | - } | |
432 | - | |
433 | - /** | |
434 | 342 | * Draws a unidirectional (but possibly multi-styled) run of text. |
435 | 343 | * |
436 | 344 | * |