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