1 /*
2  * Copyright 2019 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 package androidx.compose.ui.text.font
17 
18 private const val AllFlags = 0xffff
19 private const val WeightFlag = 0x1
20 private const val StyleFlag = 0x2
21 
22 /**
23  * Possible options for font synthesis.
24  *
25  * `FontSynthesis` is used to specify whether the system should fake bold or slanted glyphs when the
26  * [FontFamily] used does not contain bold or oblique [Font]s.
27  *
28  * If the font family does not include a requested [FontWeight] or [FontStyle], the system fakes
29  * bold or slanted glyphs when the [Weight] or [Style], respectively, or both when [All] is set. If
30  * this is not desired, use [None] to disable font synthesis.
31  *
32  * It is possible to fake an increase of [FontWeight] but not a decrease. It is possible to fake a
33  * regular font slanted, but not vice versa.
34  *
35  * `FontSynthesis` works the same way as the
36  * [CSS font-synthesis](https://www.w3.org/TR/css-fonts-4/#font-synthesis) property.
37  *
38  * @sample androidx.compose.ui.text.samples.FontFamilySynthesisSample
39  */
40 @kotlin.jvm.JvmInline
41 value class FontSynthesis internal constructor(internal val value: Int) {
42 
toStringnull43     override fun toString(): String {
44         return when (this) {
45             None -> "None"
46             Weight -> "Weight"
47             Style -> "Style"
48             All -> "All"
49             else -> "Invalid"
50         }
51     }
52 
53     // NOTE: The values below are selected to be used as flags. See isWeightOn for instance.
54     companion object {
55         /**
56          * Turns off font synthesis. Neither bold nor slanted faces are synthesized if they don't
57          * exist in the [FontFamily]
58          */
59         val None = FontSynthesis(0)
60 
61         /**
62          * Only a bold font is synthesized, if it is not available in the [FontFamily]. Slanted
63          * fonts will not be synthesized.
64          */
65         val Weight = FontSynthesis(WeightFlag)
66 
67         /**
68          * Only an slanted font is synthesized, if it is not available in the [FontFamily]. Bold
69          * fonts will not be synthesized.
70          */
71         val Style = FontSynthesis(StyleFlag)
72 
73         /**
74          * The system synthesizes both bold and slanted fonts if either of them are not available in
75          * the [FontFamily]
76          */
77         val All = FontSynthesis(AllFlags)
78     }
79 
80     internal val isWeightOn: Boolean
81         get() = value and WeightFlag != 0
82 
83     internal val isStyleOn: Boolean
84         get() = value and StyleFlag != 0
85 }
86 
87 /**
88  * Perform platform-specific font synthesis such as fake bold or fake italic.
89  *
90  * Platforms are not required to support synthesis, in which case they should return [typeface].
91  *
92  * Platforms that support synthesis should check [FontSynthesis.isWeightOn] and
93  * [FontSynthesis.isStyleOn] in this method before synthesizing bold or italic, respectively.
94  *
95  * @param typeface a platform-specific typeface
96  * @param font initial font that generated the typeface via loading
97  * @param requestedWeight app-requested weight (may be different than the font's weight)
98  * @param requestedStyle app-requested style (may be different than the font's style)
99  * @return a synthesized typeface, or the passed [typeface] if synthesis is not needed or supported.
100  */
synthesizeTypefacenull101 internal expect fun FontSynthesis.synthesizeTypeface(
102     typeface: Any,
103     font: Font,
104     requestedWeight: FontWeight,
105     requestedStyle: FontStyle
106 ): Any
107