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