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