diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/include/corecg | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2 |
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/include/corecg')
24 files changed, 4574 insertions, 0 deletions
diff --git a/skia/include/corecg/Sk64.h b/skia/include/corecg/Sk64.h new file mode 100644 index 0000000..4d5343c --- /dev/null +++ b/skia/include/corecg/Sk64.h @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Sk64_DEFINED +#define Sk64_DEFINED + +#include "SkFixed.h" +#include "SkMath.h" + +/** \class Sk64 + + Sk64 is a 64-bit math package that does not require long long support from the compiler. +*/ +struct Sk64 { + int32_t fHi; //!< the high 32 bits of the number (including sign) + uint32_t fLo; //!< the low 32 bits of the number + + /** Returns non-zero if the Sk64 can be represented as a signed 32 bit integer + */ + SkBool is32() const { return fHi == ((int32_t)fLo >> 31); } + + /** Returns non-zero if the Sk64 cannot be represented as a signed 32 bit integer + */ + SkBool is64() const { return fHi != ((int32_t)fLo >> 31); } + + /** Returns non-zero if the Sk64 can be represented as a signed 48 bit integer. Used to know + if we can shift the value down by 16 to treat it as a SkFixed. + */ + SkBool isFixed() const; + + /** Return the signed 32 bit integer equivalent. Asserts that is32() returns non-zero. + */ + int32_t get32() const { SkASSERT(this->is32()); return (int32_t)fLo; } + + /** Return the number >> 16. Asserts that this does not loose any significant high bits. + */ + SkFixed getFixed() const { + SkASSERT(this->isFixed()); + + uint32_t sum = fLo + (1 << 15); + int32_t hi = fHi; + if (sum < fLo) { + hi += 1; + } + return (hi << 16) | (sum >> 16); + } + + /** Return the number >> 30. Asserts that this does not loose any + significant high bits. + */ + SkFract getFract() const; + + /** Returns the square-root of the number as a signed 32 bit value. */ + int32_t getSqrt() const; + + /** Returns the number of leading zeros of the absolute value of this. + Will return in the range [0..64] + */ + int getClzAbs() const; + + /** Returns non-zero if the number is zero */ + SkBool isZero() const { return (fHi | fLo) == 0; } + + /** Returns non-zero if the number is non-zero */ + SkBool nonZero() const { return fHi | fLo; } + + /** Returns non-zero if the number is negative (number < 0) */ + SkBool isNeg() const { return (uint32_t)fHi >> 31; } + + /** Returns non-zero if the number is positive (number > 0) */ + SkBool isPos() const { return ~(fHi >> 31) & (fHi | fLo); } + + /** Returns -1,0,+1 based on the sign of the number */ + int sign() const { return (fHi >> 31) | Sk32ToBool(fHi | fLo); } + + /** Negate the number */ + void negate(); + + /** If the number < 0, negate the number + */ + void abs(); + + /** Returns the number of bits needed to shift the Sk64 to the right + in order to make it fit in a signed 32 bit integer. + */ + int shiftToMake32() const; + + /** Set the number to zero */ + void setZero() { fHi = fLo = 0; } + + /** Set the high and low 32 bit values of the number */ + void set(int32_t hi, uint32_t lo) { fHi = hi; fLo = lo; } + + /** Set the number to the specified 32 bit integer */ + void set(int32_t a) { fHi = a >> 31; fLo = a; } + + /** Set the number to the product of the two 32 bit integers */ + void setMul(int32_t a, int32_t b); + + /** extract 32bits after shifting right by bitCount. + Note: itCount must be [0..63]. + Asserts that no significant high bits were lost. + */ + int32_t getShiftRight(unsigned bitCount) const; + + /** Shift the number left by the specified number of bits. + @param bits How far to shift left, must be [0..63] + */ + void shiftLeft(unsigned bits); + + /** Shift the number right by the specified number of bits. + @param bits How far to shift right, must be [0..63]. This + performs an arithmetic right-shift (sign extending). + */ + void shiftRight(unsigned bits); + + /** Shift the number right by the specified number of bits, but + round the result. + @param bits How far to shift right, must be [0..63]. This + performs an arithmetic right-shift (sign extending). + */ + void roundRight(unsigned bits); + + /** Add the specified 32 bit integer to the number */ + void add(int32_t lo) { + int32_t hi = lo >> 31; // 0 or -1 + uint32_t sum = fLo + (uint32_t)lo; + + fHi = fHi + hi + (sum < fLo); + fLo = sum; + } + + /** Add the specified Sk64 to the number */ + void add(int32_t hi, uint32_t lo) { + uint32_t sum = fLo + lo; + + fHi = fHi + hi + (sum < fLo); + fLo = sum; + } + + /** Add the specified Sk64 to the number */ + void add(const Sk64& other) { this->add(other.fHi, other.fLo); } + + /** Subtract the specified Sk64 from the number. (*this) = (*this) - num + */ + void sub(const Sk64& num); + + /** Subtract the number from the specified Sk64. (*this) = num - (*this) + */ + void rsub(const Sk64& num); + + /** Multiply the number by the specified 32 bit integer + */ + void mul(int32_t); + + enum DivOptions { + kTrunc_DivOption, //!< truncate the result when calling div() + kRound_DivOption //!< round the result when calling div() + }; + + /** Divide the number by the specified 32 bit integer, using the specified + divide option (either truncate or round). + */ + void div(int32_t, DivOptions); + + /** return (this + other >> 16) as a 32bit result */ + SkFixed addGetFixed(const Sk64& other) const { + return this->addGetFixed(other.fHi, other.fLo); + } + + /** return (this + Sk64(hi, lo) >> 16) as a 32bit result */ + SkFixed addGetFixed(int32_t hi, uint32_t lo) const { +#ifdef SK_DEBUG + Sk64 tmp(*this); + tmp.add(hi, lo); +#endif + + uint32_t sum = fLo + lo; + hi += fHi + (sum < fLo); + lo = sum; + + sum = lo + (1 << 15); + if (sum < lo) + hi += 1; + + hi = (hi << 16) | (sum >> 16); + SkASSERT(hi == tmp.getFixed()); + return hi; + } + + /** Return the result of dividing the number by denom, treating the answer + as a SkFixed. (*this) << 16 / denom. It is an error for denom to be 0. + */ + SkFixed getFixedDiv(const Sk64& denom) const; + + friend bool operator==(const Sk64& a, const Sk64& b) { + return a.fHi == b.fHi && a.fLo == b.fLo; + } + + friend bool operator!=(const Sk64& a, const Sk64& b) { + return a.fHi != b.fHi || a.fLo != b.fLo; + } + + friend bool operator<(const Sk64& a, const Sk64& b) { + return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo < b.fLo); + } + + friend bool operator<=(const Sk64& a, const Sk64& b) { + return a.fHi < b.fHi || (a.fHi == b.fHi && a.fLo <= b.fLo); + } + + friend bool operator>(const Sk64& a, const Sk64& b) { + return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo > b.fLo); + } + + friend bool operator>=(const Sk64& a, const Sk64& b) { + return a.fHi > b.fHi || (a.fHi == b.fHi && a.fLo >= b.fLo); + } + +#ifdef SkLONGLONG + SkLONGLONG getLongLong() const; +#endif + +#ifdef SK_DEBUG + /** @cond UNIT_TEST */ + static void UnitTest(); + /** @endcond */ +#endif +}; + +#endif + diff --git a/skia/include/corecg/SkBuffer.h b/skia/include/corecg/SkBuffer.h new file mode 100644 index 0000000..b1cfefc --- /dev/null +++ b/skia/include/corecg/SkBuffer.h @@ -0,0 +1,142 @@ +/* include/corecg/SkBuffer.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkBuffer_DEFINED +#define SkBuffer_DEFINED + +#include "SkScalar.h" + +/** \class SkRBuffer + + Light weight class for reading data from a memory block. + The RBuffer is given the buffer to read from, with either a specified size + or no size (in which case no range checking is performed). It is iillegal + to attempt to read a value from an empty RBuffer (data == null). +*/ +class SkRBuffer : SkNoncopyable { +public: + SkRBuffer() : fData(0), fPos(0), fStop(0) {} + /** Initialize RBuffer with a data pointer, but no specified length. + This signals the RBuffer to not perform range checks during reading. + */ + SkRBuffer(const void* data) + { + fData = (const char*)data; + fPos = (const char*)data; + fStop = 0; // no bounds checking + } + /** Initialize RBuffer with a data point and length. + */ + SkRBuffer(const void* data, size_t size) + { + SkASSERT(data != 0 || size == 0); + fData = (const char*)data; + fPos = (const char*)data; + fStop = (const char*)data + size; + } + + /** Return the number of bytes that have been read from the beginning + of the data pointer. + */ + size_t pos() const { return fPos - fData; } + /** Return the total size of the data pointer. Only defined if the length was + specified in the constructor or in a call to reset(). + */ + size_t size() const { return fStop - fData; } + /** Return true if the buffer has read to the end of the data pointer. + Only defined if the length was specified in the constructor or in a call + to reset(). Always returns true if the length was not specified. + */ + bool eof() const { return fPos >= fStop; } + + /** Read the specified number of bytes from the data pointer. If buffer is not + null, copy those bytes into buffer. + */ + void read(void* buffer, size_t size) { if (size) this->readNoSizeCheck(buffer, size); } + const void* skip(size_t size); // return start of skipped data + size_t skipToAlign4(); + + void* readPtr() { void* ptr; read(&ptr, sizeof(ptr)); return ptr; } + SkScalar readScalar() { SkScalar x; read(&x, 4); return x; } + uint32_t readU32() { uint32_t x; read(&x, 4); return x; } + int32_t readS32() { int32_t x; read(&x, 4); return x; } + uint16_t readU16() { uint16_t x; read(&x, 2); return x; } + int16_t readS16() { int16_t x; read(&x, 2); return x; } + uint8_t readU8() { uint8_t x; read(&x, 1); return x; } + bool readBool() { return this->readU8() != 0; } + +protected: + void readNoSizeCheck(void* buffer, size_t size); + + const char* fData; + const char* fPos; + const char* fStop; +}; + +/** \class SkWBuffer + + Light weight class for writing data to a memory block. + The WBuffer is given the buffer to write into, with either a specified size + or no size, in which case no range checking is performed. An empty WBuffer + is legal, in which case no data is ever written, but the relative pos() + is updated. +*/ +class SkWBuffer : SkNoncopyable { +public: + SkWBuffer() : fData(0), fPos(0), fStop(0) {} + SkWBuffer(void* data) { reset(data); } + SkWBuffer(void* data, size_t size) { reset(data, size); } + + void reset(void* data) + { + fData = (char*)data; + fPos = (char*)data; + fStop = 0; // no bounds checking + } + void reset(void* data, size_t size) + { + SkASSERT(data != 0 || size == 0); + fData = (char*)data; + fPos = (char*)data; + fStop = (char*)data + size; + } + + void* data() const { return fData; } + size_t pos() const { return fPos - fData; } + size_t size() const { return fStop - fData; } + bool eof() const { return fPos >= fStop; } + void* skip(size_t size); // return start of skipped data + void write(const void* buffer, size_t size) { if (size) this->writeNoSizeCheck(buffer, size); } + size_t padToAlign4(); + + void writePtr(const void* x) { this->writeNoSizeCheck(&x, sizeof(x)); } + void writeScalar(SkScalar x) { this->writeNoSizeCheck(&x, 4); } + void write32(int32_t x) { this->writeNoSizeCheck(&x, 4); } + void write16(int16_t x) { this->writeNoSizeCheck(&x, 2); } + void write8(int8_t x) { this->writeNoSizeCheck(&x, 1); } + void writeBool(bool x) { this->write8(x); } + +protected: + void writeNoSizeCheck(const void* buffer, size_t size); + + char* fData; + char* fPos; + char* fStop; +}; + +#endif + diff --git a/skia/include/corecg/SkChunkAlloc.h b/skia/include/corecg/SkChunkAlloc.h new file mode 100644 index 0000000..aa4ebde --- /dev/null +++ b/skia/include/corecg/SkChunkAlloc.h @@ -0,0 +1,62 @@ +/* include/corecg/SkChunkAlloc.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkChunkAlloc_DEFINED +#define SkChunkAlloc_DEFINED + +#include "SkTypes.h" + +class SkChunkAlloc : SkNoncopyable { +public: + SkChunkAlloc(size_t minSize); + ~SkChunkAlloc(); + + /** Free up all allocated blocks. This invalidates all returned + pointers. + */ + void reset(); + + /** Reuse all allocated blocks. This invalidates all returned + pointers (like reset) but doesn't necessarily free up all + of the privately allocated blocks. This is more efficient + if you plan to reuse the allocator multiple times. + */ + void reuse(); + + enum AllocFailType { + kReturnNil_AllocFailType, + kThrow_AllocFailType + }; + + void* alloc(size_t bytes, AllocFailType); + void* allocThrow(size_t bytes) { + return this->alloc(bytes, kThrow_AllocFailType); + } + + size_t totalCapacity() const { return fTotalCapacity; } + +private: + struct Block; + Block* fBlock; + size_t fMinSize; + Block* fPool; + size_t fTotalCapacity; + + Block* newBlock(size_t bytes, AllocFailType ftype); +}; + +#endif diff --git a/skia/include/corecg/SkEndian.h b/skia/include/corecg/SkEndian.h new file mode 100644 index 0000000..0897914 --- /dev/null +++ b/skia/include/corecg/SkEndian.h @@ -0,0 +1,99 @@ +/* include/corecg/SkEndian.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkEndian_DEFINED +#define SkEndian_DEFINED + +#include "SkTypes.h" + +/** \file SkEndian.h + + Macros and helper functions for handling 16 and 32 bit values in + big and little endian formats. +*/ + +#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) + #error "can't have both LENDIAN and BENDIAN defined" +#endif + +#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) + #error "need either LENDIAN or BENDIAN defined" +#endif + +/** Swap the two bytes in the low 16bits of the parameters. + e.g. 0x1234 -> 0x3412 +*/ +inline uint16_t SkEndianSwap16(U16CPU value) +{ + SkASSERT(value == (uint16_t)value); + return (uint16_t)((value >> 8) | (value << 8)); +} + +/** Vector version of SkEndianSwap16(), which swaps the + low two bytes of each value in the array. +*/ +inline void SkEndianSwap16s(uint16_t array[], int count) +{ + SkASSERT(count == 0 || array != NULL); + + while (--count >= 0) + { + *array = SkEndianSwap16(*array); + array += 1; + } +} + +/** Reverse all 4 bytes in a 32bit value. + e.g. 0x12345678 -> 0x78563412 +*/ +inline uint32_t SkEndianSwap32(uint32_t value) +{ + return ((value & 0xFF) << 24) | + ((value & 0xFF00) << 8) | + ((value & 0xFF0000) >> 8) | + (value >> 24); +} + +/** Vector version of SkEndianSwap16(), which swaps the + bytes of each value in the array. +*/ +inline void SkEndianSwap32s(uint32_t array[], int count) +{ + SkASSERT(count == 0 || array != NULL); + + while (--count >= 0) + { + *array = SkEndianSwap32(*array); + array += 1; + } +} + +#ifdef SK_CPU_LENDIAN + #define SkEndian_SwapBE16(n) SkEndianSwap16(n) + #define SkEndian_SwapBE32(n) SkEndianSwap32(n) + #define SkEndian_SwapLE16(n) (n) + #define SkEndian_SwapLE32(n) (n) +#else // SK_CPU_BENDIAN + #define SkEndian_SwapBE16(n) (n) + #define SkEndian_SwapBE32(n) (n) + #define SkEndian_SwapLE16(n) SkEndianSwap16(n) + #define SkEndian_SwapLE32(n) SkEndianSwap32(n) +#endif + + +#endif + diff --git a/skia/include/corecg/SkFDot6.h b/skia/include/corecg/SkFDot6.h new file mode 100644 index 0000000..57d4516 --- /dev/null +++ b/skia/include/corecg/SkFDot6.h @@ -0,0 +1,68 @@ +/* include/corecg/SkFDot6.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkFDot6_DEFINED +#define SkFDot6_DEFINED + +#include "SkMath.h" + +typedef int32_t SkFDot6; + +#define SK_FDot61 (64) +#define SK_FDot6Half (32) + +#ifdef SK_DEBUG + inline SkFDot6 SkIntToFDot6(S16CPU x) + { + SkASSERT(SkToS16(x) == x); + return x << 6; + } +#else + #define SkIntToFDot6(x) ((x) << 6) +#endif + +#define SkFDot6Floor(x) ((x) >> 6) +#define SkFDot6Ceil(x) (((x) + 63) >> 6) +#define SkFDot6Round(x) (((x) + 32) >> 6) + +#define SkFixedToFDot6(x) ((x) >> 10) + +inline SkFixed SkFDot6ToFixed(SkFDot6 x) +{ + SkASSERT((x << 10 >> 10) == x); + + return x << 10; +} + +#ifdef SK_SCALAR_IS_FLOAT + #define SkScalarToFDot6(x) (SkFDot6)((x) * 64) +#else + #define SkScalarToFDot6(x) ((x) >> 10) +#endif + +inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) +{ + SkASSERT(b != 0); + + if (a == (int16_t)a) + return (a << 16) / b; + else + return SkFixedDiv(a, b); +} + +#endif + diff --git a/skia/include/corecg/SkFixed.h b/skia/include/corecg/SkFixed.h new file mode 100644 index 0000000..e77d455 --- /dev/null +++ b/skia/include/corecg/SkFixed.h @@ -0,0 +1,254 @@ +/* include/corecg/SkFixed.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkFixed_DEFINED +#define SkFixed_DEFINED + +#include "SkTypes.h" + +/** \file SkFixed.h + + Types and macros for 16.16 fixed point +*/ + +/** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point +*/ +typedef int32_t SkFixed; +#define SK_Fixed1 (1 << 16) +#define SK_FixedHalf (1 << 15) +#define SK_FixedMax (0x7FFFFFFF) +#define SK_FixedMin (0x1) +#define SK_FixedNaN ((int) 0x80000000) +#define SK_FixedPI (0x3243F) +#define SK_FixedSqrt2 (92682) +#define SK_FixedTanPIOver8 (0x6A0A) +#define SK_FixedRoot2Over2 (0xB505) + +#ifdef SK_CAN_USE_FLOAT + #define SkFixedToFloat(x) ((x) * 1.5258789e-5f) + #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) + + #define SkFixedToDouble(x) ((x) * 1.5258789e-5) + #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) +#endif + +/** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point +*/ +typedef int32_t SkFract; +#define SK_Fract1 (1 << 30) +#define Sk_FracHalf (1 << 29) +#define SK_FractPIOver180 (0x11DF46A) + +#ifdef SK_CAN_USE_FLOAT + #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) + #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) +#endif + +/** Converts an integer to a SkFixed, asserting that the result does not overflow + a 32 bit signed integer +*/ +#ifdef SK_DEBUG + inline SkFixed SkIntToFixed(int n) + { + SkASSERT(n >= -32768 && n <= 32767); + return n << 16; + } +#else + // force the cast to SkFixed to ensure that the answer is signed (like the debug version) + #define SkIntToFixed(n) (SkFixed)((n) << 16) +#endif + +/** Converts a SkFixed to a SkFract, asserting that the result does not overflow + a 32 bit signed integer +*/ +#ifdef SK_DEBUG + inline SkFract SkFixedToFract(SkFixed x) + { + SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1); + return x << 14; + } +#else + #define SkFixedToFract(x) ((x) << 14) +#endif + +/** Returns the signed fraction of a SkFixed +*/ +inline SkFixed SkFixedFraction(SkFixed x) +{ + SkFixed mask = x >> 31 << 16; + return (x & 0xFFFF) | mask; +} + +/** Converts a SkFract to a SkFixed +*/ +#define SkFractToFixed(x) ((x) >> 14) +/** Round a SkFixed to an integer +*/ +#define SkFixedRound(x) (((x) + SK_FixedHalf) >> 16) +#define SkFixedCeil(x) (((x) + SK_Fixed1 - 1) >> 16) +#define SkFixedFloor(x) ((x) >> 16) +#define SkFixedAbs(x) SkAbs32(x) +#define SkFixedAve(a, b) (((a) + (b)) >> 1) + +SkFixed SkFixedMul_portable(SkFixed, SkFixed); +SkFract SkFractMul_portable(SkFract, SkFract); +inline SkFixed SkFixedSquare_portable(SkFixed value) +{ + uint32_t a = SkAbs32(value); + uint32_t ah = a >> 16; + uint32_t al = a & 0xFFFF; + return ah * a + al * ah + (al * al >> 16); +} + +#define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) +SkFixed SkFixedDivInt(int32_t numer, int32_t denom); +SkFixed SkFixedMod(SkFixed numer, SkFixed denom); +#define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16) +SkFixed SkFixedFastInvert(SkFixed n); +#define SkFixedSqrt(n) SkSqrtBits(n, 23) +SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y) +int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound + +#define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30) +#define SkFractSqrt(n) SkSqrtBits(n, 30) + +SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull); +#define SkFixedSin(radians) SkFixedSinCos(radians, NULL) +inline SkFixed SkFixedCos(SkFixed radians) +{ + SkFixed cosValue; + (void)SkFixedSinCos(radians, &cosValue); + return cosValue; +} +SkFixed SkFixedTan(SkFixed radians); +SkFixed SkFixedASin(SkFixed); +SkFixed SkFixedACos(SkFixed); +SkFixed SkFixedATan2(SkFixed y, SkFixed x); +SkFixed SkFixedExp(SkFixed); +SkFixed SkFixedLog(SkFixed); + +#define SK_FixedNearlyZero (SK_Fixed1 >> 12) + +inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) +{ + SkASSERT(tolerance > 0); + return SkAbs32(x) < tolerance; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// Now look for ASM overrides for our portable versions (should consider putting this in its own file) + +#ifdef SkLONGLONG + inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) + { + return (SkFixed)((SkLONGLONG)a * b >> 16); + } + inline SkFract SkFractMul_longlong(SkFract a, SkFract b) + { + return (SkFixed)((SkLONGLONG)a * b >> 30); + } + inline SkFixed SkFixedSquare_longlong(SkFixed value) + { + return (SkFixed)((SkLONGLONG)value * value >> 16); + } + #define SkFixedMul(a,b) SkFixedMul_longlong(a,b) + #define SkFractMul(a,b) SkFractMul_longlong(a,b) + #define SkFixedSquare(a) SkFixedSquare_longlong(a) +#endif + +#if defined(__arm__) && !defined(__thumb__) + /* This guy does not handle NaN or other obscurities, but is faster than + than (int)(x*65536) when we only have software floats + */ + inline SkFixed SkFloatToFixed_arm(float x) + { + register int32_t y, z; + asm("movs %1, %3, lsl #1 \n" + "mov %2, #0x8E \n" + "sub %1, %2, %1, lsr #24 \n" + "mov %2, %3, lsl #8 \n" + "orr %2, %2, #0x80000000 \n" + "mov %1, %2, lsr %1 \n" + "rsbcs %1, %1, #0 \n" + : "=r"(x), "=&r"(y), "=&r"(z) + : "r"(x) + : "cc" + ); + return y; + } + inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) + { + register int32_t t; + asm("smull %0, %2, %1, %3 \n" + "mov %0, %0, lsr #16 \n" + "orr %0, %0, %2, lsl #16 \n" + : "=r"(x), "=&r"(y), "=r"(t) + : "r"(x), "1"(y) + : + ); + return x; + } + inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a) + { + register int32_t t; + asm("smull %0, %3, %1, %4 \n" + "add %0, %2, %0, lsr #16 \n" + "add %0, %0, %3, lsl #16 \n" + : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t) + : "%r"(x), "1"(y), "2"(a) + : + ); + return x; + } + inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y) + { + register int32_t t; + asm("smull %0, %2, %1, %3 \n" + "mov %0, %0, lsr #30 \n" + "orr %0, %0, %2, lsl #2 \n" + : "=r"(x), "=&r"(y), "=r"(t) + : "r"(x), "1"(y) + : + ); + return x; + } + #undef SkFixedMul + #undef SkFractMul + #define SkFixedMul(x, y) SkFixedMul_arm(x, y) + #define SkFractMul(x, y) SkFractMul_arm(x, y) + #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a) + + #undef SkFloatToFixed + #define SkFloatToFixed(x) SkFloatToFixed_arm(x) +#endif + +/////////////////////// Now define our macros to the portable versions if they weren't overridden + +#ifndef SkFixedSquare + #define SkFixedSquare(x) SkFixedSquare_portable(x) +#endif +#ifndef SkFixedMul + #define SkFixedMul(x, y) SkFixedMul_portable(x, y) +#endif +#ifndef SkFractMul + #define SkFractMul(x, y) SkFractMul_portable(x, y) +#endif +#ifndef SkFixedMulAdd + #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) +#endif + +#endif diff --git a/skia/include/corecg/SkFloatingPoint.h b/skia/include/corecg/SkFloatingPoint.h new file mode 100644 index 0000000..b7c0435 --- /dev/null +++ b/skia/include/corecg/SkFloatingPoint.h @@ -0,0 +1,65 @@ +/* include/corecg/SkFloatingPoint.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkFloatingPoint_DEFINED +#define SkFloatingPoint_DEFINED + +#include "SkTypes.h" + +#ifdef SK_CAN_USE_FLOAT + +#include <math.h> +#include <float.h> + +#ifdef SK_BUILD_FOR_WINCE + #define sk_float_sqrt(x) (float)::sqrt(x) + #define sk_float_sin(x) (float)::sin(x) + #define sk_float_cos(x) (float)::cos(x) + #define sk_float_tan(x) (float)::tan(x) + #define sk_float_acos(x) (float)::acos(x) + #define sk_float_asin(x) (float)::asin(x) + #define sk_float_atan2(y,x) (float)::atan2(y,x) + #define sk_float_abs(x) (float)::fabs(x) + #define sk_float_mod(x,y) (float)::fmod(x,y) + #define sk_float_exp(x) (float)::exp(x) + #define sk_float_log(x) (float)::log(x) + #define sk_float_floor(x) (float)::floor(x) + #define sk_float_ceil(x) (float)::ceil(x) +#else + #define sk_float_sqrt(x) sqrtf(x) + #define sk_float_sin(x) sinf(x) + #define sk_float_cos(x) cosf(x) + #define sk_float_tan(x) tanf(x) + #define sk_float_floor(x) floorf(x) + #define sk_float_ceil(x) ceilf(x) +#ifdef SK_BUILD_FOR_MAC + #define sk_float_acos(x) acos(x) + #define sk_float_asin(x) asin(x) +#else + #define sk_float_acos(x) acosf(x) + #define sk_float_asin(x) asinf(x) +#endif + #define sk_float_atan2(y,x) atan2f(y,x) + #define sk_float_abs(x) fabsf(x) + #define sk_float_mod(x,y) fmodf(x,y) + #define sk_float_exp(x) expf(x) + #define sk_float_log(x) logf(x) + #define sk_float_isNaN(x) _isnan(x) +#endif + +#endif +#endif diff --git a/skia/include/corecg/SkInterpolator.h b/skia/include/corecg/SkInterpolator.h new file mode 100644 index 0000000..d98196d --- /dev/null +++ b/skia/include/corecg/SkInterpolator.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkInterpolator_DEFINED +#define SkInterpolator_DEFINED + +#include "SkScalar.h" + +class SkInterpolatorBase : SkNoncopyable { +public: + enum Result { + kNormal_Result, + kFreezeStart_Result, + kFreezeEnd_Result + }; +protected: + SkInterpolatorBase(); + ~SkInterpolatorBase(); +public: + void reset(int elemCount, int frameCount); + + /** Return the start and end time for this interpolator. + If there are no key frames, return false. + @param startTime If not null, returns the time (in milliseconds) of the + first keyframe. If there are no keyframes, this param + is ignored (left unchanged). + @param endTime If not null, returns the time (in milliseconds) of the + last keyframe. If there are no keyframes, this parameter + is ignored (left unchanged). + @return True if there are key frames, or false if there are none. + */ + bool getDuration(SkMSec* startTime, SkMSec* endTime) const; + + + /** Set the whether the repeat is mirrored. + @param mirror If true, the odd repeats interpolate from the last key + frame and the first. + */ + void setMirror(bool mirror) { + fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror); + } + + /** Set the repeat count. The repeat count may be fractional. + @param repeatCount Multiplies the total time by this scalar. + */ + void setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; } + + /** Set the whether the repeat is mirrored. + @param reset If true, the odd repeats interpolate from the last key + frame and the first. + */ + void setReset(bool reset) { + fFlags = SkToU8((fFlags & ~kReset) | (int)reset); + } + + Result timeToT(SkMSec time, SkScalar* T, int* index, SkBool* exact) const; + +protected: + enum Flags { + kMirror = 1, + kReset = 2, + kHasBlend = 4 + }; + static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, + SkMSec nextTime, const SkScalar blend[4] = NULL); + int16_t fFrameCount; + uint8_t fElemCount; + uint8_t fFlags; + SkScalar fRepeat; + struct SkTimeCode { + SkMSec fTime; + SkScalar fBlend[4]; + }; + SkTimeCode* fTimes; // pointer into fStorage + void* fStorage; +#ifdef SK_DEBUG + SkTimeCode(* fTimesArray)[10]; +#endif +}; + +class SkInterpolator : public SkInterpolatorBase { +public: + SkInterpolator(); + SkInterpolator(int elemCount, int frameCount); + void reset(int elemCount, int frameCount); + + /** Add or replace a key frame, copying the values[] data into the + interpolator. + @param index The index of this frame (frames must be ordered by time) + @param time The millisecond time for this frame + @param values The array of values [elemCount] for this frame. The data + is copied into the interpolator. + @param blend A positive scalar specifying how to blend between this + and the next key frame. [0...1) is a cubic lag/log/lag + blend (slow to change at the beginning and end) + 1 is a linear blend (default) + */ + bool setKeyFrame(int index, SkMSec time, const SkScalar values[], + const SkScalar blend[4] = NULL); + + /** Return the computed values given the specified time. Return whether + those values are the result of pinning to either the first + (kFreezeStart) or last (kFreezeEnd), or from interpolated the two + nearest key values (kNormal). + @param time The time to sample (in milliseconds) + @param (may be null) where to write the computed values. + */ + Result timeToValues(SkMSec time, SkScalar values[] = NULL) const; + + SkDEBUGCODE(static void UnitTest();) +private: + SkScalar* fValues; // pointer into fStorage +#ifdef SK_DEBUG + SkScalar(* fScalarsArray)[10]; +#endif + typedef SkInterpolatorBase INHERITED; +}; + +/** Given all the parameters are [0...1], apply the cubic specified by (0,0) + (bx,by) (cx,cy) (1,1) to value, returning the answer, also [0...1]. +*/ +SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, + SkScalar cx, SkScalar cy); + +#endif + diff --git a/skia/include/corecg/SkMath.h b/skia/include/corecg/SkMath.h new file mode 100644 index 0000000..7519dee --- /dev/null +++ b/skia/include/corecg/SkMath.h @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkMath_DEFINED +#define SkMath_DEFINED + +#include "SkTypes.h" + +//! Returns the number of leading zero bits (0...32) +int SkCLZ_portable(uint32_t); + +/** Computes the 64bit product of a * b, and then shifts the answer down by + shift bits, returning the low 32bits. shift must be [0..63] + e.g. to perform a fixedmul, call SkMulShift(a, b, 16) +*/ +int32_t SkMulShift(int32_t a, int32_t b, unsigned shift); + +/** Computes numer1 * numer2 / denom in full 64 intermediate precision. + It is an error for denom to be 0. There is no special handling if + the result overflows 32bits. +*/ +int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom); + +/** Computes (numer1 << shift) / denom in full 64 intermediate precision. + It is an error for denom to be 0. There is no special handling if + the result overflows 32bits. +*/ +int32_t SkDivBits(int32_t numer, int32_t denom, int shift); + +/** Return the integer square root of value, with a bias of bitBias +*/ +int32_t SkSqrtBits(int32_t value, int bitBias); + +/** Return the integer square root of n, treated as a SkFixed (16.16) +*/ +#define SkSqrt32(n) SkSqrtBits(n, 15) + +/** Return the integer cube root of value, with a bias of bitBias + */ +int32_t SkCubeRootBits(int32_t value, int bitBias); + +/** Returns -1 if n < 0, else returns 0 +*/ +#define SkExtractSign(n) ((int32_t)(n) >> 31) + +/** If sign == -1, returns -n, else sign must be 0, and returns n. + Typically used in conjunction with SkExtractSign(). +*/ +static inline int32_t SkApplySign(int32_t n, int32_t sign) { + SkASSERT(sign == 0 || sign == -1); + return (n ^ sign) - sign; +} + +/** Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches) +*/ +static inline int SkClampPos(int value) { + return value & ~(value >> 31); +} + +/** Given an integer and a positive (max) integer, return the value + pinned against 0 and max, inclusive. + Note: only works as long as max - value doesn't wrap around + @param value The value we want returned pinned between [0...max] + @param max The positive max value + @return 0 if value < 0, max if value > max, else value +*/ +static inline int SkClampMax(int value, int max) { + // ensure that max is positive + SkASSERT(max >= 0); + // ensure that if value is negative, max - value doesn't wrap around + SkASSERT(value >= 0 || max - value > 0); + +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < 0) { + value = 0; + } + if (value > max) { + value = max; + } + return value; +#else + + int diff = max - value; + // clear diff if diff is positive + diff &= diff >> 31; + + // clear the result if value < 0 + return (value + diff) & ~(value >> 31); +#endif +} + +/** Given a positive value and a positive max, return the value + pinned against max. + Note: only works as long as max - value doesn't wrap around + @return max if value >= max, else value +*/ +static inline unsigned SkClampUMax(unsigned value, unsigned max) { +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value > max) { + value = max; + } + return value; +#else + int diff = max - value; + // clear diff if diff is positive + diff &= diff >> 31; + + return value + diff; +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +#if defined(__arm__) && !defined(__thumb__) + #define SkCLZ(x) __builtin_clz(x) +#endif + +#ifndef SkCLZ + #define SkCLZ(x) SkCLZ_portable(x) +#endif + +/////////////////////////////////////////////////////////////////////////////// + +/** Returns the smallest power-of-2 that is >= the specified value. If value + is already a power of 2, then it is returned unchanged. It is undefined + if value is <= 0. +*/ +static inline int SkNextPow2(int value) { + SkASSERT(value > 0); + return 1 << (32 - SkCLZ(value - 1)); +} + +/** Returns the log2 of the specified value, were that value to be rounded up + to the next power of 2. It is undefined to pass 0. Examples: + SkNextLog2(1) -> 0 + SkNextLog2(2) -> 1 + SkNextLog2(3) -> 2 + SkNextLog2(4) -> 2 + SkNextLog2(5) -> 3 +*/ +static inline int SkNextLog2(uint32_t value) { + SkASSERT(value != 0); + return 32 - SkCLZ(value - 1); +} + +/////////////////////////////////////////////////////////////////////////////// + +/** SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t. + With this requirement, we can generate faster instructions on some + architectures. +*/ +#if defined(__arm__) && !defined(__thumb__) + static inline int32_t SkMulS16(S16CPU x, S16CPU y) { + SkASSERT((int16_t)x == x); + SkASSERT((int16_t)y == y); + int32_t product; + asm("smulbb %0, %1, %2 \n" + : "=r"(product) + : "r"(x), "r"(y) + : + ); + return product; + } +#else + #ifdef SK_DEBUG + static inline int32_t SkMulS16(S16CPU x, S16CPU y) { + SkASSERT((int16_t)x == x); + SkASSERT((int16_t)y == y); + return x * y; + } + #else + #define SkMulS16(x, y) ((x) * (y)) + #endif +#endif + +/** Return a*b/255, truncating away any fractional bits. Only valid if both + a and b are 0..255 +*/ +static inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) { + SkASSERT((uint8_t)a == a); + SkASSERT((uint8_t)b == b); + unsigned prod = SkMulS16(a, b) + 1; + return (prod + (prod >> 8)) >> 8; +} + +/** Return a*b/255, rounding any fractional bits. Only valid if both + a and b are 0..255 + */ +static inline U8CPU SkMulDiv255Round(U8CPU a, U8CPU b) { + SkASSERT((uint8_t)a == a); + SkASSERT((uint8_t)b == b); + unsigned prod = SkMulS16(a, b) + 128; + return (prod + (prod >> 8)) >> 8; +} + +/** Return a*b/((1 << shift) - 1), rounding any fractional bits. + Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8 +*/ +static unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) { + SkASSERT(a <= 32767); + SkASSERT(b <= 32767); + SkASSERT(shift > 0 && shift <= 8); + unsigned prod = SkMulS16(a, b) + (1 << (shift - 1)); + return (prod + (prod >> shift)) >> shift; +} + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG + class SkMath { + public: + static void UnitTest(); + }; +#endif + +#endif + diff --git a/skia/include/corecg/SkMatrix.h b/skia/include/corecg/SkMatrix.h new file mode 100644 index 0000000..60fdd42 --- /dev/null +++ b/skia/include/corecg/SkMatrix.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkMatrix_DEFINED +#define SkMatrix_DEFINED + +#include "SkRect.h" + +/** \class SkMatrix + + The SkMatrix class holds a 3x3 matrix for transforming coordinates. + SkMatrix does not have a constructor, so it must be explicitly initialized + using either reset() - to construct an identity matrix, or one of the set + functions (e.g. setTranslate, setRotate, etc.). +*/ +class SkMatrix { +public: + /** Enum of bit fields for the mask return by getType(). + Use this to identify the complexity of the matrix. + */ + enum TypeMask { + kIdentity_Mask = 0, + kTranslate_Mask = 0x01, //!< set if the matrix has translation + kScale_Mask = 0x02, //!< set if the matrix has X or Y scale + kAffine_Mask = 0x04, //!< set if the matrix skews or rotates + kPerspective_Mask = 0x08 //!< set if the matrix is in perspective + }; + + /** Returns a mask bitfield describing the types of transformations + that the matrix will perform. This information is used by routines + like mapPoints, to optimize its inner loops to only perform as much + arithmetic as is necessary. + */ + TypeMask getType() const { + if (fTypeMask & kUnknown_Mask) { + fTypeMask = this->computeTypeMask(); + } + // only return the public masks + return (TypeMask)(fTypeMask & 0xF); + } + + /** Returns true if the matrix is identity. + */ + bool isIdentity() const { + return this->getType() == 0; + } + + /** Returns true if will map a rectangle to another rectangle. This can be + true if the matrix is identity, scale-only, or rotates a multiple of + 90 degrees. + */ + bool rectStaysRect() const { + if (fTypeMask & kUnknown_Mask) { + fTypeMask = this->computeTypeMask(); + } + return (fTypeMask & kRectStaysRect_Mask) != 0; + } + + enum { + kMScaleX, + kMSkewX, + kMTransX, + kMSkewY, + kMScaleY, + kMTransY, + kMPersp0, + kMPersp1, + kMPersp2 + }; + + SkScalar operator[](int index) const { + SkASSERT((unsigned)index < 9); + return fMat[index]; + } + + SkScalar get(int index) const { + SkASSERT((unsigned)index < 9); + return fMat[index]; + } + + SkScalar getScaleX() const { return fMat[kMScaleX]; } + SkScalar getScaleY() const { return fMat[kMScaleY]; } + SkScalar getSkewY() const { return fMat[kMSkewY]; } + SkScalar getSkewX() const { return fMat[kMSkewX]; } + SkScalar getTranslateX() const { return fMat[kMTransX]; } + SkScalar getTranslateY() const { return fMat[kMTransY]; } + SkScalar getPerspX() const { return fMat[kMPersp0]; } + SkScalar getPerspY() const { return fMat[kMPersp1]; } + + void set(int index, SkScalar value) { + SkASSERT((unsigned)index < 9); + fMat[index] = value; + this->setTypeMask(kUnknown_Mask); + } + + void setScaleX(SkScalar v) { this->set(kMScaleX, v); } + void setScaleY(SkScalar v) { this->set(kMScaleY, v); } + void setSkewY(SkScalar v) { this->set(kMSkewY, v); } + void setSkewX(SkScalar v) { this->set(kMSkewX, v); } + void setTranslateX(SkScalar v) { this->set(kMTransX, v); } + void setTranslateY(SkScalar v) { this->set(kMTransY, v); } + void setPerspX(SkScalar v) { this->set(kMPersp0, v); } + void setPerspY(SkScalar v) { this->set(kMPersp1, v); } + + /** Set the matrix to identity + */ + void reset(); + + /** Set the matrix to translate by (dx, dy). + */ + void setTranslate(SkScalar dx, SkScalar dy); + /** Set the matrix to scale by sx and sy, with a pivot point at (px, py). + The pivot point is the coordinate that should remain unchanged by the + specified transformation. + */ + void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); + /** Set the matrix to scale by sx and sy. + */ + void setScale(SkScalar sx, SkScalar sy); + /** Set the matrix to rotate by the specified number of degrees, with a + pivot point at (px, py). The pivot point is the coordinate that should + remain unchanged by the specified transformation. + */ + void setRotate(SkScalar degrees, SkScalar px, SkScalar py); + /** Set the matrix to rotate about (0,0) by the specified number of degrees. + */ + void setRotate(SkScalar degrees); + /** Set the matrix to rotate by the specified sine and cosine values, with + a pivot point at (px, py). The pivot point is the coordinate that + should remain unchanged by the specified transformation. + */ + void setSinCos(SkScalar sinValue, SkScalar cosValue, + SkScalar px, SkScalar py); + /** Set the matrix to rotate by the specified sine and cosine values. + */ + void setSinCos(SkScalar sinValue, SkScalar cosValue); + /** Set the matrix to skew by sx and sy, with a pivot point at (px, py). + The pivot point is the coordinate that should remain unchanged by the + specified transformation. + */ + void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); + /** Set the matrix to skew by sx and sy. + */ + void setSkew(SkScalar kx, SkScalar ky); + /** Set the matrix to the concatenation of the two specified matrices, + returning true if the the result can be represented. Either of the + two matrices may also be the target matrix. *this = a * b; + */ + bool setConcat(const SkMatrix& a, const SkMatrix& b); + + /** Preconcats the matrix with the specified translation. + M' = M * T(dx, dy) + */ + bool preTranslate(SkScalar dx, SkScalar dy); + /** Preconcats the matrix with the specified scale. + M' = M * S(sx, sy, px, py) + */ + bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); + /** Preconcats the matrix with the specified scale. + M' = M * S(sx, sy) + */ + bool preScale(SkScalar sx, SkScalar sy); + /** Preconcats the matrix with the specified rotation. + M' = M * R(degrees, px, py) + */ + bool preRotate(SkScalar degrees, SkScalar px, SkScalar py); + /** Preconcats the matrix with the specified rotation. + M' = M * R(degrees) + */ + bool preRotate(SkScalar degrees); + /** Preconcats the matrix with the specified skew. + M' = M * K(kx, ky, px, py) + */ + bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); + /** Preconcats the matrix with the specified skew. + M' = M * K(kx, ky) + */ + bool preSkew(SkScalar kx, SkScalar ky); + /** Preconcats the matrix with the specified matrix. + M' = M * other + */ + bool preConcat(const SkMatrix& other); + + /** Postconcats the matrix with the specified translation. + M' = T(dx, dy) * M + */ + bool postTranslate(SkScalar dx, SkScalar dy); + /** Postconcats the matrix with the specified scale. + M' = S(sx, sy, px, py) * M + */ + bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); + /** Postconcats the matrix with the specified scale. + M' = S(sx, sy) * M + */ + bool postScale(SkScalar sx, SkScalar sy); + /** Postconcats the matrix by dividing it by the specified integers. + M' = S(1/divx, 1/divy, 0, 0) * M + */ + bool postIDiv(int divx, int divy); + /** Postconcats the matrix with the specified rotation. + M' = R(degrees, px, py) * M + */ + bool postRotate(SkScalar degrees, SkScalar px, SkScalar py); + /** Postconcats the matrix with the specified rotation. + M' = R(degrees) * M + */ + bool postRotate(SkScalar degrees); + /** Postconcats the matrix with the specified skew. + M' = K(kx, ky, px, py) * M + */ + bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); + /** Postconcats the matrix with the specified skew. + M' = K(kx, ky) * M + */ + bool postSkew(SkScalar kx, SkScalar ky); + /** Postconcats the matrix with the specified matrix. + M' = other * M + */ + bool postConcat(const SkMatrix& other); + + enum ScaleToFit { + /** + * Scale in X and Y independently, so that src matches dst exactly. + * This may change the aspect ratio of the src. + */ + kFill_ScaleToFit, + /** + * Compute a scale that will maintain the original src aspect ratio, + * but will also ensure that src fits entirely inside dst. At least one + * axis (X or Y) will fit exactly. kStart aligns the result to the + * left and top edges of dst. + */ + kStart_ScaleToFit, + /** + * Compute a scale that will maintain the original src aspect ratio, + * but will also ensure that src fits entirely inside dst. At least one + * axis (X or Y) will fit exactly. The result is centered inside dst. + */ + kCenter_ScaleToFit, + /** + * Compute a scale that will maintain the original src aspect ratio, + * but will also ensure that src fits entirely inside dst. At least one + * axis (X or Y) will fit exactly. kEnd aligns the result to the + * right and bottom edges of dst. + */ + kEnd_ScaleToFit + }; + + /** Set the matrix to the scale and translate values that map the source + rectangle to the destination rectangle, returning true if the the result + can be represented. + @param src the source rectangle to map from. + @param dst the destination rectangle to map to. + @param stf the ScaleToFit option + @return true if the matrix can be represented by the rectangle mapping. + */ + bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf); + + /** Set the matrix such that the specified src points would map to the + specified dst points. count must be within [0..4]. + @param src The array of src points + @param dst The array of dst points + @param count The number of points to use for the transformation + @return true if the matrix was set to the specified transformation + */ + bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count); + + /** If this matrix can be inverted, return true and if inverse is not null, + set inverse to be the inverse of this matrix. If this matrix cannot be + inverted, ignore inverse and return false + */ + bool invert(SkMatrix* inverse) const; + + /** Apply this matrix to the array of points specified by src, and write + the transformed points into the array of points specified by dst. + dst[] = M * src[] + @param dst Where the transformed coordinates are written. It must + contain at least count entries + @param src The original coordinates that are to be transformed. It + must contain at least count entries + @param count The number of points in src to read, and then transform + into dst. + */ + void mapPoints(SkPoint dst[], const SkPoint src[], int count) const; + + /** Apply this matrix to the array of points, overwriting it with the + transformed values. + dst[] = M * pts[] + @param pts The points to be transformed. It must contain at least + count entries + @param count The number of points in pts. + */ + void mapPoints(SkPoint pts[], int count) const { + this->mapPoints(pts, pts, count); + } + + void mapXY(SkScalar x, SkScalar y, SkPoint* result) const { + SkASSERT(result); + this->getMapXYProc()(*this, x, y, result); + } + + /** Apply this matrix to the array of vectors specified by src, and write + the transformed vectors into the array of vectors specified by dst. + This is similar to mapPoints, but ignores any translation in the matrix. + @param dst Where the transformed coordinates are written. It must + contain at least count entries + @param src The original coordinates that are to be transformed. It + must contain at least count entries + @param count The number of vectors in src to read, and then transform + into dst. + */ + void mapVectors(SkVector dst[], const SkVector src[], int count) const; + + /** Apply this matrix to the array of vectors specified by src, and write + the transformed vectors into the array of vectors specified by dst. + This is similar to mapPoints, but ignores any translation in the matrix. + @param vecs The vectors to be transformed. It must contain at least + count entries + @param count The number of vectors in vecs. + */ + void mapVectors(SkVector vecs[], int count) const { + this->mapVectors(vecs, vecs, count); + } + + /** Apply this matrix to the src rectangle, and write the transformed + rectangle into dst. This is accomplished by transforming the 4 corners + of src, and then setting dst to the bounds of those points. + @param dst Where the transformed rectangle is written. + @param src The original rectangle to be transformed. + @return the result of calling rectStaysRect() + */ + bool mapRect(SkRect* dst, const SkRect& src) const; + + /** Apply this matrix to the rectangle, and write the transformed rectangle + back into it. This is accomplished by transforming the 4 corners of + rect, and then setting it to the bounds of those points + @param rect The rectangle to transform. + @return the result of calling rectStaysRect() + */ + bool mapRect(SkRect* rect) const { + return this->mapRect(rect, *rect); + } + + /** Return the mean radius of a circle after it has been mapped by + this matrix. NOTE: in perspective this value assumes the circle + has its center at the origin. + */ + SkScalar mapRadius(SkScalar radius) const; + + typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y, + SkPoint* result); + + static MapXYProc GetMapXYProc(TypeMask mask) { + SkASSERT((mask & ~kAllMasks) == 0); + return gMapXYProcs[mask & kAllMasks]; + } + + MapXYProc getMapXYProc() const { + return GetMapXYProc(this->getType()); + } + + typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[], + const SkPoint src[], int count); + + static MapPtsProc GetMapPtsProc(TypeMask mask) { + SkASSERT((mask & ~kAllMasks) == 0); + return gMapPtsProcs[mask & kAllMasks]; + } + + MapPtsProc getMapPtsProc() const { + return GetMapPtsProc(this->getType()); + } + + /** If the matrix can be stepped in X (not complex perspective) + then return true and if step[XY] is not null, return the step[XY] value. + If it cannot, return false and ignore step. + */ + bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; + + friend bool operator==(const SkMatrix& a, const SkMatrix& b) { + return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0; + } + + friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { + return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0; + } + + void dump() const; + +#ifdef SK_DEBUG + /** @cond UNIT_TEST */ + + static void UnitTest(); + /** @endcond */ +#endif + +private: + enum { + /** Set if the matrix will map a rectangle to another rectangle. This + can be true if the matrix is scale-only, or rotates a multiple of + 90 degrees. This bit is not set if the matrix is identity. + + This bit will be set on identity matrices + */ + kRectStaysRect_Mask = 0x10, + + kUnknown_Mask = 0x80, + + kAllMasks = kTranslate_Mask | + kScale_Mask | + kAffine_Mask | + kPerspective_Mask | + kRectStaysRect_Mask + }; + + SkScalar fMat[9]; + mutable uint8_t fTypeMask; + + uint8_t computeTypeMask() const; + + void setTypeMask(int mask) { + // allow kUnknown or a valid mask + SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask); + fTypeMask = SkToU8(mask); + } + + void clearTypeMask(int mask) { + // only allow a valid mask + SkASSERT((mask & kAllMasks) == mask); + fTypeMask &= ~mask; + } + + static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); + static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); + static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); + + static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); + + static const MapXYProc gMapXYProcs[]; + + static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int); + static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); + static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); + static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], + int count); + static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); + static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], + int count); + static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); + + static const MapPtsProc gMapPtsProcs[]; + + friend class SkPerspIter; +}; + +#endif + diff --git a/skia/include/corecg/SkPerspIter.h b/skia/include/corecg/SkPerspIter.h new file mode 100644 index 0000000..1a5d82f --- /dev/null +++ b/skia/include/corecg/SkPerspIter.h @@ -0,0 +1,56 @@ +/* include/corecg/SkPerspIter.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkPerspIter_DEFINED +#define SkPerspIter_DEFINED + +#include "SkMatrix.h" + +class SkPerspIter { +public: + /** Iterate a line through the matrix [x,y] ... [x+count-1, y]. + @param m The matrix we will be iterating a line through + @param x The initial X coordinate to be mapped through the matrix + @param y The initial Y coordinate to be mapped through the matrix + @param count The number of points (x,y) (x+1,y) (x+2,y) ... we will eventually map + */ + SkPerspIter(const SkMatrix& m, SkScalar x, SkScalar y, int count); + + /** Return the buffer of [x,y] fixed point values we will be filling. + This always returns the same value, so it can be saved across calls to + next(). + */ + const SkFixed* getXY() const { return fStorage; } + + /** Return the number of [x,y] pairs that have been filled in the getXY() buffer. + When this returns 0, the iterator is finished. + */ + int next(); + +private: + enum { + kShift = 4, + kCount = (1 << kShift) + }; + const SkMatrix& fMatrix; + SkFixed fStorage[kCount * 2]; + SkFixed fX, fY; + SkScalar fSX, fSY; + int fCount; +}; + +#endif diff --git a/skia/include/corecg/SkPoint.h b/skia/include/corecg/SkPoint.h new file mode 100644 index 0000000..4493ce3 --- /dev/null +++ b/skia/include/corecg/SkPoint.h @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkPoint_DEFINED +#define SkPoint_DEFINED + +#include "SkMath.h" +#include "SkScalar.h" + +/** \struct SkIPoint + + SkIPoint holds two 32 bit integer coordinates +*/ +struct SkIPoint { + int32_t fX, fY; + + /** Set the x and y values of the point. */ + void set(int32_t x, int32_t y) { fX = x; fY = y; } + + /** Rotate the point clockwise, writing the new point into dst + It is legal for dst == this + */ + void rotateCW(SkIPoint* dst) const; + + /** Rotate the point clockwise, writing the new point back into the point + */ + + void rotateCW() { this->rotateCW(this); } + + /** Rotate the point counter-clockwise, writing the new point into dst. + It is legal for dst == this + */ + void rotateCCW(SkIPoint* dst) const; + + /** Rotate the point counter-clockwise, writing the new point back into + the point + */ + void rotateCCW() { this->rotateCCW(this); } + + /** Negate the X and Y coordinates of the point. + */ + void negate() { fX = -fX; fY = -fY; } + + /** Return a new point whose X and Y coordinates are the negative of the + original point's + */ + SkIPoint operator-() const { + SkIPoint neg; + neg.fX = -fX; + neg.fY = -fY; + return neg; + } + + /** Add v's coordinates to this point's */ + void operator+=(const SkIPoint& v) { + fX += v.fX; + fY += v.fY; + } + + /** Subtract v's coordinates from this point's */ + void operator-=(const SkIPoint& v) { + fX -= v.fX; + fY -= v.fY; + } + + /** Returns true if the point's coordinates equal (x,y) */ + bool equals(int32_t x, int32_t y) const { + return fX == x && fY == y; + } + + friend bool operator==(const SkIPoint& a, const SkIPoint& b) { + return a.fX == b.fX && a.fY == b.fY; + } + + friend bool operator!=(const SkIPoint& a, const SkIPoint& b) { + return a.fX != b.fX || a.fY != b.fY; + } + + /** Returns a new point whose coordinates are the difference between + a and b (i.e. a - b) + */ + friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) { + SkIPoint v; + v.set(a.fX - b.fX, a.fY - b.fY); + return v; + } + + /** Returns a new point whose coordinates are the sum of a and b (a + b) + */ + friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) { + SkIPoint v; + v.set(a.fX + b.fX, a.fY + b.fY); + return v; + } + + /** Returns the dot product of a and b, treating them as 2D vectors + */ + static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) { + return a.fX * b.fX + a.fY * b.fY; + } + + /** Returns the cross product of a and b, treating them as 2D vectors + */ + static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) { + return a.fX * b.fY - a.fY * b.fX; + } +}; + +struct SkPoint { + SkScalar fX, fY; + + /** Set the point's X and Y coordinates */ + void set(SkScalar x, SkScalar y) { fX = x; fY = y; } + + /** Set the point's X and Y coordinates by automatically promoting (x,y) to + SkScalar values. + */ + void iset(int32_t x, int32_t y) { + fX = SkIntToScalar(x); + fY = SkIntToScalar(y); + } + + /** Set the point's X and Y coordinates by automatically promoting p's + coordinates to SkScalar values. + */ + void iset(const SkIPoint& p) { + fX = SkIntToScalar(p.fX); + fY = SkIntToScalar(p.fY); + } + + /** Return the euclidian distance from (0,0) to the point + */ + SkScalar length() const { return SkPoint::Length(fX, fY); } + + /** Set the point (vector) to be unit-length in the same direction as it + currently is, and return its old length. If the old length is + degenerately small (nearly zero), do nothing and return false, otherwise + return true. + */ + bool normalize(); + + /** Set the point (vector) to be unit-length in the same direction as the + x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0) + then return false and do nothing, otherwise return true. + */ + bool setNormalize(SkScalar x, SkScalar y); + + /** Scale the point (vector) to have the specified length, and return that + length. If the original length is degenerately small (nearly zero), + do nothing and return false, otherwise return true. + */ + bool setLength(SkScalar length); + + /** Set the point (vector) to have the specified length in the same + direction as (x,y). If the vector (x,y) has a degenerate length + (i.e. nearly 0) then return false and do nothing, otherwise return true. + */ + bool setLength(SkScalar x, SkScalar y, SkScalar length); + + /** Scale the point's coordinates by scale, writing the answer into dst. + It is legal for dst == this. + */ + void scale(SkScalar scale, SkPoint* dst) const; + + /** Scale the point's coordinates by scale, writing the answer back into + the point. + */ + void scale(SkScalar scale) { this->scale(scale, this); } + + /** Rotate the point clockwise by 90 degrees, writing the answer into dst. + It is legal for dst == this. + */ + void rotateCW(SkPoint* dst) const; + + /** Rotate the point clockwise by 90 degrees, writing the answer back into + the point. + */ + void rotateCW() { this->rotateCW(this); } + + /** Rotate the point counter-clockwise by 90 degrees, writing the answer + into dst. It is legal for dst == this. + */ + void rotateCCW(SkPoint* dst) const; + + /** Rotate the point counter-clockwise by 90 degrees, writing the answer + back into the point. + */ + void rotateCCW() { this->rotateCCW(this); } + + /** Negate the point's coordinates + */ + void negate() { + fX = -fX; + fY = -fY; + } + + /** Returns a new point whose coordinates are the negative of the point's + */ + SkPoint operator-() const { + SkPoint neg; + neg.fX = -fX; + neg.fY = -fY; + return neg; + } + + /** Add v's coordinates to the point's + */ + void operator+=(const SkPoint& v) { + fX += v.fX; + fY += v.fY; + } + + /** Subtract v's coordinates from the point's + */ + void operator-=(const SkPoint& v) { + fX -= v.fX; + fY -= v.fY; + } + + /** Returns true if the point's coordinates equal (x,y) + */ + bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; } + + friend bool operator==(const SkPoint& a, const SkPoint& b) { + return a.fX == b.fX && a.fY == b.fY; + } + + friend bool operator!=(const SkPoint& a, const SkPoint& b) { + return a.fX != b.fX || a.fY != b.fY; + } + + /** Returns a new point whose coordinates are the difference between + a's and b's (a - b) + */ + friend SkPoint operator-(const SkPoint& a, const SkPoint& b) { + SkPoint v; + v.set(a.fX - b.fX, a.fY - b.fY); + return v; + } + + /** Returns a new point whose coordinates are the sum of a's and b's (a + b) + */ + friend SkPoint operator+(const SkPoint& a, const SkPoint& b) { + SkPoint v; + v.set(a.fX + b.fX, a.fY + b.fY); + return v; + } + + /** Returns the euclidian distance from (0,0) to (x,y) + */ + static SkScalar Length(SkScalar x, SkScalar y); + + /** Returns the euclidian distance between a and b + */ + static SkScalar Distance(const SkPoint& a, const SkPoint& b) { + return Length(a.fX - b.fX, a.fY - b.fY); + } + + /** Returns the dot product of a and b, treating them as 2D vectors + */ + static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) { + return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY); + } + + /** Returns the cross product of a and b, treating them as 2D vectors + */ + static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) { + return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX); + } +}; + +typedef SkPoint SkVector; + +#endif + diff --git a/skia/include/corecg/SkPostConfig.h b/skia/include/corecg/SkPostConfig.h new file mode 100644 index 0000000..3ca5f75 --- /dev/null +++ b/skia/include/corecg/SkPostConfig.h @@ -0,0 +1,211 @@ +/* include/corecg/SkPostConfig.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkPostConfig_DEFINED +#define SkPostConfig_DEFINED + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE) + #define SK_BUILD_FOR_WIN +#endif + +#if defined(SK_DEBUG) && defined(SK_RELEASE) + #error "cannot define both SK_DEBUG and SK_RELEASE" +#elif !defined(SK_DEBUG) && !defined(SK_RELEASE) + #error "must define either SK_DEBUG or SK_RELEASE" +#endif + +#if defined SK_SUPPORT_UNITTEST && !defined(SK_DEBUG) + #error "can't have unittests without debug" +#endif + +#if defined(SK_SCALAR_IS_FIXED) && defined(SK_SCALAR_IS_FLOAT) + #error "cannot define both SK_SCALAR_IS_FIXED and SK_SCALAR_IS_FLOAT" +#elif !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT) + #ifdef SK_CAN_USE_FLOAT + #define SK_SCALAR_IS_FLOAT + #else + #define SK_SCALAR_IS_FIXED + #endif +#endif + +#if defined(SK_SCALAR_IS_FLOAT) && !defined(SK_CAN_USE_FLOAT) + #define SK_CAN_USE_FLOAT + // we do nothing in the else case: fixed-scalars can have floats or not +#endif + +#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) + #error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN" +#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) + #error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN" +#endif + +// ensure the port has defined all of these, or none of them +#ifdef SK_A32_SHIFT + #if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT) + #error "all or none of the 32bit SHIFT amounts must be defined" + #endif +#else + #if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT) + #error "all or none of the 32bit SHIFT amounts must be defined" + #endif +#endif + +#ifndef SkNEW + #define SkNEW(type_name) new type_name + #define SkNEW_ARGS(type_name, args) new type_name args + #define SkNEW_ARRAY(type_name, count) new type_name[count] + #define SkDELETE(obj) delete obj + #define SkDELETE_ARRAY(array) delete[] array +#endif + +#ifndef SK_CRASH +#if 1 // set to 0 for infinite loop, which can help connecting gdb + #define SK_CRASH() *(int *)(uintptr_t)0xbbadbeef = 0 +#else + #define SK_CRASH() do {} while (true) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_BUILD_FOR_WIN + ////////////////////////////////////////////////////////////////////// + // Begin Chrome-specific changes + // Chrome already defines WIN32_LEAN_AND_MEAN so no need to define it here. + + #include <windows.h> + // End Chrome-specific changes + + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) do { if (!(cond)) DebugBreak(); } while (false) + #endif + + #ifdef SK_BUILD_FOR_WIN32 + #define strcasecmp(a, b) stricmp(a, b) + #define strncasecmp(a, b, c) strnicmp(a, b, c) + #elif defined(SK_BUILD_FOR_WINCE) + #define strcasecmp(a, b) _stricmp(a, b) + #define strncasecmp(a, b, c) _strnicmp(a, b, c) + #endif +#elif defined(SK_BUILD_FOR_MAC) + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) do { if (!(cond)) SK_CRASH(); } while (false) + #endif +#else + #ifdef SK_DEBUG + #include <stdio.h> + #ifndef SK_DEBUGBREAK + #define SK_DEBUGBREAK(cond) do { if (cond) break; \ + SkDebugf("%s:%d: failed assertion \"%s\"\n", \ + __FILE__, __LINE__, #cond); SK_CRASH(); } while (false) + #endif + #endif +#endif + +// stdlib macros + +#if 0 +#if !defined(strlen) && defined(SK_DEBUG) + extern size_t sk_strlen(const char*); + #define strlen(s) sk_strlen(s) +#endif +#ifndef sk_strcpy + #define sk_strcpy(dst, src) strcpy(dst, src) +#endif +#ifndef sk_strchr + #define sk_strchr(s, c) strchr(s, c) +#endif +#ifndef sk_strrchr + #define sk_strrchr(s, c) strrchr(s, c) +#endif +#ifndef sk_strcmp + #define sk_strcmp(s, t) strcmp(s, t) +#endif +#ifndef sk_strncmp + #define sk_strncmp(s, t, n) strncmp(s, t, n) +#endif +#ifndef sk_memcpy + #define sk_memcpy(dst, src, n) memcpy(dst, src, n) +#endif +#ifndef memmove + #define memmove(dst, src, n) memmove(dst, src, n) +#endif +#ifndef sk_memset + #define sk_memset(dst, val, n) memset(dst, val, n) +#endif +#ifndef sk_memcmp + #define sk_memcmp(s, t, n) memcmp(s, t, n) +#endif + +#define sk_strequal(s, t) (!sk_strcmp(s, t)) +#define sk_strnequal(s, t, n) (!sk_strncmp(s, t, n)) +#endif + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef SK_BUILD_FOR_WINCE +#include <string.h> +#include <stdlib.h> +#else +#define _CMNINTRIN_DECLARE_ONLY +#include "cmnintrin.h" +#endif + +#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32 +//#define _CRTDBG_MAP_ALLOC +#ifdef free +#undef free +#endif +#include <crtdbg.h> +#undef free + +#ifdef SK_DEBUGx +#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus) + void * operator new( + size_t cb, + int nBlockUse, + const char * szFileName, + int nLine, + int foo + ); + void * operator new[]( + size_t cb, + int nBlockUse, + const char * szFileName, + int nLine, + int foo + ); + void operator delete( + void *pUserData, + int, const char*, int, int + ); + void operator delete( + void *pUserData + ); + void operator delete[]( void * p ); + #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__, 0) +#else + #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) +#endif + #define new DEBUG_CLIENTBLOCK +#else +#define DEBUG_CLIENTBLOCK +#endif // _DEBUG + +#endif + +#endif + diff --git a/skia/include/corecg/SkPreConfig.h b/skia/include/corecg/SkPreConfig.h new file mode 100644 index 0000000..c651dd4 --- /dev/null +++ b/skia/include/corecg/SkPreConfig.h @@ -0,0 +1,111 @@ +/* include/corecg/SkPreConfig.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkPreConfig_DEFINED +#define SkPreConfig_DEFINED + +#ifdef ANDROID + #define SK_BUILD_FOR_UNIX + #define SkLONGLONG int64_t +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_SYMBIAN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) + + #if defined(PALMOS_SDK_VERSION) + #define SK_BUILD_FOR_PALM + #elif defined(UNDER_CE) + #define SK_BUILD_FOR_WINCE + #elif defined(WIN32) + #define SK_BUILD_FOR_WIN32 + #elif defined(__SYMBIAN32__) + #define SK_BUILD_FOR_WIN32 + #elif defined(linux) + #define SK_BUILD_FOR_UNIX + #else + #define SK_BUILD_FOR_MAC + #endif + +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_DEBUG) && !defined(SK_RELEASE) + #ifdef NDEBUG + #define SK_RELEASE + #else + #define SK_DEBUG + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +// define to blank or change this in SkUserConfig.h as needed +#define SK_RESTRICT __restrict__ + +////////////////////////////////////////////////////////////////////// + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) + #ifndef SK_CAN_USE_FLOAT + #define SK_CAN_USE_FLOAT + #endif + #if !defined(SK_SCALAR_IS_FIXED) && !defined(SK_SCALAR_IS_FLOAT) + #define SK_SCALAR_IS_FIXED + #endif + + #ifndef SkLONGLONG + #ifdef SK_BUILD_FOR_WIN32 + #define SkLONGLONG __int64 + #else + #define SkLONGLONG long long + #endif + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN) + #if defined (__ppc__) || defined(__ppc64__) + #define SK_CPU_BENDIAN + #else + #define SK_CPU_LENDIAN + #endif +#endif + +////////////////////////////////////////////////////////////////////// + +#if (defined(__arm__) && !defined(__thumb__)) || defined(SK_BUILD_FOR_BREW) || defined(SK_BUILD_FOR_WINCE) || (defined(SK_BUILD_FOR_SYMBIAN) && !defined(__MARM_THUMB__)) + /* e.g. the ARM instructions have conditional execution, making tiny branches cheap */ + #define SK_CPU_HAS_CONDITIONAL_INSTR +#endif + +////////////////////////////////////////////////////////////////////// +// Conditional features based on build target + +#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX) + #ifndef SK_BUILD_NO_IMAGE_ENCODE + #define SK_SUPPORT_IMAGE_ENCODE + #endif +#endif + +#ifdef SK_BUILD_FOR_SYMBIAN + #define SK_USE_RUNTIME_GLOBALS +#endif + +#endif + diff --git a/skia/include/corecg/SkRandom.h b/skia/include/corecg/SkRandom.h new file mode 100644 index 0000000..8994fc4 --- /dev/null +++ b/skia/include/corecg/SkRandom.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2006-2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkRandom_DEFINED +#define SkRandom_DEFINED + +#include "Sk64.h" +#include "SkScalar.h" + +/** \class SkRandom + + Utility class that implements pseudo random 32bit numbers using a fast + linear equation. Unlike rand(), this class holds its own seed (initially + set to 0), so that multiple instances can be used with no side-effects. +*/ +class SkRandom { +public: + SkRandom() : fSeed(0) {} + SkRandom(uint32_t seed) : fSeed(seed) {} + + /** Return the next pseudo random number as an unsigned 32bit value. + */ + uint32_t nextU() { uint32_t r = fSeed * kMul + kAdd; fSeed = r; return r; } + + /** Return the next pseudo random number as a signed 32bit value. + */ + int32_t nextS() { return (int32_t)this->nextU(); } + + /** Return the next pseudo random number as an unsigned 16bit value. + */ + U16CPU nextU16() { return this->nextU() >> 16; } + + /** Return the next pseudo random number as a signed 16bit value. + */ + S16CPU nextS16() { return this->nextS() >> 16; } + + /** Return the next pseudo random number, as an unsigned value of + at most bitCount bits. + @param bitCount The maximum number of bits to be returned + */ + uint32_t nextBits(unsigned bitCount) { + SkASSERT(bitCount > 0 && bitCount <= 32); + return this->nextU() >> (32 - bitCount); + } + + /** Return the next pseudo random unsigned number, mapped to lie within + [min, max] inclusive. + */ + uint32_t nextRangeU(uint32_t min, uint32_t max) { + SkASSERT(min <= max); + return min + this->nextU() % (max - min + 1); + } + + /** Return the next pseudo random number expressed as an unsigned SkFixed + in the range [0..SK_Fixed1). + */ + SkFixed nextUFixed1() { return this->nextU() >> 16; } + + /** Return the next pseudo random number expressed as a signed SkFixed + in the range (-SK_Fixed1..SK_Fixed1). + */ + SkFixed nextSFixed1() { return this->nextS() >> 15; } + + /** Return the next pseudo random number expressed as a SkScalar + in the range [0..SK_Scalar1). + */ + SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); } + + /** Return the next pseudo random number expressed as a SkScalar + in the range (-SK_Scalar1..SK_Scalar1). + */ + SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); } + + /** Return the next pseudo random number as a signed 64bit value. + */ + void next64(Sk64* a) { + SkASSERT(a); + a->set(this->nextS(), this->nextU()); + } + + /** Set the seed of the random object. The seed is initialized to 0 when the + object is first created, and is updated each time the next pseudo random + number is requested. + */ + void setSeed(int32_t seed) { fSeed = (uint32_t)seed; } + +private: + // See "Numerical Recipes in C", 1992 page 284 for these constants + enum { + kMul = 1664525, + kAdd = 1013904223 + }; + uint32_t fSeed; +}; + +#endif + diff --git a/skia/include/corecg/SkRect.h b/skia/include/corecg/SkRect.h new file mode 100644 index 0000000..65a562e --- /dev/null +++ b/skia/include/corecg/SkRect.h @@ -0,0 +1,426 @@ +/* include/corecg/SkRect.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkRect_DEFINED +#define SkRect_DEFINED + +#include "SkPoint.h" + +/** \struct SkIRect + + SkIRect holds four 32 bit integer coordinates for a rectangle +*/ +struct SkIRect { + int32_t fLeft, fTop, fRight, fBottom; + + /** Return true if the rectangle's width or height are <= 0 + */ + bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + + /** Returns the rectangle's width. This does not check for a valid rectangle (i.e. left <= right) + so the result may be negative. + */ + int width() const { return fRight - fLeft; } + + /** Returns the rectangle's height. This does not check for a valid rectangle (i.e. top <= bottom) + so the result may be negative. + */ + int height() const { return fBottom - fTop; } + + friend int operator==(const SkIRect& a, const SkIRect& b) + { + return !memcmp(&a, &b, sizeof(a)); + } + friend int operator!=(const SkIRect& a, const SkIRect& b) + { + return memcmp(&a, &b, sizeof(a)); + } + + /** Set the rectangle to (0,0,0,0) + */ + void setEmpty() { memset(this, 0, sizeof(*this)); } + + void set(int32_t left, int32_t top, int32_t right, int32_t bottom) + { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + /** Offset set the rectangle by adding dx to its left and right, + and adding dy to its top and bottom. + */ + void offset(int32_t dx, int32_t dy) + { + fLeft += dx; + fTop += dy; + fRight += dx; + fBottom += dy; + } + + /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards, + making the rectangle narrower. If dx is negative, then the sides are moved outwards, + making the rectangle wider. The same hods true for dy and the top and bottom. + */ + void inset(int32_t dx, int32_t dy) + { + fLeft += dx; + fTop += dy; + fRight -= dx; + fBottom -= dy; + } + /** Returns true if (x,y) is inside the rectangle and the rectangle is not + empty. The left and top are considered to be inside, while the right + and bottom are not. Thus for the rectangle (0, 0, 5, 10), the + points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not. + */ + bool contains(int32_t x, int32_t y) const + { + return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) && + (unsigned)(y - fTop) < (unsigned)(fBottom - fTop); + } + + /** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle. + If either rectangle is empty, contains() returns false. + */ + bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const + { + return left < right && top < bottom && !this->isEmpty() && // check for empties + fLeft <= left && fTop <= top && + fRight >= right && fBottom >= bottom; + } + + /** Returns true if the specified rectangle r is inside or equal to this rectangle. + */ + bool contains(const SkIRect& r) const + { + return !r.isEmpty() && !this->isEmpty() && // check for empties + fLeft <= r.fLeft && fTop <= r.fTop && + fRight >= r.fRight && fBottom >= r.fBottom; + } + + /** Return true if this rectangle contains the specified rectangle. + For speed, this method does not check if either this or the specified + rectangles are empty, and if either is, its return value is undefined. + In the debugging build however, we assert that both this and the + specified rectangles are non-empty. + */ + bool containsNoEmptyCheck(int32_t left, int32_t top, + int32_t right, int32_t bottom) const + { + SkASSERT(fLeft < fRight && fTop < fBottom); + SkASSERT(left < right && top < bottom); + + return fLeft <= left && fTop <= top && + fRight >= right && fBottom >= bottom; + } + + /** If r intersects this rectangle, return true and set this rectangle to that + intersection, otherwise return false and do not change this rectangle. + If either rectangle is empty, do nothing and return false. + */ + bool intersect(const SkIRect& r) + { + SkASSERT(&r); + return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom); + } + + /** If rectangles a and b intersect, return true and set this rectangle to + that intersection, otherwise return false and do not change this + rectangle. If either rectangle is empty, do nothing and return false. + */ + bool intersect(const SkIRect& a, const SkIRect& b) + { + SkASSERT(&a && &b); + + if (!a.isEmpty() && !b.isEmpty() && + a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom) + { + fLeft = SkMax32(a.fLeft, b.fLeft); + fTop = SkMax32(a.fTop, b.fTop); + fRight = SkMin32(a.fRight, b.fRight); + fBottom = SkMin32(a.fBottom, b.fBottom); + return true; + } + return false; + } + + /** If rectangles a and b intersect, return true and set this rectangle to + that intersection, otherwise return false and do not change this + rectangle. For speed, no check to see if a or b are empty is performed. + If either is, then the return result is undefined. In the debug build, + we assert that both rectangles are non-empty. + */ + bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) + { + SkASSERT(&a && &b); + SkASSERT(!a.isEmpty() && !b.isEmpty()); + + if (a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom) + { + fLeft = SkMax32(a.fLeft, b.fLeft); + fTop = SkMax32(a.fTop, b.fTop); + fRight = SkMin32(a.fRight, b.fRight); + fBottom = SkMin32(a.fBottom, b.fBottom); + return true; + } + return false; + } + + /** If the rectangle specified by left,top,right,bottom intersects this rectangle, + return true and set this rectangle to that intersection, + otherwise return false and do not change this rectangle. + If either rectangle is empty, do nothing and return false. + */ + bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) + { + if (left < right && top < bottom && !this->isEmpty() && + fLeft < right && left < fRight && fTop < bottom && top < fBottom) + { + if (fLeft < left) fLeft = left; + if (fTop < top) fTop = top; + if (fRight > right) fRight = right; + if (fBottom > bottom) fBottom = bottom; + return true; + } + return false; + } + + /** Returns true if a and b are not empty, and they intersect + */ + static bool Intersects(const SkIRect& a, const SkIRect& b) + { + return !a.isEmpty() && !b.isEmpty() && // check for empties + a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom; + } + + /** Update this rectangle to enclose itself and the specified rectangle. + If this rectangle is empty, just set it to the specified rectangle. If the specified + rectangle is empty, do nothing. + */ + void join(int32_t left, int32_t top, int32_t right, int32_t bottom); + + /** Update this rectangle to enclose itself and the specified rectangle. + If this rectangle is empty, just set it to the specified rectangle. If the specified + rectangle is empty, do nothing. + */ + void join(const SkIRect& r) + { + this->join(r.fLeft, r.fTop, r.fRight, r.fBottom); + } + + /** Swap top/bottom or left/right if there are flipped. + This can be called if the edges are computed separately, + and may have crossed over each other. + When this returns, left <= right && top <= bottom + */ + void sort(); +}; + +/** \struct SkRect +*/ +struct SkRect { + SkScalar fLeft, fTop, fRight, fBottom; + + /** Return true if the rectangle's width or height are <= 0 + */ + bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } + SkScalar width() const { return fRight - fLeft; } + SkScalar height() const { return fBottom - fTop; } + SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); } + SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); } + + friend int operator==(const SkRect& a, const SkRect& b) + { + return !memcmp(&a, &b, sizeof(a)); + } + friend int operator!=(const SkRect& a, const SkRect& b) + { + return memcmp(&a, &b, sizeof(a)); + } + + /** return the 4 points that enclose the rectangle + */ + void toQuad(SkPoint quad[4]) const; + + /** Set this rectangle to the empty rectangle (0,0,0,0) + */ + void setEmpty() { memset(this, 0, sizeof(*this)); } + + void set(const SkIRect& src) + { + fLeft = SkIntToScalar(src.fLeft); + fTop = SkIntToScalar(src.fTop); + fRight = SkIntToScalar(src.fRight); + fBottom = SkIntToScalar(src.fBottom); + } + + void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) + { + fLeft = left; + fTop = top; + fRight = right; + fBottom = bottom; + } + + /** Set this rectangle to be the bounds of the array of points. + If the array is empty (count == 0), then set this rectangle + to the empty rectangle (0,0,0,0) + */ + void set(const SkPoint pts[], int count); + + /** Offset set the rectangle by adding dx to its left and right, + and adding dy to its top and bottom. + */ + void offset(SkScalar dx, SkScalar dy) + { + fLeft += dx; + fTop += dy; + fRight += dx; + fBottom += dy; + } + + /** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards, + making the rectangle narrower. If dx is negative, then the sides are moved outwards, + making the rectangle wider. The same hods true for dy and the top and bottom. + */ + void inset(SkScalar dx, SkScalar dy) + { + fLeft += dx; + fTop += dy; + fRight -= dx; + fBottom -= dy; + } + + /** If this rectangle intersects r, return true and set this rectangle to that + intersection, otherwise return false and do not change this rectangle. + If either rectangle is empty, do nothing and return false. + */ + bool intersect(const SkRect& r); + + /** If this rectangle intersects the rectangle specified by left, top, right, bottom, + return true and set this rectangle to that intersection, otherwise return false + and do not change this rectangle. + If either rectangle is empty, do nothing and return false. + */ + bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); + + /** Return true if this rectangle is not empty, and the specified sides of + a rectangle are not empty, and they intersect. + */ + bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const + { + return // first check that both are not empty + left < right && top < bottom && + fLeft < fRight && fTop < fBottom && + // now check for intersection + fLeft < right && left < fRight && + fTop < bottom && top < fBottom; + } + + /** Return true if rectangles a and b are not empty and intersect. + */ + static bool Intersects(const SkRect& a, const SkRect& b) + { + return !a.isEmpty() && !b.isEmpty() && // check for empties + a.fLeft < b.fRight && b.fLeft < a.fRight && + a.fTop < b.fBottom && b.fTop < a.fBottom; + } + + /** Update this rectangle to enclose itself and the specified rectangle. + If this rectangle is empty, just set it to the specified rectangle. If the specified + rectangle is empty, do nothing. + */ + void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom); + + /** Update this rectangle to enclose itself and the specified rectangle. + If this rectangle is empty, just set it to the specified rectangle. If the specified + rectangle is empty, do nothing. + */ + void join(const SkRect& r) + { + this->join(r.fLeft, r.fTop, r.fRight, r.fBottom); + } + + /** Returns true if (p.fX,p.fY) is inside the rectangle. The left and top coordinates of + the rectangle are considered to be inside, while the right and bottom coordinates + are not. Thus for the rectangle (0, 0, 5, 10), the points (0,0) and (0,9) are inside, + while (-1,0) and (5,9) are not. + If this rectangle is empty, return false. + */ + bool contains(const SkPoint& p) const + { + return !this->isEmpty() && + fLeft <= p.fX && p.fX < fRight && + fTop <= p.fY && p.fY < fBottom; + } + + /** Returns true if (x,y) is inside the rectangle. The left and top coordinates of + the rectangle are considered to be inside, while the right and bottom coordinates + are not. Thus for the rectangle (0, 0, 5, 10), the points (0,0) and (0,9) are inside, + while (-1,0) and (5,9) are not. + If this rectangle is empty, return false. + */ + bool contains(SkScalar x, SkScalar y) const + { + return !this->isEmpty() && + fLeft <= x && x < fRight && + fTop <= y && y < fBottom; + } + + /** Return true if this rectangle contains r. + If either rectangle is empty, return false. + */ + bool contains(const SkRect& r) const + { + return !r.isEmpty() && !this->isEmpty() && // check for empties + fLeft <= r.fLeft && fTop <= r.fTop && + fRight >= r.fRight && fBottom >= r.fBottom; + } + + /** Set the dst integer rectangle by rounding this rectangle's coordinates + to their nearest integer values. + */ + void round(SkIRect* dst) const + { + SkASSERT(dst); + dst->set(SkScalarRound(fLeft), SkScalarRound(fTop), SkScalarRound(fRight), SkScalarRound(fBottom)); + } + + /** Set the dst integer rectangle by rounding "out" this rectangle, choosing the floor of top and left, + and the ceiling of right and bototm. + */ + void roundOut(SkIRect* dst) const + { + SkASSERT(dst); + dst->set(SkScalarFloor(fLeft), SkScalarFloor(fTop), SkScalarCeil(fRight), SkScalarCeil(fBottom)); + } + + /** Swap top/bottom or left/right if there are flipped. + This can be called if the edges are computed separately, + and may have crossed over each other. + When this returns, left <= right && top <= bottom + */ + void sort(); +}; + +#endif + diff --git a/skia/include/corecg/SkRegion.h b/skia/include/corecg/SkRegion.h new file mode 100644 index 0000000..238524a --- /dev/null +++ b/skia/include/corecg/SkRegion.h @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2005-2007 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkRegion_DEFINED +#define SkRegion_DEFINED + +#include "SkRect.h" + +class SkPath; +class SkRgnBuilder; + +namespace android { + class Region; +} + +#define SkRegion_gEmptyRunHeadPtr ((SkRegion::RunHead*)-1) +#define SkRegion_gRectRunHeadPtr 0 + +/** \class SkRegion + + The SkRegion class encapsulates the geometric region used to specify + clipping areas for drawing. +*/ +class SkRegion { +public: + typedef int32_t RunType; + enum { + kRunTypeSentinel = 0x7FFFFFFF + }; + + SkRegion(); + SkRegion(const SkRegion&); + explicit SkRegion(const SkIRect&); + ~SkRegion(); + + SkRegion& operator=(const SkRegion&); + + friend int operator==(const SkRegion& a, const SkRegion& b); + friend int operator!=(const SkRegion& a, const SkRegion& b) { + return !(a == b); + } + + /** Replace this region with the specified region, and return true if the + resulting region is non-empty. + */ + bool set(const SkRegion& src) { + SkASSERT(&src); + *this = src; + return !this->isEmpty(); + } + + /** Swap the contents of this and the specified region. This operation + is gauarenteed to never fail. + */ + void swap(SkRegion&); + + /** Return true if this region is empty */ + bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; } + /** Return true if this region is a single, non-empty rectangle */ + bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; } + /** Return true if this region consists of more than 1 rectangular area */ + bool isComplex() const { return !this->isEmpty() && !this->isRect(); } + /** Return the bounds of this region. If the region is empty, returns an + empty rectangle. + */ + const SkIRect& getBounds() const { return fBounds; } + + /** Returns true if the region is non-empty, and if so, sets the specified + path to the boundary(s) of the region. + */ + bool getBoundaryPath(SkPath* path) const; + + /** Set the region to be empty, and return false, since the resulting + region is empty + */ + bool setEmpty(); + + /** If rect is non-empty, set this region to that rectangle and return true, + otherwise set this region to empty and return false. + */ + bool setRect(const SkIRect&); + + /** If left < right and top < bottom, set this region to that rectangle and + return true, otherwise set this region to empty and return false. + */ + bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom); + + /** Set this region to the specified region, and return true if it is + non-empty. */ + bool setRegion(const SkRegion&); + + /** Set this region to the area described by the path, clipped. + Return true if the resulting region is non-empty. + This produces a region that is identical to the pixels that would be + drawn by the path (with no antialiasing) with the specified clip. + */ + bool setPath(const SkPath&, const SkRegion& clip); + + /** Return true if the specified x,y coordinate is inside the region. + */ + bool contains(int32_t x, int32_t y) const; + + /** Return true if the specified rectangle is completely inside the region. + This works for simple (rectangular) and complex regions, and always + returns the correct result. Note: if either this region or the rectangle + is empty, contains() returns false. + */ + bool contains(const SkIRect&) const; + + /** Return true if the specified region is completely inside the region. + This works for simple (rectangular) and complex regions, and always + returns the correct result. Note: if either region is empty, contains() + returns false. + */ + bool contains(const SkRegion&) const; + + /** Return true if this region is a single rectangle (not complex) and the + specified rectangle is contained by this region. Returning false is not + a guarantee that the rectangle is not contained by this region, but + return true is a guarantee that the rectangle is contained by this region. + */ + bool quickContains(const SkIRect& r) const { + return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom); + } + + /** Return true if this region is a single rectangle (not complex) and the + specified rectangle is contained by this region. Returning false is not + a guarantee that the rectangle is not contained by this region, but + return true is a guarantee that the rectangle is contained by this + region. + */ + bool quickContains(int32_t left, int32_t top, int32_t right, + int32_t bottom) const { + SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region + + return left < right && top < bottom && + fRunHead == SkRegion_gRectRunHeadPtr && // this->isRect() + /* fBounds.contains(left, top, right, bottom); */ + fBounds.fLeft <= left && fBounds.fTop <= top && + fBounds.fRight >= right && fBounds.fBottom >= bottom; + } + + /** Return true if this region is empty, or if the specified rectangle does + not intersect the region. Returning false is not a guarantee that they + intersect, but returning true is a guarantee that they do not. + */ + bool quickReject(const SkIRect& rect) const + { + return this->isEmpty() || rect.isEmpty() || + !SkIRect::Intersects(fBounds, rect); + } + + /** Return true if this region, or rgn, is empty, or if their bounds do not + intersect. Returning false is not a guarantee that they intersect, but + returning true is a guarantee that they do not. + */ + bool quickReject(const SkRegion& rgn) const { + return this->isEmpty() || rgn.isEmpty() || + !SkIRect::Intersects(fBounds, rgn.fBounds); + } + + /** Translate the region by the specified (dx, dy) amount. + */ + void translate(int dx, int dy) { this->translate(dx, dy, this); } + + /** Translate the region by the specified (dx, dy) amount, writing the + resulting region into dst. Note: it is legal to pass this region as the + dst parameter, effectively translating the region in place. If dst is + null, nothing happens. + */ + void translate(int dx, int dy, SkRegion* dst) const; + + /** The logical operations that can be performed when combining two regions. + */ + enum Op { + kDifference_Op, //!< subtract the op region from the first region + kIntersect_Op, //!< intersect the two regions + kUnion_Op, //!< union (inclusive-or) the two regions + kXOR_Op, //!< exclusive-or the two regions + /** subtract the first region from the op region */ + kReverseDifference_Op, + kReplace_Op //!< replace the dst region with the op region + }; + + /** Set this region to the result of applying the Op to this region and the + specified rectangle: this = (this op rect). + Return true if the resulting region is non-empty. + */ + bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); } + + /** Set this region to the result of applying the Op to this region and the + specified rectangle: this = (this op rect). + Return true if the resulting region is non-empty. + */ + bool op(int left, int top, int right, int bottom, Op op) { + SkIRect rect; + rect.set(left, top, right, bottom); + return this->op(*this, rect, op); + } + + /** Set this region to the result of applying the Op to this region and the + specified region: this = (this op rgn). + Return true if the resulting region is non-empty. + */ + bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); } + /** Set this region to the result of applying the Op to the specified + rectangle and region: this = (rect op rgn). + Return true if the resulting region is non-empty. + */ + bool op(const SkIRect& rect, const SkRegion& rgn, Op); + /** Set this region to the result of applying the Op to the specified + region and rectangle: this = (rgn op rect). + Return true if the resulting region is non-empty. + */ + bool op(const SkRegion& rgn, const SkIRect& rect, Op); + /** Set this region to the result of applying the Op to the specified + regions: this = (rgna op rgnb). + Return true if the resulting region is non-empty. + */ + bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op); + + /** Returns the sequence of rectangles, sorted in Y and X, that make up + this region. + */ + class Iterator { + public: + Iterator() : fRgn(NULL), fDone(true) {} + Iterator(const SkRegion&); + // if we have a region, reset to it and return true, else return false + bool rewind(); + // reset the iterator, using the new region + void reset(const SkRegion&); + bool done() { return fDone; } + void next(); + const SkIRect& rect() const { return fRect; } + + private: + const SkRegion* fRgn; + const RunType* fRuns; + SkIRect fRect; + bool fDone; + }; + + /** Returns the sequence of rectangles, sorted in Y and X, that make up + this region intersected with the specified clip rectangle. + */ + class Cliperator { + public: + Cliperator(const SkRegion&, const SkIRect& clip); + bool done() { return fDone; } + void next(); + const SkIRect& rect() const { return fRect; } + + private: + Iterator fIter; + SkIRect fClip; + SkIRect fRect; + bool fDone; + }; + + /** Returns the sequence of runs that make up this region for the specified + Y scanline, clipped to the specified left and right X values. + */ + class Spanerator { + public: + Spanerator(const SkRegion&, int y, int left, int right); + bool next(int* left, int* right); + + private: + const SkRegion::RunType* fRuns; + int fLeft, fRight; + bool fDone; + }; + + /** Write the region to the buffer, and return the number of bytes written. + If buffer is NULL, it still returns the number of bytes. + */ + uint32_t flatten(void* buffer) const; + /** Initialized the region from the buffer, returning the number + of bytes actually read. + */ + uint32_t unflatten(const void* buffer); + + SkDEBUGCODE(void dump() const;) + SkDEBUGCODE(void validate() const;) + SkDEBUGCODE(static void UnitTest();) + +private: + enum { + kOpCount = kReplace_Op + 1 + }; + + enum { + kRectRegionRuns = 6 // need to store a region of a rect [T B L R S S] + }; + + friend class android::Region; // needed for marshalling efficiently + void allocateRuns(int count); // allocate space for count runs + + struct RunHead; + + SkIRect fBounds; + RunHead* fRunHead; + + void freeRuns(); + const RunType* getRuns(RunType tmpStorage[], int* count) const; + bool setRuns(RunType runs[], int count); + + int count_runtype_values(int* itop, int* ibot) const; + + static void BuildRectRuns(const SkIRect& bounds, + RunType runs[kRectRegionRuns]); + // returns true if runs are just a rect + static bool ComputeRunBounds(const RunType runs[], int count, + SkIRect* bounds); + + friend struct RunHead; + friend class Iterator; + friend class Spanerator; + friend class SkRgnBuilder; + friend class SkFlatRegion; +}; + + +#endif + diff --git a/skia/include/corecg/SkScalar.h b/skia/include/corecg/SkScalar.h new file mode 100644 index 0000000..3e737ae --- /dev/null +++ b/skia/include/corecg/SkScalar.h @@ -0,0 +1,261 @@ +/* include/corecg/SkScalar.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkScalar_DEFINED +#define SkScalar_DEFINED + +#include "SkFixed.h" + +/** \file SkScalar.h + + Types and macros for the data type SkScalar. This is the fractional numeric type + that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented + either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written + to allow the calling code to manipulate SkScalar values without knowing which representation + is in effect. +*/ + +#ifdef SK_SCALAR_IS_FLOAT + #include "SkFloatingPoint.h" + + /** SkScalar is our type for fractional values and coordinates. Depending on + compile configurations, it is either represented as an IEEE float, or + as a 16.16 fixed point integer. + */ + typedef float SkScalar; + extern const uint32_t gIEEENotANumber; + extern const uint32_t gIEEEInfinity; + + /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar + */ + #define SK_Scalar1 (1.0f) + /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar + */ + #define SK_ScalarHalf (0.5f) + /** SK_ScalarInfinity is defined to be infinity as an SkScalar + */ + #define SK_ScalarInfinity (*(const float*)&gIEEEInfinity) + /** SK_ScalarMax is defined to be the largest value representable as an SkScalar + */ + #define SK_ScalarMax (3.4028235e+38f) + /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar + */ + #define SK_ScalarMin (1.1754944e-38f) + /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar + */ + #define SK_ScalarNaN (*(const float*)(const void*)&gIEEENotANumber) + /** SkScalarIsNaN(n) returns true if argument is not a number + */ + static inline bool SkScalarIsNaN(float x) { return x != x; } + /** SkIntToScalar(n) returns its integer argument as an SkScalar + */ + #define SkIntToScalar(n) ((float)(n)) + /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar + */ + #define SkFixedToScalar(x) SkFixedToFloat(x) + /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed + */ + #define SkScalarToFixed(x) SkFloatToFixed(x) + + #define SkScalarToFloat(n) (n) + #define SkFloatToScalar(n) (n) + + #define SkScalarToDouble(n) (double)(n) + #define SkDoubleToScalar(n) (float)(n) + + /** SkScalarFraction(x) returns the signed fractional part of the argument + */ + #define SkScalarFraction(x) sk_float_mod(x, 1.0f) + /** Rounds the SkScalar to the nearest integer value + */ + #define SkScalarRound(x) (int)sk_float_floor((x) + 0.5f) + /** Returns the smallest integer that is >= the specified SkScalar + */ + #define SkScalarCeil(x) (int)sk_float_ceil(x) + /** Returns the largest integer that is <= the specified SkScalar + */ + #define SkScalarFloor(x) (int)sk_float_floor(x) + /** Returns the absolute value of the specified SkScalar + */ + #define SkScalarAbs(x) sk_float_abs(x) + /** Returns the value pinned between 0 and max inclusive + */ + inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) { + return x < 0 ? 0 : x > max ? max : x; + } + /** Returns the value pinned between min and max inclusive + */ + inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) { + return x < min ? min : x > max ? max : x; + } + /** Returns the specified SkScalar squared (x*x) + */ + inline SkScalar SkScalarSquare(SkScalar x) { return x * x; } + /** Returns the product of two SkScalars + */ + #define SkScalarMul(a, b) ((float)(a) * (b)) + /** Returns the product of two SkScalars plus a third SkScalar + */ + #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c)) + /** Returns the product of a SkScalar and an int rounded to the nearest integer value + */ + #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b)) + /** Returns the product of a SkScalar and an int promoted to the next larger int + */ + #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b)) + /** Returns the product of a SkScalar and an int truncated to the next smaller int + */ + #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b)) + /** Returns the quotient of two SkScalars (a/b) + */ + #define SkScalarDiv(a, b) ((float)(a) / (b)) + /** Returns the mod of two SkScalars (a mod b) + */ + #define SkScalarMod(x,y) sk_float_mod(x,y) + /** Returns the product of the first two arguments, divided by the third argument + */ + #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c)) + /** Returns the multiplicative inverse of the SkScalar (1/x) + */ + #define SkScalarInvert(x) (SK_Scalar1 / (x)) + #define SkScalarFastInvert(x) (SK_Scalar1 / (x)) + /** Returns the square root of the SkScalar + */ + #define SkScalarSqrt(x) sk_float_sqrt(x) + /** Returns the average of two SkScalars (a+b)/2 + */ + #define SkScalarAve(a, b) (((a) + (b)) * 0.5f) + /** Returns the geometric mean of two SkScalars + */ + #define SkScalarMean(a, b) sk_float_sqrt((float)(a) * (b)) + /** Returns one half of the specified SkScalar + */ + #define SkScalarHalf(a) ((a) * 0.5f) + + #define SK_ScalarSqrt2 1.41421356f + #define SK_ScalarPI 3.14159265f + #define SK_ScalarTanPIOver8 0.414213562f + #define SK_ScalarRoot2Over2 0.707106781f + + #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180)) + float SkScalarSinCos(SkScalar radians, SkScalar* cosValue); + #define SkScalarSin(radians) (float)sk_float_sin(radians) + #define SkScalarCos(radians) (float)sk_float_cos(radians) + #define SkScalarTan(radians) (float)sk_float_tan(radians) + #define SkScalarASin(val) (float)sk_float_asin(val) + #define SkScalarACos(val) (float)sk_float_acos(val) + #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x) + #define SkScalarExp(x) (float)sk_float_exp(x) + #define SkScalarLog(x) (float)sk_float_log(x) + + inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; } + inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; } + +#else + typedef SkFixed SkScalar; + + #define SK_Scalar1 SK_Fixed1 + #define SK_ScalarHalf SK_FixedHalf + #define SK_ScalarInfinity SK_FixedMax + #define SK_ScalarMax SK_FixedMax + #define SK_ScalarMin SK_FixedMin + #define SK_ScalarNaN SK_FixedNaN + #define SkScalarIsNaN(x) ((x) == SK_FixedNaN) + #define SkIntToScalar(n) SkIntToFixed(n) + #define SkFixedToScalar(x) (x) + #define SkScalarToFixed(x) (x) + #ifdef SK_CAN_USE_FLOAT + #define SkScalarToFloat(n) SkFixedToFloat(n) + #define SkFloatToScalar(n) SkFloatToFixed(n) + + #define SkScalarToDouble(n) SkFixedToDouble(n) + #define SkDoubleToScalar(n) SkDoubleToFixed(n) + #endif + #define SkScalarFraction(x) SkFixedFraction(x) + #define SkScalarRound(x) SkFixedRound(x) + #define SkScalarCeil(x) SkFixedCeil(x) + #define SkScalarFloor(x) SkFixedFloor(x) + #define SkScalarAbs(x) SkFixedAbs(x) + #define SkScalarClampMax(x, max) SkClampMax(x, max) + #define SkScalarPin(x, min, max) SkPin32(x, min, max) + #define SkScalarSquare(x) SkFixedSquare(x) + #define SkScalarMul(a, b) SkFixedMul(a, b) + #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c) + #define SkScalarMulRound(a, b) SkFixedMulCommon(a, b, SK_FixedHalf) + #define SkScalarMulCeil(a, b) SkFixedMulCommon(a, b, SK_Fixed1 - 1) + #define SkScalarMulFloor(a, b) SkFixedMulCommon(a, b, 0) + #define SkScalarDiv(a, b) SkFixedDiv(a, b) + #define SkScalarMod(a, b) SkFixedMod(a, b) + #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c) + #define SkScalarInvert(x) SkFixedInvert(x) + #define SkScalarFastInvert(x) SkFixedFastInvert(x) + #define SkScalarSqrt(x) SkFixedSqrt(x) + #define SkScalarAve(a, b) SkFixedAve(a, b) + #define SkScalarMean(a, b) SkFixedMean(a, b) + #define SkScalarHalf(a) ((a) >> 1) + + #define SK_ScalarSqrt2 SK_FixedSqrt2 + #define SK_ScalarPI SK_FixedPI + #define SK_ScalarTanPIOver8 SK_FixedTanPIOver8 + #define SK_ScalarRoot2Over2 SK_FixedRoot2Over2 + + #define SkDegreesToRadians(degrees) SkFractMul(degrees, SK_FractPIOver180) + #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr) + #define SkScalarSin(radians) SkFixedSin(radians) + #define SkScalarCos(radians) SkFixedCos(radians) + #define SkScalarTan(val) SkFixedTan(val) + #define SkScalarASin(val) SkFixedASin(val) + #define SkScalarACos(val) SkFixedACos(val) + #define SkScalarATan2(y, x) SkFixedATan2(y,x) + #define SkScalarExp(x) SkFixedExp(x) + #define SkScalarLog(x) SkFixedLog(x) + + #define SkMaxScalar(a, b) SkMax32(a, b) + #define SkMinScalar(a, b) SkMin32(a, b) +#endif + +#ifndef SK_SCALAR_IS_FLOAT +#define SK_ScalarNearlyZero SK_FixedNearlyZero +#else +/* Allow a little more flexibility for floating-point scalars + */ +#define SK_ScalarNearlyZero (SK_Scalar1 / (1<<15)) +#endif + +/* <= is slower than < for floats, so we use < for our tolerance test +*/ + +inline bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) +{ + SkASSERT(tolerance > 0); + return SkScalarAbs(x) < tolerance; +} + +/** Linearly interpolate between A and B, based on t. + If t is 0, return A + If t is 1, return B + else interpolate. + t must be [0..SK_Scalar1] +*/ +inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) +{ + SkASSERT(t >= 0 && t <= SK_Scalar1); + return A + SkScalarMul(B - A, t); +} + +#endif + diff --git a/skia/include/corecg/SkTSearch.h b/skia/include/corecg/SkTSearch.h new file mode 100644 index 0000000..ca1e467 --- /dev/null +++ b/skia/include/corecg/SkTSearch.h @@ -0,0 +1,168 @@ +/* include/corecg/SkTSearch.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkTSearch_DEFINED +#define SkTSearch_DEFINED + +#include "SkTypes.h" + +template <typename T> +int SkTSearch(const T* base, int count, const T& target, size_t elemSize) +{ + SkASSERT(count >= 0); + if (count <= 0) + return ~0; + + SkASSERT(base != NULL); // base may be NULL if count is zero + + int lo = 0; + int hi = count - 1; + + while (lo < hi) + { + int mid = (hi + lo) >> 1; + const T* elem = (const T*)((const char*)base + mid * elemSize); + + if (*elem < target) + lo = mid + 1; + else + hi = mid; + } + + const T* elem = (const T*)((const char*)base + hi * elemSize); + if (*elem != target) + { + if (*elem < target) + hi += 1; + hi = ~hi; + } + return hi; +} + +template <typename T> +int SkTSearch(const T* base, int count, const T& target, size_t elemSize, + int (*compare)(const T&, const T&)) +{ + SkASSERT(count >= 0); + if (count <= 0) { + return ~0; + } + + SkASSERT(base != NULL); // base may be NULL if count is zero + + int lo = 0; + int hi = count - 1; + + while (lo < hi) { + int mid = (hi + lo) >> 1; + const T* elem = (const T*)((const char*)base + mid * elemSize); + + if ((*compare)(*elem, target) < 0) + lo = mid + 1; + else + hi = mid; + } + + const T* elem = (const T*)((const char*)base + hi * elemSize); + int pred = (*compare)(*elem, target); + if (pred != 0) { + if (pred < 0) + hi += 1; + hi = ~hi; + } + return hi; +} + +template <typename T> +int SkTSearch(const T** base, int count, const T* target, size_t elemSize, + int (*compare)(const T*, const T*)) +{ + SkASSERT(count >= 0); + if (count <= 0) + return ~0; + + SkASSERT(base != NULL); // base may be NULL if count is zero + + int lo = 0; + int hi = count - 1; + + while (lo < hi) + { + int mid = (hi + lo) >> 1; + const T* elem = *(const T**)((const char*)base + mid * elemSize); + + if ((*compare)(elem, target) < 0) + lo = mid + 1; + else + hi = mid; + } + + const T* elem = *(const T**)((const char*)base + hi * elemSize); + int pred = (*compare)(elem, target); + if (pred != 0) + { + if (pred < 0) + hi += 1; + hi = ~hi; + } + return hi; +} + +int SkStrSearch(const char*const* base, int count, const char target[], + size_t target_len, size_t elemSize); +int SkStrSearch(const char*const* base, int count, const char target[], + size_t elemSize); + +/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that + base points to a table of lower-case strings. +*/ +int SkStrLCSearch(const char*const* base, int count, const char target[], + size_t target_len, size_t elemSize); +int SkStrLCSearch(const char*const* base, int count, const char target[], + size_t elemSize); + +/** Helper class to convert a string to lower-case, but only modifying the ascii + characters. This makes the routine very fast and never changes the string + length, but it is not suitable for linguistic purposes. Normally this is + used for buiding and searching string tables. +*/ +class SkAutoAsciiToLC { +public: + SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1); + ~SkAutoAsciiToLC(); + + const char* lc() const { return fLC; } + size_t length() const { return fLength; } + +private: + char* fLC; // points to either the heap or fStorage + size_t fLength; + enum { + STORAGE = 64 + }; + char fStorage[STORAGE+1]; +}; + +extern "C" { + typedef int (*SkQSortCompareProc)(const void*, const void*); + void SkQSort(void* base, size_t count, size_t elemSize, SkQSortCompareProc); +} + +SkDEBUGCODE(void SkQSort_UnitTest();) + +#endif + diff --git a/skia/include/corecg/SkTemplates.h b/skia/include/corecg/SkTemplates.h new file mode 100644 index 0000000..cfe42d9 --- /dev/null +++ b/skia/include/corecg/SkTemplates.h @@ -0,0 +1,188 @@ +/* include/corecg/SkTemplates.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkTemplates_DEFINED +#define SkTemplates_DEFINED + +#include "SkTypes.h" + +/** \file SkTemplates.h + + This file contains light-weight template classes for type-safe and exception-safe + resource management. +*/ + +/** \class SkAutoTCallVProc + + Call a function when this goes out of scope. The template uses two + parameters, the object, and a function that is to be called in the destructor. + If detach() is called, the object reference is set to null. If the object + reference is null when the destructor is called, we do not call the + function. +*/ +template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable { +public: + SkAutoTCallVProc(T* obj): fObj(obj) {} + ~SkAutoTCallVProc() { if (fObj) P(fObj); } + T* detach() { T* obj = fObj; fObj = NULL; return obj; } +private: + T* fObj; +}; + +/** \class SkAutoTCallIProc + +Call a function when this goes out of scope. The template uses two +parameters, the object, and a function that is to be called in the destructor. +If detach() is called, the object reference is set to null. If the object +reference is null when the destructor is called, we do not call the +function. +*/ +template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable { +public: + SkAutoTCallIProc(T* obj): fObj(obj) {} + ~SkAutoTCallIProc() { if (fObj) P(fObj); } + T* detach() { T* obj = fObj; fObj = NULL; return obj; } +private: + T* fObj; +}; + +template <typename T> class SkAutoTDelete : SkNoncopyable { +public: + SkAutoTDelete(T* obj) : fObj(obj) {} + ~SkAutoTDelete() { delete fObj; } + + T* get() const { return fObj; } + void free() { delete fObj; fObj = NULL; } + T* detach() { T* obj = fObj; fObj = NULL; return obj; } + +private: + T* fObj; +}; + +template <typename T> class SkAutoTDeleteArray : SkNoncopyable { +public: + SkAutoTDeleteArray(T array[]) : fArray(array) {} + ~SkAutoTDeleteArray() { delete[] fArray; } + + T* get() const { return fArray; } + void free() { delete[] fArray; fArray = NULL; } + T* detach() { T* array = fArray; fArray = NULL; return array; } + +private: + T* fArray; +}; + +template <typename T> class SkAutoTArray : SkNoncopyable { +public: + SkAutoTArray(size_t count) + { + fArray = NULL; // init first in case we throw + if (count) + fArray = new T[count]; +#ifdef SK_DEBUG + fCount = count; +#endif + } + ~SkAutoTArray() + { + delete[] fArray; + } + + T* get() const { return fArray; } + T& operator[](int index) const { SkASSERT((unsigned)index < fCount); return fArray[index]; } + + void reset() + { + if (fArray) + { + delete[] fArray; + fArray = NULL; + } + } + + void replace(T* array) + { + if (fArray != array) + { + delete[] fArray; + fArray = array; + } + } + + /** Call swap to exchange your pointer to an array of T with the SkAutoTArray object. + After this call, the SkAutoTArray object will be responsible for deleting your + array, and you will be responsible for deleting its. + */ + void swap(T*& other) + { + T* tmp = fArray; + fArray = other; + other = tmp; + } + +private: +#ifdef SK_DEBUG + size_t fCount; +#endif + T* fArray; +}; + +/** Allocate a temp array on the stack/heap. + Does NOT call any constructors/destructors on T (i.e. T must be POD) +*/ +template <typename T> class SkAutoTMalloc : SkNoncopyable { +public: + SkAutoTMalloc(size_t count) + { + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoTMalloc() + { + sk_free(fPtr); + } + T* get() const { return fPtr; } + +private: + T* fPtr; +}; + +template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { +public: + SkAutoSTMalloc(size_t count) + { + if (count <= N) + fPtr = fTStorage; + else + fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoSTMalloc() + { + if (fPtr != fTStorage) + sk_free(fPtr); + } + T* get() const { return fPtr; } + +private: + T* fPtr; + union { + uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; + T fTStorage[1]; // do NOT want to invoke T::T() + }; +}; + +#endif + diff --git a/skia/include/corecg/SkThread.h b/skia/include/corecg/SkThread.h new file mode 100644 index 0000000..8dc2402 --- /dev/null +++ b/skia/include/corecg/SkThread.h @@ -0,0 +1,69 @@ +/* include/corecg/SkThread.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkThread_DEFINED +#define SkThread_DEFINED + +#include "SkTypes.h" +#include "SkThread_platform.h" + +/****** SkThread_platform needs to define the following... + +int32_t sk_atomic_inc(int32_t*); +int32_t sk_atomic_dec(int32_t*); + +class SkMutex { +public: + SkMutex(); + ~SkMutex(); + + void acquire(); + void release(); +}; + +****************/ + +class SkAutoMutexAcquire : SkNoncopyable { +public: + explicit SkAutoMutexAcquire(SkMutex& mutex) : fMutex(&mutex) + { + SkASSERT(fMutex != NULL); + mutex.acquire(); + } + /** If the mutex has not been release, release it now. + */ + ~SkAutoMutexAcquire() + { + if (fMutex) + fMutex->release(); + } + /** If the mutex has not been release, release it now. + */ + void release() + { + if (fMutex) + { + fMutex->release(); + fMutex = NULL; + } + } + +private: + SkMutex* fMutex; +}; + +#endif diff --git a/skia/include/corecg/SkThread_platform.h b/skia/include/corecg/SkThread_platform.h new file mode 100644 index 0000000..b94bc42 --- /dev/null +++ b/skia/include/corecg/SkThread_platform.h @@ -0,0 +1,72 @@ +/* include/corecg/SkThread_platform.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkThread_platform_DEFINED +#define SkThread_platform_DEFINED + +#ifdef ANDROID + +#include <utils/threads.h> +#include <utils/Atomic.h> + +#define sk_atomic_inc(addr) android_atomic_inc(addr) +#define sk_atomic_dec(addr) android_atomic_dec(addr) + +class SkMutex : android::Mutex { +public: + // if isGlobal is true, then ignore any errors in the platform-specific + // destructor + SkMutex(bool isGlobal = true) {} + ~SkMutex() {} + + void acquire() { this->lock(); } + void release() { this->unlock(); } +}; + +#else + +/** Implemented by the porting layer, this function adds 1 to the int specified + by the address (in a thread-safe manner), and returns the previous value. +*/ +int32_t sk_atomic_inc(int32_t* addr); +/** Implemented by the porting layer, this function subtracts 1 to the int + specified by the address (in a thread-safe manner), and returns the previous + value. +*/ +int32_t sk_atomic_dec(int32_t* addr); + +class SkMutex { +public: + // if isGlobal is true, then ignore any errors in the platform-specific + // destructor + SkMutex(bool isGlobal = true); + ~SkMutex(); + + void acquire(); + void release(); + +private: + bool fIsGlobal; + enum { + kStorageIntCount = 12 + }; + uint32_t fStorage[kStorageIntCount]; +}; + +#endif + +#endif diff --git a/skia/include/corecg/SkTypes.h b/skia/include/corecg/SkTypes.h new file mode 100644 index 0000000..b67cf1d --- /dev/null +++ b/skia/include/corecg/SkTypes.h @@ -0,0 +1,377 @@ +/* + * Copyright 2006, Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkTypes_DEFINED +#define SkTypes_DEFINED + +#include "SkPreConfig.h" +#include "SkUserConfig.h" +#include "SkPostConfig.h" + +#ifndef SK_IGNORE_STDINT_DOT_H + #include <stdint.h> +#endif + +#include <stdio.h> + +/** \file SkTypes.h +*/ + +/* + memory wrappers to be implemented by the porting layer (platform) +*/ + +/** Called internally if we run out of memory. The platform implementation must + not return, but should either throw an exception or otherwise exit. +*/ +extern void sk_out_of_memory(void); +/** Called internally if we hit an unrecoverable error. + The platform implementation must not return, but should either throw + an exception or otherwise exit. +*/ +extern void sk_throw(void); + +enum { + SK_MALLOC_TEMP = 0x01, //!< hint to sk_malloc that the requested memory will be freed in the scope of the stack frame + SK_MALLOC_THROW = 0x02 //!< instructs sk_malloc to call sk_throw if the memory cannot be allocated. +}; +/** Return a block of memory (at least 4-byte aligned) of at least the + specified size. If the requested memory cannot be returned, either + return null (if SK_MALLOC_TEMP bit is clear) or call sk_throw() + (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free(). +*/ +extern void* sk_malloc_flags(size_t size, unsigned flags); +/** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag +*/ +extern void* sk_malloc_throw(size_t size); +/** Same as standard realloc(), but this one never returns null on failure. It will throw + an exception if it fails. +*/ +extern void* sk_realloc_throw(void* buffer, size_t size); +/** Free memory returned by sk_malloc(). It is safe to pass null. +*/ +extern void sk_free(void*); + +/////////////////////////////////////////////////////////////////////// + +#define SK_INIT_TO_AVOID_WARNING = 0 + +#ifndef SkDebugf + void SkDebugf(const char format[], ...); +#endif + +#ifdef SK_DEBUG + #define SkASSERT(cond) SK_DEBUGBREAK(cond) + #define SkDEBUGCODE(code) code + #define SkDECLAREPARAM(type, var) , type var + #define SkPARAM(var) , var +// #define SkDEBUGF(args ) SkDebugf##args + #define SkDEBUGF(args ) SkDebugf args + #define SkAssertResult(cond) SkASSERT(cond) +#else + #define SkASSERT(cond) + #define SkDEBUGCODE(code) + #define SkDEBUGF(args) + #define SkDECLAREPARAM(type, var) + #define SkPARAM(var) + + // unlike SkASSERT, this guy executes its condition in the non-debug build + #define SkAssertResult(cond) cond +#endif + +/////////////////////////////////////////////////////////////////////// + +/** Fast type for signed 8 bits. Use for parameter passing and local variables, not for storage +*/ +typedef int S8CPU; +/** Fast type for unsigned 8 bits. Use for parameter passing and local variables, not for storage +*/ +typedef int S16CPU; +/** Fast type for signed 16 bits. Use for parameter passing and local variables, not for storage +*/ +typedef unsigned U8CPU; +/** Fast type for unsigned 16 bits. Use for parameter passing and local variables, not for storage +*/ +typedef unsigned U16CPU; + +/** Meant to be faster than bool (doesn't promise to be 0 or 1, just 0 or non-zero +*/ +typedef int SkBool; +/** Meant to be a small version of bool, for storage purposes. Will be 0 or 1 +*/ +typedef uint8_t SkBool8; + +#ifdef SK_DEBUG + int8_t SkToS8(long); + uint8_t SkToU8(size_t); + int16_t SkToS16(long); + uint16_t SkToU16(size_t); + int32_t SkToS32(long); + uint32_t SkToU32(size_t); +#else + #define SkToS8(x) ((int8_t)(x)) + #define SkToU8(x) ((uint8_t)(x)) + #define SkToS16(x) ((int16_t)(x)) + #define SkToU16(x) ((uint16_t)(x)) + #define SkToS32(x) ((int32_t)(x)) + #define SkToU32(x) ((uint32_t)(x)) +#endif + +/** Returns 0 or 1 based on the condition +*/ +#define SkToBool(cond) ((cond) != 0) + +#define SK_MaxS16 32767 +#define SK_MinS16 -32767 +#define SK_MaxU16 0xFFFF +#define SK_MinU16 0 +#define SK_MaxS32 0x7FFFFFFF +#define SK_MinS32 0x80000001 +#define SK_MaxU32 0xFFFFFFFF +#define SK_MinU32 0 +#define SK_NaN32 0x80000000 + +#ifndef SK_OFFSETOF + #define SK_OFFSETOF(type, field) ((char*)&(((type*)1)->field) - (char*)1) +#endif + +/** Returns the number of entries in an array (not a pointer) +*/ +#define SK_ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) + +/** Returns x rounded up to a multiple of 2 +*/ +#define SkAlign2(x) (((x) + 1) >> 1 << 1) +/** Returns x rounded up to a multiple of 4 +*/ +#define SkAlign4(x) (((x) + 3) >> 2 << 2) + +typedef uint32_t SkFourByteTag; +#define SkSetFourByteTag(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +/** 32 bit integer to hold a unicode value +*/ +typedef int32_t SkUnichar; +/** 32 bit value to hold a millisecond count +*/ +typedef uint32_t SkMSec; +/** 1 second measured in milliseconds +*/ +#define SK_MSec1 1000 +/** maximum representable milliseconds +*/ +#define SK_MSecMax 0x7FFFFFFF +/** Returns a < b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0 +*/ +#define SkMSec_LT(a, b) ((int32_t)(a) - (int32_t)(b) < 0) +/** Returns a <= b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0 +*/ +#define SkMSec_LE(a, b) ((int32_t)(a) - (int32_t)(b) <= 0) + + +/**************************************************************************** + The rest of these only build with C++ +*/ +#ifdef __cplusplus + +/** Faster than SkToBool for integral conditions. Returns 0 or 1 +*/ +inline int Sk32ToBool(uint32_t n) +{ + return (n | (0-n)) >> 31; +} + +template <typename T> inline void SkTSwap(T& a, T& b) +{ + T c(a); + a = b; + b = c; +} + +inline int32_t SkAbs32(int32_t value) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < 0) + value = -value; + return value; +#else + int32_t mask = value >> 31; + return (value ^ mask) - mask; +#endif +} + +inline int32_t SkMax32(int32_t a, int32_t b) +{ + if (a < b) + a = b; + return a; +} + +inline int32_t SkMin32(int32_t a, int32_t b) +{ + if (a > b) + a = b; + return a; +} + +inline int32_t SkSign32(int32_t a) +{ + return (a >> 31) | ((unsigned) -a >> 31); +} + +inline int32_t SkFastMin32(int32_t value, int32_t max) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value > max) + value = max; + return value; +#else + int diff = max - value; + // clear diff if it is negative (clear if value > max) + diff &= (diff >> 31); + return value + diff; +#endif +} + +/** Returns signed 32 bit value pinned between min and max, inclusively +*/ +inline int32_t SkPin32(int32_t value, int32_t min, int32_t max) +{ +#ifdef SK_CPU_HAS_CONDITIONAL_INSTR + if (value < min) + value = min; + if (value > max) + value = max; +#else + if (value < min) + value = min; + else if (value > max) + value = max; +#endif + return value; +} + +inline uint32_t SkSetClearShift(uint32_t bits, bool cond, unsigned shift) +{ + SkASSERT((int)cond == 0 || (int)cond == 1); + return (bits & ~(1 << shift)) | ((int)cond << shift); +} + +inline uint32_t SkSetClearMask(uint32_t bits, bool cond, uint32_t mask) +{ + return cond ? bits | mask : bits & ~mask; +} + +////////////////////////////////////////////////////////////////////////////// + +/** \class SkNoncopyable + +SkNoncopyable is the base class for objects that may do not want to +be copied. It hides its copy-constructor and its assignment-operator. +*/ +class SkNoncopyable { +public: + SkNoncopyable() {} + +private: + SkNoncopyable(const SkNoncopyable&); + SkNoncopyable& operator=(const SkNoncopyable&); +}; + +class SkAutoFree : SkNoncopyable { +public: + SkAutoFree() : fPtr(NULL) {} + explicit SkAutoFree(void* ptr) : fPtr(ptr) {} + ~SkAutoFree() { sk_free(fPtr); } + + /** Return the currently allocate buffer, or null + */ + void* get() const { return fPtr; } + + /** Assign a new ptr allocated with sk_malloc (or null), and return the + previous ptr. Note it is the caller's responsibility to sk_free the + returned ptr. + */ + void* set(void* ptr) { + void* prev = fPtr; + fPtr = ptr; + return prev; + } + + /** Transfer ownership of the current ptr to the caller, setting the + internal reference to null. Note the caller is reponsible for calling + sk_free on the returned address. + */ + void* detach() { return this->set(NULL); } + + /** Free the current buffer, and set the internal reference to NULL. Same + as calling sk_free(detach()) + */ + void free() { + sk_free(fPtr); + fPtr = NULL; + } + +private: + void* fPtr; + // illegal + SkAutoFree(const SkAutoFree&); + SkAutoFree& operator=(const SkAutoFree&); +}; + +class SkAutoMalloc : public SkAutoFree { +public: + explicit SkAutoMalloc(size_t size) + : SkAutoFree(sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP)) {} + + SkAutoMalloc(size_t size, unsigned flags) + : SkAutoFree(sk_malloc_flags(size, flags)) {} + SkAutoMalloc() {} + + void* alloc(size_t size, + unsigned flags = (SK_MALLOC_THROW | SK_MALLOC_TEMP)) { + sk_free(set(sk_malloc_flags(size, flags))); + return get(); + } +}; + +template <size_t kSize> class SkAutoSMalloc : SkNoncopyable { +public: + explicit SkAutoSMalloc(size_t size) + { + if (size <= kSize) + fPtr = fStorage; + else + fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); + } + ~SkAutoSMalloc() + { + if (fPtr != (void*)fStorage) + sk_free(fPtr); + } + void* get() const { return fPtr; } +private: + void* fPtr; + uint32_t fStorage[(kSize + 3) >> 2]; + // illegal + SkAutoSMalloc(const SkAutoSMalloc&); + SkAutoSMalloc& operator=(const SkAutoSMalloc&); +}; + +#endif /* C++ */ + +#endif + diff --git a/skia/include/corecg/SkUserConfig.h b/skia/include/corecg/SkUserConfig.h new file mode 100644 index 0000000..be7622f --- /dev/null +++ b/skia/include/corecg/SkUserConfig.h @@ -0,0 +1,118 @@ +/* include/corecg/SkUserConfig.h +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef SkUserConfig_DEFINED +#define SkUserConfig_DEFINED + +// remove the x if you want to force us into SK_DEBUG mode +#ifdef SK_RELEASEx + #undef SK_RELEASE + #define SK_DEBUG +#endif + +#ifdef ANDROID + #include <utils/misc.h> + +#if 0 + // force fixed + #define SK_SCALAR_IS_FIXED + #undef SK_SCALAR_IS_FLOAT +#else + // force floats + #ifdef SK_SCALAR_IS_FIXED + #undef SK_SCALAR_IS_FIXED + #endif + #define SK_SCALAR_IS_FLOAT +#endif + + #define SK_CAN_USE_FLOAT + #define SkLONGLONG int64_t + + #if __BYTE_ORDER == __BIG_ENDIAN + #define SK_CPU_BENDIAN + #undef SK_CPU_LENDIAN + #else + #define SK_CPU_LENDIAN + #undef SK_CPU_BENDIAN + #endif + + // define SkDebugf to record file/line + #define SkDebugf(...) Android_SkDebugf(__FILE__, __LINE__, \ + __FUNCTION__, __VA_ARGS__) + void Android_SkDebugf(const char* file, int line, + const char* function, const char* format, ...); +#endif + +/* This file is included before all other headers, except for SkPreConfig.h. + That file uses various heuristics to make a "best guess" at settings for + the following build defines. + + However, in this file you can override any of those decisions by either + defining new symbols, or #undef symbols that were already set. +*/ + +// experimental for now +#define SK_SUPPORT_MIPMAP + +#ifdef SK_DEBUG + #define SK_SUPPORT_UNITTEST + /* Define SK_SIMULATE_FAILED_MALLOC to have + * sk_malloc throw an exception. Use this to + * detect unhandled memory leaks. */ + //#define SK_SIMULATE_FAILED_MALLOC + //#define SK_FIND_MEMORY_LEAKS +#endif + +#ifdef SK_BUILD_FOR_BREW + #include "SkBrewUserConfig.h" +#endif + +// ===== Begin Chrome-specific definitions ===== + +#define SK_SCALAR_IS_FLOAT +#undef SK_SCALAR_IS_FIXED + +#define SK_BUILD_FOR_WIN + +// VC8 doesn't support stdint.h, so we define those types here. +#define SK_IGNORE_STDINT_DOT_H +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; + +// Don't use skia debug mode even when compiled as debug, because we don't +// care about debugging this library, only our app. +#undef SK_DEBUG +#undef SK_SUPPORT_UNITTEST +#define SK_RELEASE +#undef SK_RESTRICT +#define SK_RESTRICT +// Skia uses this deprecated bzero function to fill zeros into a string. +#define bzero(str, len) memset(str, 0, len) +#define SkDebugf(...) ((void)0) +#define SK_A32_SHIFT 24 +#define SK_R32_SHIFT 16 +#define SK_G32_SHIFT 8 +#define SK_B32_SHIFT 0 + +// ===== End Chrome-specific definitions ===== + +#endif + |