Hide packing structure from public API
The hyphen edit is packed into 8bit integer in native library, but this
should not be exposed to public API as API council suggested.
This CL includes:
- Removing packing structure from HyphenEdit and move constants from
Hyphenator to Paint.
- Replace LineBreaker's getLineHyphenEdit with two separate start/end
function.
- Replace Paint's getHyphenEdit with two separate start/end function.
- StaticLayout still relies on this packing mechanism but no longer need
to be the same packing structure as in Minikin.
Bug: 124794844
Test: atest CtsGraphicsTestCases
Test: atest CtsTextTestCases
Change-Id: I8206061f554cf6e119b2b565162f54317eac630a
diff --git a/api/current.txt b/api/current.txt
index 3489335..a977820 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14428,6 +14428,7 @@
method @ColorInt public int getColor();
method public android.graphics.ColorFilter getColorFilter();
method @ColorLong public long getColorLong();
+ method public int getEndHyphenEdit();
method public boolean getFillPath(android.graphics.Path, android.graphics.Path);
method public int getFlags();
method public String getFontFeatureSettings();
@@ -14438,7 +14439,6 @@
method public float getFontSpacing();
method public String getFontVariationSettings();
method public int getHinting();
- method public int getHyphenEdit();
method public float getLetterSpacing();
method public android.graphics.MaskFilter getMaskFilter();
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
@@ -14452,6 +14452,7 @@
method public float getShadowLayerDx();
method public float getShadowLayerDy();
method public float getShadowLayerRadius();
+ method public int getStartHyphenEdit();
method @Px public float getStrikeThruPosition();
method @Px public float getStrikeThruThickness();
method public android.graphics.Paint.Cap getStrokeCap();
@@ -14507,13 +14508,13 @@
method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
method public void setDither(boolean);
method public void setElegantTextHeight(boolean);
+ method public void setEndHyphenEdit(int);
method public void setFakeBoldText(boolean);
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(String);
method public boolean setFontVariationSettings(String);
method public void setHinting(int);
- method public void setHyphenEdit(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
method public android.graphics.MaskFilter setMaskFilter(android.graphics.MaskFilter);
@@ -14521,6 +14522,7 @@
method public android.graphics.Shader setShader(android.graphics.Shader);
method public void setShadowLayer(float, float, float, @ColorInt int);
method public void setShadowLayer(float, float, float, @ColorLong long);
+ method public void setStartHyphenEdit(int);
method public void setStrikeThruText(boolean);
method public void setStrokeCap(android.graphics.Paint.Cap);
method public void setStrokeJoin(android.graphics.Paint.Join);
@@ -14547,11 +14549,21 @@
field public static final int DEV_KERN_TEXT_FLAG = 256; // 0x100
field public static final int DITHER_FLAG = 4; // 0x4
field public static final int EMBEDDED_BITMAP_TEXT_FLAG = 1024; // 0x400
+ field public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 3; // 0x3
+ field public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 2; // 0x2
+ field public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 4; // 0x4
+ field public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 5; // 0x5
+ field public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 6; // 0x6
+ field public static final int END_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
+ field public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 1; // 0x1
field public static final int FAKE_BOLD_TEXT_FLAG = 32; // 0x20
field public static final int FILTER_BITMAP_FLAG = 2; // 0x2
field public static final int HINTING_OFF = 0; // 0x0
field public static final int HINTING_ON = 1; // 0x1
field public static final int LINEAR_TEXT_FLAG = 64; // 0x40
+ field public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 1; // 0x1
+ field public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 2; // 0x2
+ field public static final int START_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
field public static final int STRIKE_THRU_TEXT_FLAG = 16; // 0x10
field public static final int SUBPIXEL_TEXT_FLAG = 128; // 0x80
field public static final int UNDERLINE_TEXT_FLAG = 8; // 0x8
@@ -15925,12 +15937,13 @@
}
public static class LineBreaker.Result {
+ method public int getEndLineHyphenEdit(int);
method @Px public float getLineAscent(@IntRange(from=0) int);
method @IntRange(from=0) public int getLineBreakOffset(@IntRange(from=0) int);
method @IntRange(from=0) public int getLineCount();
method @Px public float getLineDescent(@IntRange(from=0) int);
- method public int getLineHyphenEdit(int);
method @Px public float getLineWidth(@IntRange(from=0) int);
+ method public int getStartLineHyphenEdit(int);
method public boolean hasLineTab(int);
}
@@ -45992,22 +46005,6 @@
method public void handleTag(boolean, String, android.text.Editable, org.xml.sax.XMLReader);
}
- public class Hyphenator {
- method public static int packHyphenEdit(int, int);
- method public static int unpackEndHyphenEdit(int);
- method public static int unpackStartHyphenEdit(int);
- field public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 3; // 0x3
- field public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 2; // 0x2
- field public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 4; // 0x4
- field public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 5; // 0x5
- field public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 6; // 0x6
- field public static final int END_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
- field public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 1; // 0x1
- field public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 1; // 0x1
- field public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 2; // 0x2
- field public static final int START_HYPHEN_EDIT_NO_EDIT = 0; // 0x0
- }
-
public interface InputFilter {
method public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index c928da1..32982f9 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -674,7 +674,8 @@
objects[0] = reflowed.getLineDirections(i);
final int end = (i == n - 1) ? where + after : reflowed.getLineStart(i + 1);
- ints[HYPHEN] = reflowed.getHyphen(i) & HYPHEN_MASK;
+ ints[HYPHEN] = StaticLayout.packHyphenEdit(
+ reflowed.getStartHyphenEdit(i), reflowed.getEndHyphenEdit(i));
ints[MAY_PROTRUDE_FROM_TOP_OR_BOTTOM] |=
contentMayProtrudeFromLineTopOrBottom(text, start, end) ?
MAY_PROTRUDE_FROM_TOP_OR_BOTTOM_MASK : 0;
@@ -1056,8 +1057,16 @@
* @hide
*/
@Override
- public int getHyphen(int line) {
- return mInts.getValue(line, HYPHEN) & HYPHEN_MASK;
+ public @Paint.StartHyphenEdit int getStartHyphenEdit(int line) {
+ return StaticLayout.unpackStartHyphenEdit(mInts.getValue(line, HYPHEN) & HYPHEN_MASK);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public @Paint.EndHyphenEdit int getEndHyphenEdit(int line) {
+ return StaticLayout.unpackEndHyphenEdit(mInts.getValue(line, HYPHEN) & HYPHEN_MASK);
}
private boolean getContentMayProtrudeFromTopOrBottom(int line) {
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index e4200ac..6f0628a 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -16,142 +16,15 @@
package android.text;
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
/**
- * Provides constants and pack/unpack methods for the HyphenEdit.
+ * Does the native Hyphenator initialization.
*
- * Hyphenator provides constant values for start of line and end of line modification.
- * For example, by passing {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
- * character is appended at the end of line.
- *
- * <pre>
- * <code>
- * Paint paint = new Paint();
- * paint.setHyphenEdit(Hyphenator.packHyphenEdit(
- * Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
- * Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
- * paint.measureText("abc", 0, 3); // Returns the width of "abc‐"
- * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc‐"
- * </code>
- * </pre>
- *
- * @see android.graphics.Paint#setHyphenEdit(int)
+ * @hide
*/
public class Hyphenator {
private Hyphenator() {}
- /** @hide */
- @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
- START_HYPHEN_EDIT_NO_EDIT,
- START_HYPHEN_EDIT_INSERT_HYPHEN,
- START_HYPHEN_EDIT_INSERT_ZWJ
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface StartHyphenEdit {}
-
- /**
- * An integer representing the starting of the line has no modification for hyphenation.
- */
- public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
-
- /**
- * An integer representing the starting of the line has normal hyphen character (U+002D).
- */
- public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
-
- /**
- * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
- */
- public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
-
- /** @hide */
- @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
- END_HYPHEN_EDIT_NO_EDIT,
- END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
- END_HYPHEN_EDIT_INSERT_HYPHEN,
- END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
- END_HYPHEN_EDIT_INSERT_MAQAF,
- END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
- END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface EndHyphenEdit {}
-
- /**
- * An integer representing the end of the line has no modification for hyphenation.
- */
- public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
-
- /**
- * An integer representing the character at the end of the line is replaced with hyphen
- * character (U+002D).
- */
- public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
-
- /**
- * An integer representing the end of the line has normal hyphen character (U+002D).
- */
- public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
-
- /**
- * An integer representing the end of the line has Armentian hyphen (U+058A).
- */
- public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
-
- /**
- * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
- */
- public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
-
- /**
- * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
- */
- public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
-
- /**
- * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
- * hyphen character (U+002D).
- */
- public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
-
- // Following three constants are used for packing start hyphen edit and end hyphen edit into
- // single integer. Following encodings must be the same as the minikin's one.
- // See frameworks/minikin/include/Hyphenator.h for more details.
- private static final int END_HYPHEN_EDIT_MASK = 0x07; // 0b00111
- private static final int START_HYPHEN_EDIT_MASK = 0x18; // 0b11000
- private static final int START_HYPHEN_EDIT_SHIFT = 0x03;
-
- /**
- * Extract start hyphen edit from packed value.
- */
- public static @StartHyphenEdit int unpackStartHyphenEdit(int hyphenEdit) {
- return (hyphenEdit & START_HYPHEN_EDIT_MASK) >> START_HYPHEN_EDIT_SHIFT;
- }
-
- /**
- * Extract end hyphen edit from packed value.
- */
- public static @EndHyphenEdit int unpackEndHyphenEdit(int hyphenEdit) {
- return hyphenEdit & END_HYPHEN_EDIT_MASK;
- }
-
- /**
- * Pack the start hyphen edit and end hyphen edit into single integer.
- */
- public static int packHyphenEdit(@StartHyphenEdit int startHyphenEdit,
- @EndHyphenEdit int endHyphenEdit) {
- return ((startHyphenEdit << START_HYPHEN_EDIT_SHIFT) & START_HYPHEN_EDIT_MASK)
- | (endHyphenEdit & END_HYPHEN_EDIT_MASK);
- }
-
-
- /**
- * @hide
- */
+ // This method is called from Zygote.
public static void init() {
nInit();
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2d5f3bf..fb6dc22 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -437,7 +437,8 @@
previousLineEnd = getLineStart(lineNum + 1);
final boolean justify = isJustificationRequired(lineNum);
int end = getLineVisibleEnd(lineNum, start, previousLineEnd);
- paint.setHyphenEdit(getHyphen(lineNum));
+ paint.setStartHyphenEdit(getStartHyphenEdit(lineNum));
+ paint.setEndHyphenEdit(getEndHyphenEdit(lineNum));
int ltop = previousLineBottom;
int lbottom = getLineTop(lineNum + 1);
@@ -910,12 +911,21 @@
public abstract int getBottomPadding();
/**
- * Returns the hyphen edit for a line.
+ * Returns the start hyphen edit for a line.
*
* @hide
*/
- public int getHyphen(int line) {
- return 0;
+ public @Paint.StartHyphenEdit int getStartHyphenEdit(int line) {
+ return Paint.START_HYPHEN_EDIT_NO_EDIT;
+ }
+
+ /**
+ * Returns the end hyphen edit for a line.
+ *
+ * @hide
+ */
+ public @Paint.EndHyphenEdit int getEndHyphenEdit(int line) {
+ return Paint.END_HYPHEN_EDIT_NO_EDIT;
}
/**
@@ -1418,7 +1428,8 @@
final TextLine tl = TextLine.obtain();
final TextPaint paint = mWorkPaint;
paint.set(mPaint);
- paint.setHyphenEdit(getHyphen(line));
+ paint.setStartHyphenEdit(getStartHyphenEdit(line));
+ paint.setEndHyphenEdit(getEndHyphenEdit(line));
tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
if (isJustificationRequired(line)) {
@@ -1447,7 +1458,8 @@
final TextLine tl = TextLine.obtain();
final TextPaint paint = mWorkPaint;
paint.set(mPaint);
- paint.setHyphenEdit(getHyphen(line));
+ paint.setStartHyphenEdit(getStartHyphenEdit(line));
+ paint.setEndHyphenEdit(getEndHyphenEdit(line));
tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
if (isJustificationRequired(line)) {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index defe2ce..9fefc83 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -779,7 +779,8 @@
ascents[i] = res.getLineAscent(i);
descents[i] = res.getLineDescent(i);
hasTabs[i] = res.hasLineTab(i);
- hyphenEdits[i] = res.getLineHyphenEdit(i);
+ hyphenEdits[i] =
+ packHyphenEdit(res.getStartLineHyphenEdit(i), res.getEndLineHyphenEdit(i));
}
final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
@@ -1258,20 +1259,42 @@
return mBottomPadding;
}
+ // To store into single int field, pack the pair of start and end hyphen edit.
+ static int packHyphenEdit(
+ @Paint.StartHyphenEdit int start, @Paint.EndHyphenEdit int end) {
+ return start << START_HYPHEN_BITS_SHIFT | end;
+ }
+
+ static int unpackStartHyphenEdit(int packedHyphenEdit) {
+ return (packedHyphenEdit & START_HYPHEN_MASK) >> START_HYPHEN_BITS_SHIFT;
+ }
+
+ static int unpackEndHyphenEdit(int packedHyphenEdit) {
+ return packedHyphenEdit & END_HYPHEN_MASK;
+ }
+
/**
- * Returns the packed hyphen edit value for this line.
- *
- * You can extract start hyphen edit and end hyphen edit by using
- * {@link Hyphenator#unpackStartHyphenEdit(int)} and
- * {@link Hyphenator#unpackEndHyphenEdit(int)}.
+ * Returns the start hyphen edit value for this line.
*
* @param lineNumber a line number
- * @return A packed hyphen edit value.
+ * @return A start hyphen edit value.
* @hide
*/
@Override
- public int getHyphen(int lineNumber) {
- return mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK;
+ public @Paint.StartHyphenEdit int getStartHyphenEdit(int lineNumber) {
+ return unpackStartHyphenEdit(mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK);
+ }
+
+ /**
+ * Returns the packed hyphen edit value for this line.
+ *
+ * @param lineNumber a line number
+ * @return An end hyphen edit value.
+ * @hide
+ */
+ @Override
+ public @Paint.EndHyphenEdit int getEndHyphenEdit(int lineNumber) {
+ return unpackEndHyphenEdit(mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK);
}
/**
@@ -1395,6 +1418,9 @@
private static final int DIR_SHIFT = 30;
private static final int TAB_MASK = 0x20000000;
private static final int HYPHEN_MASK = 0xFF;
+ private static final int START_HYPHEN_BITS_SHIFT = 3;
+ private static final int START_HYPHEN_MASK = 0x18; // 0b11000
+ private static final int END_HYPHEN_MASK = 0x7; // 0b00111
private static final int TAB_INCREMENT = 20; // same as Layout, but that's private
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 915a18e..8665106 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -1012,19 +1012,14 @@
return runIsRtl ? -ret : ret;
}
- private int adjustHyphenEdit(int start, int limit, int packedHyphenEdit) {
- int result = packedHyphenEdit;
- // Only draw hyphens on first or last run in line. Disable them otherwise.
- if (start > 0) { // not the first run
- result = Hyphenator.packHyphenEdit(Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
- Hyphenator.unpackEndHyphenEdit(packedHyphenEdit));
- }
- if (limit < mLen) { // not the last run
- result = Hyphenator.packHyphenEdit(Hyphenator.unpackStartHyphenEdit(packedHyphenEdit),
- Hyphenator.END_HYPHEN_EDIT_NO_EDIT);
- result &= ~Paint.HYPHENEDIT_MASK_END_OF_LINE;
- }
- return result;
+ private int adjustStartHyphenEdit(int start, @Paint.StartHyphenEdit int startHyphenEdit) {
+ // Only draw hyphens on first in line. Disable them otherwise.
+ return start > 0 ? Paint.START_HYPHEN_EDIT_NO_EDIT : startHyphenEdit;
+ }
+
+ private int adjustEndHyphenEdit(int limit, @Paint.EndHyphenEdit int endHyphenEdit) {
+ // Only draw hyphens on last run in line. Disable them otherwise.
+ return limit < mLen ? Paint.END_HYPHEN_EDIT_NO_EDIT : endHyphenEdit;
}
private static final class DecorationInfo {
@@ -1115,7 +1110,8 @@
if (!needsSpanMeasurement) {
final TextPaint wp = mWorkPaint;
wp.set(mPaint);
- wp.setHyphenEdit(adjustHyphenEdit(start, limit, wp.getHyphenEdit()));
+ wp.setStartHyphenEdit(adjustStartHyphenEdit(start, wp.getStartHyphenEdit()));
+ wp.setEndHyphenEdit(adjustEndHyphenEdit(limit, wp.getEndHyphenEdit()));
return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top,
y, bottom, fmi, needWidth, measureLimit, null);
}
@@ -1193,8 +1189,10 @@
// The style of the present chunk of text is substantially different from the
// style of the previous chunk. We need to handle the active piece of text
// and restart with the present chunk.
- activePaint.setHyphenEdit(adjustHyphenEdit(
- activeStart, activeEnd, mPaint.getHyphenEdit()));
+ activePaint.setStartHyphenEdit(
+ adjustStartHyphenEdit(activeStart, mPaint.getStartHyphenEdit()));
+ activePaint.setEndHyphenEdit(
+ adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, x,
top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
Math.min(activeEnd, mlimit), mDecorations);
@@ -1218,8 +1216,10 @@
}
}
// Handle the final piece of text.
- activePaint.setHyphenEdit(adjustHyphenEdit(
- activeStart, activeEnd, mPaint.getHyphenEdit()));
+ activePaint.setStartHyphenEdit(
+ adjustStartHyphenEdit(activeStart, mPaint.getStartHyphenEdit()));
+ activePaint.setEndHyphenEdit(
+ adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, x,
top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
Math.min(activeEnd, mlimit), mDecorations);
@@ -1323,7 +1323,8 @@
&& lp.getTextSkewX() == rp.getTextSkewX()
&& lp.getLetterSpacing() == rp.getLetterSpacing()
&& lp.getWordSpacing() == rp.getWordSpacing()
- && lp.getHyphenEdit() == rp.getHyphenEdit()
+ && lp.getStartHyphenEdit() == rp.getStartHyphenEdit()
+ && lp.getEndHyphenEdit() == rp.getEndHyphenEdit()
&& lp.bgColor == rp.bgColor
&& lp.baselineShift == rp.baselineShift
&& lp.linkColor == rp.linkColor
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 85f1159..cd7346e 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -923,14 +923,24 @@
paint->setWordSpacing(wordSpacing);
}
- static jint getHyphenEdit(jlong paintHandle, jint hyphen) {
+ static jint getStartHyphenEdit(jlong paintHandle, jint hyphen) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- return paint->getHyphenEdit();
+ return static_cast<jint>(paint->getStartHyphenEdit());
}
- static void setHyphenEdit(jlong paintHandle, jint hyphen) {
+ static jint getEndHyphenEdit(jlong paintHandle, jint hyphen) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- paint->setHyphenEdit((uint32_t)hyphen);
+ return static_cast<jint>(paint->getEndHyphenEdit());
+ }
+
+ static void setStartHyphenEdit(jlong paintHandle, jint hyphen) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ paint->setStartHyphenEdit((uint32_t)hyphen);
+ }
+
+ static void setEndHyphenEdit(jlong paintHandle, jint hyphen) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ paint->setEndHyphenEdit((uint32_t)hyphen);
}
static jfloat ascent(jlong paintHandle) {
@@ -1105,8 +1115,10 @@
{"nSetLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing},
{"nGetWordSpacing","(J)F", (void*) PaintGlue::getWordSpacing},
{"nSetWordSpacing","(JF)V", (void*) PaintGlue::setWordSpacing},
- {"nGetHyphenEdit", "(J)I", (void*) PaintGlue::getHyphenEdit},
- {"nSetHyphenEdit", "(JI)V", (void*) PaintGlue::setHyphenEdit},
+ {"nGetStartHyphenEdit", "(J)I", (void*) PaintGlue::getStartHyphenEdit},
+ {"nGetEndHyphenEdit", "(J)I", (void*) PaintGlue::getEndHyphenEdit},
+ {"nSetStartHyphenEdit", "(JI)V", (void*) PaintGlue::setStartHyphenEdit},
+ {"nSetEndHyphenEdit", "(JI)V", (void*) PaintGlue::setEndHyphenEdit},
{"nAscent","(J)F", (void*) PaintGlue::ascent},
{"nDescent","(J)F", (void*) PaintGlue::descent},
{"nGetUnderlinePosition","(J)F", (void*) PaintGlue::getUnderlinePosition},
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index b1c896e..0ebf03f 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.os.LocaleList;
import android.platform.test.annotations.Presubmit;
@@ -799,11 +800,13 @@
@Test
public void testLayoutDoesntModifyPaint() {
final TextPaint paint = new TextPaint();
- paint.setHyphenEdit(31);
+ paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
+ paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
final StaticLayout layout = StaticLayout.Builder.obtain("", 0, 0, paint, 100).build();
final Canvas canvas = new Canvas();
layout.drawText(canvas, 0, 0);
- assertEquals(31, paint.getHyphenEdit());
+ assertEquals(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN, paint.getStartHyphenEdit());
+ assertEquals(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN, paint.getEndHyphenEdit());
}
@Test
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 585360f..0617caf5 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -209,7 +209,8 @@
int lineCount = layout.getLineCount();
boolean hyphenationHappend = false;
for (int i = 0; i < lineCount; ++i) {
- if (layout.getHyphen(i) == 0) {
+ if (layout.getStartHyphenEdit(i) == Paint.START_HYPHEN_EDIT_NO_EDIT
+ && layout.getEndHyphenEdit(i) == Paint.END_HYPHEN_EDIT_NO_EDIT) {
continue; // Hyphantion does not happen.
}
hyphenationHappend = true;
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 9eeb43b..452f7c9 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -364,19 +364,79 @@
*/
private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
- /**
- * Mask for hyphen edits that happen at the end of a line. Keep in sync with the definition in
- * Minikin's Hyphenator.h.
- * @hide
- */
- public static final int HYPHENEDIT_MASK_END_OF_LINE = 0x07;
+ /** @hide */
+ @IntDef(prefix = { "START_HYPHEN_EDIT_" }, value = {
+ START_HYPHEN_EDIT_NO_EDIT,
+ START_HYPHEN_EDIT_INSERT_HYPHEN,
+ START_HYPHEN_EDIT_INSERT_ZWJ
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StartHyphenEdit {}
/**
- * Mask for hyphen edits that happen at the start of a line. Keep in sync with the definition in
- * Minikin's Hyphenator.h.
- * @hide
+ * An integer representing the starting of the line has no modification for hyphenation.
*/
- public static final int HYPHENEDIT_MASK_START_OF_LINE = 0x03 << 3;
+ public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+ /**
+ * An integer representing the starting of the line has normal hyphen character (U+002D).
+ */
+ public static final int START_HYPHEN_EDIT_INSERT_HYPHEN = 0x01;
+
+ /**
+ * An integer representing the starting of the line has Zero-Width-Joiner (U+200D).
+ */
+ public static final int START_HYPHEN_EDIT_INSERT_ZWJ = 0x02;
+
+ /** @hide */
+ @IntDef(prefix = { "END_HYPHEN_EDIT_" }, value = {
+ END_HYPHEN_EDIT_NO_EDIT,
+ END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN,
+ END_HYPHEN_EDIT_INSERT_HYPHEN,
+ END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN,
+ END_HYPHEN_EDIT_INSERT_MAQAF,
+ END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN,
+ END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EndHyphenEdit {}
+
+ /**
+ * An integer representing the end of the line has no modification for hyphenation.
+ */
+ public static final int END_HYPHEN_EDIT_NO_EDIT = 0x00;
+
+ /**
+ * An integer representing the character at the end of the line is replaced with hyphen
+ * character (U+002D).
+ */
+ public static final int END_HYPHEN_EDIT_REPLACE_WITH_HYPHEN = 0x01;
+
+ /**
+ * An integer representing the end of the line has normal hyphen character (U+002D).
+ */
+ public static final int END_HYPHEN_EDIT_INSERT_HYPHEN = 0x02;
+
+ /**
+ * An integer representing the end of the line has Armentian hyphen (U+058A).
+ */
+ public static final int END_HYPHEN_EDIT_INSERT_ARMENIAN_HYPHEN = 0x03;
+
+ /**
+ * An integer representing the end of the line has maqaf (Hebrew hyphen, U+05BE).
+ */
+ public static final int END_HYPHEN_EDIT_INSERT_MAQAF = 0x04;
+
+ /**
+ * An integer representing the end of the line has Canadian Syllabics hyphen (U+1400).
+ */
+ public static final int END_HYPHEN_EDIT_INSERT_UCAS_HYPHEN = 0x05;
+
+ /**
+ * An integer representing the end of the line has Zero-Width-Joiner (U+200D) followed by normal
+ * hyphen character (U+002D).
+ */
+ public static final int END_HYPHEN_EDIT_INSERT_ZWJ_AND_HYPHEN = 0x06;
/**
* The Style specifies if the primitive being drawn is filled, stroked, or
@@ -1873,54 +1933,80 @@
}
/**
- * Get the current value of packed hyphen edit.
+ * Get the current value of start hyphen edit.
*
- * You can extract start hyphen edit and end hyphen edit by using
- * {@link android.text.Hyphenator#unpackStartHyphenEdit(int)} and
- * {@link android.text.Hyphenator#unpackEndHyphenEdit(int)}.
+ * The default value is 0 which is equivalent to {@link #START_HYPHEN_EDIT_NO_EDIT}.
*
- * The default value is 0 which is equivalent to packed value of
- * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
- * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
- *
- * @return the current hyphen edit value
- * @see #setHyphenEdit(int)
+ * @return the current starting hyphen edit value
+ * @see #setStartHyphenEdit(int)
*/
- public int getHyphenEdit() {
- return nGetHyphenEdit(mNativePaint);
+ public @StartHyphenEdit int getStartHyphenEdit() {
+ return nGetStartHyphenEdit(mNativePaint);
}
/**
- * Set a packed hyphen edit on the paint.
+ * Get the current value of end hyphen edit.
*
- * By setting hyphen edit, the measurement and drawing is performed with modifying hyphenation
- * at the start of line and end of line. For example, by passing
- * {@link android.text.Hyphenator#END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+ * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
+ *
+ * @return the current starting hyphen edit value
+ * @see #setStartHyphenEdit(int)
+ */
+ public @EndHyphenEdit int getEndHyphenEdit() {
+ return nGetEndHyphenEdit(mNativePaint);
+ }
+
+ /**
+ * Set a start hyphen edit on the paint.
+ *
+ * By setting start hyphen edit, the measurement and drawing is performed with modifying
+ * hyphenation at the start of line. For example, by passing
+ * {@link #START_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
+ * character is appended at the start of line.
+ *
+ * <pre>
+ * <code>
+ * Paint paint = new Paint();
+ * paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
+ * paint.measureText("abc", 0, 3); // Returns the width of "‐abc"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "‐abc"
+ * </code>
+ * </pre>
+ *
+ * The default value is 0 which is equivalent to
+ * {@link #START_HYPHEN_EDIT_NO_EDIT}.
+ *
+ * @param startHyphen a start hyphen edit value.
+ * @see #getStartHyphenEdit()
+ */
+ public void setStartHyphenEdit(@StartHyphenEdit int startHyphen) {
+ nSetStartHyphenEdit(mNativePaint, startHyphen);
+ }
+
+ /**
+ * Set a end hyphen edit on the paint.
+ *
+ * By setting end hyphen edit, the measurement and drawing is performed with modifying
+ * hyphenation at the end of line. For example, by passing
+ * {@link #END_HYPHEN_EDIT_INSERT_HYPHEN} like as follows, HYPHEN(U+2010)
* character is appended at the end of line.
*
* <pre>
* <code>
* Paint paint = new Paint();
- * paint.setHyphenEdit(Hyphenator.packHyphenEdit(
- * Hyphenator.START_HYPHEN_EDIT_NO_EDIT,
- * Hyphenator.END_HYPHEN_EDIT_INSERT_HYPHEN));
+ * paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
* paint.measureText("abc", 0, 3); // Returns the width of "abc‐"
* Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc‐"
* </code>
* </pre>
*
- * You can pack start hyphen edit and end hyphen edit by
- * {@link android.text.Hyphenator#packHyphenEdit(int,int)}
+ * The default value is 0 which is equivalent to {@link #END_HYPHEN_EDIT_NO_EDIT}.
*
- * The default value is 0 which is equivalent to packed value of
- * {@link android.text.Hyphenator#START_HYPHEN_EDIT_NO_EDIT} and
- * {@link android.text.Hyphenator#END_HYPHEN_EDIT_NO_EDIT}.
- *
- * @param hyphen a packed hyphen edit value.
- * @see #getHyphenEdit()
+ * @param endHyphen a end hyphen edit value.
+ * @see #getEndHyphenEdit()
*/
- public void setHyphenEdit(int hyphen) {
- nSetHyphenEdit(mNativePaint, hyphen);
+ public void setEndHyphenEdit(@EndHyphenEdit int endHyphen) {
+ nSetEndHyphenEdit(mNativePaint, endHyphen);
}
/**
@@ -3063,9 +3149,13 @@
@CriticalNative
private static native void nSetWordSpacing(long paintPtr, float wordSpacing);
@CriticalNative
- private static native int nGetHyphenEdit(long paintPtr);
+ private static native int nGetStartHyphenEdit(long paintPtr);
@CriticalNative
- private static native void nSetHyphenEdit(long paintPtr, int hyphen);
+ private static native int nGetEndHyphenEdit(long paintPtr);
+ @CriticalNative
+ private static native void nSetStartHyphenEdit(long paintPtr, int hyphen);
+ @CriticalNative
+ private static native void nSetEndHyphenEdit(long paintPtr, int hyphen);
@CriticalNative
private static native void nSetStrokeMiter(long paintPtr, float miter);
@CriticalNative
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index 046bbcf..9cabf1c 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -342,8 +342,12 @@
*/
public static class Result {
// Following two contstant must be synced with minikin's line breaker.
+ // TODO(nona): Remove these constatns by introducing native methods.
private static final int TAB_MASK = 0x20000000;
private static final int HYPHEN_MASK = 0xFF;
+ private static final int START_HYPHEN_MASK = 0x18; // 0b11000
+ private static final int END_HYPHEN_MASK = 0x7; // 0b00111
+ private static final int START_HYPHEN_BITS_SHIFT = 3;
private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
Result.class.getClassLoader(), nGetReleaseResultFunc(), 32);
@@ -414,17 +418,29 @@
}
/**
- * Returns a packed hyphen edit for the line.
+ * Returns a start hyphen edit for the line.
*
* @param lineIndex an index of the line.
- * @return a packed hyphen edit for the line.
+ * @return a start hyphen edit for the line.
*
- * @see android.text.Hyphenator#unpackStartHyphenEdit(int)
- * @see android.text.Hyphenator#unpackEndHyphenEdit(int)
- * @see android.text.Hyphenator#packHyphenEdit(int,int)
+ * @see android.graphics.Paint#setStartHyphenEdit
+ * @see android.graphics.Paint#getStartHyphenEdit
*/
- public int getLineHyphenEdit(int lineIndex) {
- return (nGetLineFlag(mPtr, lineIndex) & HYPHEN_MASK);
+ public int getStartLineHyphenEdit(int lineIndex) {
+ return (nGetLineFlag(mPtr, lineIndex) & START_HYPHEN_MASK) >> START_HYPHEN_BITS_SHIFT;
+ }
+
+ /**
+ * Returns an end hyphen edit for the line.
+ *
+ * @param lineIndex an index of the line.
+ * @return an end hyphen edit for the line.
+ *
+ * @see android.graphics.Paint#setEndHyphenEdit
+ * @see android.graphics.Paint#getEndHyphenEdit
+ */
+ public int getEndLineHyphenEdit(int lineIndex) {
+ return nGetLineFlag(mPtr, lineIndex) & END_HYPHEN_MASK;
}
}
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 733f8e4..5f6b53a 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -58,9 +58,8 @@
const minikin::U16StringPiece textBuf(buf, bufSize);
const minikin::Range range(start, start + count);
const minikin::Range contextRange(contextStart, contextStart + contextCount);
- const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
- const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
- const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+ const minikin::StartHyphenEdit startHyphen = paint->getStartHyphenEdit();
+ const minikin::EndHyphenEdit endHyphen = paint->getEndHyphenEdit();
if (mt == nullptr) {
return minikin::Layout(textBuf.substr(contextRange), range - contextStart, bidiFlags,
@@ -76,9 +75,8 @@
minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
const minikin::U16StringPiece textBuf(buf, bufSize);
const minikin::Range range(start, start + count);
- const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit());
- const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit);
- const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit);
+ const minikin::StartHyphenEdit startHyphen = paint->getStartHyphenEdit();
+ const minikin::EndHyphenEdit endHyphen = paint->getEndHyphenEdit();
return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen,
endHyphen, advances);
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 601b3c2..9b2fa9d 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -27,6 +27,7 @@
#include <minikin/FontFamily.h>
#include <minikin/FamilyVariant.h>
+#include <minikin/Hyphenator.h>
namespace android {
@@ -89,9 +90,25 @@
minikin::FamilyVariant getFamilyVariant() const { return mFamilyVariant; }
- void setHyphenEdit(uint32_t hyphen) { mHyphenEdit = hyphen; }
+ void setStartHyphenEdit(uint32_t startHyphen) {
+ mHyphenEdit = minikin::packHyphenEdit(
+ static_cast<minikin::StartHyphenEdit>(startHyphen),
+ minikin::endHyphenEdit(mHyphenEdit));
+ }
- uint32_t getHyphenEdit() const { return mHyphenEdit; }
+ void setEndHyphenEdit(uint32_t endHyphen) {
+ mHyphenEdit = minikin::packHyphenEdit(
+ minikin::startHyphenEdit(mHyphenEdit),
+ static_cast<minikin::EndHyphenEdit>(endHyphen));
+ }
+
+ minikin::StartHyphenEdit getStartHyphenEdit() const {
+ return minikin::startHyphenEdit(mHyphenEdit);
+ }
+
+ minikin::EndHyphenEdit getEndHyphenEdit() const {
+ return minikin::endHyphenEdit(mHyphenEdit);
+ }
void setAndroidTypeface(Typeface* typeface) { mTypeface = typeface; }