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