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 #include "Paint.h"
18 
19 namespace android {
20 
Paint()21 Paint::Paint()
22         : SkPaint()
23         , mLetterSpacing(0)
24         , mWordSpacing(0)
25         , mFontFeatureSettings()
26         , mMinikinLocaleListId(0)
27         , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {
28     // SkPaint::antialiasing defaults to false, but
29     // SkFont::edging defaults to kAntiAlias. To keep them
30     // insync, we manually set the font to kAilas.
31     mFont.setEdging(SkFont::Edging::kAlias);
32 }
33 
Paint(const Paint & paint)34 Paint::Paint(const Paint& paint)
35         : SkPaint(paint)
36         , mFont(paint.mFont)
37         , mLetterSpacing(paint.mLetterSpacing)
38         , mWordSpacing(paint.mWordSpacing)
39         , mFontFeatureSettings(paint.mFontFeatureSettings)
40         , mMinikinLocaleListId(paint.mMinikinLocaleListId)
41         , mFamilyVariant(paint.mFamilyVariant)
42         , mHyphenEdit(paint.mHyphenEdit)
43         , mTypeface(paint.mTypeface)
44         , mAlign(paint.mAlign)
45         , mStrikeThru(paint.mStrikeThru)
46         , mUnderline(paint.mUnderline)
47         , mDevKern(paint.mDevKern) {}
48 
49 
~Paint()50 Paint::~Paint() {}
51 
operator =(const Paint & other)52 Paint& Paint::operator=(const Paint& other) {
53     SkPaint::operator=(other);
54     mFont = other.mFont;
55     mLetterSpacing = other.mLetterSpacing;
56     mWordSpacing = other.mWordSpacing;
57     mFontFeatureSettings = other.mFontFeatureSettings;
58     mMinikinLocaleListId = other.mMinikinLocaleListId;
59     mFamilyVariant = other.mFamilyVariant;
60     mHyphenEdit = other.mHyphenEdit;
61     mTypeface = other.mTypeface;
62     mAlign = other.mAlign;
63     mStrikeThru = other.mStrikeThru;
64     mUnderline = other.mUnderline;
65     mDevKern = other.mDevKern;
66     return *this;
67 }
68 
operator ==(const Paint & a,const Paint & b)69 bool operator==(const Paint& a, const Paint& b) {
70     return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) &&
71            a.mFont == b.mFont &&
72            a.mLetterSpacing == b.mLetterSpacing && a.mWordSpacing == b.mWordSpacing &&
73            a.mFontFeatureSettings == b.mFontFeatureSettings &&
74            a.mMinikinLocaleListId == b.mMinikinLocaleListId &&
75            a.mFamilyVariant == b.mFamilyVariant && a.mHyphenEdit == b.mHyphenEdit &&
76            a.mTypeface == b.mTypeface && a.mAlign == b.mAlign &&
77            a.mStrikeThru == b.mStrikeThru && a.mUnderline == b.mUnderline &&
78            a.mDevKern == b.mDevKern;
79 }
80 
reset()81 void Paint::reset() {
82     SkPaint::reset();
83 
84     mFont = SkFont();
85     mFont.setEdging(SkFont::Edging::kAlias);
86 
87     mStrikeThru = false;
88     mUnderline = false;
89     mDevKern = false;
90 }
91 
setAntiAlias(bool aa)92 void Paint::setAntiAlias(bool aa) {
93     // Java does not support/understand subpixel(lcd) antialiasing
94     SkASSERT(mFont.getEdging() != SkFont::Edging::kSubpixelAntiAlias);
95     // JavaPaint antialiasing affects both the SkPaint and SkFont settings.
96     SkPaint::setAntiAlias(aa);
97     mFont.setEdging(aa ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias);
98 }
99 
100 ////////////////// Java flags compatibility //////////////////
101 
102 /*  Flags are tricky. Java has its own idea of the "paint" flags, but they don't really
103     match up with skia anymore, so we have to do some shuffling in get/set flags()
104 
105 	3 flags apply to SkPaint (antialias, dither, filter -> enum)
106     5 flags (merged with antialias) are for SkFont
107     2 flags are for minikin::Paint (underline and strikethru)
108 */
109 
110 // flags relating to SkPaint
111 static const uint32_t sAntiAliasFlag    = 0x01;   // affects paint and font-edging
112 static const uint32_t sFilterBitmapFlag = 0x02;   // maps to enum
113 static const uint32_t sDitherFlag       = 0x04;
114 // flags relating to SkFont
115 static const uint32_t sFakeBoldFlag     = 0x020;
116 static const uint32_t sLinearMetrics    = 0x040;
117 static const uint32_t sSubpixelMetrics  = 0x080;
118 static const uint32_t sEmbeddedBitmaps  = 0x400;
119 static const uint32_t sForceAutoHinting = 0x800;
120 // flags related to minikin::Paint
121 static const uint32_t sUnderlineFlag    = 0x08;
122 static const uint32_t sStrikeThruFlag   = 0x10;
123 // flags no longer supported on native side (but mirrored for compatibility)
124 static const uint32_t sDevKernFlag      = 0x100;
125 
paintToLegacyFlags(const SkPaint & paint)126 static uint32_t paintToLegacyFlags(const SkPaint& paint) {
127     uint32_t flags = 0;
128     flags |= -(int)paint.isAntiAlias() & sAntiAliasFlag;
129     flags |= -(int)paint.isDither()    & sDitherFlag;
130     if (paint.getFilterQuality() != kNone_SkFilterQuality) {
131         flags |= sFilterBitmapFlag;
132     }
133     return flags;
134 }
135 
fontToLegacyFlags(const SkFont & font)136 static uint32_t fontToLegacyFlags(const SkFont& font) {
137     uint32_t flags = 0;
138     flags |= -(int)font.isEmbolden()         & sFakeBoldFlag;
139     flags |= -(int)font.isLinearMetrics()    & sLinearMetrics;
140     flags |= -(int)font.isSubpixel()         & sSubpixelMetrics;
141     flags |= -(int)font.isEmbeddedBitmaps()  & sEmbeddedBitmaps;
142     flags |= -(int)font.isForceAutoHinting() & sForceAutoHinting;
143     return flags;
144 }
145 
applyLegacyFlagsToPaint(uint32_t flags,SkPaint * paint)146 static void applyLegacyFlagsToPaint(uint32_t flags, SkPaint* paint) {
147     paint->setAntiAlias((flags & sAntiAliasFlag) != 0);
148     paint->setDither   ((flags & sDitherFlag) != 0);
149 
150     if (flags & sFilterBitmapFlag) {
151         paint->setFilterQuality(kLow_SkFilterQuality);
152     } else {
153         paint->setFilterQuality(kNone_SkFilterQuality);
154     }
155 }
156 
applyLegacyFlagsToFont(uint32_t flags,SkFont * font)157 static void applyLegacyFlagsToFont(uint32_t flags, SkFont* font) {
158     font->setEmbolden        ((flags & sFakeBoldFlag) != 0);
159     font->setLinearMetrics   ((flags & sLinearMetrics) != 0);
160     font->setSubpixel        ((flags & sSubpixelMetrics) != 0);
161     font->setEmbeddedBitmaps ((flags & sEmbeddedBitmaps) != 0);
162     font->setForceAutoHinting((flags & sForceAutoHinting) != 0);
163 
164     if (flags & sAntiAliasFlag) {
165         font->setEdging(SkFont::Edging::kAntiAlias);
166     } else {
167         font->setEdging(SkFont::Edging::kAlias);
168     }
169 }
170 
GetSkPaintJavaFlags(const SkPaint & paint)171 uint32_t Paint::GetSkPaintJavaFlags(const SkPaint& paint) {
172     return paintToLegacyFlags(paint);
173 }
174 
SetSkPaintJavaFlags(SkPaint * paint,uint32_t flags)175 void Paint::SetSkPaintJavaFlags(SkPaint* paint, uint32_t flags) {
176     applyLegacyFlagsToPaint(flags, paint);
177 }
178 
getJavaFlags() const179 uint32_t Paint::getJavaFlags() const {
180     uint32_t flags = paintToLegacyFlags(*this) | fontToLegacyFlags(mFont);
181     flags |= -(int)mStrikeThru & sStrikeThruFlag;
182     flags |= -(int)mUnderline  & sUnderlineFlag;
183     flags |= -(int)mDevKern    & sDevKernFlag;
184     return flags;
185 }
186 
setJavaFlags(uint32_t flags)187 void Paint::setJavaFlags(uint32_t flags) {
188     applyLegacyFlagsToPaint(flags, this);
189     applyLegacyFlagsToFont(flags, &mFont);
190     mStrikeThru = (flags & sStrikeThruFlag) != 0;
191     mUnderline  = (flags & sUnderlineFlag) != 0;
192     mDevKern    = (flags & sDevKernFlag) != 0;
193 }
194 
195 }  // namespace android
196