diff options
| -rw-r--r-- | api/current.txt | 35 | ||||
| -rw-r--r-- | core/java/android/text/DynamicLayout.java | 15 | ||||
| -rw-r--r-- | core/java/android/text/Hyphenator.java | 133 | ||||
| -rw-r--r-- | core/java/android/text/Layout.java | 24 | ||||
| -rw-r--r-- | core/java/android/text/StaticLayout.java | 42 | ||||
| -rw-r--r-- | core/java/android/text/TextLine.java | 39 | ||||
| -rw-r--r-- | core/jni/android/graphics/Paint.cpp | 24 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/text/StaticLayoutTest.java | 7 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/widget/TextViewTest.java | 3 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Paint.java | 166 | ||||
| -rw-r--r-- | graphics/java/android/graphics/text/LineBreaker.java | 30 | ||||
| -rw-r--r-- | libs/hwui/hwui/MinikinUtils.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/hwui/Paint.h | 21 |
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; } |