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 
28 namespace android {
29 
prepareMinikinPaint(const Paint * paint,const Typeface * typeface)30 minikin::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 
doLayout(const Paint * paint,minikin::Bidi bidiFlags,const Typeface * typeface,const uint16_t * buf,size_t start,size_t count,size_t bufSize,minikin::MeasuredText * mt)50 minikin::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 
measureText(const Paint * paint,minikin::Bidi bidiFlags,const Typeface * typeface,const uint16_t * buf,size_t start,size_t count,size_t bufSize,float * advances)70 float 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 
hasVariationSelector(const Typeface * typeface,uint32_t codepoint,uint32_t vs)85 bool 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 
xOffsetForTextAlign(Paint * paint,const minikin::Layout & layout)90 float 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 
hOffsetForTextAlign(Paint * paint,const minikin::Layout & layout,const SkPath & path)104 float 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