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 #ifndef ANDROID_GRAPHICS_PAINT_H_
18 #define ANDROID_GRAPHICS_PAINT_H_
19 
20 #include <SkFont.h>
21 #include <SkPaint.h>
22 #include <SkSamplingOptions.h>
23 #include <cutils/compiler.h>
24 #include <minikin/FamilyVariant.h>
25 #include <minikin/FontFamily.h>
26 #include <minikin/FontFeature.h>
27 #include <minikin/Hyphenator.h>
28 #include <minikin/Layout.h>
29 
30 #include <string>
31 
32 #include "Typeface.h"
33 
34 namespace android {
35 
36 class BlurDrawLooper;
37 
38 class Paint : public SkPaint {
39 public:
40     // Default values for underlined and strikethrough text,
41     // as defined by Skia in SkTextFormatParams.h.
42     constexpr static float kStdStrikeThru_Offset = (-6.0f / 21.0f);
43     constexpr static float kStdUnderline_Offset = (1.0f / 9.0f);
44     constexpr static float kStdUnderline_Thickness = (1.0f / 18.0f);
45 
46     constexpr static float kStdUnderline_Top =
47             kStdUnderline_Offset - 0.5f * kStdUnderline_Thickness;
48 
49     constexpr static float kStdStrikeThru_Thickness = kStdUnderline_Thickness;
50     constexpr static float kStdStrikeThru_Top =
51             kStdStrikeThru_Offset - 0.5f * kStdStrikeThru_Thickness;
52 
53     Paint();
54     Paint(const Paint& paint);
55     ~Paint();
56 
57     Paint& operator=(const Paint& other);
58 
59     friend bool operator==(const Paint& a, const Paint& b);
60     friend bool operator!=(const Paint& a, const Paint& b) { return !(a == b); }
61 
getSkFont()62     SkFont& getSkFont() { return mFont; }
getSkFont()63     const SkFont& getSkFont() const { return mFont; }
64 
getLooper()65     BlurDrawLooper* getLooper() const { return mLooper.get(); }
66     void setLooper(sk_sp<BlurDrawLooper> looper);
67 
68     // These shadow the methods on SkPaint, but we need to so we can keep related
69     // attributes in-sync.
70 
71     void reset();
72     void setAntiAlias(bool);
73 
nothingToDraw()74     bool nothingToDraw() const { return !mLooper && SkPaint::nothingToDraw(); }
75 
76     // End method shadowing
77 
setLetterSpacing(float letterSpacing)78     void setLetterSpacing(float letterSpacing) { mLetterSpacing = letterSpacing; }
79 
getLetterSpacing()80     float getLetterSpacing() const { return mLetterSpacing; }
81 
setWordSpacing(float wordSpacing)82     void setWordSpacing(float wordSpacing) { mWordSpacing = wordSpacing; }
83 
getWordSpacing()84     float getWordSpacing() const { return mWordSpacing; }
85 
setFontFeatureSettings(std::string_view fontFeatures)86     void setFontFeatureSettings(std::string_view fontFeatures) {
87         mFontFeatureSettings = minikin::FontFeature::parse(fontFeatures);
88     }
89 
resetFontFeatures()90     void resetFontFeatures() { mFontFeatureSettings.clear(); }
91 
getFontFeatureSettings()92     const std::vector<minikin::FontFeature>& getFontFeatureSettings() const {
93         return mFontFeatureSettings;
94     }
95 
setMinikinLocaleListId(uint32_t minikinLocaleListId)96     void setMinikinLocaleListId(uint32_t minikinLocaleListId) {
97         mMinikinLocaleListId = minikinLocaleListId;
98     }
99 
getMinikinLocaleListId()100     uint32_t getMinikinLocaleListId() const { return mMinikinLocaleListId; }
101 
resetFamilyVariant()102     void resetFamilyVariant() { mFamilyVariant.reset(); }
setFamilyVariant(minikin::FamilyVariant variant)103     void setFamilyVariant(minikin::FamilyVariant variant) { mFamilyVariant = variant; }
104 
getFamilyVariant()105     std::optional<minikin::FamilyVariant> getFamilyVariant() const { return mFamilyVariant; }
106 
setStartHyphenEdit(uint32_t startHyphen)107     void setStartHyphenEdit(uint32_t startHyphen) {
108         mHyphenEdit = minikin::packHyphenEdit(
109             static_cast<minikin::StartHyphenEdit>(startHyphen),
110             minikin::endHyphenEdit(mHyphenEdit));
111     }
112 
setEndHyphenEdit(uint32_t endHyphen)113     void setEndHyphenEdit(uint32_t endHyphen) {
114         mHyphenEdit = minikin::packHyphenEdit(
115             minikin::startHyphenEdit(mHyphenEdit),
116             static_cast<minikin::EndHyphenEdit>(endHyphen));
117     }
118 
getStartHyphenEdit()119     minikin::StartHyphenEdit getStartHyphenEdit() const {
120         return minikin::startHyphenEdit(mHyphenEdit);
121     }
122 
getEndHyphenEdit()123     minikin::EndHyphenEdit getEndHyphenEdit() const {
124         return minikin::endHyphenEdit(mHyphenEdit);
125     }
126 
setAndroidTypeface(Typeface * typeface)127     void setAndroidTypeface(Typeface* typeface) { mTypeface = typeface; }
128 
getAndroidTypeface()129     const Typeface* getAndroidTypeface() const { return mTypeface; }
130 
131     enum Align {
132         kLeft_Align,
133         kCenter_Align,
134         kRight_Align,
135     };
getTextAlign()136     Align getTextAlign() const { return mAlign; }
setTextAlign(Align align)137     void setTextAlign(Align align) { mAlign = align; }
138 
isStrikeThru()139     bool isStrikeThru() const { return mStrikeThru; }
setStrikeThru(bool st)140     void setStrikeThru(bool st) { mStrikeThru = st; }
141 
isUnderline()142     bool isUnderline() const { return mUnderline; }
setUnderline(bool u)143     void setUnderline(bool u) { mUnderline = u; }
144 
isDevKern()145     bool isDevKern() const { return mDevKern; }
setDevKern(bool d)146     void setDevKern(bool d) { mDevKern = d; }
147 
getRunFlag()148     minikin::RunFlag getRunFlag() const { return mRunFlag; }
setRunFlag(minikin::RunFlag runFlag)149     void setRunFlag(minikin::RunFlag runFlag) { mRunFlag = runFlag; }
150 
151     // Deprecated -- bitmapshaders will be taking this flag explicitly
isFilterBitmap()152     bool isFilterBitmap() const { return mFilterBitmap; }
setFilterBitmap(bool filter)153     void setFilterBitmap(bool filter) { mFilterBitmap = filter; }
154 
filterMode()155     SkFilterMode filterMode() const {
156         return mFilterBitmap ? SkFilterMode::kLinear : SkFilterMode::kNearest;
157     }
sampling()158     SkSamplingOptions sampling() const {
159         return SkSamplingOptions(this->filterMode());
160     }
161 
162     // The Java flags (Paint.java) no longer fit into the native apis directly.
163     // These methods handle converting to and from them and the native representations
164     // in android::Paint.
165 
166     uint32_t getJavaFlags() const;
167     void setJavaFlags(uint32_t);
168 
169     // Helpers that return or apply legacy java flags to SkPaint, ignoring all flags
170     // that are meant for SkFont or Paint (e.g. underline, strikethru)
171     // The only respected flags are : [ antialias, dither, filterBitmap ]
172     static uint32_t GetSkPaintJavaFlags(const SkPaint&);
173     static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
174 
175 private:
176     SkFont mFont;
177     sk_sp<BlurDrawLooper> mLooper;
178 
179     float mLetterSpacing = 0;
180     float mWordSpacing = 0;
181     std::vector<minikin::FontFeature> mFontFeatureSettings;
182     uint32_t mMinikinLocaleListId;
183     std::optional<minikin::FamilyVariant> mFamilyVariant;
184     uint32_t mHyphenEdit = 0;
185     // The native Typeface object has the same lifetime of the Java Typeface
186     // object. The Java Paint object holds a strong reference to the Java Typeface
187     // object. Thus, following pointer can never be a dangling pointer. Note that
188     // nullptr is valid: it means the default typeface.
189     const Typeface* mTypeface = nullptr;
190     Align mAlign = kLeft_Align;
191     bool mFilterBitmap = false;
192     bool mStrikeThru = false;
193     bool mUnderline = false;
194     bool mDevKern = false;
195     minikin::RunFlag mRunFlag = minikin::RunFlag::NONE;
196 };
197 
198 }  // namespace android
199 
200 #endif  // ANDROID_GRAPHICS_PAINT_H_
201