MinikinUtils.cpp revision da252ac5c17426f28b8e18a2b8942c6880e4055b
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 */ 1652eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn 17dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "MinikinUtils.h" 181a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 1952eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <string> 2052eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn 2152eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <log/log.h> 2252eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn 23783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka#include <minikin/MeasuredText.h> 24afbd0f1fef46ef0ddf633dfde0de724db3da1405Sergei Vasilinetc#include "Paint.h" 25dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "SkPathMeasure.h" 26bad99183916ba2bac6659efc8a28273e344ba511sergeyv#include "Typeface.h" 271a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 281a73f732f91e97c9c66b808c245ddda36a10e987Raph Leviennamespace android { 291a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 3020866c140438a9aca3e1ad09fe646308678e9383Seigo Nonakaminikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, 3120866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka const Typeface* typeface) { 32bad99183916ba2bac6659efc8a28273e344ba511sergeyv const Typeface* resolvedFace = Typeface::resolveDefault(typeface); 331c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka 34976f707fbf15296ea98ece91c506ae4e64dc7e66Seigo Nonaka minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection); 351c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka /* Prepare minikin Paint */ 361c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.size = 371c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize()); 381c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.scaleX = paint->getTextScaleX(); 391c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.skewX = paint->getTextSkewX(); 401c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.letterSpacing = paint->getLetterSpacing(); 411c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.wordSpacing = paint->getWordSpacing(); 421c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint); 431c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.localeListId = paint->getMinikinLocaleListId(); 44c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka minikinPaint.familyVariant = paint->getFamilyVariant(); 45c52075ee2bcfde4cf9b091e404517a74ff7cec60Seigo Nonaka minikinPaint.fontStyle = resolvedFace->fStyle; 461c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); 471c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka return minikinPaint; 48c94f742f7e07a3b86c8f603836c19638472b3e83Raph Levien} 495ec789608bda858a0c6d669bb44a35a5a99abcdbBehdad Esfahbod 507c93e868825225a270c993ac058687adde682626Seigo Nonakaminikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFlags, 511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const Typeface* typeface, const uint16_t* buf, size_t start, 52783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka size_t count, size_t bufSize, minikin::MeasuredText* mt, 53783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka int mtOffset) { 541c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); 5551218e80f70601193e43d90aaf1599a7f6d11062Seigo Nonaka minikin::Layout layout; 56783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka 57da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::U16StringPiece textBuf(buf, bufSize); 58da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::Range range(start, start + count); 59da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit()); 60da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); 61da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); 62da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka 63783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka if (mt == nullptr) { 64da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka layout.doLayout(textBuf,range, bidiFlags, minikinPaint, startHyphen, endHyphen); 65783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka return layout; 66783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka } 67783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka 68da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka if (mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, mtOffset, startHyphen, endHyphen, 69da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka &layout)) { 70783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka return layout; 71783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka } 72783f961d2fa6f916009844dafeaa08ffaf96a4d3Seigo Nonaka 73da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka layout.doLayout(textBuf, range, bidiFlags, minikinPaint, startHyphen, endHyphen); 74c7064146f959caec058980ced144942c8044a169Seigo Nonaka return layout; 751a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 761a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 777c93e868825225a270c993ac058687adde682626Seigo Nonakafloat MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags, 781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const Typeface* typeface, const uint16_t* buf, size_t start, 791bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck size_t count, size_t bufSize, float* advances) { 801c4ab704d14c047775b3e42f87ea4081fa204e37Seigo Nonaka minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); 81da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::U16StringPiece textBuf(buf, bufSize); 82da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::Range range(start, start + count); 83da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit()); 84da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); 85da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); 86da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka 87da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen, 88da252ac5c17426f28b8e18a2b8942c6880e4055bSeigo Nonaka endHyphen, advances, nullptr /* extent */); 89a3024bd7026deb777556dd75dd34a719ea1c2b39Keisuke Kuroyanagi} 90a3024bd7026deb777556dd75dd34a719ea1c2b39Keisuke Kuroyanagi 91318ca04079bd6242cb6186d9005b9caeee22e845Seigo Nonakabool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) { 92bad99183916ba2bac6659efc8a28273e344ba511sergeyv const Typeface* resolvedFace = Typeface::resolveDefault(typeface); 93bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs); 94bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka} 95bb1a96647a82df5a134bf631fc9db342e7ef61deSeigo Nonaka 96ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonakafloat MinikinUtils::xOffsetForTextAlign(Paint* paint, const minikin::Layout& layout) { 97f2114d5646194100242206b267ddd6e7194b7da9Raph Levien switch (paint->getTextAlign()) { 986ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod case Paint::kCenter_Align: 99f2114d5646194100242206b267ddd6e7194b7da9Raph Levien return layout.getAdvance() * -0.5f; 100f2114d5646194100242206b267ddd6e7194b7da9Raph Levien break; 1016ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod case Paint::kRight_Align: 102f2114d5646194100242206b267ddd6e7194b7da9Raph Levien return -layout.getAdvance(); 103f2114d5646194100242206b267ddd6e7194b7da9Raph Levien break; 104f2114d5646194100242206b267ddd6e7194b7da9Raph Levien default: 105f2114d5646194100242206b267ddd6e7194b7da9Raph Levien break; 106f2114d5646194100242206b267ddd6e7194b7da9Raph Levien } 107f2114d5646194100242206b267ddd6e7194b7da9Raph Levien return 0; 108f2114d5646194100242206b267ddd6e7194b7da9Raph Levien} 109f2114d5646194100242206b267ddd6e7194b7da9Raph Levien 110ae1aa85d0c7305bb621f1f8003bd674285aa3b63Seigo Nonakafloat MinikinUtils::hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout, 1111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const SkPath& path) { 1129d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien float align = 0; 1139d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien switch (paint->getTextAlign()) { 1146ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod case Paint::kCenter_Align: 1159d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien align = -0.5f; 1169d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien break; 1176ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod case Paint::kRight_Align: 1189d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien align = -1; 1199d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien break; 1209d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien default: 1219d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien return 0; 1229d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien } 1239d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien SkPathMeasure measure(path, false); 1249d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien return align * (layout.getAdvance() - measure.getLength()); 1259d2b5e1930bfc4b1da1c865843c247c708ea1565Raph Levien} 12620866c140438a9aca3e1ad09fe646308678e9383Seigo Nonaka} // namespace android 127