• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #define LOG_TAG "Minikin"
18 
19 #include "minikin/Font.h"
20 
21 #include <vector>
22 
23 #include <hb-ot.h>
24 #include <hb.h>
25 #include <log/log.h>
26 
27 #include "minikin/HbUtils.h"
28 #include "minikin/MinikinFont.h"
29 
30 #include "FontUtils.h"
31 #include "MinikinInternal.h"
32 
33 namespace minikin {
34 
build()35 std::shared_ptr<Font> Font::Builder::build() {
36     if (mIsWeightSet && mIsSlantSet) {
37         // No need to read OS/2 header of the font file.
38         return std::shared_ptr<Font>(new Font(std::move(mTypeface), FontStyle(mWeight, mSlant),
39                                               prepareFont(mTypeface), mLocaleListId));
40     }
41 
42     HbFontUniquePtr font = prepareFont(mTypeface);
43     FontStyle styleFromFont = analyzeStyle(font);
44     if (!mIsWeightSet) {
45         mWeight = styleFromFont.weight();
46     }
47     if (!mIsSlantSet) {
48         mSlant = styleFromFont.slant();
49     }
50     return std::shared_ptr<Font>(new Font(std::move(mTypeface), FontStyle(mWeight, mSlant),
51                                           std::move(font), mLocaleListId));
52 }
53 
typeface() const54 const std::shared_ptr<MinikinFont>& Font::typeface() const {
55     std::lock_guard lock(mTypefaceMutex);
56     if (mTypeface) return mTypeface;
57     initTypefaceLocked();
58     return mTypeface;
59 }
60 
baseFont() const61 const HbFontUniquePtr& Font::baseFont() const {
62     std::lock_guard lock(mTypefaceMutex);
63     if (mBaseFont) return mBaseFont;
64     initTypefaceLocked();
65     mBaseFont = prepareFont(mTypeface);
66     return mBaseFont;
67 }
68 
initTypefaceLocked() const69 void Font::initTypefaceLocked() const {
70     if (mTypeface) return;
71     MINIKIN_ASSERT(mTypefaceLoader, "mTypefaceLoader should not be empty when mTypeface is null");
72     mTypeface = mTypefaceLoader(mTypefaceMetadataReader);
73 }
74 
75 // static
prepareFont(const std::shared_ptr<MinikinFont> & typeface)76 HbFontUniquePtr Font::prepareFont(const std::shared_ptr<MinikinFont>& typeface) {
77     const char* buf = reinterpret_cast<const char*>(typeface->GetFontData());
78     size_t size = typeface->GetFontSize();
79     uint32_t ttcIndex = typeface->GetFontIndex();
80 
81     HbBlobUniquePtr blob(hb_blob_create(buf, size, HB_MEMORY_MODE_READONLY, nullptr, nullptr));
82     HbFaceUniquePtr face(hb_face_create(blob.get(), ttcIndex));
83     HbFontUniquePtr parent(hb_font_create(face.get()));
84     hb_ot_font_set_funcs(parent.get());
85 
86     uint32_t upem = hb_face_get_upem(face.get());
87     hb_font_set_scale(parent.get(), upem, upem);
88 
89     HbFontUniquePtr font(hb_font_create_sub_font(parent.get()));
90     std::vector<hb_variation_t> variations;
91     variations.reserve(typeface->GetAxes().size());
92     for (const FontVariation& variation : typeface->GetAxes()) {
93         variations.push_back({variation.axisTag, variation.value});
94     }
95     hb_font_set_variations(font.get(), variations.data(), variations.size());
96     return font;
97 }
98 
99 // static
analyzeStyle(const HbFontUniquePtr & font)100 FontStyle Font::analyzeStyle(const HbFontUniquePtr& font) {
101     HbBlob os2Table(font, MinikinFont::MakeTag('O', 'S', '/', '2'));
102     if (!os2Table) {
103         return FontStyle();
104     }
105 
106     int weight;
107     bool italic;
108     if (!::minikin::analyzeStyle(os2Table.get(), os2Table.size(), &weight, &italic)) {
109         return FontStyle();
110     }
111     // TODO: Update weight/italic based on fvar value.
112     return FontStyle(static_cast<uint16_t>(weight), static_cast<FontStyle::Slant>(italic));
113 }
114 
getSupportedAxes() const115 std::unordered_set<AxisTag> Font::getSupportedAxes() const {
116     HbBlob fvarTable(baseFont(), MinikinFont::MakeTag('f', 'v', 'a', 'r'));
117     if (!fvarTable) {
118         return std::unordered_set<AxisTag>();
119     }
120     std::unordered_set<AxisTag> supportedAxes;
121     analyzeAxes(fvarTable.get(), fvarTable.size(), &supportedAxes);
122     return supportedAxes;
123 }
124 
125 }  // namespace minikin
126