summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt35
-rw-r--r--core/java/android/text/DynamicLayout.java15
-rw-r--r--core/java/android/text/Hyphenator.java133
-rw-r--r--core/java/android/text/Layout.java24
-rw-r--r--core/java/android/text/StaticLayout.java42
-rw-r--r--core/java/android/text/TextLine.java39
-rw-r--r--core/jni/android/graphics/Paint.cpp24
-rw-r--r--core/tests/coretests/src/android/text/StaticLayoutTest.java7
-rw-r--r--core/tests/coretests/src/android/widget/TextViewTest.java3
-rw-r--r--graphics/java/android/graphics/Paint.java166
-rw-r--r--graphics/java/android/graphics/text/LineBreaker.java30
-rw-r--r--libs/hwui/hwui/MinikinUtils.cpp10
-rw-r--r--libs/hwui/hwui/Paint.h21
13 files changed, 302 insertions, 247 deletions
diff --git a/api/current.txt b/api/current.txt
index 440a2fc36805..9dc51b13229f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14431,6 +14431,7 @@ package android.graphics {
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();
@@ -14441,7 +14442,6 @@ package android.graphics {
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);
@@ -14455,6 +14455,7 @@ package android.graphics {
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();
@@ -14510,13 +14511,13 @@ package android.graphics {
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);
@@ -14524,6 +14525,7 @@ package android.graphics {
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);
@@ -14550,11 +14552,21 @@ package android.graphics {
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
@@ -15928,12 +15940,13 @@ package android.graphics.text {
}
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);
}
@@ -46004,22 +46017,6 @@ package android.text {
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 c928da103557..32982f9df15d 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -674,7 +674,8 @@ public class DynamicLayout extends Layout {
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 @@ public class DynamicLayout extends Layout {
* @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 e4200ac0bc6c..6f0628ad38e6 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.
- *
- * 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.
+ * Does the native Hyphenator initialization.
*
- * <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 2d5f3bf8c862..fb6dc228e786 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -437,7 +437,8 @@ public abstract class Layout {
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 class Layout {
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 @@ public abstract class Layout {
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 @@ public abstract class Layout {
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 defe2cefc1f7..9fefc83056ac 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -779,7 +779,8 @@ public class StaticLayout extends Layout {
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 @@ public class StaticLayout extends Layout {
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.
+ * Returns the start 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)}.
+ * @param lineNumber a line number
+ * @return A start hyphen edit value.
+ * @hide
+ */
+ @Override
+ 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 A packed hyphen edit value.
+ * @return An end hyphen edit value.
* @hide
*/
@Override
- public int getHyphen(int lineNumber) {
- return mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK;
+ public @Paint.EndHyphenEdit int getEndHyphenEdit(int lineNumber) {
+ return unpackEndHyphenEdit(mLines[mColumns * lineNumber + HYPHEN] & HYPHEN_MASK);
}
/**
@@ -1395,6 +1418,9 @@ public class StaticLayout extends Layout {
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 915a18e59226..86651060a394 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -1012,19 +1012,14 @@ public class TextLine {
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 @@ public class TextLine {
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 @@ public class TextLine {
// 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 @@ public class TextLine {
}
}
// 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 @@ public class TextLine {
&& 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 85f11595346f..cd7346eb0215 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -923,14 +923,24 @@ namespace PaintGlue {
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 @@ static const JNINativeMethod methods[] = {
{"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 b1c896ec2ce4..0ebf03fab966 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.assertEquals;
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 @@ public class StaticLayoutTest {
@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 585360fdd2f3..0617caf57308 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -209,7 +209,8 @@ public class TextViewTest {
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 9eeb43b579bc..452f7c93f8aa 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -364,19 +364,79 @@ public class Paint {
*/
private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
+ /** @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 end 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_END_OF_LINE = 0x07;
+ public static final int START_HYPHEN_EDIT_NO_EDIT = 0x00;
/**
- * 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 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 HYPHENEDIT_MASK_START_OF_LINE = 0x03 << 3;
+ 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 @@ public class Paint {
}
/**
- * Get the current value of packed hyphen edit.
+ * Get the current value of start hyphen edit.
+ *
+ * The default value is 0 which is equivalent to {@link #START_HYPHEN_EDIT_NO_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)}.
+ * @return the current starting hyphen edit value
+ * @see #setStartHyphenEdit(int)
+ */
+ public @StartHyphenEdit int getStartHyphenEdit() {
+ return nGetStartHyphenEdit(mNativePaint);
+ }
+
+ /**
+ * Get the current value of end hyphen 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}.
+ * The default value is 0 which is equivalent to {@link #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 @EndHyphenEdit int getEndHyphenEdit() {
+ return nGetEndHyphenEdit(mNativePaint);
}
/**
- * Set a packed hyphen edit on the paint.
+ * Set a start hyphen edit on the paint.
*
- * 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)
+ * 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 @@ public class Paint {
@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 int nGetEndHyphenEdit(long paintPtr);
+ @CriticalNative
+ private static native void nSetStartHyphenEdit(long paintPtr, int hyphen);
@CriticalNative
- private static native void nSetHyphenEdit(long paintPtr, int hyphen);
+ 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 046bbcffb76a..9cabf1ce185d 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -342,8 +342,12 @@ public class LineBreaker {
*/
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 @@ public class LineBreaker {
}
/**
- * 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 733f8e415270..5f6b53ac767f 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -58,9 +58,8 @@ minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFla
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 @@ float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags,
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 601b3c23cc1f..9b2fa9df1e8f 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 @@ public:
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));
+ }
+
+ void setEndHyphenEdit(uint32_t endHyphen) {
+ mHyphenEdit = minikin::packHyphenEdit(
+ minikin::startHyphenEdit(mHyphenEdit),
+ static_cast<minikin::EndHyphenEdit>(endHyphen));
+ }
- uint32_t getHyphenEdit() const { return mHyphenEdit; }
+ minikin::StartHyphenEdit getStartHyphenEdit() const {
+ return minikin::startHyphenEdit(mHyphenEdit);
+ }
+
+ minikin::EndHyphenEdit getEndHyphenEdit() const {
+ return minikin::endHyphenEdit(mHyphenEdit);
+ }
void setAndroidTypeface(Typeface* typeface) { mTypeface = typeface; }