Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26d443ae authored by Raph Levien's avatar Raph Levien
Browse files

Revert "Fix build: Revert "Record hyphens from Minikin and draw them""

This reverts commit 5a6eeb3c and
fixes the underlying issue (needed to @hide getHyphen() for subclasses
of Layout, not just the base class), and layoutlib changes for
checkbuild.

Change-Id: I7a2b5f20ae014ea8e224d8c4079cf9131e17e1c1
parent dc0078b7
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -356,6 +356,8 @@ public class DynamicLayout extends Layout
            ints[DESCENT] = desc;
            objects[0] = reflowed.getLineDirections(i);

            ints[HYPHEN] = reflowed.getHyphen(i);

            if (mEllipsize) {
                ints[ELLIPSIS_START] = reflowed.getEllipsisStart(i);
                ints[ELLIPSIS_COUNT] = reflowed.getEllipsisCount(i);
@@ -631,6 +633,14 @@ public class DynamicLayout extends Layout
        return mBottomPadding;
    }

    /**
     * @hide
     */
    @Override
    public int getHyphen(int line) {
        return mInts.getValue(line, HYPHEN);
    }

    @Override
    public int getEllipsizedWidth() {
        return mEllipsizedWidth;
@@ -739,11 +749,12 @@ public class DynamicLayout extends Layout
    private static final int TAB = START;
    private static final int TOP = 1;
    private static final int DESCENT = 2;
    private static final int COLUMNS_NORMAL = 3;
    private static final int HYPHEN = 3;
    private static final int COLUMNS_NORMAL = 4;

    private static final int ELLIPSIS_START = 3;
    private static final int ELLIPSIS_COUNT = 4;
    private static final int COLUMNS_ELLIPSIZE = 5;
    private static final int ELLIPSIS_START = 4;
    private static final int ELLIPSIS_COUNT = 5;
    private static final int COLUMNS_ELLIPSIZE = 6;

    private static final int START_MASK = 0x1FFFFFFF;
    private static final int DIR_SHIFT  = 30;
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Locale;

/**
 * Hyphenator is a wrapper class for a native implementation of automatic hyphenation,
 * in essence finding valid hyphenation opportunities in a word.
 *
 * @hide
 */
/* package */ class Hyphenator {
    // This class has deliberately simple lifetime management (no finalizer) because in
    // the common case a process will use a very small number of locales.

    private static String TAG = "Hyphenator";

    static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>();

    private long mNativePtr;

    private Hyphenator(long nativePtr) {
        mNativePtr = nativePtr;
    }

    public static long get(Locale locale) {
        synchronized (sMap) {
            Hyphenator result = sMap.get(locale);
            if (result == null) {
                result = loadHyphenator(locale);
                sMap.put(locale, result);
            }
            return result == null ? 0 : result.mNativePtr;
        }
    }

    private static Hyphenator loadHyphenator(Locale locale) {
        // TODO: find pattern dictionary (from system location) that best matches locale
        if (Locale.US.equals(locale)) {
            File f = new File("/data/local/tmp/hyph-en-us.pat.txt");
            try {
                RandomAccessFile rf = new RandomAccessFile(f, "r");
                byte[] buf = new byte[(int)rf.length()];
                rf.read(buf);
                rf.close();
                String patternData = new String(buf);
                long nativePtr = StaticLayout.nLoadHyphenator(patternData);
                return new Hyphenator(nativePtr);
            } catch (IOException e) {
                Log.e(TAG, "error loading hyphenation " + f);
            }
        }
        return null;
    }
}
+21 −11
Original line number Diff line number Diff line
@@ -225,17 +225,17 @@ public abstract class Layout {

        // Draw the lines, one at a time.
        // The baseline is the top of the following line minus the current line's descent.
        for (int i = firstLine; i <= lastLine; i++) {
        for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) {
            int start = previousLineEnd;
            previousLineEnd = getLineStart(i + 1);
            int end = getLineVisibleEnd(i, start, previousLineEnd);
            previousLineEnd = getLineStart(lineNum + 1);
            int end = getLineVisibleEnd(lineNum, start, previousLineEnd);

            int ltop = previousLineBottom;
            int lbottom = getLineTop(i+1);
            int lbottom = getLineTop(lineNum + 1);
            previousLineBottom = lbottom;
            int lbaseline = lbottom - getLineDescent(i);
            int lbaseline = lbottom - getLineDescent(lineNum);

            int dir = getParagraphDirection(i);
            int dir = getParagraphDirection(lineNum);
            int left = 0;
            int right = mWidth;

@@ -254,7 +254,7 @@ public abstract class Layout {
                // just collect the ones present at the start of the paragraph.
                // If spanEnd is before the end of the paragraph, that's not
                // our problem.
                if (start >= spanEnd && (i == firstLine || isFirstParaLine)) {
                if (start >= spanEnd && (lineNum == firstLine || isFirstParaLine)) {
                    spanEnd = sp.nextSpanTransition(start, textLength,
                                                    ParagraphStyle.class);
                    spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
@@ -280,7 +280,7 @@ public abstract class Layout {
                        int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
                        // if there is more than one LeadingMarginSpan2, use
                        // the count that is greatest
                        if (i < startLine + count) {
                        if (lineNum < startLine + count) {
                            useFirstLineMargin = true;
                            break;
                        }
@@ -304,7 +304,7 @@ public abstract class Layout {
                }
            }

            boolean hasTabOrEmoji = getLineContainsTab(i);
            boolean hasTabOrEmoji = getLineContainsTab(lineNum);
            // Can't tell if we have tabs for sure, currently
            if (hasTabOrEmoji && !tabStopsIsInitialized) {
                if (tabStops == null) {
@@ -333,7 +333,7 @@ public abstract class Layout {
                    x = right;
                }
            } else {
                int max = (int)getLineExtent(i, tabStops, false);
                int max = (int)getLineExtent(lineNum, tabStops, false);
                if (align == Alignment.ALIGN_OPPOSITE) {
                    if (dir == DIR_LEFT_TO_RIGHT) {
                        x = right - max;
@@ -346,7 +346,8 @@ public abstract class Layout {
                }
            }

            Directions directions = getLineDirections(i);
            paint.setHyphenEdit(getHyphen(lineNum));
            Directions directions = getLineDirections(lineNum);
            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTabOrEmoji) {
                // XXX: assumes there's nothing additional to be done
                canvas.drawText(buf, start, end, x, lbaseline, paint);
@@ -677,6 +678,15 @@ public abstract class Layout {
     */
    public abstract int getBottomPadding();

    /**
     * Returns the hyphen edit for a line.
     *
     * @hide
     */
    public int getHyphen(int line) {
        return 0;
    }


    /**
     * Returns true if the character at offset and the preceding character
+29 −14
Original line number Diff line number Diff line
@@ -170,7 +170,8 @@ public class StaticLayout extends Layout {
         * Measurement and break iteration is done in native code. The protocol for using
         * the native code is as follows.
         *
         * For each paragraph, do a nSetText of the paragraph text. Also do nSetLineWidth.
         * For each paragraph, do a nSetupParagraph, which sets paragraph text, line width, tab
         * stops, break strategy (and possibly other parameters in the future).
         *
         * Then, for each run within the paragraph:
         *  - setLocale (this must be done at least for the first run, optional afterwards)
@@ -187,7 +188,7 @@ public class StaticLayout extends Layout {

        private void setLocale(Locale locale) {
            if (!locale.equals(mLocale)) {
                nSetLocale(mNativePtr, locale.toLanguageTag());
                nSetLocale(mNativePtr, locale.toLanguageTag(), Hyphenator.get(locale));
                mLocale = locale;
            }
        }
@@ -531,7 +532,7 @@ public class StaticLayout extends Layout {

            int[] breaks = lineBreaks.breaks;
            float[] lineWidths = lineBreaks.widths;
            boolean[] flags = lineBreaks.flags;
            int[] flags = lineBreaks.flags;

            // here is the offset of the starting character of the line we are currently measuring
            int here = paraStart;
@@ -617,7 +618,7 @@ public class StaticLayout extends Layout {
                    fm.top, fm.bottom,
                    v,
                    spacingmult, spacingadd, null,
                    null, fm, false,
                    null, fm, 0,
                    needMultiply, measured.mLevels, measured.mDir, measured.mEasy, bufEnd,
                    includepad, trackpad, null,
                    null, bufStart, ellipsize,
@@ -629,7 +630,7 @@ public class StaticLayout extends Layout {
                      int above, int below, int top, int bottom, int v,
                      float spacingmult, float spacingadd,
                      LineHeightSpan[] chooseHt, int[] chooseHtv,
                      Paint.FontMetricsInt fm, boolean hasTabOrEmoji,
                      Paint.FontMetricsInt fm, int flags,
                      boolean needMultiply, byte[] chdirs, int dir,
                      boolean easy, int bufEnd, boolean includePad,
                      boolean trackPad, char[] chs,
@@ -722,8 +723,10 @@ public class StaticLayout extends Layout {
        lines[off + mColumns + START] = end;
        lines[off + mColumns + TOP] = v;

        if (hasTabOrEmoji)
            lines[off + TAB] |= TAB_MASK;
        // TODO: could move TAB to share same column as HYPHEN, simplifying this code and gaining
        // one bit for start field
        lines[off + TAB] |= flags & TAB_MASK;
        lines[off + HYPHEN] = flags;

        lines[off + DIR] |= dir << DIR_SHIFT;
        Directions linedirs = DIRS_ALL_LEFT_TO_RIGHT;
@@ -942,6 +945,14 @@ public class StaticLayout extends Layout {
        return mBottomPadding;
    }

    /**
     * @hide
     */
    @Override
    public int getHyphen(int line) {
        return mLines[mColumns * line + HYPHEN] & 0xff;
    }

    @Override
    public int getEllipsisCount(int line) {
        if (mColumns < COLUMNS_ELLIPSIZE) {
@@ -968,7 +979,10 @@ public class StaticLayout extends Layout {
    private static native long nNewBuilder();
    private static native void nFreeBuilder(long nativePtr);
    private static native void nFinishBuilder(long nativePtr);
    private static native void nSetLocale(long nativePtr, String locale);

    /* package */ static native long nLoadHyphenator(String patternData);

    private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator);

    // Set up paragraph text and settings; done as one big method to minimize jni crossings
    private static native void nSetupParagraph(long nativePtr, char[] text, int length,
@@ -991,22 +1005,23 @@ public class StaticLayout extends Layout {
    // to reduce the number of JNI calls in the common case where the
    // arrays do not have to be resized
    private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle,
            int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength);
            int[] recycleBreaks, float[] recycleWidths, int[] recycleFlags, int recycleLength);

    private int mLineCount;
    private int mTopPadding, mBottomPadding;
    private int mColumns;
    private int mEllipsizedWidth;

    private static final int COLUMNS_NORMAL = 3;
    private static final int COLUMNS_ELLIPSIZE = 5;
    private static final int COLUMNS_NORMAL = 4;
    private static final int COLUMNS_ELLIPSIZE = 6;
    private static final int START = 0;
    private static final int DIR = START;
    private static final int TAB = START;
    private static final int TOP = 1;
    private static final int DESCENT = 2;
    private static final int ELLIPSIS_START = 3;
    private static final int ELLIPSIS_COUNT = 4;
    private static final int HYPHEN = 3;
    private static final int ELLIPSIS_START = 4;
    private static final int ELLIPSIS_COUNT = 5;

    private int[] mLines;
    private Directions[] mLineDirections;
@@ -1028,7 +1043,7 @@ public class StaticLayout extends Layout {
        private static final int INITIAL_SIZE = 16;
        public int[] breaks = new int[INITIAL_SIZE];
        public float[] widths = new float[INITIAL_SIZE];
        public boolean[] flags = new boolean[INITIAL_SIZE]; // hasTabOrEmoji
        public int[] flags = new int[INITIAL_SIZE]; // hasTabOrEmoji
        // breaks, widths, and flags should all have the same length
    }

+4 −0
Original line number Diff line number Diff line
@@ -955,6 +955,10 @@ class TextLine {
                    span.updateDrawState(wp);
                }

                // Only draw hyphen on last run in line
                if (jnext < mLen) {
                    wp.setHyphenEdit(0);
                }
                x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
                        top, y, bottom, fmi, needWidth || jnext < measureLimit);
            }
Loading