• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.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.text.StaticLayout_Delegate.Builder;
28 import android.text.StaticLayout_Delegate.Run;
29 
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 
33 import libcore.util.NativeAllocationRegistry_Delegate;
34 
35 /**
36  * Delegate that provides implementation for native methods in {@link android.text.MeasuredParagraph}
37  * <p/>
38  * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
39  * by calls to methods of the same name in this delegate class.
40  *
41  */
42 public class MeasuredParagraph_Delegate {
43 
44     // ---- Builder delegate manager ----
45     private static final DelegateManager<MeasuredParagraphBuilder> sBuilderManager =
46             new DelegateManager<>(MeasuredParagraphBuilder.class);
47     private static final DelegateManager<MeasuredParagraph_Delegate> sManager =
48             new DelegateManager<>(MeasuredParagraph_Delegate.class);
49     private static long sFinalizer = -1;
50 
51     private long mNativeBuilderPtr;
52 
53     @LayoutlibDelegate
nInitBuilder()54     /*package*/ static long nInitBuilder() {
55         return sBuilderManager.addNewDelegate(new MeasuredParagraphBuilder());
56     }
57 
58     /**
59      * Apply style to make native measured text.
60      *
61      * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
62      * @param paintPtr The native paint pointer to be applied.
63      * @param start The start offset in the copied buffer.
64      * @param end The end offset in the copied buffer.
65      * @param isRtl True if the text is RTL.
66      */
67     @LayoutlibDelegate
nAddStyleRun(long nativeBuilderPtr, long paintPtr, int start, int end, boolean isRtl)68     /*package*/ static void nAddStyleRun(long nativeBuilderPtr, long paintPtr, int start,
69             int end, boolean isRtl) {
70         MeasuredParagraphBuilder builder = sBuilderManager.getDelegate(nativeBuilderPtr);
71         if (builder == null) {
72             return;
73         }
74         builder.mRuns.add(new StyleRun(paintPtr, start, end, isRtl));
75     }
76 
77     /**
78      * Apply ReplacementRun to make native measured text.
79      *
80      * @param nativeBuilderPtr The native MeasuredParagraph builder pointer.
81      * @param paintPtr The native paint pointer to be applied.
82      * @param start The start offset in the copied buffer.
83      * @param end The end offset in the copied buffer.
84      * @param width The width of the replacement.
85      */
86     @LayoutlibDelegate
nAddReplacementRun(long nativeBuilderPtr, long paintPtr, int start, int end, float width)87     /*package*/ static void nAddReplacementRun(long nativeBuilderPtr, long paintPtr, int start,
88             int end, float width) {
89         MeasuredParagraphBuilder builder = sBuilderManager.getDelegate(nativeBuilderPtr);
90         if (builder == null) {
91             return;
92         }
93         builder.mRuns.add(new ReplacementRun(start, end, width));
94     }
95 
96     @LayoutlibDelegate
nBuildNativeMeasuredParagraph(long nativeBuilderPtr, @NonNull char[] text, boolean computeHyphenation, boolean computeLayout)97     /*package*/ static long nBuildNativeMeasuredParagraph(long nativeBuilderPtr,
98             @NonNull char[] text, boolean computeHyphenation, boolean computeLayout) {
99         MeasuredParagraph_Delegate delegate = new MeasuredParagraph_Delegate();
100         delegate.mNativeBuilderPtr = nativeBuilderPtr;
101         return sManager.addNewDelegate(delegate);
102     }
103 
104     @LayoutlibDelegate
nFreeBuilder(long nativeBuilderPtr)105     /*package*/ static void nFreeBuilder(long nativeBuilderPtr) {
106         sBuilderManager.removeJavaReferenceFor(nativeBuilderPtr);
107     }
108 
109     @LayoutlibDelegate
nGetWidth(long nativePtr, int start, int end)110     /*package*/ static float nGetWidth(long nativePtr, int start, int end) {
111         // Ignore as it is not used for the layoutlib implementation
112         return 0.0f;
113     }
114 
115     @LayoutlibDelegate
nGetReleaseFunc()116     /*package*/ static long nGetReleaseFunc() {
117         synchronized (MeasuredParagraph_Delegate.class) {
118             if (sFinalizer == -1) {
119                 sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
120                         sManager::removeJavaReferenceFor);
121             }
122         }
123         return sFinalizer;
124     }
125 
126     @LayoutlibDelegate
nGetMemoryUsage(long nativePtr)127     /*package*/ static int nGetMemoryUsage(long nativePtr) {
128         // Ignore as it is not used for the layoutlib implementation
129         return 0;
130     }
131 
measureText(long nativePaint, char[] text, int index, int count, float[] widths, int bidiFlags)132     private static float measureText(long nativePaint, char[] text, int index, int count,
133             float[] widths, int bidiFlags) {
134         Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
135         RectF bounds =
136                 new BidiRenderer(null, paint, text).renderText(index, index + count, bidiFlags,
137                         widths, 0, false);
138         return bounds.right - bounds.left;
139     }
140 
computeRuns(long measuredTextPtr, Builder staticLayoutBuilder)141     public static void computeRuns(long measuredTextPtr, Builder staticLayoutBuilder) {
142         MeasuredParagraph_Delegate delegate = sManager.getDelegate(measuredTextPtr);
143         if (delegate == null) {
144             return;
145         }
146         MeasuredParagraphBuilder builder = sBuilderManager.getDelegate(delegate.mNativeBuilderPtr);
147         if (builder == null) {
148             return;
149         }
150         for (Run run: builder.mRuns) {
151             run.addTo(staticLayoutBuilder);
152         }
153     }
154 
155     private static class StyleRun extends Run {
156         private final long mNativePaint;
157         private final boolean mIsRtl;
158 
StyleRun(long nativePaint, int start, int end, boolean isRtl)159         private StyleRun(long nativePaint, int start, int end, boolean isRtl) {
160             super(start, end);
161             mNativePaint = nativePaint;
162             mIsRtl = isRtl;
163         }
164 
165         @Override
addTo(Builder builder)166         void addTo(Builder builder) {
167             int bidiFlags = mIsRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
168             measureText(mNativePaint, builder.mText, mStart, mEnd - mStart, builder.mWidths,
169                     bidiFlags);
170         }
171     }
172 
173     private static class ReplacementRun extends Run {
174         private final float mWidth;
175 
ReplacementRun(int start, int end, float width)176         private ReplacementRun(int start, int end, float width) {
177             super(start, end);
178             mWidth = width;
179         }
180 
181         @Override
addTo(Builder builder)182         void addTo(Builder builder) {
183             builder.mWidths[mStart] = mWidth;
184             Arrays.fill(builder.mWidths, mStart + 1, mEnd, 0.0f);
185         }
186     }
187 
188     private static class MeasuredParagraphBuilder {
189         private final ArrayList<Run> mRuns = new ArrayList<>();
190     }
191 }
192