MinikinUtils.cpp revision 5ec789608bda858a0c6d669bb44a35a5a99abcdb
11a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien/*
21a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Copyright (C) 2014 The Android Open Source Project
31a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
41a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Licensed under the Apache License, Version 2.0 (the "License");
51a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * you may not use this file except in compliance with the License.
61a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * You may obtain a copy of the License at
71a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
81a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *      http://www.apache.org/licenses/LICENSE-2.0
91a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
101a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Unless required by applicable law or agreed to in writing, software
111a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * distributed under the License is distributed on an "AS IS" BASIS,
121a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * See the License for the specific language governing permissions and
141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * limitations under the License.
151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */
161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
17e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien#define LOG_TAG "Minikin"
18e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien#include <cutils/log.h>
196bfd7e7df3a9f9ea2f9e57a3552eed7f518be711Raph Levien#include <string>
20e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien
219d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien#include "SkPathMeasure.h"
221a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "minikin/Layout.h"
236ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "TypefaceImpl.h"
25f2114d5646194100242206b267ddd6e7194b7da9Raph Levien#include "MinikinSkia.h"
261a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
271a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "MinikinUtils.h"
281a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
291a73f732f91e97c9c66b808c245ddda36a10e987Raph Leviennamespace android {
301a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
31e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien// Do an sprintf starting at offset n, abort on overflow
32fa80f7491df82d71b7084500519a2195afbea706Behdad Esfahbodstatic int snprintfcat(char* buf, int off, int size, const char* format, ...)
33fa80f7491df82d71b7084500519a2195afbea706Behdad Esfahbod        __attribute__((__format__(__printf__, 4, 5)));
34e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levienstatic int snprintfcat(char* buf, int off, int size, const char* format, ...) {
35e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    va_list args;
36e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    va_start(args, format);
37e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    int n = vsnprintf(buf + off, size - off, format, args);
38e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    LOG_ALWAYS_FATAL_IF(n >= size - off, "String overflow in setting layout properties");
39e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    va_end(args);
40e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien    return off + n;
41e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien}
42e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien
4363c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbodvoid MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
4463c5c78a72a21d57913e8601cc2a1ab72a424a02Behdad Esfahbod        const uint16_t* buf, size_t start, size_t count, size_t bufSize) {
451a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
461a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    layout->setFontCollection(resolvedFace->fFontCollection);
475ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    FontStyle resolved = resolvedFace->fStyle;
485ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
495ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    /* Prepare minikin FontStyle */
505ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    SkString langStr = paint->getPaintOptionsAndroid().getLanguage().getTag();
515ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    FontLanguage minikinLang(langStr.c_str(), langStr.size());
52f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    SkPaintOptionsAndroid::FontVariant var = paint->getPaintOptionsAndroid().getFontVariant();
535ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    FontVariant minikinVariant = var == SkPaintOptionsAndroid::kElegant_Variant ? VARIANT_ELEGANT
545ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod            : VARIANT_COMPACT;
555ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    FontStyle minikinStyle(minikinLang, minikinVariant, resolved.getWeight(), resolved.getItalic());
565ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
575ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    /* Prepare minikin Paint */
585ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    MinikinPaint minikinPaint;
595ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    minikinPaint.size = (int)/*WHY?!*/paint->getTextSize();
605ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    minikinPaint.scaleX = paint->getTextScaleX();
615ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    minikinPaint.skewX = paint->getTextSkewX();
625ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    minikinPaint.letterSpacing = paint->getLetterSpacing();
635ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
645ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
655ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
661a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
671a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
686ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodfloat MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
69f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    switch (paint->getTextAlign()) {
706ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kCenter_Align:
71f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            return layout.getAdvance() * -0.5f;
72f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
736ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kRight_Align:
74f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            return -layout.getAdvance();
75f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
76f2114d5646194100242206b267ddd6e7194b7da9Raph Levien        default:
77f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
78f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    }
79f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    return 0;
80f2114d5646194100242206b267ddd6e7194b7da9Raph Levien}
81f2114d5646194100242206b267ddd6e7194b7da9Raph Levien
826ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodfloat MinikinUtils::hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path) {
839d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    float align = 0;
849d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    switch (paint->getTextAlign()) {
856ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kCenter_Align:
869d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            align = -0.5f;
879d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            break;
886ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kRight_Align:
899d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            align = -1;
909d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            break;
919d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien        default:
929d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            return 0;
939d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    }
949d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    SkPathMeasure measure(path, false);
959d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    return align * (layout.getAdvance() - measure.getLength());
969d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien}
979d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien
98f2114d5646194100242206b267ddd6e7194b7da9Raph Levien}
99