Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aade3bc0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add Canvas#drawGlyphs"

parents efc301a8 39c482f2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14356,6 +14356,7 @@ package android.graphics {
    method public void drawColor(@ColorLong long, @NonNull android.graphics.BlendMode);
    method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, float, float, @NonNull android.graphics.RectF, float, float, @NonNull android.graphics.Paint);
    method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.Paint);
    method public void drawGlyphs(@NonNull int[], @IntRange(from=0) int, @NonNull float[], @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.graphics.fonts.Font, @NonNull android.graphics.Paint);
    method public void drawLine(float, float, float, float, @NonNull android.graphics.Paint);
    method public void drawLines(@NonNull @Size(multiple=4) float[], int, int, @NonNull android.graphics.Paint);
    method public void drawLines(@NonNull @Size(multiple=4) float[], @NonNull android.graphics.Paint);
+61 −0
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ package android.graphics;

import android.annotation.ColorInt;
import android.annotation.ColorLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas.VertexMode;
import android.graphics.fonts.Font;
import android.graphics.text.MeasuredText;
import android.text.GraphicsOperations;
import android.text.MeasuredParagraph;
@@ -31,6 +33,10 @@ import android.text.SpannableString;
import android.text.SpannedString;
import android.text.TextUtils;

import com.android.internal.util.Preconditions;

import java.util.Objects;

/**
 * This class is a base class for Canvas's drawing operations. Any modifications here
 * should be accompanied by a similar modification to {@link BaseRecordingCanvas}.
@@ -443,6 +449,58 @@ public abstract class BaseCanvas {
                paint.getNativeInstance());
    }

    /**
     * Draw array of glyphs with specified font.
     *
     * @param glyphIds Array of glyph IDs. The length of array must be greater than or equal to
     *                 {@code glyphStart + glyphCount}.
     * @param glyphIdOffset Number of elements to skip before drawing in <code>glyphIds</code>
     *                     array.
     * @param positions A flattened X and Y position array. The first glyph X position must be
     *                  stored at {@code positionOffset}. The first glyph Y position must be stored
     *                  at {@code positionOffset + 1}, then the second glyph X position must be
     *                  stored at {@code positionOffset + 2}.
     *                 The length of array must be greater than or equal to
     *                 {@code positionOffset + glyphCount * 2}.
     * @param positionOffset Number of elements to skip before drawing in {@code positions}.
     *                       The first glyph X position must be stored at {@code positionOffset}.
     *                       The first glyph Y position must be stored at
     *                       {@code positionOffset + 1}, then the second glyph X position must be
     *                       stored at {@code positionOffset + 2}.
     * @param glyphCount Number of glyphs to be drawn.
     * @param font Font used for drawing.
     * @param paint Paint used for drawing. The typeface set to this paint is ignored.
     *
     * @see android.graphics.text.TextShaper
     * @see android.text.StyledTextShaper
     */
    public void drawGlyphs(
            @NonNull int[] glyphIds,
            @IntRange(from = 0) int glyphIdOffset,
            @NonNull float[] positions,
            @IntRange(from = 0) int positionOffset,
            @IntRange(from = 0) int glyphCount,
            @NonNull Font font,
            @NonNull Paint paint) {
        Objects.requireNonNull(glyphIds, "glyphIds must not be null.");
        Objects.requireNonNull(positions, "positions must not be null.");
        Objects.requireNonNull(font, "font must not be null.");
        Objects.requireNonNull(paint, "paint must not be null.");
        Preconditions.checkArgumentNonnegative(glyphCount);

        if (glyphIdOffset < 0 || glyphIdOffset + glyphCount > glyphIds.length) {
            throw new IndexOutOfBoundsException(
                    "glyphIds must have at least " + (glyphIdOffset + glyphCount) + " of elements");
        }
        if (positionOffset < 0 || positionOffset + glyphCount * 2 > positions.length) {
            throw new IndexOutOfBoundsException(
                    "positions must have at least " + (positionOffset + glyphCount * 2)
                            + " of elements");
        }
        nDrawGlyphs(mNativeCanvasWrapper, glyphIds, positions, glyphIdOffset, positionOffset,
                glyphCount, font.getNativePtr(), paint.getNativeInstance());
    }

    public void drawText(@NonNull char[] text, int index, int count, float x, float y,
            @NonNull Paint paint) {
        if ((index | count | (index + count) |
@@ -734,6 +792,9 @@ public abstract class BaseCanvas {
            int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
            short[] indices, int indexOffset, int indexCount, long nativePaint);

    private static native void nDrawGlyphs(long nativeCanvas, int[] glyphIds, float[] positions,
            int glyphIdStart, int positionStart, int glyphCount, long nativeFont, long nativePaint);

    private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
            float x, float y, int flags, long nativePaint);

+38 −0
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package android.graphics;

import android.annotation.ColorInt;
import android.annotation.ColorLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.graphics.fonts.Font;
import android.graphics.text.MeasuredText;
import android.text.GraphicsOperations;
import android.text.MeasuredParagraph;
@@ -29,8 +31,12 @@ import android.text.SpannableString;
import android.text.SpannedString;
import android.text.TextUtils;

import com.android.internal.util.Preconditions;

import dalvik.annotation.optimization.FastNative;

import java.util.Objects;

/**
 * This class is a base class for canvases that defer drawing operations, so all
 * the draw operations can be marked @FastNative. It contains a re-implementation of
@@ -408,6 +414,34 @@ public class BaseRecordingCanvas extends Canvas {
                paint.getNativeInstance());
    }

    @Override
    public void drawGlyphs(
            @NonNull int[] glyphIds,
            @IntRange(from = 0) int glyphIdOffset,
            @NonNull float[] positions,
            @IntRange(from = 0) int positionOffset,
            @IntRange(from = 0) int glyphCount,
            @NonNull Font font,
            @NonNull Paint paint) {
        Objects.requireNonNull(glyphIds, "glyphIds must not be null.");
        Objects.requireNonNull(positions, "positions must not be null.");
        Objects.requireNonNull(font, "font must not be null.");
        Objects.requireNonNull(paint, "paint must not be null.");
        Preconditions.checkArgumentNonnegative(glyphCount);

        if (glyphIdOffset < 0 || glyphIdOffset + glyphCount > glyphIds.length) {
            throw new IndexOutOfBoundsException(
                    "glyphIds must have at least " + (glyphIdOffset + glyphCount) + " of elements");
        }
        if (positionOffset < 0 || positionOffset + glyphCount * 2 > positions.length) {
            throw new IndexOutOfBoundsException(
                    "positions must have at least " + (positionOffset + glyphCount * 2)
                            + " of elements");
        }
        nDrawGlyphs(mNativeCanvasWrapper, glyphIds, positions, glyphIdOffset, positionOffset,
                glyphCount, font.getNativePtr(), paint.getNativeInstance());
    }

    @Override
    public final void drawText(@NonNull char[] text, int index, int count, float x, float y,
            @NonNull Paint paint) {
@@ -673,6 +707,10 @@ public class BaseRecordingCanvas extends Canvas {
            int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
            short[] indices, int indexOffset, int indexCount, long nativePaint);

    @FastNative
    private static native void nDrawGlyphs(long nativeCanvas, int[] glyphIds, float[] positions,
            int glyphIdStart, int positionStart, int glyphCount, long nativeFont, long nativePaint);

    @FastNative
    private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
            float x, float y, int flags, long nativePaint);
+39 −0
Original line number Diff line number Diff line
@@ -19,10 +19,12 @@ package android.graphics;
import android.annotation.ColorInt;
import android.annotation.ColorLong;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.Font;
import android.graphics.text.MeasuredText;
import android.os.Build;

@@ -2047,6 +2049,43 @@ public class Canvas extends BaseCanvas {
        super.drawDoubleRoundRect(outer, outerRadii, inner, innerRadii, paint);
    }

    /**
     * Draw array of glyphs with specified font.
     *
     * @param glyphIds Array of glyph IDs. The length of array must be greater than or equal to
     *                 {@code glyphStart + glyphCount}.
     * @param glyphIdOffset Number of elements to skip before drawing in <code>glyphIds</code>
     *                     array.
     * @param positions A flattened X and Y position array. The first glyph X position must be
     *                  stored at {@code positionOffset}. The first glyph Y position must be stored
     *                  at {@code positionOffset + 1}, then the second glyph X position must be
     *                  stored at {@code positionOffset + 2}.
     *                 The length of array must be greater than or equal to
     *                 {@code positionOffset + glyphCount * 2}.
     * @param positionOffset Number of elements to skip before drawing in {@code positions}.
     *                       The first glyph X position must be stored at {@code positionOffset}.
     *                       The first glyph Y position must be stored at
     *                       {@code positionOffset + 1}, then the second glyph X position must be
     *                       stored at {@code positionOffset + 2}.
     * @param glyphCount Number of glyphs to be drawn.
     * @param font Font used for drawing.
     * @param paint Paint used for drawing. The typeface set to this paint is ignored.
     *
     * @see android.graphics.text.TextShaper
     * @see android.text.StyledTextShaper
     */
    public void drawGlyphs(
            @NonNull int[] glyphIds,
            @IntRange(from = 0) int glyphIdOffset,
            @NonNull float[] positions,
            @IntRange(from = 0) int positionOffset,
            @IntRange(from = 0) int glyphCount,
            @NonNull Font font,
            @NonNull Paint paint) {
        super.drawGlyphs(glyphIds, glyphIdOffset, positions, positionOffset, glyphCount, font,
                paint);
    }

    /**
     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
     * based on the Align setting in the paint.
+20 −0
Original line number Diff line number Diff line
@@ -135,6 +135,26 @@ private:
    float totalAdvance;
};

void Canvas::drawGlyphs(const minikin::Font& font, const int* glyphIds, const float* positions,
                        int glyphCount, const Paint& paint) {
    // Minikin modify skFont for auto-fakebold/auto-fakeitalic.
    Paint copied(paint);

    auto glyphFunc = [&](uint16_t* outGlyphIds, float* outPositions) {
        for (uint32_t i = 0; i < glyphCount; ++i) {
            outGlyphIds[i] = static_cast<uint16_t>(glyphIds[i]);
        }
        memcpy(outPositions, positions, sizeof(float) * 2 * glyphCount);
    };

    const minikin::MinikinFont* minikinFont = font.typeface().get();
    SkFont* skfont = &copied.getSkFont();
    MinikinFontSkia::populateSkFont(skfont, minikinFont, minikin::FontFakery());

    // total advance is used for drawing underline. We do not support underlyine by glyph drawing.
    drawGlyphs(glyphFunc, glyphCount, copied, 0 /* x */, 0 /* y */, 0 /* total Advance */);
}

void Canvas::drawText(const uint16_t* text, int textSize, int start, int count, int contextStart,
                      int contextCount, float x, float y, minikin::Bidi bidiFlags,
                      const Paint& origPaint, const Typeface* typeface, minikin::MeasuredText* mt) {
Loading