| 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 |