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