1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "MinikinUtils.h" 18 19#include <string> 20 21#include <log/log.h> 22 23#include <minikin/MeasuredText.h> 24#include "Paint.h" 25#include "SkPathMeasure.h" 26#include "Typeface.h" 27 28namespace android { 29 30minikin::MinikinPaint MinikinUtils::prepareMinikinPaint(const Paint* paint, 31 const Typeface* typeface) { 32 const Typeface* resolvedFace = Typeface::resolveDefault(typeface); 33 34 minikin::MinikinPaint minikinPaint(resolvedFace->fFontCollection); 35 /* Prepare minikin Paint */ 36 minikinPaint.size = 37 paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize()); 38 minikinPaint.scaleX = paint->getTextScaleX(); 39 minikinPaint.skewX = paint->getTextSkewX(); 40 minikinPaint.letterSpacing = paint->getLetterSpacing(); 41 minikinPaint.wordSpacing = paint->getWordSpacing(); 42 minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint); 43 minikinPaint.localeListId = paint->getMinikinLocaleListId(); 44 minikinPaint.familyVariant = paint->getFamilyVariant(); 45 minikinPaint.fontStyle = resolvedFace->fStyle; 46 minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); 47 return minikinPaint; 48} 49 50minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFlags, 51 const Typeface* typeface, const uint16_t* buf, size_t start, 52 size_t count, size_t bufSize, minikin::MeasuredText* mt) { 53 minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); 54 minikin::Layout layout; 55 56 const minikin::U16StringPiece textBuf(buf, bufSize); 57 const minikin::Range range(start, start + count); 58 const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit()); 59 const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); 60 const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); 61 62 if (mt == nullptr) { 63 layout.doLayout(textBuf,range, bidiFlags, minikinPaint, startHyphen, endHyphen); 64 } else { 65 mt->buildLayout(textBuf, range, minikinPaint, bidiFlags, startHyphen, endHyphen, &layout); 66 } 67 return layout; 68} 69 70float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags, 71 const Typeface* typeface, const uint16_t* buf, size_t start, 72 size_t count, size_t bufSize, float* advances) { 73 minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface); 74 const minikin::U16StringPiece textBuf(buf, bufSize); 75 const minikin::Range range(start, start + count); 76 const minikin::HyphenEdit hyphenEdit = static_cast<minikin::HyphenEdit>(paint->getHyphenEdit()); 77 const minikin::StartHyphenEdit startHyphen = minikin::startHyphenEdit(hyphenEdit); 78 const minikin::EndHyphenEdit endHyphen = minikin::endHyphenEdit(hyphenEdit); 79 80 return minikin::Layout::measureText(textBuf, range, bidiFlags, minikinPaint, startHyphen, 81 endHyphen, advances, nullptr /* extent */, 82 nullptr /* layout pieces */); 83} 84 85bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) { 86 const Typeface* resolvedFace = Typeface::resolveDefault(typeface); 87 return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs); 88} 89 90float MinikinUtils::xOffsetForTextAlign(Paint* paint, const minikin::Layout& layout) { 91 switch (paint->getTextAlign()) { 92 case Paint::kCenter_Align: 93 return layout.getAdvance() * -0.5f; 94 break; 95 case Paint::kRight_Align: 96 return -layout.getAdvance(); 97 break; 98 default: 99 break; 100 } 101 return 0; 102} 103 104float MinikinUtils::hOffsetForTextAlign(Paint* paint, const minikin::Layout& layout, 105 const SkPath& path) { 106 float align = 0; 107 switch (paint->getTextAlign()) { 108 case Paint::kCenter_Align: 109 align = -0.5f; 110 break; 111 case Paint::kRight_Align: 112 align = -1; 113 break; 114 default: 115 return 0; 116 } 117 SkPathMeasure measure(path, false); 118 return align * (layout.getAdvance() - measure.getLength()); 119} 120} // namespace android 121