gfx/skia/trunk/src/gpu/GrStencil.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2011 Google Inc.
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #ifndef GrStencil_DEFINED
michael@0 11 #define GrStencil_DEFINED
michael@0 12
michael@0 13 #include "GrTypes.h"
michael@0 14 #include "SkRegion.h"
michael@0 15
michael@0 16 /**
michael@0 17 * Gr uses the stencil buffer to implement complex clipping inside the
michael@0 18 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
michael@0 19 * bits available for other uses by external code (clients). Client code can
michael@0 20 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
michael@0 21 * provided by clients that overlap the bits used to implement clipping.
michael@0 22 *
michael@0 23 * When code outside the GrDrawTarget class uses the stencil buffer the contract
michael@0 24 * is as follows:
michael@0 25 *
michael@0 26 * > Normal stencil funcs allow the client to pass / fail regardless of the
michael@0 27 * reserved clip bits.
michael@0 28 * > Additional functions allow a test against the clip along with a limited
michael@0 29 * set of tests against the client bits.
michael@0 30 * > Client can assume all client bits are zero initially.
michael@0 31 * > Client must ensure that after all its passes are finished it has only
michael@0 32 * written to the color buffer in the region inside the clip. Furthermore, it
michael@0 33 * must zero all client bits that were modifed (both inside and outside the
michael@0 34 * clip).
michael@0 35 */
michael@0 36
michael@0 37 /**
michael@0 38 * Determines which pixels pass / fail the stencil test.
michael@0 39 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true
michael@0 40 */
michael@0 41 enum GrStencilFunc {
michael@0 42 kAlways_StencilFunc = 0,
michael@0 43 kNever_StencilFunc,
michael@0 44 kGreater_StencilFunc,
michael@0 45 kGEqual_StencilFunc,
michael@0 46 kLess_StencilFunc,
michael@0 47 kLEqual_StencilFunc,
michael@0 48 kEqual_StencilFunc,
michael@0 49 kNotEqual_StencilFunc,
michael@0 50
michael@0 51 // Gr stores the current clip in the
michael@0 52 // stencil buffer in the high bits that
michael@0 53 // are not directly accessible modifiable
michael@0 54 // via the GrDrawTarget interface. The below
michael@0 55 // stencil funcs test against the current
michael@0 56 // clip in addition to the GrDrawTarget
michael@0 57 // client's stencil bits.
michael@0 58
michael@0 59 // pass if inside the clip
michael@0 60 kAlwaysIfInClip_StencilFunc,
michael@0 61 kEqualIfInClip_StencilFunc,
michael@0 62 kLessIfInClip_StencilFunc,
michael@0 63 kLEqualIfInClip_StencilFunc,
michael@0 64 kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0
michael@0 65
michael@0 66 // counts
michael@0 67 kStencilFuncCount,
michael@0 68 kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
michael@0 69 kAlwaysIfInClip_StencilFunc + 1,
michael@0 70 kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
michael@0 71 };
michael@0 72
michael@0 73 /**
michael@0 74 * Operations to perform based on whether stencil test passed failed.
michael@0 75 */
michael@0 76 enum GrStencilOp {
michael@0 77 kKeep_StencilOp = 0, // preserve existing stencil value
michael@0 78 kReplace_StencilOp, // replace with reference value from stencl test
michael@0 79 kIncWrap_StencilOp, // increment and wrap at max
michael@0 80 kIncClamp_StencilOp, // increment and clamp at max
michael@0 81 kDecWrap_StencilOp, // decrement and wrap at 0
michael@0 82 kDecClamp_StencilOp, // decrement and clamp at 0
michael@0 83 kZero_StencilOp, // zero stencil bits
michael@0 84 kInvert_StencilOp, // invert stencil bits
michael@0 85
michael@0 86 kStencilOpCount
michael@0 87 };
michael@0 88
michael@0 89 enum GrStencilFlags {
michael@0 90 kIsDisabled_StencilFlag = 0x1,
michael@0 91 kNotDisabled_StencilFlag = 0x2,
michael@0 92 kDoesWrite_StencilFlag = 0x4,
michael@0 93 kDoesNotWrite_StencilFlag = 0x8,
michael@0 94 };
michael@0 95
michael@0 96 /**
michael@0 97 * GrStencilState needs to be a class with accessors and setters so that it
michael@0 98 * can maintain flags related to its current state. However, we also want to
michael@0 99 * be able to declare pre-made stencil settings at compile time (without
michael@0 100 * inserting static initializer code). So all the data members are in this
michael@0 101 * struct. A macro defined after the class can be used to jam an instance of
michael@0 102 * this struct that is created from an initializer list into a
michael@0 103 * GrStencilSettings. (We hang our heads in shame.)
michael@0 104 */
michael@0 105 struct GrStencilSettingsStruct {
michael@0 106 uint8_t fPassOps[2]; // op to perform when faces pass (GrStencilOp)
michael@0 107 uint8_t fFailOps[2]; // op to perform when faces fail (GrStencilOp)
michael@0 108 uint8_t fFuncs[2]; // test function for faces (GrStencilFunc)
michael@0 109 uint8_t fPad0;
michael@0 110 uint8_t fPad1;
michael@0 111 uint16_t fFuncMasks[2]; // mask for face tests
michael@0 112 uint16_t fFuncRefs[2]; // reference values for face tests
michael@0 113 uint16_t fWriteMasks[2]; // stencil write masks
michael@0 114 mutable uint32_t fFlags;
michael@0 115 };
michael@0 116 // We rely on this being packed and aligned (memcmp'ed and memcpy'ed)
michael@0 117 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) % 4 == 0);
michael@0 118 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) ==
michael@0 119 4*sizeof(uint8_t) + // ops
michael@0 120 2*sizeof(uint8_t) + // funcs
michael@0 121 2*sizeof(uint8_t) + // pads
michael@0 122 2*sizeof(uint16_t) + // func masks
michael@0 123 2*sizeof(uint16_t) + // ref values
michael@0 124 2*sizeof(uint16_t) + // write masks
michael@0 125 sizeof(uint32_t)); // flags
michael@0 126
michael@0 127 // This macro is used to compute the GrStencilSettingsStructs flags
michael@0 128 // associated to disabling. It is used both to define constant structure
michael@0 129 // initializers and inside GrStencilSettings::isDisabled()
michael@0 130 //
michael@0 131 #define GR_STENCIL_SETTINGS_IS_DISABLED( \
michael@0 132 FRONT_PASS_OP, BACK_PASS_OP, \
michael@0 133 FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 134 FRONT_FUNC, BACK_FUNC) \
michael@0 135 ((FRONT_PASS_OP) == kKeep_StencilOp && \
michael@0 136 (BACK_PASS_OP) == kKeep_StencilOp && \
michael@0 137 (FRONT_FAIL_OP) == kKeep_StencilOp && \
michael@0 138 (BACK_FAIL_OP) == kKeep_StencilOp && \
michael@0 139 (FRONT_FUNC) == kAlways_StencilFunc && \
michael@0 140 (BACK_FUNC) == kAlways_StencilFunc)
michael@0 141
michael@0 142 #define GR_STENCIL_SETTINGS_DOES_WRITE( \
michael@0 143 FRONT_PASS_OP, BACK_PASS_OP, \
michael@0 144 FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 145 FRONT_FUNC, BACK_FUNC) \
michael@0 146 (!(((FRONT_FUNC) == kNever_StencilFunc || \
michael@0 147 (FRONT_PASS_OP) == kKeep_StencilOp) && \
michael@0 148 ((BACK_FUNC) == kNever_StencilFunc || \
michael@0 149 (BACK_PASS_OP) == kKeep_StencilOp) && \
michael@0 150 ((FRONT_FUNC) == kAlways_StencilFunc || \
michael@0 151 (FRONT_FAIL_OP) == kKeep_StencilOp) && \
michael@0 152 ((BACK_FUNC) == kAlways_StencilFunc || \
michael@0 153 (BACK_FAIL_OP) == kKeep_StencilOp)))
michael@0 154
michael@0 155 #define GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
michael@0 156 FRONT_PASS_OP, BACK_PASS_OP, \
michael@0 157 FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 158 FRONT_FUNC, BACK_FUNC) \
michael@0 159 ((GR_STENCIL_SETTINGS_IS_DISABLED(FRONT_PASS_OP,BACK_PASS_OP, \
michael@0 160 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
michael@0 161 kIsDisabled_StencilFlag : kNotDisabled_StencilFlag) | \
michael@0 162 (GR_STENCIL_SETTINGS_DOES_WRITE(FRONT_PASS_OP,BACK_PASS_OP, \
michael@0 163 FRONT_FAIL_OP,BACK_FAIL_OP,FRONT_FUNC,BACK_FUNC) ? \
michael@0 164 kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag))
michael@0 165
michael@0 166 /**
michael@0 167 * Class representing stencil state.
michael@0 168 */
michael@0 169 class GrStencilSettings : private GrStencilSettingsStruct {
michael@0 170
michael@0 171 public:
michael@0 172 enum Face {
michael@0 173 kFront_Face = 0,
michael@0 174 kBack_Face = 1,
michael@0 175 };
michael@0 176
michael@0 177 GrStencilSettings() {
michael@0 178 fPad0 = fPad1 = 0;
michael@0 179 this->setDisabled();
michael@0 180 }
michael@0 181
michael@0 182 GrStencilOp passOp(Face f) const { return static_cast<GrStencilOp>(fPassOps[f]); }
michael@0 183 GrStencilOp failOp(Face f) const { return static_cast<GrStencilOp>(fFailOps[f]); }
michael@0 184 GrStencilFunc func(Face f) const { return static_cast<GrStencilFunc>(fFuncs[f]); }
michael@0 185 uint16_t funcMask(Face f) const { return fFuncMasks[f]; }
michael@0 186 uint16_t funcRef(Face f) const { return fFuncRefs[f]; }
michael@0 187 uint16_t writeMask(Face f) const { return fWriteMasks[f]; }
michael@0 188
michael@0 189 void setPassOp(Face f, GrStencilOp op) { fPassOps[f] = op; fFlags = 0;}
michael@0 190 void setFailOp(Face f, GrStencilOp op) { fFailOps[f] = op; fFlags = 0;}
michael@0 191 void setFunc(Face f, GrStencilFunc func) { fFuncs[f] = func; fFlags = 0;}
michael@0 192 void setFuncMask(Face f, unsigned short mask) { fFuncMasks[f] = mask; }
michael@0 193 void setFuncRef(Face f, unsigned short ref) { fFuncRefs[f] = ref; }
michael@0 194 void setWriteMask(Face f, unsigned short writeMask) { fWriteMasks[f] = writeMask; }
michael@0 195
michael@0 196 void copyFrontSettingsToBack() {
michael@0 197 fPassOps[kBack_Face] = fPassOps[kFront_Face];
michael@0 198 fFailOps[kBack_Face] = fFailOps[kFront_Face];
michael@0 199 fFuncs[kBack_Face] = fFuncs[kFront_Face];
michael@0 200 fFuncMasks[kBack_Face] = fFuncMasks[kFront_Face];
michael@0 201 fFuncRefs[kBack_Face] = fFuncRefs[kFront_Face];
michael@0 202 fWriteMasks[kBack_Face] = fWriteMasks[kFront_Face];
michael@0 203 fFlags = 0;
michael@0 204 }
michael@0 205
michael@0 206 void setSame(GrStencilOp passOp,
michael@0 207 GrStencilOp failOp,
michael@0 208 GrStencilFunc func,
michael@0 209 unsigned short funcMask,
michael@0 210 unsigned short funcRef,
michael@0 211 unsigned short writeMask) {
michael@0 212 fPassOps[kFront_Face] = fPassOps[kBack_Face] = passOp;
michael@0 213 fFailOps[kFront_Face] = fFailOps[kBack_Face] = failOp;
michael@0 214 fFuncs[kFront_Face] = fFuncs[kBack_Face] = func;
michael@0 215 fFuncMasks[kFront_Face] = fFuncMasks[kBack_Face] = funcMask;
michael@0 216 fFuncRefs[kFront_Face] = fFuncRefs[kBack_Face] = funcRef;
michael@0 217 fWriteMasks[kFront_Face] = fWriteMasks[kBack_Face] = writeMask;
michael@0 218 fFlags = 0;
michael@0 219 }
michael@0 220
michael@0 221 void setDisabled() {
michael@0 222 memset(this, 0, sizeof(*this));
michael@0 223 GR_STATIC_ASSERT(0 == kKeep_StencilOp);
michael@0 224 GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
michael@0 225 fFlags = kIsDisabled_StencilFlag | kDoesNotWrite_StencilFlag;
michael@0 226 }
michael@0 227
michael@0 228 bool isTwoSided() const {
michael@0 229 return fPassOps[kFront_Face] != fPassOps[kBack_Face] ||
michael@0 230 fFailOps[kFront_Face] != fFailOps[kBack_Face] ||
michael@0 231 fFuncs[kFront_Face] != fFuncs[kBack_Face] ||
michael@0 232 fFuncMasks[kFront_Face] != fFuncMasks[kBack_Face] ||
michael@0 233 fFuncRefs[kFront_Face] != fFuncRefs[kBack_Face] ||
michael@0 234 fWriteMasks[kFront_Face] != fWriteMasks[kBack_Face];
michael@0 235 }
michael@0 236
michael@0 237 bool usesWrapOp() const {
michael@0 238 return kIncWrap_StencilOp == fPassOps[kFront_Face] ||
michael@0 239 kDecWrap_StencilOp == fPassOps[kFront_Face] ||
michael@0 240 kIncWrap_StencilOp == fPassOps[kBack_Face] ||
michael@0 241 kDecWrap_StencilOp == fPassOps[kBack_Face] ||
michael@0 242 kIncWrap_StencilOp == fFailOps[kFront_Face] ||
michael@0 243 kDecWrap_StencilOp == fFailOps[kFront_Face] ||
michael@0 244 kIncWrap_StencilOp == fFailOps[kBack_Face] ||
michael@0 245 kDecWrap_StencilOp == fFailOps[kBack_Face];
michael@0 246 }
michael@0 247
michael@0 248 bool isDisabled() const {
michael@0 249 if (fFlags & kIsDisabled_StencilFlag) {
michael@0 250 return true;
michael@0 251 }
michael@0 252 if (fFlags & kNotDisabled_StencilFlag) {
michael@0 253 return false;
michael@0 254 }
michael@0 255 bool disabled = GR_STENCIL_SETTINGS_IS_DISABLED(
michael@0 256 fPassOps[kFront_Face], fPassOps[kBack_Face],
michael@0 257 fFailOps[kFront_Face], fFailOps[kBack_Face],
michael@0 258 fFuncs[kFront_Face], fFuncs[kBack_Face]);
michael@0 259 fFlags |= disabled ? kIsDisabled_StencilFlag : kNotDisabled_StencilFlag;
michael@0 260 return disabled;
michael@0 261 }
michael@0 262
michael@0 263 bool doesWrite() const {
michael@0 264 if (fFlags & kDoesWrite_StencilFlag) {
michael@0 265 return true;
michael@0 266 }
michael@0 267 if (fFlags & kDoesNotWrite_StencilFlag) {
michael@0 268 return false;
michael@0 269 }
michael@0 270 bool writes = GR_STENCIL_SETTINGS_DOES_WRITE(
michael@0 271 fPassOps[kFront_Face], fPassOps[kBack_Face],
michael@0 272 fFailOps[kFront_Face], fFailOps[kBack_Face],
michael@0 273 fFuncs[kFront_Face], fFuncs[kBack_Face]);
michael@0 274 fFlags |= writes ? kDoesWrite_StencilFlag : kDoesNotWrite_StencilFlag;
michael@0 275 return writes;
michael@0 276 }
michael@0 277
michael@0 278 void invalidate() {
michael@0 279 // write an illegal value to the first member
michael@0 280 fPassOps[0] = (GrStencilOp)(uint8_t)-1;
michael@0 281 fFlags = 0;
michael@0 282 }
michael@0 283
michael@0 284 bool operator == (const GrStencilSettings& s) const {
michael@0 285 static const size_t gCompareSize = sizeof(GrStencilSettings) -
michael@0 286 sizeof(fFlags);
michael@0 287 SkASSERT((const char*)&fFlags + sizeof(fFlags) ==
michael@0 288 (const char*)this + sizeof(GrStencilSettings));
michael@0 289 if (this->isDisabled() & s.isDisabled()) { // using & not &&
michael@0 290 return true;
michael@0 291 }
michael@0 292 return 0 == memcmp(this, &s, gCompareSize);
michael@0 293 }
michael@0 294
michael@0 295 bool operator != (const GrStencilSettings& s) const {
michael@0 296 return !(*this == s);
michael@0 297 }
michael@0 298
michael@0 299 GrStencilSettings& operator =(const GrStencilSettings& s) {
michael@0 300 memcpy(this, &s, sizeof(GrStencilSettings));
michael@0 301 return *this;
michael@0 302 }
michael@0 303
michael@0 304 private:
michael@0 305 friend class GrClipMaskManager;
michael@0 306
michael@0 307 enum {
michael@0 308 kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
michael@0 309 // element to the stencil buffer.
michael@0 310 };
michael@0 311
michael@0 312 /**
michael@0 313 * Given a thing to draw into the stencil clip, a fill type, and a set op
michael@0 314 * this function determines:
michael@0 315 * 1. Whether the thing can be draw directly to the stencil clip or
michael@0 316 * needs to be drawn to the client portion of the stencil first.
michael@0 317 * 2. How many passes are needed.
michael@0 318 * 3. What those passes are.
michael@0 319 * 4. The fill rule that should actually be used to render (will
michael@0 320 * always be non-inverted).
michael@0 321 *
michael@0 322 * @param op the set op to combine this element with the
michael@0 323 * existing clip
michael@0 324 * @param stencilClipMask mask with just the stencil bit used for clipping
michael@0 325 * enabled.
michael@0 326 * @param invertedFill is this path inverted
michael@0 327 * @param numPasses out: the number of passes needed to add the
michael@0 328 * element to the clip.
michael@0 329 * @param settings out: the stencil settings to use for each pass
michael@0 330 *
michael@0 331 * @return true if the clip element's geometry can be drawn directly to the
michael@0 332 * stencil clip bit. Will only be true if canBeDirect is true.
michael@0 333 * numPasses will be 1 if return value is true.
michael@0 334 */
michael@0 335 static bool GetClipPasses(SkRegion::Op op,
michael@0 336 bool canBeDirect,
michael@0 337 unsigned int stencilClipMask,
michael@0 338 bool invertedFill,
michael@0 339 int* numPasses,
michael@0 340 GrStencilSettings settings[kMaxStencilClipPasses]);
michael@0 341 };
michael@0 342
michael@0 343 GR_STATIC_ASSERT(sizeof(GrStencilSettingsStruct) == sizeof(GrStencilSettings));
michael@0 344
michael@0 345 #define GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, \
michael@0 346 FRONT_PASS_OP, BACK_PASS_OP, \
michael@0 347 FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 348 FRONT_FUNC, BACK_FUNC, \
michael@0 349 FRONT_MASK, BACK_MASK, \
michael@0 350 FRONT_REF, BACK_REF, \
michael@0 351 FRONT_WRITE_MASK, BACK_WRITE_MASK) \
michael@0 352 static const GrStencilSettingsStruct STRUCT_NAME = { \
michael@0 353 {(FRONT_PASS_OP), (BACK_PASS_OP) }, \
michael@0 354 {(FRONT_FAIL_OP), (BACK_FAIL_OP) }, \
michael@0 355 {(FRONT_FUNC), (BACK_FUNC) }, \
michael@0 356 (0), (0), \
michael@0 357 {(FRONT_MASK), (BACK_MASK) }, \
michael@0 358 {(FRONT_REF), (BACK_REF) }, \
michael@0 359 {(FRONT_WRITE_MASK), (BACK_WRITE_MASK)}, \
michael@0 360 GR_STENCIL_SETTINGS_DEFAULT_FLAGS( \
michael@0 361 FRONT_PASS_OP, BACK_PASS_OP, FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 362 FRONT_FUNC, BACK_FUNC) \
michael@0 363 };
michael@0 364
michael@0 365 #define GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(STRUCT_PTR) \
michael@0 366 reinterpret_cast<const GrStencilSettings*>(STRUCT_PTR)
michael@0 367
michael@0 368 #define GR_STATIC_CONST_SAME_STENCIL_STRUCT(STRUCT_NAME, \
michael@0 369 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
michael@0 370 GR_STATIC_CONST_STENCIL_STRUCT(STRUCT_NAME, (PASS_OP), (PASS_OP), \
michael@0 371 (FAIL_OP),(FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), \
michael@0 372 (WRITE_MASK),(WRITE_MASK))
michael@0 373
michael@0 374 #define GR_STATIC_CONST_STENCIL(NAME, \
michael@0 375 FRONT_PASS_OP, BACK_PASS_OP, \
michael@0 376 FRONT_FAIL_OP, BACK_FAIL_OP, \
michael@0 377 FRONT_FUNC, BACK_FUNC, \
michael@0 378 FRONT_MASK, BACK_MASK, \
michael@0 379 FRONT_REF, BACK_REF, \
michael@0 380 FRONT_WRITE_MASK, BACK_WRITE_MASK) \
michael@0 381 GR_STATIC_CONST_STENCIL_STRUCT(NAME ## _STRUCT, \
michael@0 382 (FRONT_PASS_OP),(BACK_PASS_OP),(FRONT_FAIL_OP),(BACK_FAIL_OP), \
michael@0 383 (FRONT_FUNC),(BACK_FUNC),(FRONT_MASK),(BACK_MASK), \
michael@0 384 (FRONT_REF),(BACK_REF),(FRONT_WRITE_MASK),(BACK_WRITE_MASK)) \
michael@0 385 static const GrStencilSettings& NAME = \
michael@0 386 *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&(NAME ## _STRUCT));
michael@0 387
michael@0 388
michael@0 389 #define GR_STATIC_CONST_SAME_STENCIL(NAME, \
michael@0 390 PASS_OP, FAIL_OP, FUNC, MASK, REF, WRITE_MASK) \
michael@0 391 GR_STATIC_CONST_STENCIL(NAME, (PASS_OP), (PASS_OP), (FAIL_OP), \
michael@0 392 (FAIL_OP), (FUNC), (FUNC), (MASK), (MASK), (REF), (REF), (WRITE_MASK), \
michael@0 393 (WRITE_MASK))
michael@0 394
michael@0 395 #endif

mercurial