OLD | NEW |
| (Empty) |
1 /* libs/graphics/effects/SkEmbossMaskFilter.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkEmbossMaskFilter.h" | |
19 #include "SkBlurMaskFilter.h" | |
20 #include "SkBlurMask.h" | |
21 #include "SkEmbossMask.h" | |
22 #include "SkBuffer.h" | |
23 | |
24 SkMaskFilter* SkBlurMaskFilter::CreateEmboss(const SkScalar direction[3], | |
25 SkScalar ambient, SkScalar specular
, | |
26 SkScalar blurRadius) | |
27 { | |
28 if (direction == NULL) | |
29 return NULL; | |
30 | |
31 // ambient should be 0...1 as a scalar | |
32 int am = SkScalarToFixed(ambient) >> 8; | |
33 if (am < 0) am = 0; | |
34 else if (am > 0xFF) am = 0xFF; | |
35 | |
36 // specular should be 0..15.99 as a scalar | |
37 int sp = SkScalarToFixed(specular) >> 12; | |
38 if (sp < 0) sp = 0; | |
39 else if (sp > 0xFF) sp = 0xFF; | |
40 | |
41 SkEmbossMaskFilter::Light light; | |
42 | |
43 memcpy(light.fDirection, direction, sizeof(light.fDirection)); | |
44 light.fAmbient = SkToU8(am); | |
45 light.fSpecular = SkToU8(sp); | |
46 | |
47 return SkNEW_ARGS(SkEmbossMaskFilter, (light, blurRadius)); | |
48 } | |
49 | |
50 ////////////////////////////////////////////////////////////////////////////////
///////////// | |
51 | |
52 static void normalize(SkScalar v[3]) | |
53 { | |
54 SkScalar mag = SkScalarSquare(v[0]) + SkScalarSquare(v[1]) + SkScalarSquare(
v[2]); | |
55 mag = SkScalarSqrt(mag); | |
56 | |
57 for (int i = 0; i < 3; i++) | |
58 v[i] = SkScalarDiv(v[i], mag); | |
59 } | |
60 | |
61 SkEmbossMaskFilter::SkEmbossMaskFilter(const Light& light, SkScalar blurRadius) | |
62 : fLight(light), fBlurRadius(blurRadius) | |
63 { | |
64 normalize(fLight.fDirection); | |
65 } | |
66 | |
67 SkMask::Format SkEmbossMaskFilter::getFormat() | |
68 { | |
69 return SkMask::k3D_Format; | |
70 } | |
71 | |
72 bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src, const SkMatr
ix& matrix, SkIPoint* margin) | |
73 { | |
74 SkScalar radius = matrix.mapRadius(fBlurRadius); | |
75 | |
76 if (!SkBlurMask::Blur(dst, src, radius, SkBlurMask::kInner_Style)) | |
77 return false; | |
78 | |
79 dst->fFormat = SkMask::k3D_Format; | |
80 if (margin) | |
81 margin->set(SkScalarCeil(radius), SkScalarCeil(radius)); | |
82 | |
83 if (src.fImage == NULL) | |
84 return true; | |
85 | |
86 // create a larger buffer for the other two channels (should force fBlur to
do this for us) | |
87 | |
88 { | |
89 uint8_t* alphaPlane = dst->fImage; | |
90 size_t planeSize = dst->computeImageSize(); | |
91 if (0 == planeSize) { | |
92 return false; // too big to allocate, abort | |
93 } | |
94 dst->fImage = SkMask::AllocImage(planeSize * 3); | |
95 memcpy(dst->fImage, alphaPlane, planeSize); | |
96 SkMask::FreeImage(alphaPlane); | |
97 } | |
98 | |
99 // run the light direction through the matrix... | |
100 Light light = fLight; | |
101 matrix.mapVectors((SkVector*)(void*)light.fDirection, (SkVector*)(void*)fLig
ht.fDirection, 1); | |
102 | |
103 // now restore the length of the XY component | |
104 // cast to SkVector so we can call setLength (this double cast silences alia
s warnings) | |
105 SkVector* vec = (SkVector*)(void*)light.fDirection; | |
106 vec->setLength(light.fDirection[0], | |
107 light.fDirection[1], | |
108 SkPoint::Length(fLight.fDirection[0], fLight.fDirection[1])); | |
109 | |
110 SkEmbossMask::Emboss(dst, light); | |
111 | |
112 // restore original alpha | |
113 memcpy(dst->fImage, src.fImage, src.computeImageSize()); | |
114 | |
115 return true; | |
116 } | |
117 | |
118 SkFlattenable* SkEmbossMaskFilter::CreateProc(SkFlattenableReadBuffer& buffer) | |
119 { | |
120 return SkNEW_ARGS(SkEmbossMaskFilter, (buffer)); | |
121 } | |
122 | |
123 SkFlattenable::Factory SkEmbossMaskFilter::getFactory() | |
124 { | |
125 return CreateProc; | |
126 } | |
127 | |
128 SkEmbossMaskFilter::SkEmbossMaskFilter(SkFlattenableReadBuffer& buffer) : SkMask
Filter(buffer) | |
129 { | |
130 buffer.read(&fLight, sizeof(fLight)); | |
131 SkASSERT(fLight.fPad == 0); // for the font-cache lookup to be clean | |
132 fBlurRadius = buffer.readScalar(); | |
133 } | |
134 | |
135 void SkEmbossMaskFilter::flatten(SkFlattenableWriteBuffer& buffer) | |
136 { | |
137 this->INHERITED::flatten(buffer); | |
138 | |
139 fLight.fPad = 0; // for the font-cache lookup to be clean | |
140 buffer.writeMul4(&fLight, sizeof(fLight)); | |
141 buffer.writeScalar(fBlurRadius); | |
142 } | |
143 | |
OLD | NEW |