MinikinUtils.cpp revision bb1a96647a82df5a134bf631fc9db342e7ef61de
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"
226ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "Paint.h"
231a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "TypefaceImpl.h"
241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
251a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "MinikinUtils.h"
261a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
271a73f732f91e97c9c66b808c245ddda36a10e987Raph Leviennamespace android {
281a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
29c94f742f7e07a3b86c8f603836c19638472b3e83Raph LevienFontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
30c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien        const Paint* paint, TypefaceImpl* typeface) {
31c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
32c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    *pFont = resolvedFace->fFontCollection;
335ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    FontStyle resolved = resolvedFace->fStyle;
345ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
355ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    /* Prepare minikin FontStyle */
36f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader    const std::string& langs = paint->getTextLocales();
37f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader    FontLanguages minikinLangs(langs.c_str(), langs.size());
386f03023ece076d33d8b171d5398c8ed70abf3f54Derek Sollenberger    FontVariant minikinVariant = (paint->getFontVariant() == VARIANT_ELEGANT) ? VARIANT_ELEGANT
395ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod            : VARIANT_COMPACT;
40f036ead2a218ffa43697fcaa999b666a4c6d13cfRoozbeh Pournader    FontStyle minikinStyle(minikinLangs, minikinVariant, resolved.getWeight(), resolved.getItalic());
415ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
425ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    /* Prepare minikin Paint */
43c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    // Note: it would be nice to handle fractional size values (it would improve smooth zoom
44c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    // behavior), but historically size has been treated as an int.
45c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    // TODO: explore whether to enable fractional sizes, possibly when linear text flag is set.
46c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->size = (int)paint->getTextSize();
47c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->scaleX = paint->getTextScaleX();
48c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->skewX = paint->getTextSkewX();
49c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->letterSpacing = paint->getLetterSpacing();
50c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->paintFlags = MinikinFontSkia::packPaintFlags(paint);
51c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->fontFeatureSettings = paint->getFontFeatureSettings();
52c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    minikinPaint->hyphenEdit = HyphenEdit(paint->getHyphenEdit());
53c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    return minikinStyle;
54c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien}
555ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod
56c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levienvoid MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
57c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien        TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
58c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien        size_t bufSize) {
59c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    FontCollection *font;
60c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    MinikinPaint minikinPaint;
61c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    FontStyle minikinStyle = prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
62c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien    layout->setFontCollection(font);
635ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod    layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
66bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonakabool MinikinUtils::hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs) {
67bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka    const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
68bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka    return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
69bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka}
70bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka
716ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodfloat MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
72f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    switch (paint->getTextAlign()) {
736ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kCenter_Align:
74f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            return layout.getAdvance() * -0.5f;
75f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
766ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kRight_Align:
77f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            return -layout.getAdvance();
78f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
79f2114d5646194100242206b267ddd6e7194b7da9Raph Levien        default:
80f2114d5646194100242206b267ddd6e7194b7da9Raph Levien            break;
81f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    }
82f2114d5646194100242206b267ddd6e7194b7da9Raph Levien    return 0;
83f2114d5646194100242206b267ddd6e7194b7da9Raph Levien}
84f2114d5646194100242206b267ddd6e7194b7da9Raph Levien
856ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbodfloat MinikinUtils::hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path) {
869d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    float align = 0;
879d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    switch (paint->getTextAlign()) {
886ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kCenter_Align:
899d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            align = -0.5f;
909d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            break;
916ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod        case Paint::kRight_Align:
929d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            align = -1;
939d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            break;
949d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien        default:
959d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien            return 0;
969d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    }
979d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    SkPathMeasure measure(path, false);
989d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien    return align * (layout.getAdvance() - measure.getLength());
999d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien}
1009d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien
101f2114d5646194100242206b267ddd6e7194b7da9Raph Levien}
102