| OLD | NEW |
| (Empty) |
| 1 /* libs/graphics/effects/SkEmbossMask.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 "SkEmbossMask.h" | |
| 19 | |
| 20 static inline int nonzero_to_one(int x) | |
| 21 { | |
| 22 #if 0 | |
| 23 return x != 0; | |
| 24 #else | |
| 25 return ((unsigned)(x | -x)) >> 31; | |
| 26 #endif | |
| 27 } | |
| 28 | |
| 29 static inline int neq_to_one(int x, int max) | |
| 30 { | |
| 31 #if 0 | |
| 32 return x != max; | |
| 33 #else | |
| 34 SkASSERT(x >= 0 && x <= max); | |
| 35 return ((unsigned)(x - max)) >> 31; | |
| 36 #endif | |
| 37 } | |
| 38 | |
| 39 static inline int neq_to_mask(int x, int max) | |
| 40 { | |
| 41 #if 0 | |
| 42 return -(x != max); | |
| 43 #else | |
| 44 SkASSERT(x >= 0 && x <= max); | |
| 45 return (x - max) >> 31; | |
| 46 #endif | |
| 47 } | |
| 48 | |
| 49 static inline unsigned div255(unsigned x) | |
| 50 { | |
| 51 SkASSERT(x <= (255*255)); | |
| 52 return x * ((1 << 24) / 255) >> 24; | |
| 53 } | |
| 54 | |
| 55 #define kDelta 32 // small enough to show off angle differences | |
| 56 | |
| 57 #include "SkEmbossMask_Table.h" | |
| 58 | |
| 59 #if defined(SK_BUILD_FOR_WIN32) && defined(SK_DEBUG) | |
| 60 | |
| 61 #include <stdio.h> | |
| 62 | |
| 63 void SkEmbossMask_BuildTable() | |
| 64 { | |
| 65 // build it 0..127 x 0..127, so we use 2^15 - 1 in the numerator for our "fi
xed" table | |
| 66 | |
| 67 FILE* file = ::fopen("SkEmbossMask_Table.h", "w"); | |
| 68 SkASSERT(file); | |
| 69 ::fprintf(file, "#include \"SkTypes.h\"\n\n"); | |
| 70 ::fprintf(file, "static const U16 gInvSqrtTable[128 * 128] = {\n"); | |
| 71 for (int dx = 0; dx <= 255/2; dx++) | |
| 72 { | |
| 73 for (int dy = 0; dy <= 255/2; dy++) | |
| 74 { | |
| 75 if ((dy & 15) == 0) | |
| 76 ::fprintf(file, "\t"); | |
| 77 | |
| 78 uint16_t value = SkToU16((1 << 15) / SkSqrt32(dx * dx + dy * dy + kD
elta*kDelta/4)); | |
| 79 | |
| 80 ::fprintf(file, "0x%04X", value); | |
| 81 if (dx * 128 + dy < 128*128-1) | |
| 82 ::fprintf(file, ", "); | |
| 83 if ((dy & 15) == 15) | |
| 84 ::fprintf(file, "\n"); | |
| 85 } | |
| 86 } | |
| 87 ::fprintf(file, "};\n#define kDeltaUsedToBuildTable\t%d\n", kDelta); | |
| 88 ::fclose(file); | |
| 89 } | |
| 90 | |
| 91 #endif | |
| 92 | |
| 93 void SkEmbossMask::Emboss(SkMask* mask, const SkEmbossMaskFilter::Light& light) | |
| 94 { | |
| 95 SkASSERT(kDelta == kDeltaUsedToBuildTable); | |
| 96 | |
| 97 SkASSERT(mask->fFormat == SkMask::k3D_Format); | |
| 98 | |
| 99 int specular = light.fSpecular; | |
| 100 int ambient = light.fAmbient; | |
| 101 SkFixed lx = SkScalarToFixed(light.fDirection[0]); | |
| 102 SkFixed ly = SkScalarToFixed(light.fDirection[1]); | |
| 103 SkFixed lz = SkScalarToFixed(light.fDirection[2]); | |
| 104 SkFixed lz_dot_nz = lz * kDelta; | |
| 105 int lz_dot8 = lz >> 8; | |
| 106 | |
| 107 size_t planeSize = mask->computeImageSize(); | |
| 108 uint8_t* alpha = mask->fImage; | |
| 109 uint8_t* multiply = (uint8_t*)alpha + planeSize; | |
| 110 uint8_t* additive = multiply + planeSize; | |
| 111 | |
| 112 int rowBytes = mask->fRowBytes; | |
| 113 int maxy = mask->fBounds.height() - 1; | |
| 114 int maxx = mask->fBounds.width() - 1; | |
| 115 | |
| 116 int prev_row = 0; | |
| 117 for (int y = 0; y <= maxy; y++) | |
| 118 { | |
| 119 int next_row = neq_to_mask(y, maxy) & rowBytes; | |
| 120 | |
| 121 for (int x = 0; x <= maxx; x++) | |
| 122 { | |
| 123 if (alpha[x]) | |
| 124 { | |
| 125 int nx = alpha[x + neq_to_one(x, maxx)] - alpha[x - nonzero_to_o
ne(x)]; | |
| 126 int ny = alpha[x + next_row] - alpha[x - prev_row]; | |
| 127 | |
| 128 SkFixed numer = lx * nx + ly * ny + lz_dot_nz; | |
| 129 int mul = ambient; | |
| 130 int add = 0; | |
| 131 | |
| 132 if (numer > 0) // preflight when numer/denom will be <= 0 | |
| 133 { | |
| 134 #if 0 | |
| 135 int denom = SkSqrt32(nx * nx + ny * ny + kDelta*kDelta); | |
| 136 SkFixed dot = numer / denom; | |
| 137 dot >>= 8; // now dot is 2^8 instead of 2^16 | |
| 138 #else | |
| 139 // can use full numer, but then we need to call SkFixedMul,
since | |
| 140 // numer is 24 bits, and our table is 12 bits | |
| 141 | |
| 142 // SkFixed dot = SkFixedMul(numer, gTable[]) >> 8 | |
| 143 SkFixed dot = (unsigned)(numer >> 4) * gInvSqrtTable[(SkAbs3
2(nx) >> 1 << 7) | (SkAbs32(ny) >> 1)] >> 20; | |
| 144 #endif | |
| 145 mul = SkFastMin32(mul + dot, 255); | |
| 146 | |
| 147 // now for the reflection | |
| 148 | |
| 149 // R = 2 (Light * Normal) Normal - Light | |
| 150 // hilite = R * Eye(0, 0, 1) | |
| 151 | |
| 152 int hilite = (2 * dot - lz_dot8) * lz_dot8 >> 8; | |
| 153 if (hilite > 0) | |
| 154 { | |
| 155 // pin hilite to 255, since our fast math is also a litt
le sloppy | |
| 156 hilite = SkClampMax(hilite, 255); | |
| 157 | |
| 158 // specular is 4.4 | |
| 159 // would really like to compute the fractional part of t
his | |
| 160 // and then possibly cache a 256 table for a given specu
lar | |
| 161 // value in the light, and just pass that in to this fun
ction. | |
| 162 add = hilite; | |
| 163 for (int i = specular >> 4; i > 0; --i) | |
| 164 add = div255(add * hilite); | |
| 165 } | |
| 166 } | |
| 167 multiply[x] = SkToU8(mul); | |
| 168 additive[x] = SkToU8(add); | |
| 169 | |
| 170 // multiply[x] = 0xFF; | |
| 171 // additive[x] = 0; | |
| 172 // ((uint8_t*)alpha)[x] = alpha[x] * multiply[x] >> 8; | |
| 173 } | |
| 174 } | |
| 175 alpha += rowBytes; | |
| 176 multiply += rowBytes; | |
| 177 additive += rowBytes; | |
| 178 prev_row = rowBytes; | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 | |
| OLD | NEW |