Merge "Support extra linespacing based on fallback fonts"
This commit is contained in:
committed by
Android (Google) Code Review
commit
64059f2eec
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.perftests.utils.BenchmarkState;
|
||||
import android.perftests.utils.PerfStatusReporter;
|
||||
|
||||
import android.support.test.filters.LargeTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Random;
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class StaticLayoutPerfTest {
|
||||
|
||||
public StaticLayoutPerfTest() {
|
||||
}
|
||||
|
||||
@Rule
|
||||
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
|
||||
|
||||
private static final String FIXED_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing "
|
||||
+ "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad "
|
||||
+ "minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
+ "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse "
|
||||
+ "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
|
||||
+ "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
|
||||
private static final int FIXED_TEXT_LENGTH = FIXED_TEXT.length();
|
||||
|
||||
private static TextPaint PAINT = new TextPaint();
|
||||
private static final int TEXT_WIDTH = 20 * (int) PAINT.getTextSize();
|
||||
|
||||
@Test
|
||||
public void testCreate() {
|
||||
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
while (state.keepRunning()) {
|
||||
StaticLayout.Builder.obtain(FIXED_TEXT, 0, FIXED_TEXT_LENGTH, PAINT, TEXT_WIDTH)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
private static final int ALPHABET_LENGTH = ALPHABET.length();
|
||||
|
||||
private static final int PARA_LENGTH = 500;
|
||||
private final char[] mBuffer = new char[PARA_LENGTH];
|
||||
private final Random mRandom = new Random(31415926535L);
|
||||
|
||||
private CharSequence generateRandomParagraph(int wordLen) {
|
||||
for (int i = 0; i < PARA_LENGTH; i++) {
|
||||
if (i % (wordLen + 1) == wordLen) {
|
||||
mBuffer[i] = ' ';
|
||||
} else {
|
||||
mBuffer[i] = ALPHABET.charAt(mRandom.nextInt(ALPHABET_LENGTH));
|
||||
}
|
||||
}
|
||||
return CharBuffer.wrap(mBuffer);
|
||||
}
|
||||
|
||||
// This tries to simulate the case where the cache hit rate is low, and most of the text is
|
||||
// new text.
|
||||
@Test
|
||||
public void testCreateRandom() {
|
||||
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
while (state.keepRunning()) {
|
||||
final CharSequence text = generateRandomParagraph(9);
|
||||
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41781,6 +41781,7 @@ package android.text {
|
||||
method public android.text.StaticLayout.Builder setMaxLines(int);
|
||||
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
|
||||
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
|
||||
method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean);
|
||||
}
|
||||
|
||||
public abstract interface TextDirectionHeuristic {
|
||||
|
||||
@@ -45383,6 +45383,7 @@ package android.text {
|
||||
method public android.text.StaticLayout.Builder setMaxLines(int);
|
||||
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
|
||||
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
|
||||
method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean);
|
||||
}
|
||||
|
||||
public abstract interface TextDirectionHeuristic {
|
||||
|
||||
@@ -42052,6 +42052,7 @@ package android.text {
|
||||
method public android.text.StaticLayout.Builder setMaxLines(int);
|
||||
method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
|
||||
method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
|
||||
method public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean);
|
||||
}
|
||||
|
||||
public abstract interface TextDirectionHeuristic {
|
||||
|
||||
@@ -90,6 +90,7 @@ public class StaticLayout extends Layout {
|
||||
b.mSpacingMult = 1.0f;
|
||||
b.mSpacingAdd = 0.0f;
|
||||
b.mIncludePad = true;
|
||||
b.mFallbackLineSpacing = false;
|
||||
b.mEllipsizedWidth = width;
|
||||
b.mEllipsize = null;
|
||||
b.mMaxLines = Integer.MAX_VALUE;
|
||||
@@ -227,6 +228,24 @@ public class StaticLayout extends Layout {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to respect the ascent and descent of the fallback fonts that are used in
|
||||
* displaying the text (which is needed to avoid text from consecutive lines running into
|
||||
* each other). If set, fallback fonts that end up getting used can increase the ascent
|
||||
* and descent of the lines that they are used on.
|
||||
*
|
||||
* <p>For backward compatibility reasons, the default is {@code false}, but setting this to
|
||||
* true is strongly recommended. It is required to be true if text could be in languages
|
||||
* like Burmese or Tibetan where text is typically much taller or deeper than Latin text.
|
||||
*
|
||||
* @param useLineSpacingFromFallbacks whether to expand linespacing based on fallback fonts
|
||||
* @return this builder, useful for chaining
|
||||
*/
|
||||
public Builder setUseLineSpacingFromFallbacks(boolean useLineSpacingFromFallbacks) {
|
||||
mFallbackLineSpacing = useLineSpacingFromFallbacks;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width as used for ellipsizing purposes, if it differs from the
|
||||
* normal layout width. The default is the {@code width}
|
||||
@@ -432,6 +451,7 @@ public class StaticLayout extends Layout {
|
||||
float mSpacingMult;
|
||||
float mSpacingAdd;
|
||||
boolean mIncludePad;
|
||||
boolean mFallbackLineSpacing;
|
||||
int mEllipsizedWidth;
|
||||
TextUtils.TruncateAt mEllipsize;
|
||||
int mMaxLines;
|
||||
@@ -606,6 +626,7 @@ public class StaticLayout extends Layout {
|
||||
TextPaint paint = b.mPaint;
|
||||
int outerWidth = b.mWidth;
|
||||
TextDirectionHeuristic textDir = b.mTextDir;
|
||||
final boolean fallbackLineSpacing = b.mFallbackLineSpacing;
|
||||
float spacingmult = b.mSpacingMult;
|
||||
float spacingadd = b.mSpacingAdd;
|
||||
float ellipsizedWidth = b.mEllipsizedWidth;
|
||||
@@ -784,11 +805,14 @@ public class StaticLayout extends Layout {
|
||||
|
||||
nGetWidths(b.mNativePtr, widths);
|
||||
int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks,
|
||||
lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length);
|
||||
lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags,
|
||||
lineBreaks.breaks.length);
|
||||
|
||||
int[] breaks = lineBreaks.breaks;
|
||||
float[] lineWidths = lineBreaks.widths;
|
||||
int[] flags = lineBreaks.flags;
|
||||
final int[] breaks = lineBreaks.breaks;
|
||||
final float[] lineWidths = lineBreaks.widths;
|
||||
final float[] ascents = lineBreaks.ascents;
|
||||
final float[] descents = lineBreaks.descents;
|
||||
final int[] flags = lineBreaks.flags;
|
||||
|
||||
final int remainingLineCount = mMaximumVisibleLineCount - mLineCount;
|
||||
final boolean ellipsisMayBeApplied = ellipsize != null
|
||||
@@ -799,7 +823,7 @@ public class StaticLayout extends Layout {
|
||||
&& ellipsisMayBeApplied) {
|
||||
// Calculate width and flag.
|
||||
float width = 0;
|
||||
int flag = 0;
|
||||
int flag = 0; // XXX May need to also have starting hyphen edit
|
||||
for (int i = remainingLineCount - 1; i < breakCount; i++) {
|
||||
if (i == breakCount - 1) {
|
||||
width += lineWidths[i];
|
||||
@@ -808,7 +832,7 @@ public class StaticLayout extends Layout {
|
||||
width += widths[j];
|
||||
}
|
||||
}
|
||||
flag |= flags[i] & TAB_MASK; // XXX May need to also have starting hyphen edit
|
||||
flag |= flags[i] & TAB_MASK;
|
||||
}
|
||||
// Treat the last line and overflowed lines as a single line.
|
||||
breaks[remainingLineCount - 1] = breaks[breakCount - 1];
|
||||
@@ -859,8 +883,14 @@ public class StaticLayout extends Layout {
|
||||
|
||||
boolean moreChars = (endPos < bufEnd);
|
||||
|
||||
final int ascent = fallbackLineSpacing
|
||||
? Math.min(fmAscent, (int) Math.round(ascents[breakIndex]))
|
||||
: fmAscent;
|
||||
final int descent = fallbackLineSpacing
|
||||
? Math.max(fmDescent, (int) Math.round(descents[breakIndex]))
|
||||
: fmDescent;
|
||||
v = out(source, here, endPos,
|
||||
fmAscent, fmDescent, fmTop, fmBottom,
|
||||
ascent, descent, fmTop, fmBottom,
|
||||
v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex],
|
||||
needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad,
|
||||
addLastLineSpacing, chs, widths, paraStart, ellipsize,
|
||||
@@ -891,8 +921,6 @@ public class StaticLayout extends Layout {
|
||||
|
||||
if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) &&
|
||||
mLineCount < mMaximumVisibleLineCount) {
|
||||
// Log.e("text", "output last " + bufEnd);
|
||||
|
||||
measured.setPara(source, bufEnd, bufEnd, textDir, b);
|
||||
|
||||
paint.getFontMetricsInt(fm);
|
||||
@@ -1470,7 +1498,8 @@ 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, int[] recycleFlags, int recycleLength);
|
||||
int[] recycleBreaks, float[] recycleWidths, float[] recycleAscents,
|
||||
float[] recycleDescents, int[] recycleFlags, int recycleLength);
|
||||
|
||||
private int mLineCount;
|
||||
private int mTopPadding, mBottomPadding;
|
||||
@@ -1529,6 +1558,8 @@ 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 float[] ascents = new float[INITIAL_SIZE];
|
||||
public float[] descents = new float[INITIAL_SIZE];
|
||||
public int[] flags = new int[INITIAL_SIZE]; // hasTab
|
||||
// breaks, widths, and flags should all have the same length
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace android {
|
||||
struct JLineBreaksID {
|
||||
jfieldID breaks;
|
||||
jfieldID widths;
|
||||
jfieldID ascents;
|
||||
jfieldID descents;
|
||||
jfieldID flags;
|
||||
};
|
||||
|
||||
@@ -73,35 +75,45 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex
|
||||
}
|
||||
|
||||
static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
|
||||
jfloatArray recycleWidths, jintArray recycleFlags,
|
||||
jfloatArray recycleWidths, jfloatArray recycleAscents,
|
||||
jfloatArray recycleDescents, jintArray recycleFlags,
|
||||
jint recycleLength, size_t nBreaks, const jint* breaks,
|
||||
const jfloat* widths, const jint* flags) {
|
||||
const jfloat* widths, const jfloat* ascents, const jfloat* descents,
|
||||
const jint* flags) {
|
||||
if ((size_t)recycleLength < nBreaks) {
|
||||
// have to reallocate buffers
|
||||
recycleBreaks = env->NewIntArray(nBreaks);
|
||||
recycleWidths = env->NewFloatArray(nBreaks);
|
||||
recycleAscents = env->NewFloatArray(nBreaks);
|
||||
recycleDescents = env->NewFloatArray(nBreaks);
|
||||
recycleFlags = env->NewIntArray(nBreaks);
|
||||
|
||||
env->SetObjectField(recycle, gLineBreaks_fieldID.breaks, recycleBreaks);
|
||||
env->SetObjectField(recycle, gLineBreaks_fieldID.widths, recycleWidths);
|
||||
env->SetObjectField(recycle, gLineBreaks_fieldID.ascents, recycleAscents);
|
||||
env->SetObjectField(recycle, gLineBreaks_fieldID.descents, recycleDescents);
|
||||
env->SetObjectField(recycle, gLineBreaks_fieldID.flags, recycleFlags);
|
||||
}
|
||||
// copy data
|
||||
env->SetIntArrayRegion(recycleBreaks, 0, nBreaks, breaks);
|
||||
env->SetFloatArrayRegion(recycleWidths, 0, nBreaks, widths);
|
||||
env->SetFloatArrayRegion(recycleAscents, 0, nBreaks, ascents);
|
||||
env->SetFloatArrayRegion(recycleDescents, 0, nBreaks, descents);
|
||||
env->SetIntArrayRegion(recycleFlags, 0, nBreaks, flags);
|
||||
}
|
||||
|
||||
static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
|
||||
jobject recycle, jintArray recycleBreaks,
|
||||
jfloatArray recycleWidths, jintArray recycleFlags,
|
||||
jfloatArray recycleWidths, jfloatArray recycleAscents,
|
||||
jfloatArray recycleDescents, jintArray recycleFlags,
|
||||
jint recycleLength) {
|
||||
minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr);
|
||||
|
||||
size_t nBreaks = b->computeBreaks();
|
||||
|
||||
recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength,
|
||||
nBreaks, b->getBreaks(), b->getWidths(), b->getFlags());
|
||||
recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleAscents, recycleDescents,
|
||||
recycleFlags, recycleLength, nBreaks, b->getBreaks(), b->getWidths(), b->getAscents(),
|
||||
b->getDescents(), b->getFlags());
|
||||
|
||||
b->finish();
|
||||
|
||||
@@ -205,7 +217,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun},
|
||||
{"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun},
|
||||
{"nGetWidths", "(J[F)V", (void*) nGetWidths},
|
||||
{"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[II)I",
|
||||
{"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[F[F[II)I",
|
||||
(void*) nComputeLineBreaks}
|
||||
};
|
||||
|
||||
@@ -216,6 +228,8 @@ int register_android_text_StaticLayout(JNIEnv* env)
|
||||
|
||||
gLineBreaks_fieldID.breaks = GetFieldIDOrDie(env, gLineBreaks_class, "breaks", "[I");
|
||||
gLineBreaks_fieldID.widths = GetFieldIDOrDie(env, gLineBreaks_class, "widths", "[F");
|
||||
gLineBreaks_fieldID.ascents = GetFieldIDOrDie(env, gLineBreaks_class, "ascents", "[F");
|
||||
gLineBreaks_fieldID.descents = GetFieldIDOrDie(env, gLineBreaks_class, "descents", "[F");
|
||||
gLineBreaks_fieldID.flags = GetFieldIDOrDie(env, gLineBreaks_class, "flags", "[I");
|
||||
|
||||
return RegisterMethodsOrDie(env, "android/text/StaticLayout", gMethods, NELEM(gMethods));
|
||||
|
||||
BIN
core/tests/coretests/assets/fonts/ascent1em-descent2em.ttf
Normal file
BIN
core/tests/coretests/assets/fonts/ascent1em-descent2em.ttf
Normal file
Binary file not shown.
181
core/tests/coretests/assets/fonts/ascent1em-descent2em.ttx
Normal file
181
core/tests/coretests/assets/fonts/ascent1em-descent2em.ttx
Normal file
@@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
|
||||
|
||||
<GlyphOrder>
|
||||
<GlyphID id="0" name=".notdef"/>
|
||||
<GlyphID id="1" name="1em"/>
|
||||
</GlyphOrder>
|
||||
|
||||
<head>
|
||||
<tableVersion value="1.0"/>
|
||||
<fontRevision value="1.0"/>
|
||||
<checkSumAdjustment value="0x640cdb2f"/>
|
||||
<magicNumber value="0x5f0f3cf5"/>
|
||||
<flags value="00000000 00000011"/>
|
||||
<unitsPerEm value="1000"/>
|
||||
<created value="Fri Mar 17 07:26:00 2017"/>
|
||||
<macStyle value="00000000 00000000"/>
|
||||
<lowestRecPPEM value="7"/>
|
||||
<fontDirectionHint value="2"/>
|
||||
<glyphDataFormat value="0"/>
|
||||
</head>
|
||||
|
||||
<hhea>
|
||||
<tableVersion value="0x10000"/>
|
||||
<ascent value="1000"/>
|
||||
<descent value="-2000"/>
|
||||
<lineGap value="0"/>
|
||||
<caretSlopeRise value="1"/>
|
||||
<caretSlopeRun value="0"/>
|
||||
<caretOffset value="0"/>
|
||||
<reserved0 value="0"/>
|
||||
<reserved1 value="0"/>
|
||||
<reserved2 value="0"/>
|
||||
<reserved3 value="0"/>
|
||||
<metricDataFormat value="0"/>
|
||||
</hhea>
|
||||
|
||||
<maxp>
|
||||
<tableVersion value="0x10000"/>
|
||||
<maxZones value="0"/>
|
||||
<maxTwilightPoints value="0"/>
|
||||
<maxStorage value="0"/>
|
||||
<maxFunctionDefs value="0"/>
|
||||
<maxInstructionDefs value="0"/>
|
||||
<maxStackElements value="0"/>
|
||||
<maxSizeOfInstructions value="0"/>
|
||||
<maxComponentElements value="0"/>
|
||||
</maxp>
|
||||
|
||||
<OS_2>
|
||||
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
|
||||
will be recalculated by the compiler -->
|
||||
<version value="3"/>
|
||||
<xAvgCharWidth value="594"/>
|
||||
<usWeightClass value="400"/>
|
||||
<usWidthClass value="5"/>
|
||||
<fsType value="00000000 00001000"/>
|
||||
<ySubscriptXSize value="650"/>
|
||||
<ySubscriptYSize value="600"/>
|
||||
<ySubscriptXOffset value="0"/>
|
||||
<ySubscriptYOffset value="75"/>
|
||||
<ySuperscriptXSize value="650"/>
|
||||
<ySuperscriptYSize value="600"/>
|
||||
<ySuperscriptXOffset value="0"/>
|
||||
<ySuperscriptYOffset value="350"/>
|
||||
<yStrikeoutSize value="50"/>
|
||||
<yStrikeoutPosition value="300"/>
|
||||
<sFamilyClass value="0"/>
|
||||
<panose>
|
||||
<bFamilyType value="0"/>
|
||||
<bSerifStyle value="0"/>
|
||||
<bWeight value="5"/>
|
||||
<bProportion value="0"/>
|
||||
<bContrast value="0"/>
|
||||
<bStrokeVariation value="0"/>
|
||||
<bArmStyle value="0"/>
|
||||
<bLetterForm value="0"/>
|
||||
<bMidline value="0"/>
|
||||
<bXHeight value="0"/>
|
||||
</panose>
|
||||
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
|
||||
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
|
||||
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
|
||||
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
|
||||
<achVendID value="UKWN"/>
|
||||
<fsSelection value="00000000 01000000"/>
|
||||
<usFirstCharIndex value="32"/>
|
||||
<usLastCharIndex value="122"/>
|
||||
<sTypoAscender value="800"/>
|
||||
<sTypoDescender value="-200"/>
|
||||
<sTypoLineGap value="200"/>
|
||||
<usWinAscent value="1000"/>
|
||||
<usWinDescent value="200"/>
|
||||
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
|
||||
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
|
||||
<sxHeight value="500"/>
|
||||
<sCapHeight value="700"/>
|
||||
<usDefaultChar value="0"/>
|
||||
<usBreakChar value="32"/>
|
||||
<usMaxContext value="0"/>
|
||||
</OS_2>
|
||||
|
||||
<hmtx>
|
||||
<mtx name=".notdef" width="1000" lsb="0"/>
|
||||
<mtx name="1em" width="1000" lsb="0"/>
|
||||
</hmtx>
|
||||
|
||||
<cmap>
|
||||
<tableVersion version="0"/>
|
||||
<cmap_format_4 platformID="3" platEncID="10" language="0">
|
||||
<map code="0x0020" name="1em" /> <!-- SPACE -->
|
||||
<map code="0x0061" name="1em" /> <!-- LATIN SMALL LETTER A -->
|
||||
</cmap_format_4>
|
||||
</cmap>
|
||||
|
||||
<loca>
|
||||
<!-- The 'loca' table will be calculated by the compiler -->
|
||||
</loca>
|
||||
|
||||
<glyf>
|
||||
<TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
|
||||
<TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
|
||||
</glyf>
|
||||
|
||||
<name>
|
||||
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
</namerecord>
|
||||
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
|
||||
Sample Font
|
||||
</namerecord>
|
||||
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
|
||||
Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
|
||||
Sample Font
|
||||
</namerecord>
|
||||
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
|
||||
SampleFont-Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
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.
|
||||
</namerecord>
|
||||
<namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
</namerecord>
|
||||
</name>
|
||||
|
||||
<post>
|
||||
<formatType value="3.0"/>
|
||||
<italicAngle value="0.0"/>
|
||||
<underlinePosition value="-75"/>
|
||||
<underlineThickness value="50"/>
|
||||
<isFixedPitch value="0"/>
|
||||
<minMemType42 value="0"/>
|
||||
<maxMemType42 value="0"/>
|
||||
<minMemType1 value="0"/>
|
||||
<maxMemType1 value="0"/>
|
||||
</post>
|
||||
|
||||
</ttFont>
|
||||
BIN
core/tests/coretests/assets/fonts/ascent3em-descent4em.ttf
Normal file
BIN
core/tests/coretests/assets/fonts/ascent3em-descent4em.ttf
Normal file
Binary file not shown.
180
core/tests/coretests/assets/fonts/ascent3em-descent4em.ttx
Normal file
180
core/tests/coretests/assets/fonts/ascent3em-descent4em.ttx
Normal file
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
|
||||
|
||||
<GlyphOrder>
|
||||
<GlyphID id="0" name=".notdef"/>
|
||||
<GlyphID id="1" name="1em"/>
|
||||
</GlyphOrder>
|
||||
|
||||
<head>
|
||||
<tableVersion value="1.0"/>
|
||||
<fontRevision value="1.0"/>
|
||||
<checkSumAdjustment value="0x640cdb2f"/>
|
||||
<magicNumber value="0x5f0f3cf5"/>
|
||||
<flags value="00000000 00000011"/>
|
||||
<unitsPerEm value="1000"/>
|
||||
<created value="Fri Mar 17 07:26:00 2017"/>
|
||||
<macStyle value="00000000 00000000"/>
|
||||
<lowestRecPPEM value="7"/>
|
||||
<fontDirectionHint value="2"/>
|
||||
<glyphDataFormat value="0"/>
|
||||
</head>
|
||||
|
||||
<hhea>
|
||||
<tableVersion value="0x10000"/>
|
||||
<ascent value="3000"/>
|
||||
<descent value="-4000"/>
|
||||
<lineGap value="0"/>
|
||||
<caretSlopeRise value="1"/>
|
||||
<caretSlopeRun value="0"/>
|
||||
<caretOffset value="0"/>
|
||||
<reserved0 value="0"/>
|
||||
<reserved1 value="0"/>
|
||||
<reserved2 value="0"/>
|
||||
<reserved3 value="0"/>
|
||||
<metricDataFormat value="0"/>
|
||||
</hhea>
|
||||
|
||||
<maxp>
|
||||
<tableVersion value="0x10000"/>
|
||||
<maxZones value="0"/>
|
||||
<maxTwilightPoints value="0"/>
|
||||
<maxStorage value="0"/>
|
||||
<maxFunctionDefs value="0"/>
|
||||
<maxInstructionDefs value="0"/>
|
||||
<maxStackElements value="0"/>
|
||||
<maxSizeOfInstructions value="0"/>
|
||||
<maxComponentElements value="0"/>
|
||||
</maxp>
|
||||
|
||||
<OS_2>
|
||||
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
|
||||
will be recalculated by the compiler -->
|
||||
<version value="3"/>
|
||||
<xAvgCharWidth value="594"/>
|
||||
<usWeightClass value="400"/>
|
||||
<usWidthClass value="5"/>
|
||||
<fsType value="00000000 00001000"/>
|
||||
<ySubscriptXSize value="650"/>
|
||||
<ySubscriptYSize value="600"/>
|
||||
<ySubscriptXOffset value="0"/>
|
||||
<ySubscriptYOffset value="75"/>
|
||||
<ySuperscriptXSize value="650"/>
|
||||
<ySuperscriptYSize value="600"/>
|
||||
<ySuperscriptXOffset value="0"/>
|
||||
<ySuperscriptYOffset value="350"/>
|
||||
<yStrikeoutSize value="50"/>
|
||||
<yStrikeoutPosition value="300"/>
|
||||
<sFamilyClass value="0"/>
|
||||
<panose>
|
||||
<bFamilyType value="0"/>
|
||||
<bSerifStyle value="0"/>
|
||||
<bWeight value="5"/>
|
||||
<bProportion value="0"/>
|
||||
<bContrast value="0"/>
|
||||
<bStrokeVariation value="0"/>
|
||||
<bArmStyle value="0"/>
|
||||
<bLetterForm value="0"/>
|
||||
<bMidline value="0"/>
|
||||
<bXHeight value="0"/>
|
||||
</panose>
|
||||
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
|
||||
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
|
||||
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
|
||||
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
|
||||
<achVendID value="UKWN"/>
|
||||
<fsSelection value="00000000 01000000"/>
|
||||
<usFirstCharIndex value="32"/>
|
||||
<usLastCharIndex value="122"/>
|
||||
<sTypoAscender value="800"/>
|
||||
<sTypoDescender value="-200"/>
|
||||
<sTypoLineGap value="200"/>
|
||||
<usWinAscent value="1000"/>
|
||||
<usWinDescent value="200"/>
|
||||
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
|
||||
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
|
||||
<sxHeight value="500"/>
|
||||
<sCapHeight value="700"/>
|
||||
<usDefaultChar value="0"/>
|
||||
<usBreakChar value="32"/>
|
||||
<usMaxContext value="0"/>
|
||||
</OS_2>
|
||||
|
||||
<hmtx>
|
||||
<mtx name=".notdef" width="1000" lsb="0"/>
|
||||
<mtx name="1em" width="1000" lsb="0"/>
|
||||
</hmtx>
|
||||
|
||||
<cmap>
|
||||
<tableVersion version="0"/>
|
||||
<cmap_format_4 platformID="3" platEncID="10" language="0">
|
||||
<map code="0x0062" name="1em" /> <!-- LATIN SMALL LETTER B -->
|
||||
</cmap_format_4>
|
||||
</cmap>
|
||||
|
||||
<loca>
|
||||
<!-- The 'loca' table will be calculated by the compiler -->
|
||||
</loca>
|
||||
|
||||
<glyf>
|
||||
<TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
|
||||
<TTGlyph name="1em" xMin="0" yMin="0" xMax="0" yMax="0" />
|
||||
</glyf>
|
||||
|
||||
<name>
|
||||
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
</namerecord>
|
||||
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
|
||||
Sample Font
|
||||
</namerecord>
|
||||
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
|
||||
Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
|
||||
Sample Font
|
||||
</namerecord>
|
||||
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
|
||||
SampleFont-Regular
|
||||
</namerecord>
|
||||
<namerecord nameID="13" platformID="3" platEncID="1" langID="0x409">
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
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.
|
||||
</namerecord>
|
||||
<namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
</namerecord>
|
||||
</name>
|
||||
|
||||
<post>
|
||||
<formatType value="3.0"/>
|
||||
<italicAngle value="0.0"/>
|
||||
<underlinePosition value="-75"/>
|
||||
<underlineThickness value="50"/>
|
||||
<isFixedPitch value="0"/>
|
||||
<minMemType42 value="0"/>
|
||||
<maxMemType42 value="0"/>
|
||||
<minMemType1 value="0"/>
|
||||
<maxMemType1 value="0"/>
|
||||
</post>
|
||||
|
||||
</ttFont>
|
||||
@@ -21,20 +21,33 @@ import static android.text.Layout.Alignment.ALIGN_NORMAL;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.FontFamily;
|
||||
import android.graphics.Paint.FontMetricsInt;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.LocaleList;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.text.Layout.Alignment;
|
||||
import android.text.method.EditorState;
|
||||
import android.text.style.LocaleSpan;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -799,4 +812,129 @@ public class StaticLayoutTest {
|
||||
layout.drawText(canvas, 0, 0);
|
||||
assertEquals(31, paint.getHyphenEdit());
|
||||
}
|
||||
|
||||
private String getTestFontsDir() {
|
||||
final Context targetCtx = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
final File cacheDir = new File(targetCtx.getCacheDir(), "StaticLayoutTest");
|
||||
if (!cacheDir.isDirectory()) {
|
||||
final boolean dirsCreated = cacheDir.mkdirs();
|
||||
if (!dirsCreated) {
|
||||
throw new RuntimeException("Creating test directories for fonts failed.");
|
||||
}
|
||||
}
|
||||
return cacheDir.getAbsolutePath() + "/";
|
||||
}
|
||||
|
||||
private TextPaint setupPaintForFallbackFonts(String[] fontFiles, String xml) {
|
||||
final String testFontsDir = getTestFontsDir();
|
||||
final String testFontsXml = new File(testFontsDir, "fonts.xml").getAbsolutePath();
|
||||
final AssetManager am =
|
||||
InstrumentationRegistry.getInstrumentation().getContext().getAssets();
|
||||
for (String fontFile : fontFiles) {
|
||||
final String sourceInAsset = "fonts/" + fontFile;
|
||||
final File outInCache = new File(testFontsDir, fontFile);
|
||||
try (InputStream is = am.open(sourceInAsset)) {
|
||||
Files.copy(is, outInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(testFontsXml)) {
|
||||
fos.write(xml.getBytes(Charset.forName("UTF-8")));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
|
||||
final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
|
||||
Typeface.buildSystemFallback(testFontsXml, testFontsDir, fontMap, fallbackMap);
|
||||
|
||||
final TextPaint paint = new TextPaint();
|
||||
final Typeface testTypeface = fontMap.get("sans-serif");
|
||||
paint.setTypeface(testTypeface);
|
||||
return paint;
|
||||
}
|
||||
|
||||
void destroyFallbackFonts(String[] fontFiles) {
|
||||
final String testFontsDir = getTestFontsDir();
|
||||
for (String fontFile : fontFiles) {
|
||||
final File outInCache = new File(testFontsDir, fontFile);
|
||||
outInCache.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallbackLineSpacing() {
|
||||
// All glyphs in the fonts are 1em wide.
|
||||
final String[] testFontFiles = {
|
||||
// ascent == 1em, descent == 2em, only supports 'a' and space
|
||||
"ascent1em-descent2em.ttf",
|
||||
// ascent == 3em, descent == 4em, only supports 'b'
|
||||
"ascent3em-descent4em.ttf"
|
||||
};
|
||||
final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
|
||||
+ "<familyset>"
|
||||
+ " <family name='sans-serif'>"
|
||||
+ " <font weight='400' style='normal'>ascent1em-descent2em.ttf</font>"
|
||||
+ " </family>"
|
||||
+ " <family>"
|
||||
+ " <font weight='400' style='normal'>ascent3em-descent4em.ttf</font>"
|
||||
+ " </family>"
|
||||
+ "</familyset>";
|
||||
|
||||
try {
|
||||
final TextPaint paint = setupPaintForFallbackFonts(testFontFiles, xml);
|
||||
final int textSize = 100;
|
||||
paint.setTextSize(textSize);
|
||||
assertEquals(-textSize, paint.ascent(), 0.0f);
|
||||
assertEquals(2 * textSize, paint.descent(), 0.0f);
|
||||
|
||||
final int paraWidth = 5 * textSize;
|
||||
final String text = "aaaaa aabaa aaaaa"; // This should result in three lines.
|
||||
|
||||
// Old line spacing. All lines should get their ascent and descents from the first font.
|
||||
StaticLayout layout = StaticLayout.Builder
|
||||
.obtain(text, 0, text.length(), paint, paraWidth)
|
||||
.setIncludePad(false)
|
||||
.setUseLineSpacingFromFallbacks(false)
|
||||
.build();
|
||||
assertEquals(3, layout.getLineCount());
|
||||
assertEquals(-textSize, layout.getLineAscent(0));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(0));
|
||||
assertEquals(-textSize, layout.getLineAscent(1));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(1));
|
||||
assertEquals(-textSize, layout.getLineAscent(2));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(2));
|
||||
|
||||
// New line spacing. The second line has a 'b', so it needs more ascent and descent.
|
||||
layout = StaticLayout.Builder
|
||||
.obtain(text, 0, text.length(), paint, paraWidth)
|
||||
.setIncludePad(false)
|
||||
.setUseLineSpacingFromFallbacks(true)
|
||||
.build();
|
||||
assertEquals(3, layout.getLineCount());
|
||||
assertEquals(-textSize, layout.getLineAscent(0));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(0));
|
||||
assertEquals(-3 * textSize, layout.getLineAscent(1));
|
||||
assertEquals(4 * textSize, layout.getLineDescent(1));
|
||||
assertEquals(-textSize, layout.getLineAscent(2));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(2));
|
||||
|
||||
// The default is the old line spacing, for backward compatibility.
|
||||
layout = StaticLayout.Builder
|
||||
.obtain(text, 0, text.length(), paint, paraWidth)
|
||||
.setIncludePad(false)
|
||||
.build();
|
||||
assertEquals(3, layout.getLineCount());
|
||||
assertEquals(-textSize, layout.getLineAscent(0));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(0));
|
||||
assertEquals(-textSize, layout.getLineAscent(1));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(1));
|
||||
assertEquals(-textSize, layout.getLineAscent(2));
|
||||
assertEquals(2 * textSize, layout.getLineDescent(2));
|
||||
} finally {
|
||||
destroyFallbackFonts(testFontFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1729,6 +1729,9 @@ public class Paint {
|
||||
* Return the distance above (negative) the baseline (ascent) based on the
|
||||
* current typeface and text size.
|
||||
*
|
||||
* <p>Note that this is the ascent of the main typeface, and actual text rendered may need a
|
||||
* larger ascent because fallback fonts may get used in rendering the text.
|
||||
*
|
||||
* @return the distance above (negative) the baseline (ascent) based on the
|
||||
* current typeface and text size.
|
||||
*/
|
||||
@@ -1740,6 +1743,9 @@ public class Paint {
|
||||
* Return the distance below (positive) the baseline (descent) based on the
|
||||
* current typeface and text size.
|
||||
*
|
||||
* <p>Note that this is the descent of the main typeface, and actual text rendered may need a
|
||||
* larger descent because fallback fonts may get used in rendering the text.
|
||||
*
|
||||
* @return the distance below (positive) the baseline (descent) based on
|
||||
* the current typeface and text size.
|
||||
*/
|
||||
@@ -1783,6 +1789,9 @@ public class Paint {
|
||||
* settings for typeface, textSize, etc. If metrics is not null, return the
|
||||
* fontmetric values in it.
|
||||
*
|
||||
* <p>Note that these are the values for the main typeface, and actual text rendered may need a
|
||||
* larger set of values because fallback fonts may get used in rendering the text.
|
||||
*
|
||||
* @param metrics If this object is not null, its fields are filled with
|
||||
* the appropriate values given the paint's text attributes.
|
||||
* @return the font's recommended interline spacing.
|
||||
@@ -1844,6 +1853,9 @@ public class Paint {
|
||||
* and clipping. If you want more control over the rounding, call
|
||||
* getFontMetrics().
|
||||
*
|
||||
* <p>Note that these are the values for the main typeface, and actual text rendered may need a
|
||||
* larger set of values because fallback fonts may get used in rendering the text.
|
||||
*
|
||||
* @return the font's interline spacing.
|
||||
*/
|
||||
public int getFontMetricsInt(FontMetricsInt fmi) {
|
||||
@@ -1860,6 +1872,9 @@ public class Paint {
|
||||
* Return the recommend line spacing based on the current typeface and
|
||||
* text size.
|
||||
*
|
||||
* <p>Note that this is the value for the main typeface, and actual text rendered may need a
|
||||
* larger value because fallback fonts may get used in rendering the text.
|
||||
*
|
||||
* @return recommend line spacing based on the current typeface and
|
||||
* text size.
|
||||
*/
|
||||
|
||||
@@ -67,6 +67,17 @@ void MinikinFontSkia::GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
|
||||
bounds->mBottom = skBounds.fBottom;
|
||||
}
|
||||
|
||||
void MinikinFontSkia::GetFontExtent(minikin::MinikinExtent* extent,
|
||||
const minikin::MinikinPaint& paint) const {
|
||||
SkPaint skPaint;
|
||||
MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
|
||||
SkPaint::FontMetrics metrics;
|
||||
skPaint.getFontMetrics(&metrics);
|
||||
extent->ascent = metrics.fAscent;
|
||||
extent->descent = metrics.fDescent;
|
||||
extent->line_gap = metrics.fLeading;
|
||||
}
|
||||
|
||||
SkTypeface *MinikinFontSkia::GetSkTypeface() const {
|
||||
return mTypeface.get();
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ public:
|
||||
void GetBounds(minikin::MinikinRect* bounds, uint32_t glyph_id,
|
||||
const minikin::MinikinPaint &paint) const;
|
||||
|
||||
void GetFontExtent(minikin::MinikinExtent* extent,
|
||||
const minikin::MinikinPaint &paint) const;
|
||||
|
||||
SkTypeface* GetSkTypeface() const;
|
||||
sk_sp<SkTypeface> RefSkTypeface() const;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ float MinikinUtils::measureText(const Paint* paint, int bidiFlags, const Typefac
|
||||
minikin::FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, paint, typeface);
|
||||
const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
|
||||
return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinStyle,
|
||||
minikinPaint, resolvedTypeface->fFontCollection, advances);
|
||||
minikinPaint, resolvedTypeface->fFontCollection, advances, nullptr /* extent */);
|
||||
}
|
||||
|
||||
bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) {
|
||||
|
||||
Reference in New Issue
Block a user