OSDN Git Service

ca43156e88a153b5cf0be0012ce1fb97235ae83c
[android-x86/frameworks-base.git] / libs / hwui / hwui / Typeface.cpp
1 /*
2  * Copyright (C) 2013 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 /**
18  * This is the implementation of the Typeface object. Historically, it has
19  * just been SkTypeface, but we are migrating to Minikin. For the time
20  * being, that choice is hidden under the USE_MINIKIN compile-time flag.
21  */
22
23 #include "Typeface.h"
24
25 #include <pthread.h>
26 #include <fcntl.h>  // For tests.
27 #include <sys/stat.h>  // For tests.
28 #include <sys/mman.h>  // For tests.
29
30 #include "MinikinSkia.h"
31 #include "SkTypeface.h"
32 #include "SkPaint.h"
33 #include "SkStream.h"  // Fot tests.
34
35 #include <minikin/FontCollection.h>
36 #include <minikin/FontFamily.h>
37 #include <minikin/Layout.h>
38 #include <utils/Log.h>
39
40 namespace android {
41
42 // Resolve the 1..9 weight based on base weight and bold flag
43 static void resolveStyle(Typeface* typeface) {
44     int weight = typeface->fBaseWeight / 100;
45     if (typeface->fSkiaStyle & SkTypeface::kBold) {
46         weight += 3;
47     }
48     if (weight > 9) {
49         weight = 9;
50     }
51     bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
52     typeface->fStyle = minikin::FontStyle(weight, italic);
53 }
54
55 Typeface* gDefaultTypeface = NULL;
56
57 Typeface* Typeface::resolveDefault(Typeface* src) {
58     LOG_ALWAYS_FATAL_IF(gDefaultTypeface == nullptr);
59     return src == nullptr ? gDefaultTypeface : src;
60 }
61
62 Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
63     Typeface* resolvedFace = Typeface::resolveDefault(src);
64     Typeface* result = new Typeface;
65     if (result != 0) {
66         result->fFontCollection = resolvedFace->fFontCollection;
67         result->fFontCollection->Ref();
68         result->fSkiaStyle = style;
69         result->fBaseWeight = resolvedFace->fBaseWeight;
70         resolveStyle(result);
71     }
72     return result;
73 }
74
75 Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
76     Typeface* resolvedFace = Typeface::resolveDefault(src);
77     Typeface* result = new Typeface;
78     if (result != 0) {
79         result->fFontCollection = resolvedFace->fFontCollection;
80         result->fFontCollection->Ref();
81         result->fSkiaStyle = resolvedFace->fSkiaStyle;
82         result->fBaseWeight = weight;
83         resolveStyle(result);
84     }
85     return result;
86 }
87
88 Typeface* Typeface::createFromFamilies(const std::vector<minikin::FontFamily*>& families) {
89     Typeface* result = new Typeface;
90     result->fFontCollection = new minikin::FontCollection(families);
91     if (families.empty()) {
92         ALOGW("createFromFamilies creating empty collection");
93         result->fSkiaStyle = SkTypeface::kNormal;
94     } else {
95         const minikin::FontStyle defaultStyle;
96         minikin::FontFamily* firstFamily = reinterpret_cast<minikin::FontFamily*>(families[0]);
97         minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
98         if (mf != NULL) {
99             SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
100             // TODO: probably better to query more precise style from family, will be important
101             // when we open up API to access 100..900 weights
102             result->fSkiaStyle = skTypeface->style();
103         } else {
104             result->fSkiaStyle = SkTypeface::kNormal;
105         }
106     }
107     result->fBaseWeight = 400;
108     resolveStyle(result);
109     return result;
110 }
111
112 void Typeface::unref() {
113     fFontCollection->Unref();
114     delete this;
115 }
116
117 void Typeface::setDefault(Typeface* face) {
118     gDefaultTypeface = face;
119 }
120
121 void Typeface::setRobotoTypefaceForTest() {
122     const char* kRobotoFont = "/system/fonts/Roboto-Regular.ttf";
123
124     int fd = open(kRobotoFont, O_RDONLY);
125     LOG_ALWAYS_FATAL_IF(fd == -1, "Failed to open file %s", kRobotoFont);
126     struct stat st = {};
127     LOG_ALWAYS_FATAL_IF(fstat(fd, &st) == -1, "Failed to stat file %s", kRobotoFont);
128     void* data = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
129     std::unique_ptr<SkMemoryStream> fontData(new SkMemoryStream(data, st.st_size));
130     sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release());
131     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
132
133     minikin::FontFamily* family = new minikin::FontFamily();
134     minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0);
135     family->addFont(font);
136     font->Unref();
137
138     std::vector<minikin::FontFamily*> typefaces = { family };
139     minikin::FontCollection *collection = new minikin::FontCollection(typefaces);
140     family->Unref();
141
142     Typeface* hwTypeface = new Typeface();
143     hwTypeface->fFontCollection = collection;
144     hwTypeface->fSkiaStyle = SkTypeface::kNormal;
145     hwTypeface->fBaseWeight = 400;
146     hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
147
148     Typeface::setDefault(hwTypeface);
149 }
150
151 }