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

Commit e95b5850 authored by Raph Levien's avatar Raph Levien
Browse files

Support for scaleX and skewX in Minikin

Passes textScaleX and textSkewX parameters, as well as paint flags from
the paint to Minikin, to support nontrivial scale and stretch of text.
Passing paint flags should minimize kerning artifacts arising from
mismatch of glyph rendering in layout and drawing.

Also, replaces unsafe snprintf to a fixed size buffer with a safe
version, which still avoids an allocation per layout operation.

This is part of the fix for bug 15186705 "Usability of the suggestion
strip in recent OTA's is severely reduced"

Change-Id: I79788383135836f4c21fb84405f36382627bf959
parent dd125329
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -46,8 +46,10 @@ bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
static void MinikinFontSkia_SetSkiaPaint(SkTypeface* typeface, SkPaint* skPaint, const MinikinPaint& paint) {
    skPaint->setTypeface(typeface);
    skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    // TODO: set more paint parameters from Minikin
    skPaint->setTextSize(paint.size);
    skPaint->setTextScaleX(paint.scaleX);
    skPaint->setTextSkewX(paint.skewX);
    MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
}

float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
@@ -96,4 +98,21 @@ int32_t MinikinFontSkia::GetUniqueId() const {
    return mTypeface->uniqueID();
}

uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
    uint32_t flags = paint->getFlags();
    SkPaint::Hinting hinting = paint->getHinting();
    // select only flags that might affect text layout
    flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
            SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag |
            SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag |
            SkPaint::kVerticalText_Flag);
    flags |= (hinting << 16);
    return flags;
}

void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
    paint->setFlags(paintFlags & SkPaint::kAllFlags);
    paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
}

}
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ public:

    SkTypeface *GetSkTypeface();

    static uint32_t packPaintFlags(const SkPaint* paint);
    static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
private:
    SkTypeface *mTypeface;
};
+21 −4
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
 * limitations under the License.
 */

#define LOG_TAG "Minikin"
#include <cutils/log.h>

#include "SkPaint.h"
#include "minikin/Layout.h"
#include "TypefaceImpl.h"
@@ -23,23 +26,37 @@

namespace android {

// Do an sprintf starting at offset n, abort on overflow
static int snprintfcat(char* buf, int off, int size, const char* format, ...) {
    va_list args;
    va_start(args, format);
    int n = vsnprintf(buf + off, size - off, format, args);
    LOG_ALWAYS_FATAL_IF(n >= size - off, "String overflow in setting layout properties");
    va_end(args);
    return off + n;
}

void MinikinUtils::SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
    TypefaceImpl* typeface) {
    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
    layout->setFontCollection(resolvedFace->fFontCollection);
    FontStyle style = resolvedFace->fStyle;
    char css[256];
    int off = snprintf(css, sizeof(css),
        "font-size: %d; font-weight: %d; font-style: %s; -minikin-bidi: %d;",
    int off = snprintfcat(css, 0, sizeof(css),
        "font-size: %d; font-scale-x: %f; font-skew-x: %f; -paint-flags: %d;"
        " font-weight: %d; font-style: %s; -minikin-bidi: %d;",
        (int)paint->getTextSize(),
        paint->getTextScaleX(),
        paint->getTextSkewX(),
        MinikinFontSkia::packPaintFlags(paint),
        style.getWeight() * 100,
        style.getItalic() ? "italic" : "normal",
        flags);
    SkString langString = paint->getPaintOptionsAndroid().getLanguage().getTag();
    off += snprintf(css + off, sizeof(css) - off, " lang: %s;", langString.c_str());
    off = snprintfcat(css, off, sizeof(css), " lang: %s;", langString.c_str());
    SkPaintOptionsAndroid::FontVariant var = paint->getPaintOptionsAndroid().getFontVariant();
    const char* varstr = var == SkPaintOptionsAndroid::kElegant_Variant ? "elegant" : "compact";
    off += snprintf(css + off, sizeof(css) - off, " -minikin-variant: %s;", varstr);
    off = snprintfcat(css, off, sizeof(css), " -minikin-variant: %s;", varstr);
    layout->setProperties(css);
}

+4 −0
Original line number Diff line number Diff line
@@ -26,10 +26,14 @@

namespace android {

class Layout;
class TypefaceImpl;

class MinikinUtils {
public:
    static void SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
        TypefaceImpl* face);

    static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);

    // f is a functor of type void f(SkTypeface *, size_t start, size_t end);
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <minikin/FontCollection.h>
#include <minikin/FontFamily.h>
#include <minikin/Layout.h>
#include "SkPaint.h"
#include "MinikinSkia.h"
#endif