Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.graphics.text;
     18 
     19 import com.android.layoutlib.bridge.impl.DelegateManager;
     20 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
     21 
     22 import android.annotation.NonNull;
     23 import android.graphics.BidiRenderer;
     24 import android.graphics.Paint;
     25 import android.graphics.Paint_Delegate;
     26 import android.graphics.RectF;
     27 import android.graphics.text.LineBreaker_Delegate.Builder;
     28 import android.graphics.text.LineBreaker_Delegate.Run;
     29 
     30 import java.util.ArrayList;
     31 import java.util.Arrays;
     32 
     33 /**
     34  * Delegate that provides implementation for native methods in
     35  * {@link android.graphics.text.MeasuredText}
     36  * <p/>
     37  * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
     38  * by calls to methods of the same name in this delegate class.
     39  *
     40  */
     41 public class MeasuredText_Builder_Delegate {
     42     // ---- Builder delegate manager ----
     43     protected static final DelegateManager<MeasuredText_Builder_Delegate>
     44             sBuilderManager =
     45             new DelegateManager<>(MeasuredText_Builder_Delegate.class);
     46 
     47     protected final ArrayList<Run> mRuns = new ArrayList<>();
     48 
     49     @LayoutlibDelegate
     50     /*package*/ static long nInitBuilder() {
     51         return sBuilderManager.addNewDelegate(new MeasuredText_Builder_Delegate());
     52     }
     53 
     54     /**
     55      * Apply style to make native measured text.
     56      *
     57      * @param nativeBuilderPtr The native NativeMeasuredParagraph builder pointer.
     58      * @param paintPtr The native paint pointer to be applied.
     59      * @param start The start offset in the copied buffer.
     60      * @param end The end offset in the copied buffer.
     61      * @param isRtl True if the text is RTL.
     62      */
     63     @LayoutlibDelegate
     64     /*package*/ static void nAddStyleRun(long nativeBuilderPtr, long paintPtr, int start,
     65             int end, boolean isRtl) {
     66         MeasuredText_Builder_Delegate builder = sBuilderManager.getDelegate(nativeBuilderPtr);
     67         if (builder == null) {
     68             return;
     69         }
     70         builder.mRuns.add(new StyleRun(paintPtr, start, end, isRtl));
     71     }
     72 
     73     /**
     74      * Apply ReplacementRun to make native measured text.
     75      *
     76      * @param nativeBuilderPtr The native NativeMeasuredParagraph builder pointer.
     77      * @param paintPtr The native paint pointer to be applied.
     78      * @param start The start offset in the copied buffer.
     79      * @param end The end offset in the copied buffer.
     80      * @param width The width of the replacement.
     81      */
     82     @LayoutlibDelegate
     83     /*package*/ static void nAddReplacementRun(long nativeBuilderPtr, long paintPtr, int start,
     84             int end, float width) {
     85         MeasuredText_Builder_Delegate builder = sBuilderManager.getDelegate(nativeBuilderPtr);
     86         if (builder == null) {
     87             return;
     88         }
     89         builder.mRuns.add(new ReplacementRun(start, end, width));
     90     }
     91 
     92     @LayoutlibDelegate
     93     /*package*/ static long nBuildMeasuredText(long nativeBuilderPtr, long hintMtPtr,
     94             @NonNull char[] text, boolean computeHyphenation, boolean computeLayout) {
     95         MeasuredText_Delegate delegate = new MeasuredText_Delegate();
     96         delegate.mNativeBuilderPtr = nativeBuilderPtr;
     97         return MeasuredText_Delegate.sManager.addNewDelegate(delegate);
     98     }
     99 
    100     @LayoutlibDelegate
    101     /*package*/ static void nFreeBuilder(long nativeBuilderPtr) {
    102         sBuilderManager.removeJavaReferenceFor(nativeBuilderPtr);
    103     }
    104 
    105     private static float measureText(long nativePaint, char[] text, int index, int count,
    106             float[] widths, int bidiFlags) {
    107         Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
    108         RectF bounds =
    109                 new BidiRenderer(null, paint, text).renderText(index, index + count, bidiFlags,
    110                         widths, 0, false);
    111         return bounds.right - bounds.left;
    112     }
    113 
    114     private static class StyleRun extends Run {
    115         private final long mNativePaint;
    116         private final boolean mIsRtl;
    117 
    118         private StyleRun(long nativePaint, int start, int end, boolean isRtl) {
    119             super(start, end);
    120             mNativePaint = nativePaint;
    121             mIsRtl = isRtl;
    122         }
    123 
    124         @Override
    125         void addTo(Builder builder) {
    126             int bidiFlags = mIsRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
    127             measureText(mNativePaint, builder.mText, mStart, mEnd - mStart, builder.mWidths,
    128                     bidiFlags);
    129         }
    130     }
    131 
    132     private static class ReplacementRun extends Run {
    133         private final float mWidth;
    134 
    135         private ReplacementRun(int start, int end, float width) {
    136             super(start, end);
    137             mWidth = width;
    138         }
    139 
    140         @Override
    141         void addTo(Builder builder) {
    142             builder.mWidths[mStart] = mWidth;
    143             Arrays.fill(builder.mWidths, mStart + 1, mEnd, 0.0f);
    144         }
    145     }
    146 }
    147