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

Commit 1eb12937 authored by Fabrice Di Meglio's avatar Fabrice Di Meglio Committed by Android (Google) Code Review
Browse files

Merge "Add TextLayout Cache"

parents 84af86c4 d313c665
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ LOCAL_SRC_FILES:= \
	android/graphics/Shader.cpp \
	android/graphics/SurfaceTexture.cpp \
	android/graphics/TextLayout.cpp \
	android/graphics/TextLayoutCache.cpp \
	android/graphics/Typeface.cpp \
	android/graphics/Utils.cpp \
	android/graphics/Xfermode.cpp \
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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.
 */

#ifndef ANDROID_RTL_PROPERTIES_H
#define ANDROID_RTL_PROPERTIES_H

#include <cutils/properties.h>
#include <stdlib.h>

namespace android {

/**
 * Debug level for app developers.
 */
#define RTL_PROPERTY_DEBUG "rtl.debug_level"

/**
 * Debug levels. Debug levels are used as flags.
 */
enum RtlDebugLevel {
    kRtlDebugDisabled = 0,
    kRtlDebugMemory = 1,
    kRtlDebugCaches = 2,
    kRtlDebugAllocations = 3
};

static RtlDebugLevel readRtlDebugLevel() {
    char property[PROPERTY_VALUE_MAX];
    if (property_get(RTL_PROPERTY_DEBUG, property, NULL) > 0) {
        return (RtlDebugLevel) atoi(property);
    }
    return kRtlDebugDisabled;
}

} // namespace android
#endif // ANDROID_RTL_PROPERTIES_H
+20 −81
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#include "TextLayout.h"
#include "TextLayoutCache.h"

#include <android_runtime/AndroidRuntime.h>

@@ -23,10 +24,12 @@
#include "unicode/ushape.h"
#include <utils/Log.h>

// Log debug messages from RTL related allocations
#define DEBUG_RTL_ALLOCATIONS 0

namespace android {

#if USE_TEXT_LAYOUT_CACHE
TextLayoutCache TextLayout::mCache;
#endif

// Returns true if we might need layout.  If bidiFlags force LTR, assume no layout, if
// bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text
// looking for a character >= the first RTL character in unicode and assume we do if
@@ -64,10 +67,6 @@ int TextLayout::shapeRtlText(const jchar* context, jsize start, jsize count, jsi
    SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
    jchar* buffer = tempBuffer.get();

#if DEBUG_RTL_ALLOCATIONS
    LOGD("TextLayout::shapeRtlText - allocated buffer with size: %d", contextCount);
#endif

    // Use fixed length since we need to keep start and count valid
    u_shapeArabic(context, contextCount, buffer, contextCount,
                   U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
@@ -166,11 +165,6 @@ bool TextLayout::prepareText(SkPaint *paint, const jchar* text, jsize len, jint
        if (!buffer) {
            return false;
        }

#if DEBUG_RTL_ALLOCATIONS
    LOGD("TextLayout::prepareText - allocated buffer with size: %d", len);
#endif

        UErrorCode status = U_ZERO_ERROR;
        len = layoutLine(text, len, bidiFlags, dir, buffer, status); // might change len, dir
        if (!U_SUCCESS(status)) {
@@ -178,7 +172,6 @@ bool TextLayout::prepareText(SkPaint *paint, const jchar* text, jsize len, jint
            free(buffer);
            return false; // can't render
        }

        workText = buffer; // use the shaped text
    }

@@ -265,71 +258,21 @@ void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars,
void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
                                    jint count, jint contextCount, jint dirFlags,
                                    jfloat* resultAdvances, jfloat& resultTotalAdvance) {
    resultTotalAdvance = 0;

    SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
    jchar* buffer = tempBuffer.get();

#if DEBUG_RTL_ALLOCATIONS
    LOGD("TextLayout::getTextRunAdvances - allocated buffer with size: %d", contextCount);
#if USE_TEXT_LAYOUT_CACHE
    // Return advances from the cache. Compute them if needed
    mCache.getRunAdvances(paint, chars, start, count, contextCount,
            dirFlags, resultAdvances, &resultTotalAdvance);
#else
    // Compute advances and return them
    RunAdvanceDescription::computeAdvances(paint, chars, start, count, contextCount, dirFlags,
            resultAdvances, &resultTotalAdvance);
#endif

    SkScalar* scalarArray = (SkScalar*)resultAdvances;

    // this is where we'd call harfbuzz
    // for now we just use ushape.c

    int widths;
    const jchar* text;
    if (dirFlags & 0x1) { // rtl, call arabic shaping in case
        UErrorCode status = U_ZERO_ERROR;
        // Use fixed length since we need to keep start and count valid
        u_shapeArabic(chars, contextCount, buffer, contextCount,
                      U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
                      U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE |
                      U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status);
        // we shouldn't fail unless there's an out of memory condition,
        // in which case we're hosed anyway
        for (int i = start, e = i + count; i < e; ++i) {
          if (buffer[i] == UNICODE_NOT_A_CHAR) {
            buffer[i] = UNICODE_ZWSP; // zero-width-space for skia
          }
        }
        text = buffer + start;
        widths = paint->getTextWidths(text, count << 1, scalarArray);
    } else {
        text = chars + start;
        widths = paint->getTextWidths(text, count << 1, scalarArray);
    }

    if (widths < count) {
        // Skia operates on code points, not code units, so surrogate pairs return only
        // one value. Expand the result so we have one value per UTF-16 code unit.

        // Note, skia's getTextWidth gets confused if it encounters a surrogate pair,
        // leaving the remaining widths zero.  Not nice.
        for (int i = 0, p = 0; i < widths; ++i) {
            resultTotalAdvance += resultAdvances[p++] = SkScalarToFloat(scalarArray[i]);
            if (p < count &&
                    text[p] >= UNICODE_FIRST_LOW_SURROGATE &&
                    text[p] < UNICODE_FIRST_PRIVATE_USE &&
                    text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE &&
                    text[p-1] < UNICODE_FIRST_LOW_SURROGATE) {
                resultAdvances[p++] = 0;
            }
        }
    } else {
        for (int i = 0; i < count; i++) {
            resultTotalAdvance += resultAdvances[i] = SkScalarToFloat(scalarArray[i]);
        }
    }
}


// Draws a paragraph of text on a single line, running bidi and shaping
void TextLayout::drawText(SkPaint* paint, const jchar* text, jsize len,
                          int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas) {

    handleText(paint, text, len, bidiFlags, x, y, canvas, NULL);
}

@@ -353,10 +296,6 @@ void TextLayout::drawTextOnPath(SkPaint* paint, const jchar* text, int count,

    SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> buffer(count);

#if DEBUG_RTL_ALLOCATIONS
    LOGD("TextLayout::drawTextOnPath - allocated buffer with size: %d", count);
#endif

    int dir = kDirection_LTR;
    UErrorCode status = U_ZERO_ERROR;
    count = layoutLine(text, count, bidiFlags, dir, buffer.get(), status);
+20 −8
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include "SkPaint.h"
#include "unicode/utypes.h"

#include "TextLayoutCache.h"

namespace android {

#define UNICODE_NOT_A_CHAR              0xffff
@@ -34,6 +36,11 @@ namespace android {
 */
#define CHAR_BUFFER_SIZE 80

/**
 * Turn on for using the Cache
 */
#define USE_TEXT_LAYOUT_CACHE 1

class TextLayout {
public:

@@ -78,6 +85,7 @@ public:
                               
    static bool prepareText(SkPaint* paint, const jchar* text, jsize len, jint bidiFlags,
        const jchar** outText, int32_t* outBytes, jchar** outBuffer);

    static bool prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
        jsize contextCount, jchar* shaped);
        
@@ -90,6 +98,10 @@ private:
                           UErrorCode &status);
    static void handleText(SkPaint* paint, const jchar* text, jsize len,
                           int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas, SkPath* path);

#if USE_TEXT_LAYOUT_CACHE
    static TextLayoutCache mCache;
#endif
};

}
Loading