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