1 /*
2  * Copyright (C) 2020 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 android.annotation.NonNull;
20 import android.graphics.Paint;
21 import android.text.TextDirectionHeuristic;
22 import android.text.TextPaint;
23 import android.text.TextUtils;
24 
25 import com.android.internal.util.Preconditions;
26 
27 import dalvik.annotation.optimization.FastNative;
28 
29 /**
30  * Provides conversion from a text into glyph array.
31  *
32  * Text shaping is a preprocess for drawing text into canvas with glyphs. The glyph is a most
33  * primitive unit of the text drawing, consist of glyph identifier in the font file and its position
34  * and style. You can draw the shape result to Canvas by calling Canvas#drawGlyphs.
35  *
36  * For most of the use cases, {@link android.text.TextShaper} will provide text shaping
37  * functionalities needed. {@link TextRunShaper} is a lower level API that is used by
38  * {@link android.text.TextShaper}.
39  *
40  * @see TextRunShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)
41  * @see TextRunShaper#shapeTextRun(char[], int, int, int, int, float, float, boolean, Paint)
42  * @see android.text.TextShaper#shapeText(CharSequence, int, int, TextDirectionHeuristic, TextPaint,
43  * TextShaper.GlyphsConsumer)
44  */
45 public class TextRunShaper {
TextRunShaper()46     private TextRunShaper() {}  // Do not instantiate
47 
48     /**
49      * Shape non-styled text.
50      *
51      * This function shapes the text of the given range under the context of given context range.
52      * Some script, e.g. Arabic or Devanagari, changes letter shape based on its location or
53      * surrounding characters.
54      *
55      * @param text a text buffer to be shaped
56      * @param start a start index of shaping target in the buffer.
57      * @param count a length of shaping target in the buffer.
58      * @param contextStart a start index of context used for shaping in the buffer.
59      * @param contextCount a length of context used for shaping in the buffer.
60      * @param xOffset an additional amount of x offset of the result glyphs.
61      * @param yOffset an additional amount of y offset of the result glyphs.
62      * @param isRtl true if this text is shaped for RTL direction, false otherwise.
63      * @param paint a paint used for shaping text.
64      * @return a shape result.
65      */
66     @NonNull
shapeTextRun( @onNull char[] text, int start, int count, int contextStart, int contextCount, float xOffset, float yOffset, boolean isRtl, @NonNull Paint paint)67     public static PositionedGlyphs shapeTextRun(
68             @NonNull char[] text, int start, int count, int contextStart, int contextCount,
69             float xOffset, float yOffset, boolean isRtl, @NonNull Paint paint) {
70         Preconditions.checkNotNull(text);
71         Preconditions.checkNotNull(paint);
72         return new PositionedGlyphs(
73                 nativeShapeTextRun(text, start, count, contextStart, contextCount, isRtl,
74                         paint.getNativeInstance()),
75                 xOffset, yOffset);
76     }
77 
78     /**
79      * Shape non-styled text.
80      *
81      * This function shapes the text of the given range under the context of given context range.
82      * Some script, e.g. Arabic or Devanagari, changes letter shape based on its location or
83      * surrounding characters.
84      *
85      * @param text a text buffer to be shaped. Any styled spans stored in this text are ignored.
86      * @param start a start index of shaping target in the buffer.
87      * @param count a length of shaping target in the buffer.
88      * @param contextStart a start index of context used for shaping in the buffer.
89      * @param contextCount a length of context used for shaping in the buffer.
90      * @param xOffset an additional amount of x offset of the result glyphs.
91      * @param yOffset an additional amount of y offset of the result glyphs.
92      * @param isRtl true if this text is shaped for RTL direction, false otherwise.
93      * @param paint a paint used for shaping text.
94      * @return a shape result
95      */
96     @NonNull
shapeTextRun( @onNull CharSequence text, int start, int count, int contextStart, int contextCount, float xOffset, float yOffset, boolean isRtl, @NonNull Paint paint)97     public static PositionedGlyphs shapeTextRun(
98             @NonNull CharSequence text, int start, int count, int contextStart, int contextCount,
99             float xOffset, float yOffset, boolean isRtl, @NonNull Paint paint) {
100         Preconditions.checkNotNull(text);
101         Preconditions.checkNotNull(paint);
102         if (text instanceof String) {
103             return new PositionedGlyphs(
104                     nativeShapeTextRun(
105                             (String) text, start, count, contextStart, contextCount, isRtl,
106                             paint.getNativeInstance()),
107                     xOffset, yOffset);
108         } else {
109             char[] buf = new char[contextCount];
110             TextUtils.getChars(text, contextStart, contextStart + contextCount, buf, 0);
111             return new PositionedGlyphs(
112                     nativeShapeTextRun(
113                             buf, start - contextStart, count,
114                             0, contextCount, isRtl, paint.getNativeInstance()),
115                     xOffset, yOffset);
116         }
117     }
118 
119     @FastNative
nativeShapeTextRun( char[] text, int start, int count, int contextStart, int contextCount, boolean isRtl, long nativePaint)120     private static native long nativeShapeTextRun(
121             char[] text, int start, int count, int contextStart, int contextCount,
122             boolean isRtl, long nativePaint);
123 
124     @FastNative
nativeShapeTextRun( String text, int start, int count, int contextStart, int contextCount, boolean isRtl, long nativePaint)125     private static native long nativeShapeTextRun(
126             String text, int start, int count, int contextStart, int contextCount,
127             boolean isRtl, long nativePaint);
128 
129 }
130