Bug 1299435 - part 4 - update Skia source to m55. r=mchang

MozReview-Commit-ID: 8TA6Lovdc28

--HG--
rename : gfx/skia/skia/src/animator/SkCondensedDebug.cpp => gfx/skia/skia/src/animator/SkCondensedDebug.inc
rename : gfx/skia/skia/src/animator/SkCondensedRelease.cpp => gfx/skia/skia/src/animator/SkCondensedRelease.inc
This commit is contained in:
Lee Salzman 2016-10-24 15:22:26 -04:00
Родитель 1509100554
Коммит 97e509997e
1398 изменённых файлов: 98444 добавлений и 55387 удалений

Просмотреть файл

@ -21,7 +21,6 @@ class SkBitmapRegionDecoder {
public:
enum Strategy {
kCanvas_Strategy, // Draw to the canvas, uses SkCodec
kAndroidCodec_Strategy, // Uses SkAndroidCodec for scaling and subsetting
};
@ -30,8 +29,7 @@ public:
* @param strategy Strategy used for scaling and subsetting
* @return Tries to create an SkBitmapRegionDecoder, returns NULL on failure
*/
static SkBitmapRegionDecoder* Create(
SkData* data, Strategy strategy);
static SkBitmapRegionDecoder* Create(sk_sp<SkData>, Strategy strategy);
/*
* @param stream Takes ownership of the stream

Просмотреть файл

@ -23,8 +23,20 @@
#define SK_C_PLUS_PLUS_END_GUARD
#endif
#ifndef SK_API
#define SK_API
#if !defined(SK_API)
#if defined(SKIA_DLL)
#if defined(_MSC_VER)
#if SKIA_IMPLEMENTATION
#define SK_API __declspec(dllexport)
#else
#define SK_API __declspec(dllimport)
#endif
#else
#define SK_API __attribute__((visibility("default")))
#endif
#else
#define SK_API
#endif
#endif
///////////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -37,10 +37,11 @@ public:
*
* The SkPngChunkReader handles unknown chunks in PNGs.
* See SkCodec.h for more details.
*
* Will take a ref if it returns a codec, else will not affect the data.
*/
static SkAndroidCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
static SkAndroidCodec* NewFromData(sk_sp<SkData>, SkPngChunkReader* = NULL);
static SkAndroidCodec* NewFromData(SkData* data, SkPngChunkReader* reader) {
return NewFromData(sk_ref_sp(data), reader);
}
virtual ~SkAndroidCodec() {}

Просмотреть файл

@ -11,6 +11,7 @@
#include "../private/SkTemplates.h"
#include "SkColor.h"
#include "SkEncodedFormat.h"
#include "SkEncodedInfo.h"
#include "SkImageInfo.h"
#include "SkSize.h"
#include "SkStream.h"
@ -22,6 +23,12 @@ class SkData;
class SkPngChunkReader;
class SkSampler;
namespace DM {
class CodecSrc;
class ColorCodecSrc;
}
class ColorCodecBench;
/**
* Abstraction layer directly on top of an image codec.
*/
@ -88,10 +95,11 @@ public:
* failure to decode the image.
* If the PNG does not contain unknown chunks, the SkPngChunkReader
* will not be used or modified.
*
* Will take a ref if it returns a codec, else will not affect the data.
*/
static SkCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
static SkCodec* NewFromData(sk_sp<SkData>, SkPngChunkReader* = NULL);
static SkCodec* NewFromData(SkData* data, SkPngChunkReader* reader) {
return NewFromData(sk_ref_sp(data), reader);
}
virtual ~SkCodec();
@ -100,12 +108,7 @@ public:
*/
const SkImageInfo& getInfo() const { return fSrcInfo; }
/**
* Returns the color space associated with the codec.
* Does not affect ownership.
* Might be NULL.
*/
SkColorSpace* getColorSpace() const { return fColorSpace.get(); }
const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
enum Origin {
kTopLeft_Origin = 1, // Default
@ -250,8 +253,8 @@ public:
* If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
* currently supports subsets), the top and left values must be even.
*
* In getPixels, we will attempt to decode the exact rectangular
* subset specified by fSubset.
* In getPixels and incremental decode, we will attempt to decode the
* exact rectangular subset specified by fSubset.
*
* In a scanline decode, it does not make sense to specify a subset
* top or subset height, since the client already controls which rows
@ -284,6 +287,12 @@ public:
* to scale. If the generator cannot perform this scale,
* it will return kInvalidScale.
*
* If the info contains a non-null SkColorSpace, the codec
* will perform the appropriate color space transformation.
* If the caller passes in the same color space that was
* reported by the codec, the color space transformation is
* a no-op.
*
* If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
* SkPMColor values in ctable. On success the generator must copy N colors into that storage,
* (where N is the logical number of table entries) and set ctableCount to N.
@ -345,6 +354,67 @@ public:
return this->onGetYUV8Planes(sizeInfo, planes);
}
/**
* Prepare for an incremental decode with the specified options.
*
* This may require a rewind.
*
* @param dstInfo Info of the destination. If the dimensions do not match
* those of getInfo, this implies a scale.
* @param dst Memory to write to. Needs to be large enough to hold the subset,
* if present, or the full image as described in dstInfo.
* @param options Contains decoding options, including if memory is zero
* initialized and whether to decode a subset.
* @param ctable A pointer to a color table. When dstInfo.colorType() is
* kIndex8, this should be non-NULL and have enough storage for 256
* colors. The color table will be populated after decoding the palette.
* @param ctableCount A pointer to the size of the color table. When
* dstInfo.colorType() is kIndex8, this should be non-NULL. It will
* be modified to the true size of the color table (<= 256) after
* decoding the palette.
* @return Enum representing success or reason for failure.
*/
Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
const SkCodec::Options*, SkPMColor* ctable, int* ctableCount);
Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
const SkCodec::Options* options) {
return this->startIncrementalDecode(dstInfo, dst, rowBytes, options, nullptr, nullptr);
}
Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr, nullptr, nullptr);
}
/**
* Start/continue the incremental decode.
*
* Not valid to call before calling startIncrementalDecode().
*
* After the first call, should only be called again if more data has been
* provided to the source SkStream.
*
* Unlike getPixels and getScanlines, this does not do any filling. This is
* left up to the caller, since they may be skipping lines or continuing the
* decode later. In the latter case, they may choose to initialize all lines
* first, or only initialize the remaining lines after the first call.
*
* @param rowsDecoded Optional output variable returning the total number of
* lines initialized. Only meaningful if this method returns kIncompleteInput.
* Otherwise the implementation may not set it.
* Note that some implementations may have initialized this many rows, but
* not necessarily finished those rows (e.g. interlaced PNG). This may be
* useful for determining what rows the client needs to initialize.
* @return kSuccess if all lines requested in startIncrementalDecode have
* been completely decoded. kIncompleteInput otherwise.
*/
Result incrementalDecode(int* rowsDecoded = nullptr) {
if (!fStartedIncrementalDecode) {
return kInvalidParameters;
}
return this->onIncrementalDecode(rowsDecoded);
}
/**
* The remaining functions revolve around decoding scanlines.
*/
@ -465,17 +535,6 @@ public:
* Interlaced gifs are an example.
*/
kOutOfOrder_SkScanlineOrder,
/*
* Indicates that the entire image must be decoded in order to output
* any amount of scanlines. In this case, it is a REALLY BAD IDEA to
* request scanlines 1-by-1 or in small chunks. The client should
* determine which scanlines are needed and ask for all of them in
* a single call to getScanlines().
*
* Interlaced pngs are an example.
*/
kNone_SkScanlineOrder,
};
/**
@ -511,11 +570,22 @@ protected:
/**
* Takes ownership of SkStream*
*/
SkCodec(const SkImageInfo&,
SkCodec(int width,
int height,
const SkEncodedInfo&,
SkStream*,
sk_sp<SkColorSpace> = nullptr,
Origin = kTopLeft_Origin);
/**
* Takes ownership of SkStream*
* Allows the subclass to set the recommended SkImageInfo
*/
SkCodec(const SkEncodedInfo&,
const SkImageInfo&,
SkStream*,
Origin = kTopLeft_Origin);
virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
// By default, scaling is not supported.
return this->getInfo().dimensions();
@ -581,30 +651,30 @@ protected:
* On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
* scanlines. This allows the subclass to indicate what value to fill with.
*
* @param colorType Destination color type.
* @param dstInfo Describes the destination.
* @return The value with which to fill uninitialized pixels.
*
* Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color,
* an 8-bit gray color, or an 8-bit index into a color table, depending on the color
* type.
* Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,
* a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,
* depending on the color type.
*/
uint32_t getFillValue(SkColorType colorType) const {
return this->onGetFillValue(colorType);
uint64_t getFillValue(const SkImageInfo& dstInfo) const {
return this->onGetFillValue(dstInfo);
}
/**
* Some subclasses will override this function, but this is a useful default for the color
* types that we support. Note that for color types that do not use the full 32-bits,
* types that we support. Note that for color types that do not use the full 64-bits,
* we will simply take the low bits of the fill value.
*
* The defaults are:
* kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type
* kN32_SkColorType: Transparent or Black, depending on the src alpha type
* kRGB_565_SkColorType: Black
* kGray_8_SkColorType: Black
* kIndex_8_SkColorType: First color in color table
*/
virtual uint32_t onGetFillValue(SkColorType /*colorType*/) const {
return kOpaque_SkAlphaType == fSrcInfo.alphaType() ? SK_ColorBLACK : SK_ColorTRANSPARENT;
}
virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;
/**
* Get method for the input stream
@ -622,11 +692,6 @@ protected:
*/
virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
/**
* Update the current scanline. Used by interlaced png.
*/
void updateCurrScanline(int newY) { fCurrScanline = newY; }
const SkImageInfo& dstInfo() const { return fDstInfo; }
const SkCodec::Options& options() const { return fOptions; }
@ -641,18 +706,26 @@ protected:
virtual int onOutputScanline(int inputScanline) const;
/**
* Used for testing with qcms.
* FIXME: Remove this when we are done comparing with qcms.
*/
virtual sk_sp<SkData> getICCData() const { return nullptr; }
private:
const SkEncodedInfo fEncodedInfo;
const SkImageInfo fSrcInfo;
SkAutoTDelete<SkStream> fStream;
bool fNeedsRewind;
sk_sp<SkColorSpace> fColorSpace;
const Origin fOrigin;
// These fields are only meaningful during scanline decodes.
SkImageInfo fDstInfo;
SkCodec::Options fOptions;
// Only meaningful during scanline decodes.
int fCurrScanline;
bool fStartedIncrementalDecode;
/**
* Return whether these dimensions are supported as a scale.
*
@ -672,6 +745,16 @@ private:
return kUnimplemented;
}
virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
const SkCodec::Options&, SkPMColor*, int*) {
return kUnimplemented;
}
virtual Result onIncrementalDecode(int*) {
return kUnimplemented;
}
virtual bool onSkipScanlines(int /*countLines*/) { return false; }
virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
@ -703,6 +786,12 @@ private:
*/
virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
// For testing with qcms
// FIXME: Remove these when we are done comparing with qcms.
friend class DM::ColorCodecSrc;
friend class ColorCodecBench;
friend class DM::CodecSrc; // for fillIncompleteImage
friend class SkSampledCodec;
friend class SkIcoCodec;
};

Просмотреть файл

@ -0,0 +1,199 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkEncodedInfo_DEFINED
#define SkEncodedInfo_DEFINED
#include "SkImageInfo.h"
class SkColorSpace;
struct SkEncodedInfo {
public:
enum Alpha {
kOpaque_Alpha,
kUnpremul_Alpha,
// Each pixel is either fully opaque or fully transparent.
// There is no difference between requesting kPremul or kUnpremul.
kBinary_Alpha,
};
/*
* We strive to make the number of components per pixel obvious through
* our naming conventions.
* Ex: kRGB has 3 components. kRGBA has 4 components.
*
* This sometimes results in redundant Alpha and Color information.
* Ex: kRGB images must also be kOpaque.
*/
enum Color {
// PNG, WBMP
kGray_Color,
// PNG
kGrayAlpha_Color,
// PNG, GIF, BMP
kPalette_Color,
// PNG, RAW
kRGB_Color,
kRGBA_Color,
// BMP
kBGR_Color,
kBGRX_Color,
kBGRA_Color,
// JPEG, WEBP
kYUV_Color,
// WEBP
kYUVA_Color,
// JPEG
// Photoshop actually writes inverted CMYK data into JPEGs, where zero
// represents 100% ink coverage. For this reason, we treat CMYK JPEGs
// as having inverted CMYK. libjpeg-turbo warns that this may break
// other applications, but the CMYK JPEGs we see on the web expect to
// be treated as inverted CMYK.
kInvertedCMYK_Color,
kYCCK_Color,
};
static SkEncodedInfo Make(Color color, Alpha alpha, int bitsPerComponent) {
SkASSERT(1 == bitsPerComponent ||
2 == bitsPerComponent ||
4 == bitsPerComponent ||
8 == bitsPerComponent ||
16 == bitsPerComponent);
switch (color) {
case kGray_Color:
SkASSERT(kOpaque_Alpha == alpha);
break;
case kGrayAlpha_Color:
SkASSERT(kOpaque_Alpha != alpha);
break;
case kPalette_Color:
SkASSERT(16 != bitsPerComponent);
break;
case kRGB_Color:
case kBGR_Color:
case kBGRX_Color:
SkASSERT(kOpaque_Alpha == alpha);
SkASSERT(bitsPerComponent >= 8);
break;
case kYUV_Color:
case kInvertedCMYK_Color:
case kYCCK_Color:
SkASSERT(kOpaque_Alpha == alpha);
SkASSERT(8 == bitsPerComponent);
break;
case kRGBA_Color:
SkASSERT(kOpaque_Alpha != alpha);
SkASSERT(bitsPerComponent >= 8);
break;
case kBGRA_Color:
case kYUVA_Color:
SkASSERT(kOpaque_Alpha != alpha);
SkASSERT(8 == bitsPerComponent);
break;
default:
SkASSERT(false);
break;
}
return SkEncodedInfo(color, alpha, bitsPerComponent);
}
/*
* Returns an SkImageInfo with Skia color and alpha types that are the
* closest possible match to the encoded info.
*/
SkImageInfo makeImageInfo(int width, int height, sk_sp<SkColorSpace> colorSpace) const {
switch (fColor) {
case kGray_Color:
SkASSERT(kOpaque_Alpha == fAlpha);
return SkImageInfo::Make(width, height, kGray_8_SkColorType,
kOpaque_SkAlphaType, colorSpace);
case kGrayAlpha_Color:
SkASSERT(kOpaque_Alpha != fAlpha);
return SkImageInfo::Make(width, height, kN32_SkColorType,
kUnpremul_SkAlphaType, colorSpace);
case kPalette_Color: {
SkAlphaType alphaType = (kOpaque_Alpha == fAlpha) ? kOpaque_SkAlphaType :
kUnpremul_SkAlphaType;
return SkImageInfo::Make(width, height, kIndex_8_SkColorType,
alphaType, colorSpace);
}
case kRGB_Color:
case kBGR_Color:
case kBGRX_Color:
case kYUV_Color:
case kInvertedCMYK_Color:
case kYCCK_Color:
SkASSERT(kOpaque_Alpha == fAlpha);
return SkImageInfo::Make(width, height, kN32_SkColorType,
kOpaque_SkAlphaType, colorSpace);
case kRGBA_Color:
case kBGRA_Color:
case kYUVA_Color:
SkASSERT(kOpaque_Alpha != fAlpha);
return SkImageInfo::Make(width, height, kN32_SkColorType,
kUnpremul_SkAlphaType, std::move(colorSpace));
default:
SkASSERT(false);
return SkImageInfo::MakeUnknown();
}
}
Color color() const { return fColor; }
Alpha alpha() const { return fAlpha; }
uint8_t bitsPerComponent() const { return fBitsPerComponent; }
uint8_t bitsPerPixel() const {
switch (fColor) {
case kGray_Color:
return fBitsPerComponent;
case kGrayAlpha_Color:
return 2 * fBitsPerComponent;
case kPalette_Color:
return fBitsPerComponent;
case kRGB_Color:
case kBGR_Color:
case kYUV_Color:
return 3 * fBitsPerComponent;
case kRGBA_Color:
case kBGRA_Color:
case kBGRX_Color:
case kYUVA_Color:
case kInvertedCMYK_Color:
case kYCCK_Color:
return 4 * fBitsPerComponent;
default:
SkASSERT(false);
return 0;
}
}
private:
SkEncodedInfo(Color color, Alpha alpha, uint8_t bitsPerComponent)
: fColor(color)
, fAlpha(alpha)
, fBitsPerComponent(bitsPerComponent)
{}
Color fColor;
Alpha fAlpha;
uint8_t fBitsPerComponent;
};
#endif

Просмотреть файл

@ -95,7 +95,7 @@
/* Define this to provide font subsetter in PDF generation.
*/
//#define SK_SFNTLY_SUBSETTER "sfntly/subsetter/font_subsetter.h"
//#define SK_SFNTLY_SUBSETTER "sample/chromium/font_subsetter.h"
/* Define this to set the upper limit for text to support LCD. Values that
are very large increase the cost in the font cache and draw slower, without
@ -154,6 +154,8 @@
#define SK_RASTERIZE_EVEN_ROUNDING
#define SK_DISABLE_SCREENSPACE_TESS_AA_PATH_RENDERER
#define SK_DISABLE_SLOW_DEBUG_VALIDATION 1
#define MOZ_SKIA 1
@ -166,15 +168,4 @@
# endif
#endif
/* Check if building with either MSVC, libc++, or a sufficiently recent version of libstdc++.
+ * On platforms like OS X 10.6 or older Android SDKs, we need to work around a lack of certain
+ * C++11 features.
+ */
#include "mozilla/Compiler.h"
#if MOZ_IS_MSVC || MOZ_USING_LIBCXX || MOZ_LIBSTDCXX_VERSION_AT_LEAST(4, 8, 0)
# define MOZ_SKIA_AVOID_CXX11 0
#else
# define MOZ_SKIA_AVOID_CXX11 1
#endif
#endif

Просмотреть файл

@ -18,7 +18,7 @@ public:
* Allocate a new SkBBoxHierarchy. Return NULL on failure.
*/
virtual SkBBoxHierarchy* operator()(const SkRect& bounds) const = 0;
virtual ~SkBBHFactory() {};
virtual ~SkBBHFactory() {}
};
class SK_API SkRTreeFactory : public SkBBHFactory {

Просмотреть файл

@ -23,7 +23,6 @@ class SkPixelRef;
class SkPixelRefFactory;
class SkRegion;
class SkString;
class GrTexture;
/** \class SkBitmap
@ -85,7 +84,7 @@ public:
int height() const { return fInfo.height(); }
SkColorType colorType() const { return fInfo.colorType(); }
SkAlphaType alphaType() const { return fInfo.alphaType(); }
SkColorProfileType profileType() const { return fInfo.profileType(); }
SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
/**
* Return the number of bytes per pixel based on the colortype. If the colortype is
@ -105,7 +104,7 @@ public:
* Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
* colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
*/
int shiftPerPixel() const { return this->bytesPerPixel() >> 1; }
int shiftPerPixel() const { return this->fInfo.shiftPerPixel(); }
///////////////////////////////////////////////////////////////////////////
@ -455,6 +454,7 @@ public:
* not be used as targets for a raster device/canvas (since all pixels
* modifications will be lost when unlockPixels() is called.)
*/
// DEPRECATED
bool lockPixelsAreWritable() const;
bool requestLock(SkAutoPixmapUnlock* result) const;
@ -468,10 +468,6 @@ public:
(this->colorType() != kIndex_8_SkColorType || fColorTable);
}
/** Returns the pixelRef's texture, or NULL
*/
GrTexture* getTexture() const;
/** Return the bitmap's colortable, if it uses one (i.e. colorType is
Index_8) and the pixels are locked.
Otherwise returns NULL. Does not affect the colortable's
@ -774,8 +770,8 @@ private:
static void WriteRawPixels(SkWriteBuffer*, const SkBitmap&);
static bool ReadRawPixels(SkReadBuffer*, SkBitmap*);
friend class SkReadBuffer; // unflatten, rawpixels
friend class SkWriteBuffer; // rawpixels
friend class SkReadBuffer; // unflatten, rawpixels
friend class SkBinaryWriteBuffer; // rawpixels
friend struct SkBitmapProcState;
};

Просмотреть файл

@ -13,7 +13,6 @@
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkDevice.h"
#include "SkImageFilter.h"
#include "SkImageInfo.h"
#include "SkRect.h"
#include "SkScalar.h"
@ -22,6 +21,7 @@
#include "SkTypes.h"
class SkDraw;
class SkImageFilterCache;
class SkMatrix;
class SkPaint;
class SkPath;
@ -58,8 +58,6 @@ public:
static SkBitmapDevice* Create(const SkImageInfo&, const SkSurfaceProps&);
SkImageInfo imageInfo() const override;
protected:
bool onShouldDisableLCD(const SkPaint&) const override;
@ -121,6 +119,13 @@ protected:
const SkPaint& paint) override;
virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) override;
///////////////////////////////////////////////////////////////////////////
void drawSpecial(const SkDraw&, SkSpecialImage*, int x, int y, const SkPaint&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
sk_sp<SkSpecialImage> snapSpecial() override;
///////////////////////////////////////////////////////////////////////////
/** Update as needed the pixel value in the bitmap, so that the caller can
@ -128,7 +133,11 @@ protected:
altered. The config/width/height/rowbytes must remain unchanged.
@return the device contents as a bitmap
*/
#ifdef SK_SUPPORT_LEGACY_ACCESSBITMAP
const SkBitmap& onAccessBitmap() override;
#else
const SkBitmap& onAccessBitmap();
#endif
SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
// just for subclasses, to assign a custom pixelref
@ -141,8 +150,6 @@ protected:
bool onWritePixels(const SkImageInfo&, const void*, size_t, int, int) override;
bool onPeekPixels(SkPixmap*) override;
bool onAccessPixels(SkPixmap*) override;
void onAttachToCanvas(SkCanvas*) override;
void onDetachFromCanvas() override;
private:
friend class SkCanvas;
@ -162,7 +169,7 @@ private:
sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&) override;
SkImageFilter::Cache* getImageFilterCache() override;
SkImageFilterCache* getImageFilterCache() override;
SkBitmap fBitmap;

Просмотреть файл

@ -0,0 +1,51 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkBlendMode_DEFINED
#define SkBlendMode_DEFINED
enum class SkBlendMode {
kClear, //!< [0, 0]
kSrc, //!< [Sa, Sc]
kDst, //!< [Da, Dc]
kSrcOver, //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
kDstOver, //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
kSrcIn, //!< [Sa * Da, Sc * Da]
kDstIn, //!< [Da * Sa, Dc * Sa]
kSrcOut, //!< [Sa * (1 - Da), Sc * (1 - Da)]
kDstOut, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
kSrcATop, //!< [Da, Sc * Da + Dc * (1 - Sa)]
kDstATop, //!< [Sa, Dc * Sa + Sc * (1 - Da)]
kXor, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
kPlus, //!< [Sa + Da, Sc + Dc]
kModulate, // multiplies all components (= alpha and color)
// Following blend modes are defined in the CSS Compositing standard:
// https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
kScreen,
kLastCoeffMode = kScreen,
kOverlay,
kDarken,
kLighten,
kColorDodge,
kColorBurn,
kHardLight,
kSoftLight,
kDifference,
kExclusion,
kMultiply,
kLastSeparableMode = kMultiply,
kHue,
kSaturation,
kColor,
kLuminosity,
kLastMode = kLuminosity
};
#endif

Просмотреть файл

@ -9,7 +9,9 @@
#define SkCanvas_DEFINED
#include "SkTypes.h"
#include "SkBlendMode.h"
#include "SkBitmap.h"
#include "SkClipOp.h"
#include "SkDeque.h"
#include "SkImage.h"
#include "SkPaint.h"
@ -17,9 +19,11 @@
#include "SkRegion.h"
#include "SkSurfaceProps.h"
#include "SkXfermode.h"
#include "SkLights.h"
#include "../private/SkShadowParams.h"
class GrContext;
class GrRenderTarget;
class GrDrawContext;
class SkBaseDevice;
class SkCanvasClipVisitor;
class SkClipStack;
@ -32,12 +36,15 @@ class SkMetaData;
class SkPath;
class SkPicture;
class SkPixmap;
class SkRasterClip;
class SkRRect;
struct SkRSXform;
class SkSurface;
class SkSurface_Base;
class SkTextBlob;
//#define SK_SUPPORT_LEGACY_CLIP_REGIONOPS
/** \class SkCanvas
A Canvas encapsulates all of the state about drawing into a device (bitmap).
@ -57,8 +64,27 @@ class SK_API SkCanvas : public SkRefCnt {
enum PrivateSaveLayerFlags {
kDontClipToLayer_PrivateSaveLayerFlag = 1U << 31,
};
public:
#ifdef SK_SUPPORT_LEGACY_CLIP_REGIONOPS
typedef SkRegion::Op ClipOp;
static const ClipOp kDifference_Op = SkRegion::kDifference_Op;
static const ClipOp kIntersect_Op = SkRegion::kIntersect_Op;
static const ClipOp kUnion_Op = SkRegion::kUnion_Op;
static const ClipOp kXOR_Op = SkRegion::kXOR_Op;
static const ClipOp kReverseDifference_Op = SkRegion::kReverseDifference_Op;
static const ClipOp kReplace_Op = SkRegion::kReplace_Op;
#else
typedef SkClipOp ClipOp;
static const ClipOp kDifference_Op = kDifference_SkClipOp;
static const ClipOp kIntersect_Op = kIntersect_SkClipOp;
static const ClipOp kUnion_Op = kUnion_SkClipOp;
static const ClipOp kXOR_Op = kXOR_SkClipOp;
static const ClipOp kReverseDifference_Op = kReverseDifference_SkClipOp;
static const ClipOp kReplace_Op = kReplace_SkClipOp;
#endif
/**
* Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
* specified pixels. To access the pixels after drawing to them, the caller should call
@ -418,11 +444,18 @@ public:
*/
void scale(SkScalar sx, SkScalar sy);
/** Preconcat the current matrix with the specified rotation.
/** Preconcat the current matrix with the specified rotation about the origin.
@param degrees The amount to rotate, in degrees
*/
void rotate(SkScalar degrees);
/** Preconcat the current matrix with the specified rotation about a given point.
@param degrees The amount to rotate, in degrees
@param px The x coordinate of the point to rotate about.
@param py The y coordinate of the point to rotate about.
*/
void rotate(SkScalar degrees, SkScalar px, SkScalar py);
/** Preconcat the current matrix with the specified skew.
@param sx The amount to skew in X
@param sy The amount to skew in Y
@ -443,15 +476,37 @@ public:
*/
void resetMatrix();
#ifdef SK_EXPERIMENTAL_SHADOWING
/** Add the specified translation to the current draw depth of the canvas.
@param z The distance to translate in Z.
Negative into screen, positive out of screen.
Without translation, the draw depth defaults to 0.
*/
void translateZ(SkScalar z);
/** Set the current set of lights in the canvas.
@param lights The lights that we want the canvas to have.
*/
void setLights(sk_sp<SkLights> lights);
/** Returns the current set of lights the canvas uses
*/
sk_sp<SkLights> getLights() const;
#endif
/**
* Modify the current clip with the specified rectangle.
* @param rect The rect to combine with the current clip
* @param op The region op to apply to the current clip
* @param doAntiAlias true if the clip should be antialiased
*/
void clipRect(const SkRect& rect,
SkRegion::Op op = SkRegion::kIntersect_Op,
bool doAntiAlias = false);
void clipRect(const SkRect& rect, ClipOp, bool doAntiAlias);
void clipRect(const SkRect& rect, ClipOp op) {
this->clipRect(rect, op, false);
}
void clipRect(const SkRect& rect, bool doAntiAlias = false) {
this->clipRect(rect, kIntersect_Op, doAntiAlias);
}
/**
* Modify the current clip with the specified SkRRect.
@ -459,9 +514,13 @@ public:
* @param op The region op to apply to the current clip
* @param doAntiAlias true if the clip should be antialiased
*/
void clipRRect(const SkRRect& rrect,
SkRegion::Op op = SkRegion::kIntersect_Op,
bool doAntiAlias = false);
void clipRRect(const SkRRect& rrect, ClipOp op, bool doAntiAlias);
void clipRRect(const SkRRect& rrect, ClipOp op) {
this->clipRRect(rrect, op, false);
}
void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
this->clipRRect(rrect, kIntersect_Op, doAntiAlias);
}
/**
* Modify the current clip with the specified path.
@ -469,16 +528,12 @@ public:
* @param op The region op to apply to the current clip
* @param doAntiAlias true if the clip should be antialiased
*/
void clipPath(const SkPath& path,
SkRegion::Op op = SkRegion::kIntersect_Op,
bool doAntiAlias = false);
/** EXPERIMENTAL -- only used for testing
Set to false to force clips to be hard, even if doAntiAlias=true is
passed to clipRect or clipPath.
*/
void setAllowSoftClip(bool allow) {
fAllowSoftClip = allow;
void clipPath(const SkPath& path, ClipOp op, bool doAntiAlias);
void clipPath(const SkPath& path, ClipOp op) {
this->clipPath(path, op, false);
}
void clipPath(const SkPath& path, bool doAntiAlias = false) {
this->clipPath(path, kIntersect_Op, doAntiAlias);
}
/** EXPERIMENTAL -- only used for testing
@ -495,17 +550,7 @@ public:
@param deviceRgn The region to apply to the current clip
@param op The region op to apply to the current clip
*/
void clipRegion(const SkRegion& deviceRgn,
SkRegion::Op op = SkRegion::kIntersect_Op);
/** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
specified region. This does not intersect or in any other way account
for the existing clip region.
@param deviceRgn The region to copy into the current clip.
*/
void setClipRegion(const SkRegion& deviceRgn) {
this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
}
void clipRegion(const SkRegion& deviceRgn, ClipOp op = kIntersect_Op);
/** Return true if the specified rectangle, after being transformed by the
current matrix, would lie completely outside of the current clip. Call
@ -529,40 +574,6 @@ public:
*/
bool quickReject(const SkPath& path) const;
/** Return true if the horizontal band specified by top and bottom is
completely clipped out. This is a conservative calculation, meaning
that it is possible that if the method returns false, the band may still
in fact be clipped out, but the converse is not true. If this method
returns true, then the band is guaranteed to be clipped out.
@param top The top of the horizontal band to compare with the clip
@param bottom The bottom of the horizontal and to compare with the clip
@return true if the horizontal band is completely clipped out (i.e. does
not intersect the current clip)
*/
bool quickRejectY(SkScalar top, SkScalar bottom) const {
SkASSERT(top <= bottom);
#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
// TODO: add a hasPerspective method similar to getLocalClipBounds. This
// would cache the SkMatrix::hasPerspective result. Alternatively, have
// the MC stack just set a hasPerspective boolean as it is updated.
if (this->getTotalMatrix().hasPerspective()) {
// TODO: consider implementing some half-plane test between the
// two Y planes and the device-bounds (i.e., project the top and
// bottom Y planes and then determine if the clip bounds is completely
// outside either one).
return false;
}
#endif
const SkRect& clipR = this->getLocalClipBounds();
// In the case where the clip is empty and we are provided with a
// negative top and positive bottom parameter then this test will return
// false even though it will be clipped. We have chosen to exclude that
// check as it is rare and would result double the comparisons.
return top >= clipR.fBottom || bottom <= clipR.fTop;
}
/** Return the bounds of the current clip (in local coordinates) in the
bounds parameter, and return true if it is non-empty. This can be useful
in a way similar to quickReject, in that it tells you that drawing
@ -585,22 +596,31 @@ public:
@param b the blue component (0..255) of the color to fill the canvas
@param mode the mode to apply the color in (defaults to SrcOver)
*/
void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode = SkBlendMode::kSrcOver);
#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkXfermode::Mode mode) {
this->drawARGB(a, r, g, b, (SkBlendMode)mode);
}
#endif
/** Fill the entire canvas' bitmap (restricted to the current clip) with the
specified color and mode.
@param color the color to draw with
@param mode the mode to apply the color in (defaults to SrcOver)
*/
void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
void drawColor(SkColor color, SkXfermode::Mode mode) {
this->drawColor(color, (SkBlendMode)mode);
}
#endif
/**
* Helper method for drawing a color in SRC mode, completely replacing all the pixels
* in the current clip with this color.
*/
void clear(SkColor color) {
this->drawColor(color, SkXfermode::kSrc_Mode);
this->drawColor(color, SkBlendMode::kSrc);
}
/**
@ -709,6 +729,12 @@ public:
void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
SkScalar bottom, const SkPaint& paint);
/** Draw the outline of the specified region using the specified paint.
@param region The region to be drawn
@param paint The paint used to draw the region
*/
void drawRegion(const SkRegion& region, const SkPaint& paint);
/** Draw the specified oval using the specified paint. The oval will be
filled or framed based on the Style in the paint.
@param oval The rectangle bounds of the oval to be drawn
@ -743,14 +769,17 @@ public:
const SkPaint& paint);
/** Draw the specified arc, which will be scaled to fit inside the
specified oval. If the sweep angle is >= 360, then the oval is drawn
completely. Note that this differs slightly from SkPath::arcTo, which
treats the sweep angle mod 360.
@param oval The bounds of oval used to define the shape of the arc
specified oval. Sweep angles are not treated as modulo 360 and thus can
exceed a full sweep of the oval. Note that this differs slightly from
SkPath::arcTo, which treats the sweep angle mod 360. If the oval is empty
or the sweep angle is zero nothing is drawn. If useCenter is true the oval
center is inserted into the implied path before the arc and the path is
closed back to the, center forming a wedge. Otherwise, the implied path
contains just the arc and is not closed.
@param oval The bounds of oval used to define the shape of the arc.
@param startAngle Starting angle (in degrees) where the arc begins
@param sweepAngle Sweep angle (in degrees) measured clockwise
@param useCenter true means include the center of the oval. For filling
this will draw a wedge. False means just use the arc.
@param sweepAngle Sweep angle (in degrees) measured clockwise.
@param useCenter true means include the center of the oval.
@param paint The paint used to draw the arc
*/
void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
@ -911,7 +940,7 @@ public:
SrcRectConstraint = kStrict_SrcRectConstraint);
/**
* Draw the bitmap stretched differentially to fit into dst.
* Draw the bitmap stretched or shrunk differentially to fit into dst.
* center is a rect within the bitmap, and logically divides the bitmap
* into 9 sections (3x3). For example, if the middle pixel of a [5x5]
* bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
@ -927,6 +956,69 @@ public:
void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
const SkPaint* paint = NULL);
/**
* Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
*
* If the lattice divs or bounds are invalid, the entire lattice
* struct will be ignored on the draw call.
*/
struct Lattice {
enum Flags : uint8_t {
// If set, indicates that we should not draw corresponding rect.
kTransparent_Flags = 1 << 0,
};
// An array of x-coordinates that divide the bitmap vertically.
// These must be unique, increasing, and in the set [fBounds.fLeft, fBounds.fRight).
// Does not have ownership.
const int* fXDivs;
// An array of y-coordinates that divide the bitmap horizontally.
// These must be unique, increasing, and in the set [fBounds.fTop, fBounds.fBottom).
// Does not have ownership.
const int* fYDivs;
// If non-null, the length of this array must be equal to
// (fXCount + 1) * (fYCount + 1). Note that we allow the first rect
// in each direction to be empty (ex: fXDivs[0] = fBounds.fLeft).
// In this case, the caller still must specify a flag (as a placeholder)
// for these empty rects.
// The flags correspond to the rects in the lattice, first moving
// left to right and then top to bottom.
const Flags* fFlags;
// The number of fXDivs.
int fXCount;
// The number of fYDivs.
int fYCount;
// The bound to draw from. Must be contained by the src that is being drawn,
// non-empty, and non-inverted.
// If nullptr, the bounds are the entire src.
const SkIRect* fBounds;
};
/**
* Draw the bitmap stretched or shrunk differentially to fit into dst.
*
* Moving horizontally across the bitmap, alternating rects will be "scalable"
* (in the x-dimension) to fit into dst or must be left "fixed". The first rect
* is treated as "fixed", but it's possible to specify an empty first rect by
* making lattice.fXDivs[0] = 0.
*
* The scale factor for all "scalable" rects will be the same, and may be greater
* than or less than 1 (meaning we can stretch or shrink). If the number of
* "fixed" pixels is greater than the width of the dst, we will collapse all of
* the "scalable" regions and appropriately downscale the "fixed" regions.
*
* The same interpretation also applies to the y-dimension.
*/
void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint = nullptr);
void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
const SkPaint* paint = nullptr);
/** Draw the text, with origin at (x,y), using the specified paint.
The origin is interpreted based on the Align setting in the paint.
@param text The text to be drawn
@ -988,6 +1080,14 @@ public:
void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
const SkMatrix* matrix, const SkPaint& paint);
/**
* Draw the text with each character/glyph individually transformed by its xform.
* If cullRect is not null, it is a conservative bounds of what will be drawn
* taking into account the xforms and the paint, and will be used to accelerate culling.
*/
void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
const SkRect* cullRect, const SkPaint& paint);
/** Draw the text blob, offset by (x,y), using the specified paint.
@param blob The text blob to be drawn
@param x The x-offset of the text being drawn
@ -995,6 +1095,9 @@ public:
@param paint The paint used for the text (e.g. color, size, style)
*/
void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
this->drawTextBlob(blob.get(), x, y, paint);
}
/** Draw the picture into this canvas. This method effective brackets the
playback of the picture's draw calls with save/restore, so the state
@ -1026,6 +1129,53 @@ public:
this->drawPicture(picture.get(), matrix, paint);
}
#ifdef SK_EXPERIMENTAL_SHADOWING
/**
* Draw the picture into this canvas, with shadows!
*
* We will use the canvas's lights along with the picture information (draw depths of
* objects, etc) to first create a set of shadowmaps for the light-picture pairs, and
* then use that set of shadowmaps to render the scene with shadows.
*
* If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
* logically equivalent to
* save/concat/drawPicture/restore
*
* If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
* alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
* This is logically equivalent to
* saveLayer(paint)/drawPicture/restore
*
* We also support using variance shadow maps for blurred shadows; the user can specify
* what shadow mapping algorithm to use with params.
* - Variance Shadow Mapping works by storing both the depth and depth^2 in the shadow map.
* - Then, the shadow map can be blurred, and when reading from it, the fragment shader
* can calculate the variance of the depth at a position by doing E(x^2) - E(x)^2.
* - We can then use the depth variance and depth at a fragment to arrive at an upper bound
* of the probability that the current surface is shadowed by using Chebyshev's
* inequality, and then use that to shade the fragment.
*
* - There are a few problems with VSM.
* * Light Bleeding | Areas with high variance, such as near the edges of high up rects,
* will cause their shadow penumbras to overwrite otherwise solid
* shadows.
* * Shape Distortion | We can combat Light Bleeding by biasing the shadow (setting
* mostly shaded fragments to completely shaded) and increasing
* the minimum allowed variance. However, this warps and rounds
* out the shape of the shadow.
*/
void drawShadowedPicture(const SkPicture*,
const SkMatrix* matrix,
const SkPaint* paint,
const SkShadowParams& params);
void drawShadowedPicture(const sk_sp<SkPicture>& picture,
const SkMatrix* matrix,
const SkPaint* paint,
const SkShadowParams& params) {
this->drawShadowedPicture(picture.get(), matrix, paint, params);
}
#endif
enum VertexMode {
kTriangles_VertexMode,
kTriangleStrip_VertexMode,
@ -1220,46 +1370,8 @@ public:
///////////////////////////////////////////////////////////////////////////
/** After calling saveLayer(), there can be any number of devices that make
up the top-most drawing area. LayerIter can be used to iterate through
those devices. Note that the iterator is only valid until the next API
call made on the canvas. Ownership of all pointers in the iterator stays
with the canvas, so none of them should be modified or deleted.
*/
class SK_API LayerIter /*: SkNoncopyable*/ {
public:
/** Initialize iterator with canvas, and set values for 1st device */
LayerIter(SkCanvas*, bool skipEmptyClips);
~LayerIter();
/** Return true if the iterator is done */
bool done() const { return fDone; }
/** Cycle to the next device */
void next();
// These reflect the current device in the iterator
SkBaseDevice* device() const;
const SkMatrix& matrix() const;
const SkRegion& clip() const;
const SkPaint& paint() const;
int x() const;
int y() const;
private:
// used to embed the SkDrawIter object directly in our instance, w/o
// having to expose that class def to the public. There is an assert
// in our constructor to ensure that fStorage is large enough
// (though needs to be a compile-time-assert!). We use intptr_t to work
// safely with 32 and 64 bit machines (to ensure the storage is enough)
intptr_t fStorage[32];
class SkDrawIter* fImpl; // this points at fStorage
SkPaint fDefaultPaint;
bool fDone;
};
// don't call
GrRenderTarget* internal_private_accessTopLayerRenderTarget();
GrDrawContext* internal_private_accessTopLayerDrawContext();
// don't call
static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
@ -1275,13 +1387,30 @@ public:
const SkPaint* paint,
SrcRectConstraint constraint = kStrict_SrcRectConstraint);
// expose minimum amount of information necessary for transitional refactoring
/**
* Returns CTM and clip bounds, translated from canvas coordinates to top layer coordinates.
*/
void temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds);
protected:
#ifdef SK_EXPERIMENTAL_SHADOWING
/** Returns the current (cumulative) draw depth of the canvas.
*/
SkScalar getZ() const;
sk_sp<SkLights> fLights;
#endif
// default impl defers to getDevice()->newSurface(info)
virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
// default impl defers to its device
virtual bool onPeekPixels(SkPixmap*);
virtual bool onAccessTopLayerPixels(SkPixmap*);
virtual SkImageInfo onImageInfo() const;
virtual bool onGetProps(SkSurfaceProps*) const;
virtual void onFlush();
// Subclass save/restore notifiers.
// Overriders should call the corresponding INHERITED method up the inheritance chain.
@ -1300,6 +1429,13 @@ protected:
virtual void didRestore() {}
virtual void didConcat(const SkMatrix&) {}
virtual void didSetMatrix(const SkMatrix&) {}
virtual void didTranslate(SkScalar dx, SkScalar dy) {
this->didConcat(SkMatrix::MakeTrans(dx, dy));
}
#ifdef SK_EXPERIMENTAL_SHADOWING
virtual void didTranslateZ(SkScalar) {}
#endif
virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
@ -1317,6 +1453,8 @@ protected:
virtual void onDrawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint);
virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
const SkRect* cullRect, const SkPaint& paint);
virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint);
@ -1328,7 +1466,10 @@ protected:
virtual void onDrawPaint(const SkPaint&);
virtual void onDrawRect(const SkRect&, const SkPaint&);
virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
virtual void onDrawOval(const SkRect&, const SkPaint&);
virtual void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
const SkPaint&);
virtual void onDrawRRect(const SkRRect&, const SkPaint&);
virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
@ -1343,27 +1484,38 @@ protected:
SrcRectConstraint);
virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
const SkPaint*);
virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
SrcRectConstraint);
virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
const SkPaint*);
virtual void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
const SkPaint*);
enum ClipEdgeStyle {
kHard_ClipEdgeStyle,
kSoft_ClipEdgeStyle
};
virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
virtual void onClipRect(const SkRect& rect, ClipOp, ClipEdgeStyle);
virtual void onClipRRect(const SkRRect& rrect, ClipOp, ClipEdgeStyle);
virtual void onClipPath(const SkPath& path, ClipOp, ClipEdgeStyle);
virtual void onClipRegion(const SkRegion& deviceRgn, ClipOp);
virtual void onDiscard();
virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
#ifdef SK_EXPERIMENTAL_SHADOWING
virtual void onDrawShadowedPicture(const SkPicture*,
const SkMatrix*,
const SkPaint*,
const SkShadowParams& params);
#endif
// Returns the canvas to be used by DrawIter. Default implementation
// returns this. Subclasses that encapsulate an indirect canvas may
// need to overload this method. The impl must keep track of this, as it
@ -1378,9 +1530,51 @@ protected:
const SkImageFilter* imageFilter = NULL);
private:
/** After calling saveLayer(), there can be any number of devices that make
up the top-most drawing area. LayerIter can be used to iterate through
those devices. Note that the iterator is only valid until the next API
call made on the canvas. Ownership of all pointers in the iterator stays
with the canvas, so none of them should be modified or deleted.
*/
class LayerIter /*: SkNoncopyable*/ {
public:
/** Initialize iterator with canvas, and set values for 1st device */
LayerIter(SkCanvas*);
~LayerIter();
/** Return true if the iterator is done */
bool done() const { return fDone; }
/** Cycle to the next device */
void next();
// These reflect the current device in the iterator
SkBaseDevice* device() const;
const SkMatrix& matrix() const;
const SkRasterClip& clip() const;
const SkPaint& paint() const;
int x() const;
int y() const;
private:
// used to embed the SkDrawIter object directly in our instance, w/o
// having to expose that class def to the public. There is an assert
// in our constructor to ensure that fStorage is large enough
// (though needs to be a compile-time-assert!). We use intptr_t to work
// safely with 32 and 64 bit machines (to ensure the storage is enough)
intptr_t fStorage[32];
class SkDrawIter* fImpl; // this points at fStorage
SkPaint fDefaultPaint;
bool fDone;
};
static bool BoundsAffectsClip(SaveLayerFlags);
static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
SkBaseDevice* dst, const SkMatrix& ctm,
const SkClipStack* clipStack);
enum ShaderOverrideOpacity {
kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
@ -1406,7 +1600,7 @@ private:
enum {
kMCRecSize = 128, // most recent measurement
kMCRecCount = 32, // common depth for save/restores
kDeviceCMSize = 136, // most recent measurement
kDeviceCMSize = 176, // most recent measurement
};
intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
@ -1430,6 +1624,7 @@ private:
void doSave();
void checkForDeferredSave();
void internalSetMatrix(const SkMatrix&);
friend class SkDrawIter; // needs setupDrawForLayerDevice()
friend class AutoDrawLooper;
@ -1437,6 +1632,7 @@ private:
friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
friend class SkSurface_Raster; // needs getDevice()
friend class SkRecorder; // InitFlags
friend class SkLiteRecorder; // InitFlags
friend class SkNoSaveLayerCanvas; // InitFlags
friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
@ -1472,7 +1668,7 @@ private:
SrcRectConstraint);
void internalDrawPaint(const SkPaint& paint);
void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
// shared by save() and saveLayer()
void internalSave();
@ -1498,25 +1694,18 @@ private:
*/
bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
/* These maintain a cache of the clip bounds in local coordinates,
(converted to 2s-compliment if floats are slow).
/**
* Keep track of the device clip bounds and if the matrix is scale-translate. This allows
* us to do a fast quick reject in the common case.
*/
mutable SkRect fCachedLocalClipBounds;
mutable bool fCachedLocalClipBoundsDirty;
bool fIsScaleTranslate;
SkRect fDeviceClipBounds;
bool fAllowSoftClip;
bool fAllowSimplifyClip;
const bool fConservativeRasterClip;
const SkRect& getLocalClipBounds() const {
if (fCachedLocalClipBoundsDirty) {
if (!this->getClipBounds(&fCachedLocalClipBounds)) {
fCachedLocalClipBounds.setEmpty();
}
fCachedLocalClipBoundsDirty = false;
}
return fCachedLocalClipBounds;
}
class AutoValidateClip : ::SkNoncopyable {
public:
explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
@ -1577,9 +1766,9 @@ private:
class SkCanvasClipVisitor {
public:
virtual ~SkCanvasClipVisitor();
virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
virtual void clipRect(const SkRect&, SkCanvas::ClipOp, bool antialias) = 0;
virtual void clipRRect(const SkRRect&, SkCanvas::ClipOp, bool antialias) = 0;
virtual void clipPath(const SkPath&, SkCanvas::ClipOp, bool antialias) = 0;
};
#endif

Просмотреть файл

@ -33,7 +33,18 @@ public:
kThrow_AllocFailType
};
/**
* Allocates a memory block of size bytes.
* On success: returns a pointer to beginning of memory block that is
* 8 byte aligned. The content of allocated block is not initialized.
* On failure: calls abort() if called with kThrow_AllocFailType,
* otherwise returns NULL pointer.
*/
void* alloc(size_t bytes, AllocFailType);
/**
* Shortcut for calling alloc with kThrow_AllocFailType.
*/
void* allocThrow(size_t bytes) {
return this->alloc(bytes, kThrow_AllocFailType);
}

Просмотреть файл

@ -0,0 +1,26 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkClipOp_DEFINED
#define SkClipOp_DEFINED
#include "SkTypes.h"
// these kept in SkRegion::Op order for now ...
enum SkClipOp {
kDifference_SkClipOp = 0,
kIntersect_SkClipOp = 1,
// Goal: remove these, since they can grow the current clip
kUnion_SkClipOp = 2,
kXOR_SkClipOp = 3,
kReverseDifference_SkClipOp = 4,
kReplace_SkClipOp = 5,
};
#endif

Просмотреть файл

@ -1,13 +1,14 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkClipStack_DEFINED
#define SkClipStack_DEFINED
#include "SkCanvas.h"
#include "SkDeque.h"
#include "SkPath.h"
#include "SkRect.h"
@ -53,21 +54,21 @@ public:
static const int kTypeCnt = kLastType + 1;
Element() {
this->initCommon(0, SkRegion::kReplace_Op, false);
this->initCommon(0, SkCanvas::kReplace_Op, false);
this->setEmpty();
}
Element(const Element&);
Element(const SkRect& rect, SkRegion::Op op, bool doAA) {
Element(const SkRect& rect, SkCanvas::ClipOp op, bool doAA) {
this->initRect(0, rect, op, doAA);
}
Element(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
Element(const SkRRect& rrect, SkCanvas::ClipOp op, bool doAA) {
this->initRRect(0, rrect, op, doAA);
}
Element(const SkPath& path, SkRegion::Op op, bool doAA) {
Element(const SkPath& path, SkCanvas::ClipOp op, bool doAA) {
this->initPath(0, path, op, doAA);
}
@ -93,7 +94,7 @@ public:
}
//!< Call if getType() is not kEmpty to get the set operation used to combine this element.
SkRegion::Op getOp() const { return fOp; }
SkCanvas::ClipOp getOp() const { return fOp; }
//!< Call to get the element as a path, regardless of its type.
void asPath(SkPath* path) const;
@ -109,7 +110,7 @@ public:
void invertShapeFillType();
//!< Sets the set operation represented by the element.
void setOp(SkRegion::Op op) { fOp = op; }
void setOp(SkCanvas::ClipOp op) { fOp = op; }
/** The GenID can be used by clip stack clients to cache representations of the clip. The
ID corresponds to the set of clip elements up to and including this element within the
@ -158,6 +159,23 @@ public:
}
}
bool contains(const SkRRect& rrect) const {
switch (fType) {
case kRect_Type:
return this->getRect().contains(rrect.getBounds());
case kRRect_Type:
// We don't currently have a generalized rrect-rrect containment.
return fRRect.contains(rrect.getBounds()) || rrect == fRRect;
case kPath_Type:
return fPath.get()->conservativelyContainsRect(rrect.getBounds());
case kEmpty_Type:
return false;
default:
SkDEBUGFAIL("Unexpected type.");
return false;
}
}
/**
* Is the clip shape inverse filled.
*/
@ -170,7 +188,7 @@ public:
*/
void replay(SkCanvasClipVisitor*) const;
#ifdef SK_DEVELOPER
#ifdef SK_DEBUG
/**
* Dumps the element to SkDebugf. This is intended for Skia development debugging
* Don't rely on the existence of this function or the formatting of its output.
@ -184,7 +202,7 @@ public:
SkTLazy<SkPath> fPath;
SkRRect fRRect;
int fSaveCount; // save count of stack when this element was added.
SkRegion::Op fOp;
SkCanvas::ClipOp fOp;
Type fType;
bool fDoAA;
@ -208,23 +226,23 @@ public:
int fGenID;
Element(int saveCount) {
this->initCommon(saveCount, SkRegion::kReplace_Op, false);
this->initCommon(saveCount, SkCanvas::kReplace_Op, false);
this->setEmpty();
}
Element(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
Element(int saveCount, const SkRRect& rrect, SkCanvas::ClipOp op, bool doAA) {
this->initRRect(saveCount, rrect, op, doAA);
}
Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
Element(int saveCount, const SkRect& rect, SkCanvas::ClipOp op, bool doAA) {
this->initRect(saveCount, rect, op, doAA);
}
Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
Element(int saveCount, const SkPath& path, SkCanvas::ClipOp op, bool doAA) {
this->initPath(saveCount, path, op, doAA);
}
void initCommon(int saveCount, SkRegion::Op op, bool doAA) {
void initCommon(int saveCount, SkCanvas::ClipOp op, bool doAA) {
fSaveCount = saveCount;
fOp = op;
fDoAA = doAA;
@ -236,13 +254,13 @@ public:
fGenID = kInvalidGenID;
}
void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
void initRect(int saveCount, const SkRect& rect, SkCanvas::ClipOp op, bool doAA) {
fRRect.setRect(rect);
fType = kRect_Type;
this->initCommon(saveCount, op, doAA);
}
void initRRect(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
void initRRect(int saveCount, const SkRRect& rrect, SkCanvas::ClipOp op, bool doAA) {
SkRRect::Type type = rrect.getType();
fRRect = rrect;
if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) {
@ -253,13 +271,13 @@ public:
this->initCommon(saveCount, op, doAA);
}
void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA);
void initPath(int saveCount, const SkPath& path, SkCanvas::ClipOp op, bool doAA);
void setEmpty();
// All Element methods below are only used within SkClipStack.cpp
inline void checkEmpty() const;
inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const;
inline bool canBeIntersectedInPlace(int saveCount, SkCanvas::ClipOp op) const;
/* This method checks to see if two rect clips can be safely merged into one. The issue here
is that to be strictly correct all the edges of the resulting rect must have the same
anti-aliasing. */
@ -284,8 +302,6 @@ public:
SkClipStack();
SkClipStack(const SkClipStack& b);
explicit SkClipStack(const SkRect& r);
explicit SkClipStack(const SkIRect& r);
~SkClipStack();
SkClipStack& operator=(const SkClipStack& b);
@ -312,11 +328,17 @@ public:
bool* isIntersectionOfRects = NULL) const;
/**
* Returns true if the input rect in device space is entirely contained
* by the clip. A return value of false does not guarantee that the rect
* Returns true if the input (r)rect in device space is entirely contained
* by the clip. A return value of false does not guarantee that the (r)rect
* is not contained by the clip.
*/
bool quickContains(const SkRect& devRect) const;
bool quickContains(const SkRect& devRect) const {
return this->isWideOpen() || this->internalQuickContains(devRect);
}
bool quickContains(const SkRRect& devRRect) const {
return this->isWideOpen() || this->internalQuickContains(devRRect);
}
/**
* Flattens the clip stack into a single SkPath. Returns true if any of
@ -324,14 +346,14 @@ public:
*/
bool asPath(SkPath* path) const;
void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
void clipDevRect(const SkIRect& ir, SkCanvas::ClipOp op) {
SkRect r;
r.set(ir);
this->clipDevRect(r, op, false);
this->clipRect(r, SkMatrix::I(), op, false);
}
void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
void clipDevRRect(const SkRRect&, SkRegion::Op, bool doAA);
void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
void clipRect(const SkRect&, const SkMatrix& matrix, SkCanvas::ClipOp, bool doAA);
void clipRRect(const SkRRect&, const SkMatrix& matrix, SkCanvas::ClipOp, bool doAA);
void clipPath(const SkPath&, const SkMatrix& matrix, SkCanvas::ClipOp, bool doAA);
// An optimized version of clipDevRect(emptyRect, kIntersect, ...)
void clipEmpty();
@ -339,7 +361,22 @@ public:
* isWideOpen returns true if the clip state corresponds to the infinite
* plane (i.e., draws are not limited at all)
*/
bool isWideOpen() const;
bool isWideOpen() const { return this->getTopmostGenID() == kWideOpenGenID; }
/**
* This method quickly and conservatively determines whether the entire stack is equivalent to
* intersection with a rrect given a bounds, where the rrect must not contain the entire bounds.
*
* @param bounds A bounds on what will be drawn through the clip. The clip only need be
* equivalent to a intersection with a rrect for draws within the bounds. The
* returned rrect must intersect the bounds but need not be contained by the
* bounds.
* @param rrect If return is true rrect will contain the rrect equivalent to the stack.
* @param aa If return is true aa will indicate whether the equivalent rrect clip is
* antialiased.
* @return true if the stack is equivalent to a single rrect intersect clip, false otherwise.
*/
bool isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const;
/**
* The generation ID has three reserved values to indicate special
@ -353,7 +390,7 @@ public:
int32_t getTopmostGenID() const;
#ifdef SK_DEVELOPER
#ifdef SK_DEBUG
/**
* Dumps the contents of the clip stack to SkDebugf. This is intended for Skia development
* debugging. Don't rely on the existence of this function or the formatting of its output.
@ -387,7 +424,7 @@ public:
* Moves the iterator to the topmost element with the specified RegionOp and returns that
* element. If no clip element with that op is found, the first element is returned.
*/
const Element* skipToTopmost(SkRegion::Op op);
const Element* skipToTopmost(SkCanvas::ClipOp op);
/**
* Restarts the iterator on a clip stack.
@ -461,6 +498,9 @@ private:
// invalid ID.
static int32_t gGenID;
bool internalQuickContains(const SkRect& devRect) const;
bool internalQuickContains(const SkRRect& devRRect) const;
/**
* Helper for clipDevPath, etc.
*/

Просмотреть файл

@ -9,6 +9,7 @@
#define SkColor_DEFINED
#include "SkScalar.h"
#include "SkPoint3.h"
#include "SkTypes.h"
/** \file SkColor.h
@ -166,10 +167,10 @@ struct SkPM4f;
* The float values are 0...1 unpremultiplied
*/
struct SkColor4f {
float fA;
float fR;
float fG;
float fB;
float fA;
bool operator==(const SkColor4f& other) const {
return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;
@ -178,14 +179,17 @@ struct SkColor4f {
return !(*this == other);
}
const float* vec() const { return &fA; }
float* vec() { return &fA; }
const float* vec() const { return &fR; }
float* vec() { return &fR; }
static SkColor4f Pin(float a, float r, float g, float b);
static SkColor4f Pin(float r, float g, float b, float a);
static SkColor4f FromColor(SkColor);
static SkColor4f FromColor3f(SkColor3f, float a);
SkColor toSkColor() const;
SkColor4f pin() const {
return Pin(fA, fR, fG, fB);
return Pin(fR, fG, fB, fA);
}
SkPM4f premul() const;

Просмотреть файл

@ -10,11 +10,13 @@
#include "SkColor.h"
#include "SkFlattenable.h"
#include "SkRefCnt.h"
#include "SkXfermode.h"
class GrContext;
class GrFragmentProcessor;
class SkBitmap;
class SkRasterPipeline;
/**
* ColorFilters are optional objects in the drawing pipeline. When present in
@ -69,6 +71,8 @@ public:
virtual void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const;
bool appendStages(SkRasterPipeline*) const;
enum Flags {
/** If set the filter methods will not change the alpha channel of the colors.
*/
@ -111,6 +115,9 @@ public:
or NULL if the mode will have no effect.
*/
static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkXfermode::Mode mode);
static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkBlendMode mode) {
return MakeModeFilter(c, (SkXfermode::Mode)mode);
}
/** Construct a colorfilter whose effect is to first apply the inner filter and then apply
* the outer filter to the result of the inner's.
@ -142,6 +149,7 @@ public:
}
#endif
#if SK_SUPPORT_GPU
/**
* A subclass may implement this factory function to work with the GPU backend. It returns
* a GrFragmentProcessor that implemets the color filter in GPU shader code.
@ -151,9 +159,8 @@ public:
*
* A null return indicates that the color filter isn't implemented for the GPU backend.
*/
virtual const GrFragmentProcessor* asFragmentProcessor(GrContext*) const {
return nullptr;
}
virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const;
#endif
bool affectsTransparentBlack() const {
return this->filterColor(0) != 0;
@ -167,6 +174,8 @@ public:
protected:
SkColorFilter() {}
virtual bool onAppendStages(SkRasterPipeline*) const;
private:
/*
* Returns 1 if this is a single filter (not a composition of other filters), otherwise it

Просмотреть файл

@ -0,0 +1,106 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkColorSpace_DEFINED
#define SkColorSpace_DEFINED
#include "SkMatrix44.h"
#include "SkRefCnt.h"
class SkData;
class SK_API SkColorSpace : public SkRefCnt {
public:
/**
* Common, named profiles that we can recognize.
*/
enum Named : uint8_t {
/**
* By far the most common color space.
* This is the default space for images, unmarked content, and monitors.
*/
kSRGB_Named,
/**
* Very common wide gamut color space.
* Often used by images and monitors.
*/
kAdobeRGB_Named,
/**
* Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
* half-float surfaces, and high precision individual colors (gradient stops, etc...)
*/
kSRGBLinear_Named,
};
enum RenderTargetGamma : uint8_t {
kLinear_RenderTargetGamma,
/**
* Transfer function is the canonical sRGB curve, which has a short linear segment
* followed by a 2.4f exponential.
*/
kSRGB_RenderTargetGamma,
};
/**
* Create an SkColorSpace from a transfer function and a color gamut transform to D50 XYZ.
*/
static sk_sp<SkColorSpace> NewRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
/**
* Create a common, named SkColorSpace.
*/
static sk_sp<SkColorSpace> NewNamed(Named);
/**
* Create an SkColorSpace from an ICC profile.
*/
static sk_sp<SkColorSpace> NewICC(const void*, size_t);
/**
* Create an SkColorSpace with the same gamut as this color space, but with linear gamma.
*/
sk_sp<SkColorSpace> makeLinearGamma();
/**
* Returns true if the color space gamma is near enough to be approximated as sRGB.
*/
bool gammaCloseToSRGB() const;
/**
* Returns true if the color space gamma is linear.
*/
bool gammaIsLinear() const;
/**
* Returns nullptr on failure. Fails when we fallback to serializing ICC data and
* the data is too large to serialize.
*/
sk_sp<SkData> serialize() const;
/**
* If |memory| is nullptr, returns the size required to serialize.
* Otherwise, serializes into |memory| and returns the size.
*/
size_t writeToMemory(void* memory) const;
static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
/**
* If both are null, we return true. If one is null and the other is not, we return false.
* If both are non-null, we do a deeper compare.
*/
static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
protected:
SkColorSpace() {}
};
#endif

Просмотреть файл

@ -10,7 +10,7 @@
#ifndef SkColorTable_DEFINED
#define SkColorTable_DEFINED
#include "../private/SkOncePtr.h"
#include "../private/SkOnce.h"
#include "SkColor.h"
#include "SkFlattenable.h"
#include "SkImageInfo.h"
@ -62,12 +62,14 @@ private:
SkColorTable(SkPMColor* colors, int count, AllocatedWithMalloc);
SkPMColor* fColors;
SkOncePtr<uint16_t[]> f16BitCache;
mutable uint16_t* f16BitCache = nullptr;
mutable SkOnce f16BitCacheOnce;
int fCount;
void init(const SkPMColor* colors, int count);
friend class SkImageGenerator;
friend class SkBitmapRegionCodec;
// Only call if no other thread or cache has seen this table.
void dangerous_overwriteColors(const SkPMColor newColors[], int count) {
if (count < 0 || count > fCount) {

Просмотреть файл

@ -14,14 +14,12 @@
class SkStream;
#define SK_SUPPORT_LEGACY_DATA_FACTORIES
/**
* SkData holds an immutable data buffer. Not only is the data immutable,
* but the actual ptr that is returned (by data() or bytes()) is guaranteed
* to always be the same for the life of this instance.
*/
class SK_API SkData : public SkRefCnt {
class SK_API SkData final : public SkNVRefCnt<SkData> {
public:
/**
* Returns the number of bytes stored.
@ -69,7 +67,6 @@ public:
* effectively returning 0 == memcmp(...)
*/
bool equals(const SkData* other) const;
bool equals(sk_sp<const SkData>& other) const { return this->equals(other.get()); }
/**
* Function that, if provided, will be called when the SkData goes out
@ -82,7 +79,7 @@ public:
*/
static sk_sp<SkData> MakeWithCopy(const void* data, size_t length);
/**
* Create a new data with uninitialized contents. The caller should call writable_data()
* to write into the buffer, but this must be done before another ref() is made.
@ -160,38 +157,8 @@ public:
*/
static sk_sp<SkData> MakeEmpty();
#ifdef SK_SUPPORT_LEGACY_DATA_FACTORIES
static SkData* NewWithCopy(const void* data, size_t length) {
return MakeWithCopy(data, length).release();
}
static SkData* NewUninitialized(size_t length) {
return MakeUninitialized(length).release();
}
static SkData* NewWithCString(const char cstr[]) {
return MakeWithCString(cstr).release();
}
static SkData* NewWithProc(const void* ptr, size_t length, ReleaseProc proc, void* context) {
return MakeWithProc(ptr, length, proc, context).release();
}
static SkData* NewWithoutCopy(const void* data, size_t length) {
return MakeWithoutCopy(data, length).release();
}
static SkData* NewFromMalloc(const void* data, size_t length) {
return MakeFromMalloc(data, length).release();
}
static SkData* NewFromFileName(const char path[]) { return MakeFromFileName(path).release(); }
static SkData* NewFromFILE(FILE* f) { return MakeFromFILE(f).release(); }
static SkData* NewFromFD(int fd) { return MakeFromFD(fd).release(); }
static SkData* NewFromStream(SkStream* stream, size_t size) {
return MakeFromStream(stream, size).release();
}
static SkData* NewSubset(const SkData* src, size_t offset, size_t length) {
return MakeSubset(src, offset, length).release();
}
static SkData* NewEmpty() { return MakeEmpty().release(); }
#endif
private:
friend class SkNVRefCnt<SkData>;
ReleaseProc fReleaseProc;
void* fReleaseProcContext;
void* fPtr;
@ -199,7 +166,7 @@ private:
SkData(const void* ptr, size_t size, ReleaseProc, void* context);
explicit SkData(size_t size); // inplace new/delete
virtual ~SkData();
~SkData();
// Objects of this type are sometimes created in a custom fashion using sk_malloc_throw and
@ -216,14 +183,9 @@ private:
// shared internal factory
static sk_sp<SkData> PrivateNewWithCopy(const void* srcOrNull, size_t length);
static void DummyReleaseProc(const void*, void*) {}
static void DummyReleaseProc(const void*, void*); // {}
typedef SkRefCnt INHERITED;
};
#ifdef SK_SUPPORT_LEGACY_DATA_FACTORIES
/** Typedef of SkAutoTUnref<SkData> for automatically unref-ing a SkData. */
typedef SkAutoTUnref<SkData> SkAutoDataUnref;
#endif
#endif

Просмотреть файл

@ -63,7 +63,7 @@ public:
typedef void (*FreeProc)(void* context);
static SkDataTable* NewEmpty();
static sk_sp<SkDataTable> MakeEmpty();
/**
* Return a new DataTable that contains a copy of the data stored in each
@ -74,8 +74,8 @@ public:
* ptrs[] array.
* @param count the number of array elements in ptrs[] and sizes[] to copy.
*/
static SkDataTable* NewCopyArrays(const void * const * ptrs,
const size_t sizes[], int count);
static sk_sp<SkDataTable> MakeCopyArrays(const void * const * ptrs,
const size_t sizes[], int count);
/**
* Return a new table that contains a copy of the data in array.
@ -85,11 +85,10 @@ public:
* @param count the number of entries to be copied out of array. The number
* of bytes that will be copied is count * elemSize.
*/
static SkDataTable* NewCopyArray(const void* array, size_t elemSize,
int count);
static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);
static SkDataTable* NewArrayProc(const void* array, size_t elemSize,
int count, FreeProc proc, void* context);
static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,
FreeProc proc, void* context);
private:
struct Dir {
@ -164,7 +163,7 @@ public:
* calls to append(). This call also clears any accumluated entries from
* this builder, so its count() will be 0 after this call.
*/
SkDataTable* detachDataTable();
sk_sp<SkDataTable> detachDataTable();
private:
SkTDArray<SkDataTable::Dir> fDir;

Просмотреть файл

@ -11,17 +11,18 @@
#include "SkRefCnt.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkImageFilter.h"
#include "SkSurfaceProps.h"
class SkBitmap;
class SkClipStack;
class SkDraw;
class SkDrawFilter;
class SkImageFilterCache;
struct SkIRect;
class SkMatrix;
class SkMetaData;
class SkRegion;
class SkSpecialImage;
class GrRenderTarget;
class SK_API SkBaseDevice : public SkRefCnt {
@ -29,7 +30,7 @@ public:
/**
* Construct a new device.
*/
explicit SkBaseDevice(const SkSurfaceProps&);
explicit SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&);
virtual ~SkBaseDevice();
SkMetaData& getMetaData();
@ -38,7 +39,7 @@ public:
* Return ImageInfo for this device. If the canvas is not backed by pixels
* (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
*/
virtual SkImageInfo imageInfo() const;
const SkImageInfo& imageInfo() const { return fInfo; }
/**
* Return SurfaceProps for this device.
@ -76,6 +77,7 @@ public:
return this->imageInfo().isOpaque();
}
#ifdef SK_SUPPORT_LEGACY_ACCESSBITMAP
/** Return the bitmap associated with this device. Call this each time you need
to access the bitmap, as it notifies the subclass to perform any flushing
etc. before you examine the pixels.
@ -83,6 +85,7 @@ public:
@return the device's bitmap
*/
const SkBitmap& accessBitmap(bool changePixels);
#endif
bool writePixels(const SkImageInfo&, const void*, size_t rowBytes, int x, int y);
@ -103,44 +106,12 @@ public:
*/
bool peekPixels(SkPixmap*);
/**
* Return the device's associated gpu render target, or NULL.
*/
virtual GrRenderTarget* accessRenderTarget() { return NULL; }
/**
* Return the device's origin: its offset in device coordinates from
* the default origin in its canvas' matrix/clip
*/
const SkIPoint& getOrigin() const { return fOrigin; }
/**
* onAttachToCanvas is invoked whenever a device is installed in a canvas
* (i.e., setDevice, saveLayer (for the new device created by the save),
* and SkCanvas' SkBaseDevice & SkBitmap -taking ctors). It allows the
* devices to prepare for drawing (e.g., locking their pixels, etc.)
*/
virtual void onAttachToCanvas(SkCanvas*) {
SkASSERT(!fAttachedToCanvas);
#ifdef SK_DEBUG
fAttachedToCanvas = true;
#endif
};
/**
* onDetachFromCanvas notifies a device that it will no longer be drawn to.
* It gives the device a chance to clean up (e.g., unlock its pixels). It
* is invoked from setDevice (for the displaced device), restore and
* possibly from SkCanvas' dtor.
*/
virtual void onDetachFromCanvas() {
SkASSERT(fAttachedToCanvas);
#ifdef SK_DEBUG
fAttachedToCanvas = false;
#endif
};
protected:
enum TileUsage {
kPossible_TileUsage, //!< the created device may be drawn tiled
@ -159,25 +130,6 @@ protected:
virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
/**
*
* DEPRECATED: This will be removed in a future change. Device subclasses
* should use the matrix and clip from the SkDraw passed to draw functions.
*
* Called with the correct matrix and clip before this device is drawn
* to using those settings. If your subclass overrides this, be sure to
* call through to the base class as well.
*
* The clipstack is another view of the clip. It records the actual
* geometry that went into building the region. It is present for devices
* that want to parse it, but is not required: the region is a complete
* picture of the current clip. (i.e. if you regionize all of the geometry
* in the clipstack, you will arrive at an equivalent region to the one
* passed in).
*/
virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
const SkClipStack&) {};
/** These are called inside the per-device-layer loop for each draw call.
When these are called, we have already applied any saveLayer operations,
and are handling any looping from the paint, and any effects from the
@ -188,8 +140,13 @@ protected:
const SkPoint[], const SkPaint& paint) = 0;
virtual void drawRect(const SkDraw&, const SkRect& r,
const SkPaint& paint) = 0;
virtual void drawRegion(const SkDraw&, const SkRegion& r,
const SkPaint& paint);
virtual void drawOval(const SkDraw&, const SkRect& oval,
const SkPaint& paint) = 0;
/** By the time this is called we know that abs(sweepAngle) is in the range [0, 360). */
virtual void drawArc(const SkDraw&, const SkRect& oval, SkScalar startAngle,
SkScalar sweepAngle, bool useCenter, const SkPaint& paint);
virtual void drawRRect(const SkDraw&, const SkRRect& rr,
const SkPaint& paint) = 0;
@ -226,13 +183,17 @@ protected:
const SkPaint& paint,
SkCanvas::SrcRectConstraint) = 0;
virtual void drawBitmapNine(const SkDraw&, const SkBitmap&, const SkIRect& center,
const SkRect& dst, const SkPaint&);
const SkRect& dst, const SkPaint&);
virtual void drawBitmapLattice(const SkDraw&, const SkBitmap&, const SkCanvas::Lattice&,
const SkRect& dst, const SkPaint&);
virtual void drawImage(const SkDraw&, const SkImage*, SkScalar x, SkScalar y, const SkPaint&);
virtual void drawImageRect(const SkDraw&, const SkImage*, const SkRect* src, const SkRect& dst,
const SkPaint&, SkCanvas::SrcRectConstraint);
virtual void drawImageNine(const SkDraw&, const SkImage*, const SkIRect& center,
const SkRect& dst, const SkPaint&);
virtual void drawImageLattice(const SkDraw&, const SkImage*, const SkCanvas::Lattice&,
const SkRect& dst, const SkPaint&);
/**
* Does not handle text decoration.
@ -269,38 +230,30 @@ protected:
virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath&,
const SkMatrix*, const SkPaint&);
virtual void drawTextRSXform(const SkDraw&, const void* text, size_t len, const SkRSXform[],
const SkPaint&);
virtual void drawSpecial(const SkDraw&, SkSpecialImage*, int x, int y, const SkPaint&);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&);
virtual sk_sp<SkSpecialImage> makeSpecial(const SkImage*);
virtual sk_sp<SkSpecialImage> snapSpecial();
bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
///////////////////////////////////////////////////////////////////////////
#ifdef SK_SUPPORT_LEGACY_ACCESSBITMAP
/** Update as needed the pixel value in the bitmap, so that the caller can
access the pixels directly.
@return The device contents as a bitmap
*/
virtual const SkBitmap& onAccessBitmap() = 0;
/**
* Override and return true for filters that the device can handle
* intrinsically. Doing so means that SkCanvas will pass-through this
* filter to drawSprite and drawDevice (and potentially filterImage).
* Returning false means the SkCanvas will have apply the filter itself,
* and just pass the resulting image to the device.
*/
virtual bool canHandleImageFilter(const SkImageFilter*) { return false; }
/**
* Related (but not required) to canHandleImageFilter, this method returns
* true if the device could apply the filter to the src bitmap and return
* the result (and updates offset as needed).
* If the device does not recognize or support this filter,
* it just returns false and leaves result and offset unchanged.
*/
virtual bool filterImage(const SkImageFilter*, const SkBitmap&,
const SkImageFilter::Context&,
SkBitmap* /*result*/, SkIPoint* /*offset*/) {
return false;
virtual const SkBitmap& onAccessBitmap() {
SkASSERT(0);
return fLegacyBitmap;
}
#endif
virtual GrContext* context() const { return nullptr; }
protected:
virtual sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps&);
@ -324,19 +277,6 @@ protected:
virtual bool onAccessPixels(SkPixmap*) { return false; }
/**
* PRIVATE / EXPERIMENTAL -- do not call
* This entry point gives the backend an opportunity to take over the rendering
* of 'picture'. If optimization data is available (due to an earlier
* 'optimize' call) this entry point should make use of it and return true
* if all rendering has been done. If false is returned, SkCanvas will
* perform its own rendering pass. It is acceptable for the backend
* to perform some device-specific warm up tasks and then let SkCanvas
* perform the main rendering loop (by return false from here).
*/
virtual bool EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*,
const SkPaint*);
struct CreateInfo {
static SkPixelGeometry AdjustGeometry(const SkImageInfo&, TileUsage, SkPixelGeometry,
bool preserveLCDText);
@ -348,22 +288,20 @@ protected:
: fInfo(info)
, fTileUsage(tileUsage)
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo, false))
, fForImageFilter(false) {}
{}
CreateInfo(const SkImageInfo& info,
TileUsage tileUsage,
SkPixelGeometry geo,
bool preserveLCDText,
bool forImageFilter)
bool preserveLCDText)
: fInfo(info)
, fTileUsage(tileUsage)
, fPixelGeometry(AdjustGeometry(info, tileUsage, geo, preserveLCDText))
, fForImageFilter(forImageFilter) {}
{}
const SkImageInfo fInfo;
const TileUsage fTileUsage;
const SkPixelGeometry fPixelGeometry;
const bool fForImageFilter;
};
/**
@ -381,11 +319,8 @@ protected:
return NULL;
}
/**
* Calls through to drawSprite, processing the imagefilter.
*/
virtual void drawSpriteWithFilter(const SkDraw&, const SkBitmap&,
int x, int y, const SkPaint&);
// A helper function used by derived classes to log the scale factor of a bitmap or image draw.
static void LogDrawScaleFactor(const SkMatrix&, SkFilterQuality);
private:
friend class SkCanvas;
@ -393,9 +328,9 @@ private:
friend class SkDraw;
friend class SkDrawIter;
friend class SkDeviceFilteredPaint;
friend class SkImageFilter::DeviceProxy;
friend class SkNoPixelsBitmapDevice;
friend class SkSurface_Raster;
friend class DeviceTestingAccess;
// used to change the backend's pixels (and possibly config/rowbytes)
// but cannot change the width/height, so there should be no change to
@ -405,6 +340,11 @@ private:
virtual bool forceConservativeRasterClip() const { return false; }
/**
* Don't call this!
*/
virtual GrDrawContext* accessDrawContext() { return nullptr; }
// just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); }
@ -412,14 +352,20 @@ private:
*/
virtual void flush() {}
virtual SkImageFilter::Cache* getImageFilterCache() { return NULL; }
virtual SkImageFilterCache* getImageFilterCache() { return NULL; }
friend class SkBitmapDevice;
void privateResize(int w, int h) {
*const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
}
SkIPoint fOrigin;
SkMetaData* fMetaData;
SkSurfaceProps fSurfaceProps;
const SkImageInfo fInfo;
const SkSurfaceProps fSurfaceProps;
#ifdef SK_DEBUG
bool fAttachedToCanvas;
#ifdef SK_SUPPORT_LEGACY_ACCESSBITMAP
SkBitmap fLegacyBitmap;
#endif
typedef SkRefCnt INHERITED;

Просмотреть файл

@ -10,13 +10,13 @@
#include "SkBitmap.h"
#include "SkPicture.h"
#include "SkPixelSerializer.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkString.h"
#include "SkTime.h"
class SkCanvas;
class SkPixelSerializer;
class SkWStream;
/** SK_ScalarDefaultDPI is 72 DPI.
@ -35,12 +35,63 @@ class SkWStream;
*/
class SK_API SkDocument : public SkRefCnt {
public:
struct OptionalTimestamp {
SkTime::DateTime fDateTime;
bool fEnabled;
OptionalTimestamp() : fEnabled(false) {}
};
/**
* Create a PDF-backed document, writing the results into a SkWStream.
* Optional metadata to be passed into the PDF factory function.
*/
struct PDFMetadata {
/**
* The documents title.
*/
SkString fTitle;
/**
* The name of the person who created the document.
*/
SkString fAuthor;
/**
* The subject of the document.
*/
SkString fSubject;
/**
* Keywords associated with the document. Commas may be used
* to delineate keywords within the string.
*/
SkString fKeywords;
/**
* If the document was converted to PDF from another format,
* the name of the conforming product that created the
* original document from which it was converted.
*/
SkString fCreator;
/**
* The product that is converting this document to PDF.
*
* Leave fProducer empty to get the default, correct value.
*/
SkString fProducer;
/**
* The date and time the document was created.
*/
OptionalTimestamp fCreation;
/**
* The date and time the document was most recently modified.
*/
OptionalTimestamp fModified;
};
/**
* Create a PDF-backed document, writing the results into a
* SkWStream.
*
* PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.
* PDF pages are sized in point units. 1 pt == 1/72 inch ==
* 127/360 mm.
*
* @param SkWStream* A PDF document will be written to this
* @param stream A PDF document will be written to this
* stream. The document may write to the stream at
* anytime during its lifetime, until either close() is
* called or the document is deleted.
@ -52,49 +103,58 @@ public:
* for larger PDF files too, which would use more memory
* while rendering, and it would be slower to be processed
* or sent online or to printer.
* @returns NULL if there is an error, otherwise a newly created
* PDF-backed SkDocument.
*/
static SkDocument* CreatePDF(SkWStream*,
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* @param metadata a PDFmetadata object. Any fields may be left
* empty.
* @param jpegEncoder For PDF documents, if a jpegEncoder is set,
* use it to encode SkImages and SkBitmaps as [JFIF]JPEGs.
* This feature is deprecated and is only supplied for
* backwards compatability.
*
* The prefered method to create PDFs with JPEG images is
* to use SkImage::NewFromEncoded() and not jpegEncoder.
* Chromium uses NewFromEncoded.
*
* If the encoder is unset, or if jpegEncoder->onEncode()
* returns NULL, fall back on encoding images losslessly
* with Deflate.
* @param pdfa Iff true, include XMP metadata, a document UUID,
* and sRGB output intent information. This adds length
* to the document and makes it non-reproducable, but are
* necessary features for PDF/A-2b conformance
*
* @returns NULL if there is an error, otherwise a newly created
* PDF-backed SkDocument.
*/
static SkDocument* CreatePDF(SkWStream*,
SkScalar dpi,
SkPixelSerializer* jpegEncoder);
static sk_sp<SkDocument> MakePDF(SkWStream* stream,
SkScalar dpi,
const SkDocument::PDFMetadata& metadata,
sk_sp<SkPixelSerializer> jpegEncoder,
bool pdfa);
static sk_sp<SkDocument> MakePDF(SkWStream* stream,
SkScalar dpi = SK_ScalarDefaultRasterDPI) {
return SkDocument::MakePDF(stream, dpi, SkDocument::PDFMetadata(),
nullptr, false);
}
/**
* Create a PDF-backed document, writing the results into a file.
*/
static SkDocument* CreatePDF(const char outputFilePath[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
static sk_sp<SkDocument> MakePDF(const char outputFilePath[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Create a XPS-backed document, writing the results into the stream.
* Returns NULL if XPS is not supported.
*/
static SkDocument* CreateXPS(SkWStream* stream,
SkScalar dpi = SK_ScalarDefaultRasterDPI);
static sk_sp<SkDocument> MakeXPS(SkWStream* stream,
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Create a XPS-backed document, writing the results into a file.
* Returns NULL if XPS is not supported.
*/
static SkDocument* CreateXPS(const char path[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
static sk_sp<SkDocument> MakeXPS(const char path[],
SkScalar dpi = SK_ScalarDefaultRasterDPI);
/**
* Begin a new page for the document, returning the canvas that will draw
* into the page. The document owns this canvas, and it will go out of
@ -115,9 +175,8 @@ public:
* or stream holding the document's contents. After close() the document
* can no longer add new pages. Deleting the document will automatically
* call close() if need be.
* Returns true on success or false on failure.
*/
bool close();
void close();
/**
* Call abort() to stop producing the document immediately.
@ -125,34 +184,6 @@ public:
*/
void abort();
/**
* Set the document's metadata, if supported by the document
* type. The creationDate and modifiedDate parameters can be
* nullptr. For example:
*
* SkDocument* make_doc(SkWStream* output) {
* std::vector<SkDocument::Attribute> info;
* info.emplace_back(SkString("Title"), SkString("..."));
* info.emplace_back(SkString("Author"), SkString("..."));
* info.emplace_back(SkString("Subject"), SkString("..."));
* info.emplace_back(SkString("Keywords"), SkString("..."));
* info.emplace_back(SkString("Creator"), SkString("..."));
* SkTime::DateTime now;
* SkTime::GetDateTime(&now);
* SkDocument* doc = SkDocument::CreatePDF(output);
* doc->setMetadata(&info[0], (int)info.size(), &now, &now);
* return doc;
* }
*/
struct Attribute {
SkString fKey, fValue;
Attribute(const SkString& k, const SkString& v) : fKey(k), fValue(v) {}
};
virtual void setMetadata(const SkDocument::Attribute[],
int /* attributeCount */,
const SkTime::DateTime* /* creationDate */,
const SkTime::DateTime* /* modifiedDate */) {}
protected:
SkDocument(SkWStream*, void (*)(SkWStream*, bool aborted));
@ -163,7 +194,7 @@ protected:
virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height,
const SkRect& content) = 0;
virtual void onEndPage() = 0;
virtual bool onClose(SkWStream*) = 0;
virtual void onClose(SkWStream*) = 0;
virtual void onAbort() = 0;
// Allows subclasses to write to the stream as pages are written.

Просмотреть файл

@ -13,6 +13,7 @@
#include "SkCanvas.h"
#include "SkMask.h"
#include "SkPaint.h"
#include "SkStrokeRec.h"
class SkBitmap;
class SkClipStack;
@ -29,7 +30,6 @@ class SkRRect;
class SkDraw {
public:
SkDraw();
SkDraw(const SkDraw& src);
void drawPaint(const SkPaint&) const;
void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[],
@ -93,7 +93,7 @@ public:
static bool DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
const SkMaskFilter*, const SkMatrix* filterMatrix,
SkMask* mask, SkMask::CreateMode mode,
SkPaint::Style style);
SkStrokeRec::InitStyle style);
enum RectType {
kHair_RectType,
@ -128,6 +128,9 @@ private:
bool pathIsMutable, bool drawCoverage,
SkBlitter* customBlitter = NULL) const;
void drawLine(const SkPoint[2], const SkPaint&) const;
void drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawCoverage,
SkBlitter* customBlitter, bool doFill) const;
/**
* Return the current clip bounds, in local coordinates, with slop to account
* for antialiasing or hairlines (i.e. device-bounds outset by 1, and then
@ -139,17 +142,16 @@ private:
bool SK_WARN_UNUSED_RESULT
computeConservativeLocalClipBounds(SkRect* bounds) const;
/** Returns the current setting for using fake gamma. */
SkPaint::FakeGamma SK_WARN_UNUSED_RESULT fakeGamma() const;
/** Returns the current setting for using fake gamma and contrast. */
uint32_t SK_WARN_UNUSED_RESULT scalerContextFlags() const;
public:
SkPixmap fDst;
const SkMatrix* fMatrix; // required
const SkRegion* fClip; // DEPRECATED
const SkRasterClip* fRC; // required
const SkClipStack* fClipStack; // optional
SkBaseDevice* fDevice; // optional
const SkClipStack* fClipStack; // optional, may be null
SkBaseDevice* fDevice; // optional, may be null
#ifdef SK_DEBUG
void validate() const;

Просмотреть файл

@ -8,9 +8,10 @@
#ifndef SkDrawable_DEFINED
#define SkDrawable_DEFINED
#include "SkRefCnt.h"
#include "SkFlattenable.h"
class SkCanvas;
class SkMatrix;
class SkPicture;
struct SkRect;
@ -21,7 +22,7 @@ struct SkRect;
* allow for clients of the drawable that may want to cache the results, the drawable must
* change its generation ID whenever its internal state changes such that it will draw differently.
*/
class SkDrawable : public SkRefCnt {
class SkDrawable : public SkFlattenable {
public:
SkDrawable();
@ -58,6 +59,9 @@ public:
*/
void notifyDrawingChanged();
SK_DEFINE_FLATTENABLE_TYPE(SkDrawable)
Factory getFactory() const override { return nullptr; }
protected:
virtual SkRect onGetBounds() = 0;
virtual void onDraw(SkCanvas*) = 0;

Просмотреть файл

@ -18,7 +18,9 @@ enum SkFilterQuality {
kNone_SkFilterQuality, //!< fastest but lowest quality, typically nearest-neighbor
kLow_SkFilterQuality, //!< typically bilerp
kMedium_SkFilterQuality, //!< typically bilerp + mipmaps for down-scaling
kHigh_SkFilterQuality //!< slowest but highest quality, typically bicubic or better
kHigh_SkFilterQuality, //!< slowest but highest quality, typically bicubic or better
kLast_SkFilterQuality = kHigh_SkFilterQuality
};
#endif

Просмотреть файл

@ -71,6 +71,7 @@ class SK_API SkFlattenable : public SkRefCnt {
public:
enum Type {
kSkColorFilter_Type,
kSkDrawable_Type,
kSkDrawLooper_Type,
kSkImageFilter_Type,
kSkMaskFilter_Type,
@ -80,6 +81,7 @@ public:
kSkShader_Type,
kSkUnused_Type, // used to be SkUnitMapper
kSkXfermode_Type,
kSkNormalSource_Type,
};
typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);
@ -92,9 +94,15 @@ public:
*/
virtual Factory getFactory() const = 0;
/** Returns the name of the object's class
*/
const char* getTypeName() const { return FactoryToName(getFactory()); }
/**
* Returns the name of the object's class.
*
* Subclasses should override this function if they intend to provide
* support for flattening without using the global registry.
*
* If the flattenable is registered, there is no need to override.
*/
virtual const char* getTypeName() const { return FactoryToName(getFactory()); }
static Factory NameToFactory(const char name[]);
static const char* FactoryToName(Factory);

Просмотреть файл

@ -117,17 +117,21 @@ public:
kLCD_MaskType,
};
static SkFont* Create(SkTypeface*, SkScalar size, MaskType, uint32_t flags);
static SkFont* Create(SkTypeface*, SkScalar size, SkScalar scaleX, SkScalar skewX,
MaskType, uint32_t flags);
static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, MaskType, uint32_t flags);
static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX,
MaskType, uint32_t flags);
/**
* Return a font with the same attributes of this font, but with the specified size.
* If size is not supported (e.g. <= 0 or non-finite) NULL will be returned.
*/
SkFont* cloneWithSize(SkScalar size) const;
sk_sp<SkFont> makeWithSize(SkScalar size) const;
/**
* Return a font with the same attributes of this font, but with the flags.
*/
sk_sp<SkFont> makeWithFlags(uint32_t newFlags) const;
SkTypeface* getTypeface() const { return fTypeface; }
SkTypeface* getTypeface() const { return fTypeface.get(); }
SkScalar getSize() const { return fSize; }
SkScalar getScaleX() const { return fScaleX; }
SkScalar getSkewX() const { return fSkewX; }
@ -139,23 +143,28 @@ public:
bool isEnableAutoHints() const { return SkToBool(fFlags & kEnableAutoHints_Flag); }
bool isEnableByteCodeHints() const { return SkToBool(fFlags & kEnableByteCodeHints_Flag); }
bool isUseNonLinearMetrics() const { return SkToBool(fFlags & kUseNonlinearMetrics_Flag); }
bool isDevKern() const { return SkToBool(fFlags & kDevKern_Flag); }
int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding,
uint16_t glyphs[], int maxGlyphCount) const;
SkGlyphID glyphs[], int maxGlyphCount) const;
int countText(const void* text, size_t byteLength, SkTextEncoding encoding) {
return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
}
SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding) const;
static SkFont* Testing_CreateFromPaint(const SkPaint&);
static sk_sp<SkFont> Testing_CreateFromPaint(const SkPaint&);
private:
enum {
kAllFlags = 0xFF,
};
SkFont(SkTypeface*, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType, uint32_t flags);
virtual ~SkFont();
SkFont(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType,
uint32_t flags);
SkTypeface* fTypeface;
sk_sp<SkTypeface> fTypeface;
SkScalar fSize;
SkScalar fScaleX;
SkScalar fSkewX;

Просмотреть файл

@ -1,95 +0,0 @@
/*
* Copyright 2006 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFontHost_DEFINED
#define SkFontHost_DEFINED
#include "SkTypeface.h"
class SkDescriptor;
class SkScalerContext;
struct SkScalerContextRec;
class SkStream;
class SkWStream;
/** \class SkFontHost
This class is ported to each environment. It is responsible for bridging
the gap between the (sort of) abstract class SkTypeface and the
platform-specific implementation that provides access to font files.
One basic task is for each create (subclass of) SkTypeface, the FontHost is
responsible for assigning a uniqueID. The ID should be unique for the
underlying font file/data, not unique per typeface instance. Thus it is
possible/common to request a typeface for the same font more than once
(e.g. asking for the same font by name several times). The FontHost may
return seperate typeface instances in that case, or it may choose to use a
cache and return the same instance (but calling typeface->ref(), since the
caller is always responsible for calling unref() on each instance that is
returned). Either way, the fontID for those instance(s) will be the same.
In addition, the fontID should never be set to 0. That value is used as a
sentinel to indicate no-font-id.
The major aspects are:
1) Given either a name/style, return a subclass of SkTypeface that
references the closest matching font available on the host system.
2) Given the data for a font (either in a stream or a file name), return
a typeface that allows access to that data.
3) Each typeface instance carries a 32bit ID for its corresponding font.
SkFontHost turns that ID into a stream to access the font's data.
4) Given a font ID, return a subclass of SkScalerContext, which connects a
font scaler (e.g. freetype or other) to the font's data.
5) Utilites to manage the font cache (budgeting) and gamma correction
*/
class SK_API SkFontHost {
public:
/** LCDs either have their color elements arranged horizontally or
vertically. When rendering subpixel glyphs we need to know which way
round they are.
Note, if you change this after startup, you'll need to flush the glyph
cache because it'll have the wrong type of masks cached.
@deprecated use SkPixelGeometry instead.
*/
enum LCDOrientation {
kHorizontal_LCDOrientation = 0, //!< this is the default
kVertical_LCDOrientation = 1
};
/** @deprecated set on Device creation. */
static void SetSubpixelOrientation(LCDOrientation orientation);
/** @deprecated get from Device. */
static LCDOrientation GetSubpixelOrientation();
/** LCD color elements can vary in order. For subpixel text we need to know
the order which the LCDs uses so that the color fringes are in the
correct place.
Note, if you change this after startup, you'll need to flush the glyph
cache because it'll have the wrong type of masks cached.
kNONE_LCDOrder means that the subpixel elements are not spatially
separated in any usable fashion.
@deprecated use SkPixelGeometry instead.
*/
enum LCDOrder {
kRGB_LCDOrder = 0, //!< this is the default
kBGR_LCDOrder = 1,
kNONE_LCDOrder = 2
};
/** @deprecated set on Device creation. */
static void SetSubpixelOrder(LCDOrder order);
/** @deprecated get from Device. */
static LCDOrder GetSubpixelOrder();
};
#endif

Просмотреть файл

@ -10,7 +10,7 @@
#include "SkTypes.h"
class SkFontLCDConfig {
class SK_API SkFontLCDConfig {
public:
/** LCDs either have their color elements arranged horizontally or
vertically. When rendering subpixel glyphs we need to know which way

Просмотреть файл

@ -13,15 +13,17 @@
class SK_API SkFontStyle {
public:
enum Weight {
kThin_Weight = 100,
kExtraLight_Weight = 200,
kLight_Weight = 300,
kNormal_Weight = 400,
kMedium_Weight = 500,
kSemiBold_Weight = 600,
kBold_Weight = 700,
kExtraBold_Weight = 800,
kBlack_Weight = 900
kInvisible_Weight = 0,
kThin_Weight = 100,
kExtraLight_Weight = 200,
kLight_Weight = 300,
kNormal_Weight = 400,
kMedium_Weight = 500,
kSemiBold_Weight = 600,
kBold_Weight = 700,
kExtraBold_Weight = 800,
kBlack_Weight = 900,
kExtraBlack_Weight = 1000,
};
enum Width {
@ -33,18 +35,19 @@ public:
kSemiExpanded_Width = 6,
kExpanded_Width = 7,
kExtraExpanded_Width = 8,
kUltaExpanded_Width = 9
kUltraExpanded_Width = 9,
};
enum Slant {
kUpright_Slant,
kItalic_Slant,
kOblique_Slant,
};
SkFontStyle();
SkFontStyle(int weight, int width, Slant);
/** oldStyle means the style-bits in SkTypeface::Style: bold=1, italic=2 */
explicit SkFontStyle(unsigned oldStyle);
static SkFontStyle FromOldStyle(unsigned oldStyle);
bool operator==(const SkFontStyle& rhs) const {
return fUnion.fU32 == rhs.fUnion.fU32;
@ -54,10 +57,6 @@ public:
int width() const { return fUnion.fR.fWidth; }
Slant slant() const { return (Slant)fUnion.fR.fSlant; }
bool isItalic() const {
return kItalic_Slant == fUnion.fR.fSlant;
}
private:
union {
struct {

Просмотреть файл

@ -28,8 +28,6 @@ class GrContext;
class GrContextThreadSafeProxy;
class GrTexture;
#define SK_SUPPORT_LEGACY_IMAGEFACTORY
/**
* SkImage is an abstraction for drawing a rectagle of pixels, though the
* particular type of image could be actually storing its data on the GPU, or
@ -75,7 +73,7 @@ public:
*
* If a subset is specified, it must be contained within the generator's bounds.
*/
static sk_sp<SkImage> MakeFromGenerator(SkImageGenerator*, const SkIRect* subset = NULL);
static sk_sp<SkImage> MakeFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr);
/**
* Construct a new SkImage based on the specified encoded data. Returns NULL on failure,
@ -83,7 +81,7 @@ public:
*
* If a subset is specified, it must be contained within the encoded data's bounds.
*/
static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = NULL);
static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
/**
* Create a new image from the specified descriptor. Note - the caller is responsible for
@ -92,12 +90,12 @@ public:
* Will return NULL if the specified descriptor is unsupported.
*/
static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc) {
return MakeFromTexture(ctx, desc, kPremul_SkAlphaType, NULL, NULL);
return MakeFromTexture(ctx, desc, kPremul_SkAlphaType, nullptr, nullptr, nullptr);
}
static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& de,
SkAlphaType at) {
return MakeFromTexture(ctx, de, at, NULL, NULL);
return MakeFromTexture(ctx, de, at, nullptr, nullptr, nullptr);
}
typedef void (*TextureReleaseProc)(ReleaseContext);
@ -109,8 +107,21 @@ public:
*
* Will return NULL if the specified descriptor is unsupported.
*/
static sk_sp<SkImage> MakeFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
SkAlphaType at, TextureReleaseProc trp,
ReleaseContext rc) {
return MakeFromTexture(ctx, desc, at, nullptr, trp, rc);
}
/**
* Create a new image from the specified descriptor. The underlying platform texture must stay
* valid and unaltered until the specified release-proc is invoked, indicating that Skia
* no longer is holding a reference to it.
*
* Will return NULL if the specified descriptor is unsupported.
*/
static sk_sp<SkImage> MakeFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
TextureReleaseProc, ReleaseContext);
sk_sp<SkColorSpace>, TextureReleaseProc, ReleaseContext);
/**
* Create a new image from the specified descriptor. Note - Skia will delete or recycle the
@ -119,16 +130,8 @@ public:
* Will return NULL if the specified descriptor is unsupported.
*/
static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext*, const GrBackendTextureDesc&,
SkAlphaType = kPremul_SkAlphaType);
/**
* Create a new image by copying the pixels from the specified descriptor. No reference is
* kept to the original platform texture.
*
* Will return NULL if the specified descriptor is unsupported.
*/
static sk_sp<SkImage> MakeFromTextureCopy(GrContext*, const GrBackendTextureDesc&,
SkAlphaType = kPremul_SkAlphaType);
SkAlphaType = kPremul_SkAlphaType,
sk_sp<SkColorSpace> = nullptr);
/**
* Create a new image by copying the pixels from the specified y, u, v textures. The data
@ -138,7 +141,18 @@ public:
static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext*, SkYUVColorSpace,
const GrBackendObject yuvTextureHandles[3],
const SkISize yuvSizes[3],
GrSurfaceOrigin);
GrSurfaceOrigin,
sk_sp<SkColorSpace> = nullptr);
/**
* Create a new image by copying the pixels from the specified y and uv textures. The data
* from the textures is immediately ingested into the image and the textures can be modified or
* deleted after the function returns. The image will have the dimensions of the y texture.
*/
static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext*, SkYUVColorSpace,
const GrBackendObject nv12TextureHandles[2],
const SkISize nv12Sizes[2], GrSurfaceOrigin,
sk_sp<SkColorSpace> = nullptr);
static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture>, const SkISize& dimensions,
const SkMatrix*, const SkPaint*);
@ -152,7 +166,8 @@ public:
SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
uint32_t uniqueID() const { return fUniqueID; }
virtual bool isOpaque() const { return false; }
SkAlphaType alphaType() const;
bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }
/**
* Extracts YUV planes from the SkImage and stores them in client-provided memory. The sizes
@ -322,10 +337,40 @@ public:
*/
sk_sp<SkImage> makeTextureImage(GrContext*) const;
/**
* If the image is texture-backed this will make a raster copy of it (or nullptr if reading back
* the pixels fails). Otherwise, it returns the original image.
*/
sk_sp<SkImage> makeNonTextureImage() const;
/**
* Apply a given image filter to this image, and return the filtered result.
*
* The subset represents the active portion of this image. The return value is similarly an
* SkImage, with an active subset (outSubset). This is usually used with texture-backed
* images, where the texture may be approx-match and thus larger than the required size.
*
* clipBounds constrains the device-space extent of the image which may be produced to the
* given rect.
*
* offset is the amount to translate the resulting image relative to the src when it is drawn.
* This is an out-param.
*
* If the result image cannot be created, or the result would be transparent black, null
* is returned, in which case the offset and outSubset parameters should be ignored by the
* caller.
*/
sk_sp<SkImage> makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
const SkIRect& clipBounds, SkIRect* outSubset,
SkIPoint* offset) const;
/** Drawing params for which a deferred texture image data should be optimized. */
struct DeferredTextureImageUsageParams {
DeferredTextureImageUsageParams(const SkMatrix matrix, const SkFilterQuality quality,
int preScaleMipLevel)
: fMatrix(matrix), fQuality(quality), fPreScaleMipLevel(preScaleMipLevel) {}
SkMatrix fMatrix;
SkFilterQuality fQuality;
int fPreScaleMipLevel;
};
/**
@ -351,7 +396,9 @@ public:
size_t getDeferredTextureImageData(const GrContextThreadSafeProxy&,
const DeferredTextureImageUsageParams[],
int paramCnt,
void* buffer) const;
void* buffer,
SkSourceGammaTreatment treatment =
SkSourceGammaTreatment::kIgnore) const;
/**
* Returns a texture-backed image from data produced in SkImage::getDeferredTextureImageData.
@ -377,7 +424,7 @@ public:
* to empty.
*/
bool asLegacyBitmap(SkBitmap*, LegacyBitmapMode) const;
/**
* Returns true if the image is backed by an image-generator or other src that creates
* (and caches) its pixels / texture on-demand.
@ -392,21 +439,19 @@ public:
static SkImage* NewFromRaster(const Info&, const void* pixels, size_t rowBytes,
RasterReleaseProc, ReleaseContext);
static SkImage* NewFromBitmap(const SkBitmap&);
static SkImage* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = NULL);
static SkImage* NewFromEncoded(SkData* encoded, const SkIRect* subset = NULL);
static SkImage* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr);
static SkImage* NewFromEncoded(SkData* encoded, const SkIRect* subset = nullptr);
static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& desc) {
return NewFromTexture(ctx, desc, kPremul_SkAlphaType, NULL, NULL);
return NewFromTexture(ctx, desc, kPremul_SkAlphaType, nullptr, nullptr);
}
static SkImage* NewFromTexture(GrContext* ctx, const GrBackendTextureDesc& de, SkAlphaType at) {
return NewFromTexture(ctx, de, at, NULL, NULL);
return NewFromTexture(ctx, de, at, nullptr, nullptr);
}
static SkImage* NewFromTexture(GrContext*, const GrBackendTextureDesc&, SkAlphaType,
TextureReleaseProc, ReleaseContext);
static SkImage* NewFromAdoptedTexture(GrContext*, const GrBackendTextureDesc&,
SkAlphaType = kPremul_SkAlphaType);
static SkImage* NewFromTextureCopy(GrContext*, const GrBackendTextureDesc&,
SkAlphaType = kPremul_SkAlphaType);
static SkImage* NewFromYUVTexturesCopy(GrContext*, SkYUVColorSpace,
const GrBackendObject yuvTextureHandles[3],
const SkISize yuvSizes[3],
@ -424,6 +469,10 @@ protected:
SkImage(int width, int height, uint32_t uniqueID);
private:
static sk_sp<SkImage> MakeTextureFromMipMap(GrContext*, const SkImageInfo&,
const GrMipLevel* texels, int mipLevelCount,
SkBudgeted, SkSourceGammaTreatment);
const int fWidth;
const int fHeight;
const uint32_t fUniqueID;

Просмотреть файл

@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkImageDeserializer_DEFINED
#define SkImageDeserializer_DEFINED
#include "SkRefCnt.h"
struct SkIRect;
class SkData;
class SkImage;
class SK_API SkImageDeserializer {
public:
virtual ~SkImageDeserializer() {}
/**
* Given a data containing serialized content, return an SkImage from it.
*
* @param data The data containing the encoded image. The subclass may ref this for later
* decoding, or read it and process it immediately.
* @param subset Optional rectangle represent the subset of the encoded data that is being
* requested to be turned into an image.
* @return The new image, or nullptr on failure.
*
* The default implementation is to call SkImage::MakeFromEncoded(...)
*/
virtual sk_sp<SkImage> makeFromData(SkData*, const SkIRect* subset);
virtual sk_sp<SkImage> makeFromMemory(const void* data, size_t length, const SkIRect* subset);
};
#endif

Просмотреть файл

@ -91,7 +91,7 @@ protected:
// This macro declares a global (i.e., non-class owned) creation entry point
// for each encoder (e.g., CreateJPEGImageEncoder)
#define DECLARE_ENCODER_CREATOR(codec) \
SkImageEncoder *Create ## codec ();
SK_API SkImageEncoder *Create ## codec ();
// This macro defines the global creation entry point for each encoder. Each
// encoder implementation that registers with the encoder factory must call it.
@ -100,22 +100,17 @@ protected:
// All the encoders known by Skia. Note that, depending on the compiler settings,
// not all of these will be available
/** An ARGBImageEncoder will always write out
* bitmap.width() * bitmap.height() * 4
* bytes.
*/
DECLARE_ENCODER_CREATOR(ARGBImageEncoder);
DECLARE_ENCODER_CREATOR(JPEGImageEncoder);
DECLARE_ENCODER_CREATOR(PNGImageEncoder);
DECLARE_ENCODER_CREATOR(KTXImageEncoder);
DECLARE_ENCODER_CREATOR(WEBPImageEncoder);
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
DECLARE_ENCODER_CREATOR(PNGImageEncoder_CG);
SkImageEncoder* CreateImageEncoder_CG(SkImageEncoder::Type type);
#endif
#if defined(SK_BUILD_FOR_WIN)
DECLARE_ENCODER_CREATOR(ImageEncoder_WIC);
SkImageEncoder* CreateImageEncoder_WIC(SkImageEncoder::Type type);
#endif
// Typedef to make registering encoder callback easier

Просмотреть файл

@ -11,19 +11,19 @@
#include "../private/SkTArray.h"
#include "../private/SkTemplates.h"
#include "../private/SkMutex.h"
#include "SkColorSpace.h"
#include "SkFilterQuality.h"
#include "SkFlattenable.h"
#include "SkMatrix.h"
#include "SkRect.h"
#include "SkSurfaceProps.h"
class GrContext;
class GrFragmentProcessor;
class GrTexture;
class SkBaseDevice;
class SkBitmap;
class SkColorFilter;
struct SkIPoint;
class SkSpecialImage;
class SkImageFilterCache;
struct SkImageFilterCacheKey;
/**
* Base class for image filters. If one is installed in the paint, then
@ -34,38 +34,42 @@ class SkSpecialImage;
*/
class SK_API SkImageFilter : public SkFlattenable {
public:
// This cache maps from (filter's unique ID + CTM + clipBounds + src bitmap generation ID) to
// (result, offset).
class Cache : public SkRefCnt {
// Extra information about the output of a filter DAG. For now, this is just the color space
// (of the original requesting device). This is used when constructing intermediate rendering
// surfaces, so that we ensure we land in a surface that's similar/compatible to the final
// consumer of the DAG's output.
class OutputProperties {
public:
struct Key;
virtual ~Cache() {}
static Cache* Create(size_t maxBytes);
static Cache* Get();
virtual bool get(const Key& key, SkBitmap* result, SkIPoint* offset) const = 0;
virtual SkSpecialImage* get(const Key& key, SkIPoint* offset) const = 0;
virtual void set(const Key& key, const SkBitmap& result, const SkIPoint& offset) = 0;
virtual void set(const Key& key, SkSpecialImage* image, const SkIPoint& offset) = 0;
virtual void purge() {}
virtual void purgeByKeys(const Key[], int) {}
explicit OutputProperties(SkColorSpace* colorSpace) : fColorSpace(colorSpace) {}
SkColorSpace* colorSpace() const { return fColorSpace; }
private:
// This will be a pointer to the device's color space, and our lifetime is bounded by
// the device, so we can store a bare pointer.
SkColorSpace* fColorSpace;
};
class Context {
public:
Context(const SkMatrix& ctm, const SkIRect& clipBounds, Cache* cache)
Context(const SkMatrix& ctm, const SkIRect& clipBounds, SkImageFilterCache* cache,
const OutputProperties& outputProperties)
: fCTM(ctm)
, fClipBounds(clipBounds)
, fCache(cache)
, fOutputProperties(outputProperties)
{}
const SkMatrix& ctm() const { return fCTM; }
const SkIRect& clipBounds() const { return fClipBounds; }
Cache* cache() const { return fCache; }
SkImageFilterCache* cache() const { return fCache; }
const OutputProperties& outputProperties() const { return fOutputProperties; }
private:
SkMatrix fCTM;
SkIRect fClipBounds;
Cache* fCache;
SkMatrix fCTM;
SkIRect fClipBounds;
SkImageFilterCache* fCache;
OutputProperties fOutputProperties;
};
class CropRect {
@ -109,38 +113,8 @@ public:
kNever_TileUsage, //!< the created device will never be drawn tiled
};
class Proxy {
public:
virtual ~Proxy() {}
virtual SkBaseDevice* createDevice(int width, int height,
TileUsage usage = kNever_TileUsage) = 0;
// Returns true if the proxy handled the filter itself. If this returns
// false then the filter's code will be called.
virtual bool filterImage(const SkImageFilter*, const SkBitmap& src,
const SkImageFilter::Context&,
SkBitmap* result, SkIPoint* offset) = 0;
};
class DeviceProxy : public Proxy {
public:
DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
SkBaseDevice* createDevice(int width, int height,
TileUsage usage = kNever_TileUsage) override;
// Returns true if the proxy handled the filter itself. If this returns
// false then the filter's code will be called.
bool filterImage(const SkImageFilter*, const SkBitmap& src, const SkImageFilter::Context&,
SkBitmap* result, SkIPoint* offset) override;
private:
SkBaseDevice* fDevice;
};
/**
* Request a new (result) image to be created from the src image.
* Request a new filtered image to be created from the src image.
*
* The context contains the environment in which the filter is occurring.
* It includes the clip bounds, CTM and cache.
@ -148,8 +122,9 @@ public:
* Offset is the amount to translate the resulting image relative to the
* src when it is drawn. This is an out-param.
*
* If the result image cannot be created, return null, in which case
* the offset parameters will be ignored by the caller.
* If the result image cannot be created, or the result would be
* transparent black, return null, in which case the offset parameter
* should be ignored by the caller.
*
* TODO: Right now the imagefilters sometimes return empty result bitmaps/
* specialimages. That doesn't seem quite right.
@ -174,27 +149,12 @@ public:
SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection = kReverse_MapDirection) const;
/**
* Returns true if the filter can be processed on the GPU. This is most
* often used for multi-pass effects, where intermediate results must be
* rendered to textures. For single-pass effects, use asFragmentProcessor().
* The default implementation returns asFragmentProcessor(NULL, NULL, SkMatrix::I(),
* SkIRect()).
*/
virtual bool canFilterImageGPU() const;
/**
* Process this image filter on the GPU. This is most often used for
* multi-pass effects, where intermediate results must be rendered to
* textures. For single-pass effects, use asFragmentProcessor(). src is the
* source image for processing, as a texture-backed bitmap. result is
* the destination bitmap, which should contain a texture-backed pixelref
* on success. offset is the amount to translate the resulting image
* relative to the src when it is drawn. The default implementation does
* single-pass processing using asFragmentProcessor().
*/
virtual bool filterImageGPUDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const;
#if SK_SUPPORT_GPU
static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,
sk_sp<GrFragmentProcessor> fp,
const SkIRect& bounds,
const OutputProperties& outputProperties);
#endif
/**
* Returns whether this image filter is a color filter and puts the color filter into the
@ -212,6 +172,10 @@ public:
return this->isColorFilterNode(filterPtr);
}
static sk_sp<SkImageFilter> MakeBlur(SkScalar sigmaX, SkScalar sigmaY,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr);
/**
* Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
* replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
@ -223,15 +187,15 @@ public:
* Returns the number of inputs this filter will accept (some inputs can
* be NULL).
*/
int countInputs() const { return fInputCount; }
int countInputs() const { return fInputs.count(); }
/**
* Returns the input filter at a given index, or NULL if no input is
* connected. The indices used are filter-specific.
*/
SkImageFilter* getInput(int i) const {
SkASSERT(i < fInputCount);
return fInputs[i];
SkASSERT(i < fInputs.count());
return fInputs[i].get();
}
/**
@ -241,9 +205,7 @@ public:
* The size of the crop rect should be
* used as the size of the destination image. The origin of this rect
* should be used to offset access to the input images, and should also
* be added to the "offset" parameter in onFilterImage and
* filterImageGPU(). (The latter ensures that the resulting buffer is
* drawn in the correct location.)
* be added to the "offset" parameter in onFilterImage.
*/
bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
@ -268,11 +230,19 @@ public:
#endif
/**
* Create an SkMatrixImageFilter, which transforms its input by the given matrix.
* ImageFilters can natively handle scaling and translate components in the CTM. Only some of
* them can handle affine (or more complex) matrices. This call returns true iff the filter
* and all of its (non-null) inputs can handle these more complex matrices.
*/
bool canHandleComplexCTM() const;
/**
* Return an imagefilter which transforms its input by the given matrix.
*/
static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,
SkFilterQuality,
SkFilterQuality quality,
sk_sp<SkImageFilter> input);
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* CreateMatrixFilter(const SkMatrix& matrix,
SkFilterQuality filterQuality,
@ -281,26 +251,9 @@ public:
}
#endif
sk_sp<SkSpecialImage> filterInput(int index,
SkSpecialImage* src,
const Context&,
SkIPoint* offset) const;
#if SK_SUPPORT_GPU
// Helper function which invokes GPU filter processing on the
// input at the specified "index". If the input is null, it leaves
// "result" and "offset" untouched, and returns true. If the input
// has a GPU implementation, it will be invoked directly.
// Otherwise, the filter will be processed in software and
// uploaded to the GPU.
bool filterInputGPUDeprecated(int index, SkImageFilter::Proxy* proxy,
const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const;
#endif
SK_TO_STRING_PUREVIRT()
SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter)
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
protected:
class Common {
@ -321,12 +274,6 @@ protected:
sk_sp<SkImageFilter> getInput(int index) const { return fInputs[index]; }
// If the caller wants a copy of the inputs, call this and it will transfer ownership
// of the unflattened input filters to the caller. This is just a short-cut for copying
// the inputs, calling ref() on each, and then waiting for Common's destructor to call
// unref() on each.
void detachInputs(SkImageFilter** inputs);
private:
CropRect fCropRect;
// most filters accept at most 2 input-filters
@ -335,8 +282,6 @@ protected:
void allocInputs(int count);
};
SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = nullptr);
SkImageFilter(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect);
virtual ~SkImageFilter();
@ -364,15 +309,15 @@ protected:
* Offset is the amount to translate the resulting image relative to the
* src when it is drawn. This is an out-param.
*
* If the result image cannot be created, this should false, in which
* case both the result and offset parameters will be ignored by the
* caller.
* If the result image cannot be created (either because of error or if, say, the result
* is entirely clipped out), this should return nullptr.
* Callers that affect transparent black should explicitly handle nullptr
* results and press on. In the error case this behavior will produce a better result
* than nothing and is necessary for the clipped out case.
* If the return value is nullptr then offset should be ignored.
*/
virtual bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const;
virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&,
SkIPoint* offset) const;
SkIPoint* offset) const = 0;
/**
* This function recurses into its inputs with the given rect (first
@ -403,12 +348,13 @@ protected:
virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const;
// Helper function which invokes filter processing on the input at the
// specified "index". If the input is null, it leaves "result" and
// "offset" untouched, and returns true. If the input is non-null, it
// calls filterImage() on that input, and returns true on success.
// i.e., return !getInput(index) || getInput(index)->filterImage(...);
bool filterInputDeprecated(int index, Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const;
// specified "index". If the input is null, it returns "src" and leaves
// "offset" untouched. If the input is non-null, it
// calls filterImage() on that input, and returns the result.
sk_sp<SkSpecialImage> filterInput(int index,
SkSpecialImage* src,
const Context&,
SkIPoint* offset) const;
/**
* Return true (and return a ref'd colorfilter) if this node in the DAG is just a
@ -418,13 +364,18 @@ protected:
return false;
}
/** Given a "srcBounds" rect, computes destination bounds for this
* destination bounds for this filter. "dstBounds" are computed by
* transforming the crop rect by the context's CTM, applying it to the
* initial bounds, and intersecting the result with the context's clip
* bounds. "srcBounds" (if non-null) are computed by intersecting the
* initial bounds with "dstBounds", to ensure that we never sample
* outside of the crop rect (this restriction may be relaxed in the
/**
* Override this to describe the behavior of your subclass - as a leaf node. The caller will
* take care of calling your inputs (and return false if any of them could not handle it).
*/
virtual bool onCanHandleComplexCTM() const { return false; }
/** Given a "srcBounds" rect, computes destination bounds for this filter.
* "dstBounds" are computed by transforming the crop rect by the context's
* CTM, applying it to the initial bounds, and intersecting the result with
* the context's clip bounds. "srcBounds" (if non-null) are computed by
* intersecting the initial bounds with "dstBounds", to ensure that we never
* sample outside of the crop rect (this restriction may be relaxed in the
* future).
*/
bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
@ -438,30 +389,9 @@ protected:
* which are not capable of processing a smaller source bitmap into a
* larger destination.
*/
bool applyCropRectDeprecated(const Context&, Proxy* proxy, const SkBitmap& src,
SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* result) const;
sk_sp<SkSpecialImage> applyCropRect(const Context&, SkSpecialImage* src, SkIPoint* srcOffset,
SkIRect* bounds) const;
/**
* Returns true if the filter can be expressed a single-pass
* GrProcessor, used to process this filter on the GPU, or false if
* not.
*
* If effect is non-NULL, a new GrProcessor instance is stored
* in it. The caller assumes ownership of the stage, and it is up to the
* caller to unref it.
*
* The effect can assume its vertexCoords space maps 1-to-1 with texels
* in the texture. "matrix" is a transformation to apply to filter
* parameters before they are used in the effect. Note that this function
* will be called with (NULL, NULL, SkMatrix::I()) to query for support,
* so returning "true" indicates support for all possible matrices.
*/
virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
const SkIRect& bounds) const;
/**
* Creates a modified Context for use when recursing up the image filter DAG.
* The clip bounds are adjusted to accommodate any margins that this
@ -474,20 +404,19 @@ private:
friend class SkGraphics;
static void PurgeCache();
bool filterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const;
void init(sk_sp<SkImageFilter>* inputs, int inputCount, const CropRect* cropRect);
bool usesSrcInput() const { return fUsesSrcInput; }
virtual bool affectsTransparentBlack() const { return false; }
typedef SkFlattenable INHERITED;
int fInputCount;
SkImageFilter** fInputs;
SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
bool fUsesSrcInput;
CropRect fCropRect;
uint32_t fUniqueID; // Globally unique
mutable SkTArray<Cache::Key> fCacheKeys;
mutable SkTArray<SkImageFilterCacheKey> fCacheKeys;
mutable SkMutex fMutex;
typedef SkFlattenable INHERITED;
};
/**

Просмотреть файл

@ -251,7 +251,11 @@ public:
}
protected:
SkImageGenerator(const SkImageInfo& info);
enum {
kNeedNewImageUniqueID = 0
};
SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);
virtual SkData* onRefEncodedData(SK_REFENCODEDDATA_CTXPARAM);

Просмотреть файл

@ -8,6 +8,7 @@
#ifndef SkImageInfo_DEFINED
#define SkImageInfo_DEFINED
#include "SkColorSpace.h"
#include "SkMath.h"
#include "SkRect.h"
#include "SkSize.h"
@ -105,6 +106,25 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) {
return gSize[ct];
}
static int SkColorTypeShiftPerPixel(SkColorType ct) {
static const uint8_t gShift[] = {
0, // Unknown
0, // Alpha_8
1, // RGB_565
1, // ARGB_4444
2, // RGBA_8888
2, // BGRA_8888
0, // kIndex_8
0, // kGray_8
3, // kRGBA_F16
};
static_assert(SK_ARRAY_COUNT(gShift) == (size_t)(kLastEnum_SkColorType + 1),
"size_mismatch_with_SkColorType_enum");
SkASSERT((size_t)ct < SK_ARRAY_COUNT(gShift));
return gShift[ct];
}
static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
return width * SkColorTypeBytesPerPixel(ct);
}
@ -114,15 +134,10 @@ static inline bool SkColorTypeIsValid(unsigned value) {
}
static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) {
int shift = 0;
switch (SkColorTypeBytesPerPixel(ct)) {
case 8: shift = 3; break;
case 4: shift = 2; break;
case 2: shift = 1; break;
case 1: shift = 0; break;
default: return 0;
if (kUnknown_SkColorType == ct) {
return 0;
}
return y * rowBytes + (x << shift);
return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct));
}
///////////////////////////////////////////////////////////////////////////////
@ -154,11 +169,9 @@ enum SkYUVColorSpace {
///////////////////////////////////////////////////////////////////////////////
enum SkColorProfileType {
kLinear_SkColorProfileType,
kSRGB_SkColorProfileType,
kLastEnum_SkColorProfileType = kSRGB_SkColorProfileType
enum class SkSourceGammaTreatment {
kRespect,
kIgnore,
};
/**
@ -168,61 +181,59 @@ enum SkColorProfileType {
struct SK_API SkImageInfo {
public:
SkImageInfo()
: fWidth(0)
: fColorSpace(nullptr)
, fWidth(0)
, fHeight(0)
, fColorType(kUnknown_SkColorType)
, fAlphaType(kUnknown_SkAlphaType)
, fProfileType(kLinear_SkColorProfileType)
{}
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
SkColorProfileType pt = kLinear_SkColorProfileType) {
return SkImageInfo(width, height, ct, at, pt);
sk_sp<SkColorSpace> cs = nullptr) {
return SkImageInfo(width, height, ct, at, std::move(cs));
}
/**
* Sets colortype to the native ARGB32 type.
*/
static SkImageInfo MakeN32(int width, int height, SkAlphaType at,
SkColorProfileType pt = kLinear_SkColorProfileType) {
return SkImageInfo(width, height, kN32_SkColorType, at, pt);
sk_sp<SkColorSpace> cs = nullptr) {
return Make(width, height, kN32_SkColorType, at, cs);
}
/**
* Create an ImageInfo marked as SRGB with N32 swizzle.
*/
static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
/**
* Sets colortype to the native ARGB32 type, and the alphatype to premul.
*/
static SkImageInfo MakeN32Premul(int width, int height,
SkColorProfileType pt = kLinear_SkColorProfileType) {
return SkImageInfo(width, height, kN32_SkColorType, kPremul_SkAlphaType, pt);
static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) {
return Make(width, height, kN32_SkColorType, kPremul_SkAlphaType, cs);
}
/**
* Sets colortype to the native ARGB32 type, and the alphatype to premul.
*/
static SkImageInfo MakeN32Premul(const SkISize& size,
SkColorProfileType pt = kLinear_SkColorProfileType) {
return MakeN32Premul(size.width(), size.height(), pt);
static SkImageInfo MakeN32Premul(const SkISize& size) {
return MakeN32Premul(size.width(), size.height());
}
static SkImageInfo MakeA8(int width, int height) {
return SkImageInfo(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType,
kLinear_SkColorProfileType);
return Make(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);
}
static SkImageInfo MakeUnknown(int width, int height) {
return SkImageInfo(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType,
kLinear_SkColorProfileType);
return Make(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr);
}
static SkImageInfo MakeUnknown() {
return SkImageInfo();
return MakeUnknown(0, 0);
}
int width() const { return fWidth; }
int height() const { return fHeight; }
SkColorType colorType() const { return fColorType; }
SkAlphaType alphaType() const { return fAlphaType; }
SkColorProfileType profileType() const { return fProfileType; }
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
@ -230,32 +241,37 @@ public:
return SkAlphaTypeIsOpaque(fAlphaType);
}
bool isLinear() const { return kLinear_SkColorProfileType == fProfileType; }
bool isSRGB() const { return kSRGB_SkColorProfileType == fProfileType; }
SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
bool gammaCloseToSRGB() const {
return fColorSpace && fColorSpace->gammaCloseToSRGB();
}
/**
* Return a new ImageInfo with the same colortype and alphatype as this info,
* but with the specified width and height.
*/
SkImageInfo makeWH(int newWidth, int newHeight) const {
return SkImageInfo::Make(newWidth, newHeight, fColorType, fAlphaType, fProfileType);
return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace);
}
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
return SkImageInfo::Make(fWidth, fHeight, fColorType, newAlphaType, fProfileType);
return Make(fWidth, fHeight, fColorType, newAlphaType, fColorSpace);
}
SkImageInfo makeColorType(SkColorType newColorType) const {
return SkImageInfo::Make(fWidth, fHeight, newColorType, fAlphaType, fProfileType);
return Make(fWidth, fHeight, newColorType, fAlphaType, fColorSpace);
}
int bytesPerPixel() const {
return SkColorTypeBytesPerPixel(fColorType);
SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {
return Make(fWidth, fHeight, fColorType, fAlphaType, std::move(cs));
}
int bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
int shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
uint64_t minRowBytes64() const {
return sk_64_mul(fWidth, this->bytesPerPixel());
}
@ -271,10 +287,12 @@ public:
}
bool operator==(const SkImageInfo& other) const {
return 0 == memcmp(this, &other, sizeof(other));
return fWidth == other.fWidth && fHeight == other.fHeight &&
fColorType == other.fColorType && fAlphaType == other.fAlphaType &&
SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());
}
bool operator!=(const SkImageInfo& other) const {
return 0 != memcmp(this, &other, sizeof(other));
return !(*this == other);
}
void unflatten(SkReadBuffer&);
@ -300,32 +318,42 @@ public:
return rowBytes >= rb;
}
void reset() {
fColorSpace = nullptr;
fWidth = 0;
fHeight = 0;
fColorType = kUnknown_SkColorType;
fAlphaType = kUnknown_SkAlphaType;
}
SkDEBUGCODE(void validate() const;)
private:
sk_sp<SkColorSpace> fColorSpace;
int fWidth;
int fHeight;
SkColorType fColorType;
SkAlphaType fAlphaType;
SkColorProfileType fProfileType;
SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, SkColorProfileType pt)
: fWidth(width)
SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs)
: fColorSpace(std::move(cs))
, fWidth(width)
, fHeight(height)
, fColorType(ct)
, fAlphaType(at)
, fProfileType(pt)
{}
};
///////////////////////////////////////////////////////////////////////////////
static inline bool SkColorAndProfileAreGammaCorrect(SkColorType ct, SkColorProfileType pt) {
return kSRGB_SkColorProfileType == pt || kRGBA_F16_SkColorType == ct;
static inline bool SkColorAndColorSpaceAreGammaCorrect(SkColorType ct, SkColorSpace* cs) {
// Anything with a color-space attached is gamma-correct, as is F16.
// To get legacy behavior, you need to ask for non-F16, with a nullptr color space.
return (cs != nullptr) || kRGBA_F16_SkColorType == ct;
}
static inline bool SkImageInfoIsGammaCorrect(const SkImageInfo& info) {
return SkColorAndProfileAreGammaCorrect(info.colorType(), info.profileType());
return SkColorAndColorSpaceAreGammaCorrect(info.colorType(), info.colorSpace());
}
#endif

Просмотреть файл

@ -0,0 +1,199 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkLights_DEFINED
#define SkLights_DEFINED
#include "../private/SkTArray.h"
#include "SkPoint3.h"
#include "SkRefCnt.h"
class SkReadBuffer;
class SkWriteBuffer;
class SkImage;
class SK_API SkLights : public SkRefCnt {
public:
class Light {
public:
enum LightType {
kDirectional_LightType,
kPoint_LightType
};
Light(const Light& other)
: fType(other.fType)
, fColor(other.fColor)
, fDirOrPos(other.fDirOrPos)
, fIntensity(other.fIntensity)
, fShadowMap(other.fShadowMap)
, fIsRadial(other.fIsRadial) {
}
Light(Light&& other)
: fType(other.fType)
, fColor(other.fColor)
, fDirOrPos(other.fDirOrPos)
, fIntensity(other.fIntensity)
, fShadowMap(std::move(other.fShadowMap))
, fIsRadial(other.fIsRadial) {
}
static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir,
bool isRadial = false) {
Light light(kDirectional_LightType, color, dir, isRadial);
if (!light.fDirOrPos.normalize()) {
light.fDirOrPos.set(0.0f, 0.0f, 1.0f);
}
return light;
}
static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity,
bool isRadial = false) {
return Light(kPoint_LightType, color, pos, intensity, isRadial);
}
LightType type() const { return fType; }
const SkColor3f& color() const { return fColor; }
const SkVector3& dir() const {
SkASSERT(kDirectional_LightType == fType);
return fDirOrPos;
}
const SkPoint3& pos() const {
SkASSERT(kPoint_LightType == fType);
return fDirOrPos;
}
SkScalar intensity() const {
SkASSERT(kPoint_LightType == fType);
return fIntensity;
}
void setShadowMap(sk_sp<SkImage> shadowMap) {
fShadowMap = std::move(shadowMap);
}
SkImage* getShadowMap() const {
return fShadowMap.get();
}
bool isRadial() const { return fIsRadial; }
Light& operator= (const Light& b) {
if (this == &b) {
return *this;
}
fColor = b.fColor;
fType = b.fType;
fDirOrPos = b.fDirOrPos;
fIntensity = b.fIntensity;
fShadowMap = b.fShadowMap;
fIsRadial = b.fIsRadial;
return *this;
}
bool operator== (const Light& b) {
if (this == &b) {
return true;
}
return (fColor == b.fColor) &&
(fType == b.fType) &&
(fDirOrPos == b.fDirOrPos) &&
(fShadowMap == b.fShadowMap) &&
(fIntensity == b.fIntensity) &&
(fIsRadial == b.fIsRadial);
}
bool operator!= (const Light& b) { return !(this->operator==(b)); }
private:
LightType fType;
SkColor3f fColor; // linear (unpremul) color. Range is 0..1 in each channel.
SkVector3 fDirOrPos; // For directional lights, holds the direction towards the
// light (+Z is out of the screen).
// If degenerate, it will be replaced with (0, 0, 1).
// For point lights, holds location of point light
SkScalar fIntensity; // For point lights, dictates the light intensity.
// Simply a multiplier to the final light output value.
sk_sp<SkImage> fShadowMap;
bool fIsRadial; // Whether the light is radial or not. Radial lights will
// cast shadows and lights radially outwards.
Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos,
SkScalar intensity = 0.0f, bool isRadial = false) {
fType = type;
fColor = color;
fDirOrPos = dirOrPos;
fIntensity = intensity;
fIsRadial = isRadial;
}
};
class Builder {
public:
Builder() : fLights(new SkLights) {}
void add(const Light& light) {
if (fLights) {
fLights->fLights.push_back(light);
}
}
void add(Light&& light) {
if (fLights) {
fLights->fLights.push_back(std::move(light));
}
}
void setAmbientLightColor(const SkColor3f& color) {
if (fLights) {
fLights->fAmbientLightColor = color;
}
}
sk_sp<SkLights> finish() {
return std::move(fLights);
}
private:
sk_sp<SkLights> fLights;
};
int numLights() const {
return fLights.count();
}
const Light& light(int index) const {
return fLights[index];
}
Light& light(int index) {
return fLights[index];
}
const SkColor3f& ambientLightColor() const {
return fAmbientLightColor;
}
static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
void flatten(SkWriteBuffer& buf) const;
private:
SkLights() {
fAmbientLightColor.set(0.0f, 0.0f, 0.0f);
}
SkTArray<Light> fLights;
SkColor3f fAmbientLightColor;
typedef SkRefCnt INHERITED;
};
#endif

Просмотреть файл

@ -14,8 +14,10 @@
#include "SkFlattenable.h"
#include "SkMask.h"
#include "SkPaint.h"
#include "SkStrokeRec.h"
class GrClip;
class GrContext;
class GrDrawContext;
class GrPaint;
class GrRenderTarget;
@ -27,7 +29,6 @@ class SkMatrix;
class SkPath;
class SkRasterClip;
class SkRRect;
class SkStrokeRec;
/** \class SkMaskFilter
@ -122,27 +123,26 @@ public:
* Try to directly render a rounded rect mask filter into the target. Returns
* true if drawing was successful.
*/
virtual bool directFilterRRectMaskGPU(GrTextureProvider* texProvider,
virtual bool directFilterRRectMaskGPU(GrContext*,
GrDrawContext* drawContext,
GrPaint* grp,
const GrClip&,
const SkMatrix& viewMatrix,
const SkStrokeRec& strokeRec,
const SkRRect& rrect) const;
const SkRRect& rrect,
const SkRRect& devRRect) const;
/**
* This function is used to implement filters that require an explicit src mask. It should only
* be called if canFilterMaskGPU returned true and the maskRect param should be the output from
* that call. canOverwriteSrc indicates whether the implementation may treat src as a scratch
* texture and overwrite its contents. When true it is also legal to return src as the result.
* that call.
* Implementations are free to get the GrContext from the src texture in order to create
* additional textures and perform multiple passes.
*/
virtual bool filterMaskGPU(GrTexture* src,
const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const;
const SkIRect& maskRect,
GrTexture** result) const;
#endif
/**
@ -228,14 +228,14 @@ private:
This method is not exported to java.
*/
bool filterPath(const SkPath& devPath, const SkMatrix& ctm, const SkRasterClip&, SkBlitter*,
SkPaint::Style) const;
SkStrokeRec::InitStyle) const;
/** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format
mask and then call filterMask(). If this returns true, the specified blitter will be called
to render that mask. Returns false if filterMask() returned false.
*/
bool filterRRect(const SkRRect& devRRect, const SkMatrix& ctm, const SkRasterClip&,
SkBlitter*, SkPaint::Style style) const;
SkBlitter*) const;
typedef SkFlattenable INHERITED;
};

Просмотреть файл

@ -52,13 +52,6 @@ static inline int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom) {
return sk_64_asS32(tmp);
}
/**
* 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
*/
@ -68,35 +61,6 @@ int32_t SkSqrtBits(int32_t value, int bitBias);
*/
#define SkSqrt32(n) SkSqrtBits(n, 15)
//! Returns the number of leading zero bits (0...32)
int SkCLZ_portable(uint32_t);
#ifndef SkCLZ
#if defined(_MSC_VER)
#include <intrin.h>
static inline int SkCLZ(uint32_t mask) {
if (mask) {
DWORD index;
_BitScanReverse(&index, mask);
// Suppress this bogus /analyze warning. The check for non-zero
// guarantees that _BitScanReverse will succeed.
#pragma warning(suppress : 6102) // Using 'index' from failed function call
return index ^ 0x1F;
} else {
return 32;
}
}
#elif defined(SK_CPU_ARM32) || defined(__GNUC__) || defined(__clang__)
static inline int SkCLZ(uint32_t mask) {
// __builtin_clz(0) is undefined, so we have to detect that case.
return mask ? __builtin_clz(mask) : 32;
}
#else
#define SkCLZ(x) SkCLZ_portable(x)
#endif
#endif
/**
* Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches)
*/
@ -122,35 +86,11 @@ static inline int SkClampMax(int value, int max) {
return value;
}
/**
* 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);
}
/**
* Returns true if value is a power of 2. Does not explicitly check for
* value <= 0.
*/
template <typename T> inline bool SkIsPow2(T value) {
template <typename T> constexpr inline bool SkIsPow2(T value) {
return (value & (value - 1)) == 0;
}

Просмотреть файл

@ -80,7 +80,7 @@ public:
/** 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.
90 degrees, or mirrors in x or y.
*/
bool rectStaysRect() const {
if (fTypeMask & kUnknown_Mask) {
@ -561,6 +561,12 @@ public:
this->mapPoints(dst, 4);
}
/**
* Maps a rect to another rect, asserting (in debug mode) that the matrix only contains
* scale and translate elements. If it contains other elements, the results are undefined.
*/
void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
/** 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.
@ -704,6 +710,37 @@ public:
this->setTypeMask(kUnknown_Mask);
}
/**
* Initialize the matrix to be scale + post-translate.
*/
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
fMat[kMScaleX] = sx;
fMat[kMSkewX] = 0;
fMat[kMTransX] = tx;
fMat[kMSkewY] = 0;
fMat[kMScaleY] = sy;
fMat[kMTransY] = ty;
fMat[kMPersp0] = 0;
fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
unsigned mask = 0;
if (sx != 1 || sy != 1) {
mask |= kScale_Mask;
}
if (tx || ty) {
mask |= kTranslate_Mask;
}
this->setTypeMask(mask | kRectStaysRect_Mask);
}
/**
* Are all elements of the matrix finite?
*/
bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
private:
enum {
/** Set if the matrix will map a rectangle to another rectangle. This
@ -736,35 +773,8 @@ private:
SkScalar fMat[9];
mutable uint32_t fTypeMask;
/** Are all elements of the matrix finite?
*/
bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
fMat[kMScaleX] = sx;
fMat[kMSkewX] = 0;
fMat[kMTransX] = tx;
fMat[kMSkewY] = 0;
fMat[kMScaleY] = sy;
fMat[kMTransY] = ty;
fMat[kMPersp0] = 0;
fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
unsigned mask = 0;
if (sx != 1 || sy != 1) {
mask |= kScale_Mask;
}
if (tx || ty) {
mask |= kTranslate_Mask;
}
this->setTypeMask(mask | kRectStaysRect_Mask);
}
uint8_t computeTypeMask() const;
uint8_t computePerspectiveTypeMask() const;
@ -833,6 +843,7 @@ private:
static const MapPtsProc gMapPtsProcs[];
friend class SkPerspIter;
friend class SkMatrixPriv;
};
SK_END_REQUIRE_DENSE

Просмотреть файл

@ -136,8 +136,15 @@ public:
kIdentity_Constructor
};
SkMatrix44(Uninitialized_Constructor) { }
SkMatrix44(Identity_Constructor) { this->setIdentity(); }
SkMatrix44(Uninitialized_Constructor) {}
constexpr SkMatrix44(Identity_Constructor)
: fMat{{ 1, 0, 0, 0, },
{ 0, 1, 0, 0, },
{ 0, 0, 1, 0, },
{ 0, 0, 0, 1, }}
, fTypeMask(kIdentity_Mask)
{}
SK_ATTR_DEPRECATED("use the constructors that take an enum")
SkMatrix44() { this->setIdentity(); }
@ -281,6 +288,10 @@ public:
* array. The given array must have room for exactly 16 entries. Whenever
* possible, they will try to use memcpy rather than an entry-by-entry
* copy.
*
* Col major indicates that consecutive elements of columns will be stored
* contiguously in memory. Row major indicates that consecutive elements
* of rows will be stored contiguously in memory.
*/
void asColMajorf(float[]) const;
void asColMajord(double[]) const;
@ -291,6 +302,11 @@ public:
* array. The given array must have room for exactly 16 entries. Whenever
* possible, they will try to use memcpy rather than an entry-by-entry
* copy.
*
* Col major indicates that input memory will be treated as if consecutive
* elements of columns are stored contiguously in memory. Row major
* indicates that input memory will be treated as if consecutive elements
* of rows are stored contiguously in memory.
*/
void setColMajorf(const float[]);
void setColMajord(const double[]);
@ -306,10 +322,12 @@ public:
#endif
/* This sets the top-left of the matrix and clears the translation and
* perspective components (with [3][3] set to 1). */
* perspective components (with [3][3] set to 1). mXY is interpreted
* as the matrix entry at col = X, row = Y. */
void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02,
SkMScalar m10, SkMScalar m11, SkMScalar m12,
SkMScalar m20, SkMScalar m21, SkMScalar m22);
void set3x3RowMajorf(const float[]);
void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
@ -429,6 +447,7 @@ public:
double determinant() const;
private:
/* This is indexed by [col][row]. */
SkMScalar fMat[4][4];
mutable unsigned fTypeMask;
@ -438,6 +457,9 @@ private:
kAllPublic_Masks = 0xF
};
void as3x4RowMajorf(float[]) const;
void set3x4RowMajorf(const float[]);
SkMScalar transX() const { return fMat[3][0]; }
SkMScalar transY() const { return fMat[3][1]; }
SkMScalar transZ() const { return fMat[3][2]; }
@ -468,6 +490,8 @@ private:
inline bool isTriviallyIdentity() const {
return 0 == fTypeMask;
}
friend class SkColorSpace;
};
#endif

Просмотреть файл

@ -5,5 +5,5 @@
* found in the LICENSE file.
*/
#ifndef SK_MILESTONE
#define SK_MILESTONE 51
#define SK_MILESTONE 55
#endif

Просмотреть файл

@ -8,11 +8,14 @@
#ifndef SkPaint_DEFINED
#define SkPaint_DEFINED
#include "SkBlendMode.h"
#include "SkColor.h"
#include "SkFilterQuality.h"
#include "SkMatrix.h"
#include "SkXfermode.h"
//#define SK_SUPPORT_LEGACY_XFERMODE_OBJECT
class SkAutoDescriptor;
class SkAutoGlyphCache;
class SkColorFilter;
@ -30,8 +33,10 @@ class SkPath;
class SkPathEffect;
struct SkPoint;
class SkRasterizer;
struct SkScalerContextEffects;
class SkShader;
class SkSurfaceProps;
class SkTextBlob;
class SkTypeface;
#define kBicubicFilterBitmap_Flag kHighQualityFilterBitmap_Flag
@ -408,9 +413,10 @@ public:
kRound_Cap, //!< begin/end contours with a semi-circle extension
kSquare_Cap, //!< begin/end contours with a half square extension
kCapCount,
kLast_Cap = kSquare_Cap,
kDefault_Cap = kButt_Cap
};
static constexpr int kCapCount = kLast_Cap + 1;
/** Join enum specifies the settings for the paint's strokejoin. This is
the treatment that is applied to corners in paths and rectangles.
@ -420,9 +426,10 @@ public:
kRound_Join, //!< connect path segments with a round join
kBevel_Join, //!< connect path segments with a flat bevel join
kJoinCount,
kLast_Join = kBevel_Join,
kDefault_Join = kMiter_Join
};
static constexpr int kJoinCount = kLast_Join + 1;
/** Return the paint's stroke cap type, controlling how the start and end
of stroked lines and paths are treated.
@ -521,12 +528,13 @@ public:
#endif
void setColorFilter(sk_sp<SkColorFilter>);
#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT
/** Get the paint's xfermode object.
<p />
The xfermode's reference count is not affected.
@return the paint's xfermode (or NULL)
*/
SkXfermode* getXfermode() const { return fXfermode.get(); }
SkXfermode* getXfermode() const;
/** Set or clear the xfermode object.
<p />
@ -548,6 +556,11 @@ public:
the paint's xfermode is set to null.
*/
SkXfermode* setXfermodeMode(SkXfermode::Mode);
#endif
SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
/** Get the paint's patheffect object.
<p />
@ -613,8 +626,10 @@ public:
paint
@return typeface
*/
SkTypeface* setTypeface(SkTypeface* typeface);
void setTypeface(sk_sp<SkTypeface>);
#ifdef SK_SUPPORT_LEGACY_TYPEFACE_PTR
SkTypeface* setTypeface(SkTypeface* typeface);
#endif
/** Get the paint's rasterizer (or NULL).
<p />
@ -647,19 +662,18 @@ public:
* Return the paint's SkDrawLooper (if any). Does not affect the looper's
* reference count.
*/
SkDrawLooper* getLooper() const { return fLooper.get(); }
SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }
SkDrawLooper* getLooper() const { return fDrawLooper.get(); }
/**
* Set or clear the looper object.
* <p />
* Pass NULL to clear any previous looper.
* As a convenience, the parameter passed is also returned.
* If a previous looper exists in the paint, its reference count is
* decremented. If looper is not NULL, its reference count is
* incremented.
* @param looper May be NULL. The new looper to be installed in the paint.
* @return looper
*/
void setDrawLooper(sk_sp<SkDrawLooper>);
#ifdef SK_SUPPORT_LEGACY_MINOR_EFFECT_PTR
SkDrawLooper* setLooper(SkDrawLooper* looper);
#endif
@ -816,7 +830,7 @@ public:
is returned.
*/
int textToGlyphs(const void* text, size_t byteLength,
uint16_t glyphs[]) const;
SkGlyphID glyphs[]) const;
/** Return true if all of the specified text has a corresponding non-zero
glyph ID. If any of the code-points in the text are not supported in
@ -831,7 +845,7 @@ public:
to zero. Note: this does not look at the text-encoding setting in the
paint, only at the typeface.
*/
void glyphsToUnichars(const uint16_t glyphs[], int count, SkUnichar text[]) const;
void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
/** Return the number of drawable units in the specified text buffer.
This looks at the current TextEncoding field of the paint. If you also
@ -959,6 +973,40 @@ public:
int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
const SkScalar bounds[2], SkScalar* intervals) const;
/** Return the number of intervals that intersect the intercept along the axis of the advance.
* The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
* string. The caller may pass nullptr for intervals to determine the size of the interval
* array, or may conservatively pre-allocate an array with length * 2 entries. The computed
* intervals are cached by glyph to improve performance for multiple calls.
* This permits constructing an underline that skips the descenders.
*
* @param text The text.
* @param length Number of bytes of text.
* @param xpos Array of x-positions, used to position each character.
* @param constY The shared Y coordinate for all of the positions.
* @param bounds The lower and upper line parallel to the advance.
* @param array If not null, the glyph bounds contained by the advance parallel lines.
*
* @return The number of intersections, which may be zero.
*/
int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
/** Return the number of intervals that intersect the intercept along the axis of the advance.
* The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
* text blob. The caller may pass nullptr for intervals to determine the size of the interval
* array. The computed intervals are cached by glyph to improve performance for multiple calls.
* This permits constructing an underline that skips the descenders.
*
* @param blob The text blob.
* @param bounds The lower and upper line parallel to the advance.
* @param array If not null, the glyph bounds contained by the advance parallel lines.
*
* @return The number of intersections, which may be zero.
*/
int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
SkScalar* intervals) const;
/**
* Return a rectangle that represents the union of the bounds of all
* of the glyphs, but each one positioned at (0,0). This may be conservatively large, and
@ -1051,11 +1099,10 @@ private:
sk_sp<SkTypeface> fTypeface;
sk_sp<SkPathEffect> fPathEffect;
sk_sp<SkShader> fShader;
sk_sp<SkXfermode> fXfermode;
sk_sp<SkMaskFilter> fMaskFilter;
sk_sp<SkColorFilter> fColorFilter;
sk_sp<SkRasterizer> fRasterizer;
sk_sp<SkDrawLooper> fLooper;
sk_sp<SkDrawLooper> fDrawLooper;
sk_sp<SkImageFilter> fImageFilter;
SkScalar fTextSize;
@ -1064,6 +1111,7 @@ private:
SkColor fColor;
SkScalar fWidth;
SkScalar fMiterLimit;
uint32_t fBlendMode; // just need 5-6 bits for SkXfermode::Mode
union {
struct {
// all of these bitfields should add up to 32
@ -1080,28 +1128,38 @@ private:
uint32_t fBitfieldsUInt;
};
GlyphCacheProc getGlyphCacheProc(bool needFullMetrics) const;
static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
bool isDevKern,
bool needFullMetrics);
SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
int* count, SkRect* bounds) const;
enum class FakeGamma {
Off = 0, On
enum ScalerContextFlags : uint32_t {
kNone_ScalerContextFlags = 0,
kFakeGamma_ScalerContextFlag = 1 << 0,
kBoostContrast_ScalerContextFlag = 1 << 1,
kFakeGammaAndBoostContrast_ScalerContextFlags =
kFakeGamma_ScalerContextFlag | kBoostContrast_ScalerContextFlag,
};
/*
* Allocs an SkDescriptor on the heap and return it to the caller as a refcnted
* SkData. Caller is responsible for managing the lifetime of this object.
*/
void getScalerContextDescriptor(SkAutoDescriptor*, const SkSurfaceProps& surfaceProps,
FakeGamma fakeGamma, const SkMatrix*) const;
void getScalerContextDescriptor(SkScalerContextEffects*, SkAutoDescriptor*,
const SkSurfaceProps& surfaceProps,
uint32_t scalerContextFlags, const SkMatrix*) const;
SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps, FakeGamma fakeGamma,
SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
const SkMatrix*) const;
void descriptorProc(const SkSurfaceProps* surfaceProps, FakeGamma fakeGamma,
void descriptorProc(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
const SkMatrix* deviceMatrix,
void (*proc)(SkTypeface*, const SkDescriptor*, void*),
void (*proc)(SkTypeface*, const SkScalerContextEffects&,
const SkDescriptor*, void*),
void* context) const;
/*

Просмотреть файл

@ -26,6 +26,13 @@ class SkWStream;
*/
class SK_API SkPath {
public:
enum Direction {
/** clockwise direction for adding closed contours */
kCW_Direction,
/** counter-clockwise direction for adding closed contours */
kCCW_Direction,
};
SkPath();
SkPath(const SkPath&);
~SkPath();
@ -166,24 +173,45 @@ public:
*
* @param rect returns the bounding rect of this oval. It's a circle
* if the height and width are the same.
*
* @param dir is the oval CCW (or CW if false).
* @param start indicates where the contour starts on the oval (see
* SkPath::addOval for intepretation of the index).
* @return true if this path is an oval.
* Tracking whether a path is an oval is considered an
* optimization for performance and so some paths that are in
* fact ovals can report false.
*/
bool isOval(SkRect* rect) const { return fPathRef->isOval(rect); }
bool isOval(SkRect* rect, Direction* dir = nullptr,
unsigned* start = nullptr) const {
bool isCCW = false;
bool result = fPathRef->isOval(rect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? kCCW_Direction : kCW_Direction;
}
return result;
}
/** Returns true if the path is a round rect.
*
* @param rrect Returns the bounding rect and radii of this round rect.
* @param dir is the rrect CCW (or CW if false).
* @param start indicates where the contour starts on the rrect (see
* SkPath::addRRect for intepretation of the index).
*
* @return true if this path is a round rect.
* Tracking whether a path is a round rect is considered an
* optimization for performance and so some paths that are in
* fact round rects can report false.
*/
bool isRRect(SkRRect* rrect) const { return fPathRef->isRRect(rrect); }
bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
unsigned* start = nullptr) const {
bool isCCW = false;
bool result = fPathRef->isRRect(rrect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? kCCW_Direction : kCW_Direction;
}
return result;
}
/** Clear any lines and curves from the path, making it empty. This frees up
internal storage associated with those segments.
@ -526,13 +554,6 @@ public:
kLarge_ArcSize,
};
enum Direction {
/** clockwise direction for adding closed contours */
kCW_Direction,
/** counter-clockwise direction for adding closed contours */
kCCW_Direction,
};
/**
* Append an elliptical arc from the current point in the format used by SVG.
* The center of the ellipse is computed to satisfy the constraints below.
@ -717,7 +738,8 @@ public:
void addOval(const SkRect& oval, Direction dir, unsigned start);
/**
* Add a closed circle contour to the path
* Add a closed circle contour to the path. The circle contour begins at
* the right-most point (as though 1 were passed to addOval's 'start' param).
*
* @param x The x-coordinate of the center of a circle to add as a
* closed contour to the path

Просмотреть файл

@ -66,7 +66,7 @@ public:
fSize.set(SK_Scalar1, SK_Scalar1);
// 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets
// the kUseClip flag
};
}
~PointData() {
delete [] fPoints;
}
@ -118,6 +118,8 @@ public:
struct DashInfo {
DashInfo() : fIntervals(NULL), fCount(0), fPhase(0) {}
DashInfo(SkScalar* intervals, int32_t count, SkScalar phase)
: fIntervals(intervals), fCount(count), fPhase(phase) {}
SkScalar* fIntervals; //!< Length of on/off intervals for dashed lines
// Even values represent ons, and odds offs
@ -153,7 +155,7 @@ private:
including flattening them. It does nothing in filterPath, and is only useful
for managing the lifetimes of its two arguments.
*/
class SkPairPathEffect : public SkPathEffect {
class SK_API SkPairPathEffect : public SkPathEffect {
protected:
SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1);
@ -174,7 +176,7 @@ private:
This subclass of SkPathEffect composes its two arguments, to create
a compound pathEffect.
*/
class SkComposePathEffect : public SkPairPathEffect {
class SK_API SkComposePathEffect : public SkPairPathEffect {
public:
/** Construct a pathEffect whose effect is to apply first the inner pathEffect
and the the outer pathEffect (e.g. outer(inner(path)))
@ -224,7 +226,7 @@ private:
This subclass of SkPathEffect applies two pathEffects, one after the other.
Its filterPath() returns true if either of the effects succeeded.
*/
class SkSumPathEffect : public SkPairPathEffect {
class SK_API SkSumPathEffect : public SkPairPathEffect {
public:
/** Construct a pathEffect whose effect is to apply two effects, in sequence.
(e.g. first(path) + second(path))

Просмотреть файл

@ -95,7 +95,8 @@ private:
SkScalar fDistance; // total distance up to this point
unsigned fPtIndex; // index into the fPts array
unsigned fTValue : 30;
unsigned fType : 2;
unsigned fType : 2; // actually the enum SkSegType
// See SkPathMeasurePriv.h
SkScalar getScalarT() const;
};

Просмотреть файл

@ -9,6 +9,7 @@
#ifndef SkPathRef_DEFINED
#define SkPathRef_DEFINED
#include "../private/SkAtomics.h"
#include "../private/SkTDArray.h"
#include "SkMatrix.h"
#include "SkPoint.h"
@ -35,7 +36,7 @@ class SkWBuffer;
* logical verb or the last verb in memory).
*/
class SK_API SkPathRef : public ::SkRefCnt {
class SK_API SkPathRef final : public SkNVRefCnt<SkPathRef> {
public:
class Editor {
public:
@ -57,11 +58,11 @@ public:
SkPoint* atPoint(int i) {
SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
return this->points() + i;
};
}
const SkPoint* atPoint(int i) const {
SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);
return this->points() + i;
};
}
/**
* Adds the verb and allocates space for the number of points indicated by the verb. The
@ -99,9 +100,13 @@ public:
*/
SkPathRef* pathRef() { return fPathRef; }
void setIsOval(bool isOval) { fPathRef->setIsOval(isOval); }
void setIsOval(bool isOval, bool isCCW, unsigned start) {
fPathRef->setIsOval(isOval, isCCW, start);
}
void setIsRRect(bool isRRect) { fPathRef->setIsRRect(isRRect); }
void setIsRRect(bool isRRect, bool isCCW, unsigned start) {
fPathRef->setIsRRect(isRRect, isCCW, start);
}
void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); }
@ -163,23 +168,42 @@ public:
*
* @param rect returns the bounding rect of this oval. It's a circle
* if the height and width are the same.
* @param isCCW is the oval CCW (or CW if false).
* @param start indicates where the contour starts on the oval (see
* SkPath::addOval for intepretation of the index).
*
* @return true if this path is an oval.
* Tracking whether a path is an oval is considered an
* optimization for performance and so some paths that are in
* fact ovals can report false.
*/
bool isOval(SkRect* rect) const {
if (fIsOval && rect) {
*rect = this->getBounds();
bool isOval(SkRect* rect, bool* isCCW, unsigned* start) const {
if (fIsOval) {
if (rect) {
*rect = this->getBounds();
}
if (isCCW) {
*isCCW = SkToBool(fRRectOrOvalIsCCW);
}
if (start) {
*start = fRRectOrOvalStartIdx;
}
}
return SkToBool(fIsOval);
}
bool isRRect(SkRRect* rrect) const {
if (fIsRRect && rrect) {
*rrect = this->getRRect();
bool isRRect(SkRRect* rrect, bool* isCCW, unsigned* start) const {
if (fIsRRect) {
if (rrect) {
*rrect = this->getRRect();
}
if (isCCW) {
*isCCW = SkToBool(fRRectOrOvalIsCCW);
}
if (start) {
*start = fRRectOrOvalStartIdx;
}
}
return SkToBool(fIsRRect);
}
@ -219,7 +243,7 @@ public:
*/
static void Rewind(SkAutoTUnref<SkPathRef>* pathRef);
virtual ~SkPathRef();
~SkPathRef();
int countPoints() const { SkDEBUGCODE(this->validate();) return fPointCnt; }
int countVerbs() const { SkDEBUGCODE(this->validate();) return fVerbCnt; }
int countWeights() const { SkDEBUGCODE(this->validate();) return fConicWeights.count(); }
@ -291,10 +315,12 @@ public:
private:
enum SerializationOffsets {
kIsRRect_SerializationShift = 26, // requires 1 bit
kIsFinite_SerializationShift = 25, // requires 1 bit
kIsOval_SerializationShift = 24, // requires 1 bit
kSegmentMask_SerializationShift = 0 // requires 4 bits
kRRectOrOvalStartIdx_SerializationShift = 28, // requires 3 bits
kRRectOrOvalIsCCW_SerializationShift = 27, // requires 1 bit
kIsRRect_SerializationShift = 26, // requires 1 bit
kIsFinite_SerializationShift = 25, // requires 1 bit
kIsOval_SerializationShift = 24, // requires 1 bit
kSegmentMask_SerializationShift = 0 // requires 4 bits
};
SkPathRef() {
@ -308,6 +334,9 @@ private:
fSegmentMask = 0;
fIsOval = false;
fIsRRect = false;
// The next two values don't matter unless fIsOval or fIsRRect are true.
fRRectOrOvalIsCCW = false;
fRRectOrOvalStartIdx = 0xAC;
SkDEBUGCODE(fEditorsAttached = 0;)
SkDEBUGCODE(this->validate();)
}
@ -453,9 +482,17 @@ private:
*/
friend SkPathRef* sk_create_empty_pathref();
void setIsOval(bool isOval) { fIsOval = isOval; }
void setIsOval(bool isOval, bool isCCW, unsigned start) {
fIsOval = isOval;
fRRectOrOvalIsCCW = isCCW;
fRRectOrOvalStartIdx = start;
}
void setIsRRect(bool isRRect) { fIsRRect = isRRect; }
void setIsRRect(bool isRRect, bool isCCW, unsigned start) {
fIsRRect = isRRect;
fRRectOrOvalIsCCW = isCCW;
fRRectOrOvalStartIdx = start;
}
// called only by the editor. Note that this is not a const function.
SkPoint* getPoints() {
@ -498,11 +535,14 @@ private:
SkBool8 fIsOval;
SkBool8 fIsRRect;
// Both the circle and rrect special cases have a notion of direction and starting point
// The next two variables store that information for either.
SkBool8 fRRectOrOvalIsCCW;
uint8_t fRRectOrOvalStartIdx;
uint8_t fSegmentMask;
friend class PathRefTest_Private;
friend class ForceIsRRect_Private; // unit test isRRect
typedef SkRefCnt INHERITED;
};
#endif

Просмотреть файл

@ -16,6 +16,9 @@ class GrContext;
class SkBigPicture;
class SkBitmap;
class SkCanvas;
class SkData;
class SkImage;
class SkImageDeserializer;
class SkPath;
class SkPictureData;
class SkPixelSerializer;
@ -49,6 +52,7 @@ public:
*/
typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst);
#ifdef SK_SUPPORT_LEGACY_PICTUREINSTALLPIXELREF
/**
* Recreate a picture that was serialized into a stream.
* @param SkStream Serialized picture data. Ownership is unchanged by this call.
@ -58,18 +62,22 @@ public:
* invalid.
*/
static sk_sp<SkPicture> MakeFromStream(SkStream*, InstallPixelRefProc proc);
static sk_sp<SkPicture> MakeFromStream(SkStream* stream, std::nullptr_t) {
return MakeFromStream(stream);
}
#endif
/**
* Recreate a picture that was serialized into a stream.
*
* Any serialized images in the stream will be passed to
* SkImageGenerator::NewFromEncoded.
*
* @param SkStream Serialized picture data. Ownership is unchanged by this call.
* @return A new SkPicture representing the serialized data, or NULL if the stream is
* invalid.
* Any serialized images in the stream will be passed the image-deserializer, or if that is
* null, to the default deserializer that will call SkImage::MakeFromEncoded().
*/
static sk_sp<SkPicture> MakeFromStream(SkStream*, SkImageDeserializer*);
static sk_sp<SkPicture> MakeFromStream(SkStream*);
static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,
SkImageDeserializer* = nullptr);
static sk_sp<SkPicture> MakeFromData(const SkData* data, SkImageDeserializer* = nullptr);
/**
* Recreate a picture that was serialized into a buffer. If the creation requires bitmap
@ -116,10 +124,16 @@ public:
uint32_t uniqueID() const;
/**
* Serialize to a stream. If non NULL, serializer will be used to serialize
* bitmaps and images in the picture.
* Serialize the picture to SkData. If non nullptr, pixel-serializer will be used to
* customize how images reference by the picture are serialized/compressed.
*/
void serialize(SkWStream*, SkPixelSerializer* = NULL) const;
sk_sp<SkData> serialize(SkPixelSerializer* = nullptr) const;
/**
* Serialize to a stream. If non nullptr, pixel-serializer will be used to
* customize how images reference by the picture are serialized/compressed.
*/
void serialize(SkWStream*, SkPixelSerializer* = nullptr) const;
/**
* Serialize to a buffer.
@ -139,10 +153,6 @@ public:
*/
virtual int approximateOpCount() const = 0;
/** Return true if this picture contains text.
*/
virtual bool hasText() const = 0;
/** Returns the approximate byte size of this picture, not including large ref'd objects. */
virtual size_t approximateBytesUsed() const = 0;
@ -157,8 +167,10 @@ public:
static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*);
static bool InternalOnly_BufferIsSKP(SkReadBuffer*, SkPictInfo*);
#ifdef SK_SUPPORT_LEGACY_PICTURE_GPUVETO
/** Return true if the picture is suitable for rendering on the GPU. */
bool suitableForGpuRasterization(GrContext*, const char** whyNot = NULL) const;
#endif
// Sent via SkMessageBus from destructor.
struct DeletionMessage { int32_t fUniqueID; }; // TODO: -> uint32_t?
@ -190,10 +202,11 @@ private:
template <typename> friend class SkMiniPicture;
void serialize(SkWStream*, SkPixelSerializer*, SkRefCntSet* typefaces) const;
static sk_sp<SkPicture> MakeFromStream(SkStream*, InstallPixelRefProc, SkTypefacePlayback*);
static sk_sp<SkPicture> MakeFromStream(SkStream*, SkImageDeserializer*, SkTypefacePlayback*);
friend class SkPictureData;
virtual int numSlowPaths() const = 0;
friend class SkPictureGpuAnalyzer;
friend struct SkPathCounter;
// V35: Store SkRect (rather then width & height) in header
@ -206,10 +219,16 @@ private:
// V42: Added a bool to SkPictureShader serialization to indicate did-we-serialize-a-picture?
// V43: Added DRAW_IMAGE and DRAW_IMAGE_RECT opt codes to serialized data
// V44: Move annotations from paint to drawAnnotation
// V45: Add invNormRotation to SkLightingShader.
// V46: Add drawTextRSXform
// V47: Add occluder rect to SkBlurMaskFilter
// V48: Read and write extended SkTextBlobs.
// V49: Gradients serialized as SkColor4f + SkColorSpace
// V50: SkXfermode -> SkBlendMode
// Only SKPs within the min/current picture version range (inclusive) can be read.
static const uint32_t MIN_PICTURE_VERSION = 35; // Produced by Chrome M39.
static const uint32_t CURRENT_PICTURE_VERSION = 44;
static const uint32_t CURRENT_PICTURE_VERSION = 50;
static_assert(MIN_PICTURE_VERSION <= 41,
"Remove kFontFileName and related code from SkFontDescriptor.cpp.");
@ -219,9 +238,17 @@ private:
static_assert(MIN_PICTURE_VERSION <= 43,
"Remove SkBitmapSourceDeserializer.");
static_assert(MIN_PICTURE_VERSION <= 45,
"Remove decoding of old SkTypeface::Style from SkFontDescriptor.cpp.");
static_assert(MIN_PICTURE_VERSION <= 48,
"Remove legacy gradient deserialization code from SkGradientShader.cpp.");
static bool IsValidPictInfo(const SkPictInfo& info);
static sk_sp<SkPicture> Forwardport(const SkPictInfo&, const SkPictureData*);
static sk_sp<SkPicture> Forwardport(const SkPictInfo&,
const SkPictureData*,
SkReadBuffer* buffer);
SkPictInfo createHeader() const;
SkPictureData* backport() const;

Просмотреть файл

@ -0,0 +1,66 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkPictureAnalyzer_DEFINED
#define SkPictureAnalyzer_DEFINED
#include "SkCanvas.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
#include "SkTypes.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
class SkPath;
class SkPicture;
/** \class SkPictureGpuAnalyzer
Gathers GPU-related statistics for one or more SkPictures.
*/
class SK_API SkPictureGpuAnalyzer final : public SkNoncopyable {
public:
explicit SkPictureGpuAnalyzer(sk_sp<GrContextThreadSafeProxy> = nullptr);
explicit SkPictureGpuAnalyzer(const sk_sp<SkPicture>& picture,
sk_sp<GrContextThreadSafeProxy> = nullptr);
/**
* Process the given picture and accumulate its stats.
*/
void analyzePicture(const SkPicture*);
/**
* Process an explicit clipPath op.
*/
void analyzeClipPath(const SkPath&, SkCanvas::ClipOp, bool doAntiAlias);
/**
* Reset all accumulated stats.
*/
void reset();
/**
* Returns true if the analyzed pictures are suitable for rendering on the GPU.
*/
bool suitableForGpuRasterization(const char** whyNot = nullptr) const;
/**
* Returns the number of commands which are slow to draw on the GPU, capped at the predicate
* max.
*/
uint32_t numSlowGpuCommands() { return fNumSlowPaths; }
private:
uint32_t fNumSlowPaths;
typedef SkNoncopyable INHERITED;
};
#endif // SK_SUPPORT_GPU
#endif // SkPictureAnalyzer_DEFINED

Просмотреть файл

@ -19,6 +19,7 @@ namespace android {
};
#endif
class GrContext;
class SkCanvas;
class SkDrawable;
class SkPictureRecord;
@ -31,13 +32,13 @@ public:
~SkPictureRecorder();
enum RecordFlags {
// This flag indicates that, if some BHH is being computed, saveLayer
// information should also be extracted at the same time.
kComputeSaveLayerInfo_RecordFlag = 0x01,
// If you call drawPicture() or drawDrawable() on the recording canvas, this flag forces
// that object to playback its contents immediately rather than reffing the object.
kPlaybackDrawPicture_RecordFlag = 0x02,
kPlaybackDrawPicture_RecordFlag = 1 << 0,
};
enum FinishFlags {
kReturnNullForEmpty_FinishFlag = 1 << 0, // no draw-ops will return nullptr
};
/** Returns the canvas that records the drawing commands.
@ -72,7 +73,7 @@ public:
* reflect their current state, but will not contain a live reference to the drawables
* themselves.
*/
sk_sp<SkPicture> finishRecordingAsPicture();
sk_sp<SkPicture> finishRecordingAsPicture(uint32_t endFlags = 0);
/**
* Signal that the caller is done recording, and update the cull rect to use for bounding
@ -83,7 +84,8 @@ public:
* and subsequent culling operations.
* @return the picture containing the recorded content.
*/
sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect);
sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect,
uint32_t endFlags = 0);
/**
* Signal that the caller is done recording. This invalidates the canvas returned by
@ -95,7 +97,7 @@ public:
* and therefore this drawable will reflect the current state of those nested drawables anytime
* it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
*/
sk_sp<SkDrawable> finishRecordingAsDrawable();
sk_sp<SkDrawable> finishRecordingAsDrawable(uint32_t endFlags = 0);
#ifdef SK_SUPPORT_LEGACY_PICTURE_PTR
SkPicture* SK_WARN_UNUSED_RESULT endRecordingAsPicture() {

Просмотреть файл

@ -206,10 +206,6 @@ public:
bool requestLock(const LockRequest&, LockResult*);
/** Are we really wrapping a texture instead of a bitmap?
*/
virtual GrTexture* getTexture() { return NULL; }
/**
* If this can efficiently return YUV data, this should return true.
* Otherwise this returns false and does not modify any of the parameters.
@ -238,20 +234,6 @@ public:
/** Populates dst with the pixels of this pixelRef, converting them to colorType. */
bool readPixels(SkBitmap* dst, SkColorType colorType, const SkIRect* subset = NULL);
/**
* Makes a deep copy of this PixelRef, respecting the requested config.
* @param colorType Desired colortype.
* @param profileType Desired colorprofiletype.
* @param subset Subset of this PixelRef to copy. Must be fully contained within the bounds of
* of this PixelRef.
* @return A new SkPixelRef, or NULL if either there is an error (e.g. the destination could
* not be created with the given config), or this PixelRef does not support deep
* copies.
*/
virtual SkPixelRef* deepCopy(SkColorType, SkColorProfileType, const SkIRect* /*subset*/) {
return NULL;
}
// Register a listener that may be called the next time our generation ID changes.
//
// We'll only call the listener if we're confident that we are the only SkPixelRef with this
@ -404,6 +386,7 @@ private:
void setImmutableWithID(uint32_t genID);
friend class SkImage_Gpu;
friend class SkImageCacherator;
friend class SkSpecialImage_Gpu;
typedef SkRefCnt INHERITED;
};

Просмотреть файл

@ -44,6 +44,9 @@ public:
this->reset(info, NULL, 0, NULL);
}
// overrides the colorspace in the SkImageInfo of the pixmap
void setColorSpace(sk_sp<SkColorSpace>);
/**
* If supported, set this pixmap to point to the pixels in the specified mask and return true.
* On failure, return false and set this pixmap to empty.
@ -80,7 +83,7 @@ public:
* Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel
* colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType.
*/
int shiftPerPixel() const { return fInfo.bytesPerPixel() >> 1; }
int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); }
uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); }
@ -141,6 +144,9 @@ public:
// Writable versions
void* writable_addr() const { return const_cast<void*>(fPixels); }
void* writable_addr(int x, int y) const {
return const_cast<void*>(this->addr(x, y));
}
uint8_t* writable_addr8(int x, int y) const {
return const_cast<uint8_t*>(this->addr8(x, y));
}

Просмотреть файл

@ -549,4 +549,8 @@ struct SK_API SkPoint {
typedef SkPoint SkVector;
static inline bool SkPointsAreFinite(const SkPoint array[], int count) {
return SkScalarsAreFinite(&array[0].fX, count << 1);
}
#endif

Просмотреть файл

@ -14,6 +14,14 @@
# define SK_BUILD_FOR_WIN
#endif
#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
#ifdef NDEBUG
#define SK_RELEASE
#else
#define SK_DEBUG
#endif
#endif
#if defined(SK_DEBUG) && defined(SK_RELEASE)
# error "cannot define both SK_DEBUG and SK_RELEASE"
#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
@ -78,6 +86,14 @@
#endif
#endif
#if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
#define SK_VECTORCALL __vectorcall
#elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
#define SK_VECTORCALL __attribute__((pcs("aapcs-vfp")))
#else
#define SK_VECTORCALL
#endif
#if !defined(SK_SUPPORT_GPU)
# define SK_SUPPORT_GPU 1
#endif
@ -107,26 +123,6 @@
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_BUILD_FOR_WIN
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
# endif
# ifndef NOMINMAX
# define NOMINMAX
# define NOMINMAX_WAS_LOCALLY_DEFINED
# endif
#
# include <windows.h>
#
# ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
# undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
# undef WIN32_LEAN_AND_MEAN
# endif
# ifdef NOMINMAX_WAS_LOCALLY_DEFINED
# undef NOMINMAX_WAS_LOCALLY_DEFINED
# undef NOMINMAX
# endif
#
# ifndef SK_A32_SHIFT
# define SK_A32_SHIFT 24
# define SK_R32_SHIFT 16
@ -145,10 +141,10 @@
#endif
#ifndef SK_ABORT
# define SK_ABORT(msg) \
# define SK_ABORT(message) \
do { \
SkNO_RETURN_HINT(); \
SkDebugf("%s:%d: fatal error: \"%s\"\n", __FILE__, __LINE__, #msg); \
SkDebugf("%s:%d: fatal error: \"%s\"\n", __FILE__, __LINE__, message); \
SK_DUMP_GOOGLE3_STACK(); \
sk_abort_no_print(); \
} while (false)
@ -249,7 +245,11 @@
//////////////////////////////////////////////////////////////////////
#if !defined(SK_UNUSED)
# define SK_UNUSED SK_ATTRIBUTE(unused)
# if defined(_MSC_VER)
# define SK_UNUSED __pragma(warning(suppress:4189))
# else
# define SK_UNUSED SK_ATTRIBUTE(unused)
# endif
#endif
#if !defined(SK_ATTR_DEPRECATED)
@ -279,6 +279,18 @@
# endif
#endif
/**
* If your judgment is better than the compiler's (i.e. you've profiled it),
* you can use SK_NEVER_INLINE to prevent inlining.
*/
#if !defined(SK_NEVER_INLINE)
# if defined(SK_BUILD_FOR_WIN)
# define SK_NEVER_INLINE __declspec(noinline)
# else
# define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
# endif
#endif
//////////////////////////////////////////////////////////////////////
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
@ -330,12 +342,8 @@
//////////////////////////////////////////////////////////////////////
#if defined(SK_GAMMA_EXPONENT) && defined(SK_GAMMA_SRGB)
# error "cannot define both SK_GAMMA_EXPONENT and SK_GAMMA_SRGB"
#elif defined(SK_GAMMA_SRGB)
# define SK_GAMMA_EXPONENT (0.0f)
#elif !defined(SK_GAMMA_EXPONENT)
# define SK_GAMMA_EXPONENT (2.2f)
#if !defined(SK_GAMMA_EXPONENT)
#define SK_GAMMA_EXPONENT (0.0f) // SRGB
#endif
//////////////////////////////////////////////////////////////////////
@ -346,6 +354,12 @@
//////////////////////////////////////////////////////////////////////
#if defined(SK_HISTOGRAM_ENUMERATION) && defined(SK_HISTOGRAM_BOOLEAN)
# define SK_HISTOGRAMS_ENABLED 1
#else
# define SK_HISTOGRAMS_ENABLED 0
#endif
#ifndef SK_HISTOGRAM_BOOLEAN
# define SK_HISTOGRAM_BOOLEAN(name, value)
#endif

Просмотреть файл

@ -24,14 +24,14 @@
#include "TargetConditionals.h"
#endif
#if defined(WIN32) || defined(__SYMBIAN32__)
#if defined(_WIN32) || defined(__SYMBIAN32__)
#define SK_BUILD_FOR_WIN32
#elif defined(ANDROID)
#elif defined(ANDROID) || defined(__ANDROID__)
#define SK_BUILD_FOR_ANDROID
#elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
defined(__DragonFly__) || defined(__GLIBC__) || defined(__GNU__) || \
defined(__unix__)
defined(__DragonFly__) || defined(__Fuchsia__) || \
defined(__GLIBC__) || defined(__GNU__) || defined(__unix__)
#define SK_BUILD_FOR_UNIX
#elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#define SK_BUILD_FOR_IOS
@ -52,14 +52,6 @@
//////////////////////////////////////////////////////////////////////
#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
#ifdef NDEBUG
#define SK_RELEASE
#else
#define SK_DEBUG
#endif
#endif
#ifdef SK_BUILD_FOR_WIN32
#if !defined(SK_RESTRICT)
#define SK_RESTRICT __restrict
@ -69,8 +61,6 @@
#endif
#endif
//////////////////////////////////////////////////////////////////////
#if !defined(SK_RESTRICT)
#define SK_RESTRICT __restrict__
#endif
@ -118,8 +108,12 @@
#define SK_CPU_SSE_LEVEL_AVX 51
#define SK_CPU_SSE_LEVEL_AVX2 52
#ifdef SK_BUILD_FOR_IOS
#define SK_CPU_SSE_LEVEL 0 // We're tired of fighting with opts/ and iOS simulator.
// When targetting iOS and using gyp to generate the build files, it is not
// possible to select files to build depending on the architecture (i.e. it
// is not possible to use hand optimized assembly implementation). In that
// configuration SK_BUILD_NO_OPTS is defined. Remove optimisation then.
#ifdef SK_BUILD_NO_OPTS
#define SK_CPU_SSE_LEVEL 0
#endif
// Are we in GCC?
@ -190,35 +184,41 @@
#endif
#endif
// Disable ARM64 optimizations for iOS due to complications regarding gyp and iOS.
#if defined(__aarch64__) && !defined(SK_BUILD_FOR_IOS)
#if defined(__aarch64__) && !defined(SK_BUILD_NO_OPTS)
#define SK_CPU_ARM64
#endif
// All 64-bit ARM chips have NEON. Many 32-bit ARM chips do too.
// TODO: Why don't we want NEON on iOS?
#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_FOR_IOS) && (defined(__ARM_NEON__) || defined(__ARM_NEON))
#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_NO_OPTS) && (defined(__ARM_NEON__) || defined(__ARM_NEON))
#define SK_ARM_HAS_NEON
#endif
// Really this __APPLE__ check shouldn't be necessary, but it seems that Apple's Clang defines
// __ARM_FEATURE_CRC32 for -arch arm64, even though their chips don't support those instructions!
#if defined(__ARM_FEATURE_CRC32) && !defined(__APPLE__)
#define SK_ARM_HAS_CRC32
#endif
//////////////////////////////////////////////////////////////////////
#if !defined(SKIA_IMPLEMENTATION)
#define SKIA_IMPLEMENTATION 0
#endif
#if defined(SKIA_DLL)
#if defined(WIN32)
#if SKIA_IMPLEMENTATION
#define SK_API __declspec(dllexport)
#if !defined(SK_API)
#if defined(SKIA_DLL)
#if defined(_MSC_VER)
#if SKIA_IMPLEMENTATION
#define SK_API __declspec(dllexport)
#else
#define SK_API __declspec(dllimport)
#endif
#else
#define SK_API __declspec(dllimport)
#define SK_API __attribute__((visibility("default")))
#endif
#else
#define SK_API __attribute__((visibility("default")))
#define SK_API
#endif
#else
#define SK_API
#endif
//////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -16,7 +16,6 @@ class SkMatrix;
// Path forward:
// core work
// add validate method (all radii positive, all radii sums < rect size, etc.)
// add contains(SkRect&) - for clip stack
// add contains(SkRRect&) - for clip stack
// add heart rect computation (max rect inside RR)
@ -47,6 +46,10 @@ class SkMatrix;
*/
class SK_API SkRRect {
public:
SkRRect() { /* unititialized */ }
SkRRect(const SkRRect&) = default;
SkRRect& operator=(const SkRRect&) = default;
/**
* Enum to capture the various possible subtypes of RR. Accessed
* by type(). The subtypes become progressively less restrictive.
@ -86,7 +89,7 @@ public:
* Returns the RR's sub type.
*/
Type getType() const {
SkDEBUGCODE(this->validate();)
SkASSERT(this->isValid());
return static_cast<Type>(fType);
}
@ -120,7 +123,7 @@ public:
memset(fRadii, 0, sizeof(fRadii));
fType = kEmpty_Type;
SkDEBUGCODE(this->validate();)
SkASSERT(this->isValid());
}
/**
@ -138,7 +141,13 @@ public:
memset(fRadii, 0, sizeof(fRadii));
fType = kRect_Type;
SkDEBUGCODE(this->validate();)
SkASSERT(this->isValid());
}
static SkRRect MakeEmpty() {
SkRRect rr;
rr.setEmpty();
return rr;
}
static SkRRect MakeRect(const SkRect& r) {
@ -146,7 +155,7 @@ public:
rr.setRect(r);
return rr;
}
static SkRRect MakeOval(const SkRect& oval) {
SkRRect rr;
rr.setOval(oval);
@ -180,7 +189,7 @@ public:
}
fType = kOval_Type;
SkDEBUGCODE(this->validate();)
SkASSERT(this->isValid());
}
/**
@ -268,13 +277,17 @@ public:
fRect.offset(dx, dy);
}
SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const {
return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
}
/**
* Returns true if 'rect' is wholy inside the RR, and both
* are not empty.
*/
bool contains(const SkRect& rect) const;
SkDEBUGCODE(void validate() const;)
bool isValid() const;
enum {
kSizeInMemory = 12 * sizeof(SkScalar)
@ -316,6 +329,11 @@ public:
void dumpHex() const { this->dump(true); }
private:
SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)
: fRect(rect)
, fRadii{radii[0], radii[1], radii[2], radii[3]}
, fType(type) {}
SkRect fRect;
// Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
SkVector fRadii[4];

Просмотреть файл

@ -25,7 +25,7 @@ public:
* Return the logical length of the data owned/shared by this buffer. It may be stored in
* multiple contiguous blocks, accessible via the iterator.
*/
size_t size() const { return fUsed; }
size_t size() const { return fAvailable; }
class SK_API Iter {
public:
@ -53,22 +53,25 @@ public:
private:
const SkBufferBlock* fBlock;
size_t fRemaining;
const SkROBuffer* fBuffer;
};
private:
SkROBuffer(const SkBufferHead* head, size_t used);
SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* fTail);
virtual ~SkROBuffer();
const SkBufferHead* fHead;
const size_t fUsed;
const SkBufferHead* fHead;
const size_t fAvailable;
const SkBufferBlock* fTail;
friend class SkRWBuffer;
};
/**
* Accumulates bytes of memory that are "appended" to it, growing internal storage as needed.
* The growth is done such that at any time, a RBuffer or StreamAsset can be snapped off, which
* can see the previously stored bytes, but which will be unaware of any future writes.
* The growth is done such that at any time in the writer's thread, an RBuffer or StreamAsset
* can be snapped off (and safely passed to another thread). The RBuffer/StreamAsset snapshot
* can see the previously stored bytes, but will be unaware of any future writes.
*/
class SK_API SkRWBuffer {
public:
@ -76,8 +79,15 @@ public:
~SkRWBuffer();
size_t size() const { return fTotalUsed; }
void append(const void* buffer, size_t length);
void* append(size_t length);
/**
* Append |length| bytes from |buffer|.
*
* If the caller knows in advance how much more data they are going to append, they can
* pass a |reserve| hint (representing the number of upcoming bytes *in addition* to the
* current append), to minimize the number of internal allocations.
*/
void append(const void* buffer, size_t length, size_t reserve = 0);
SkROBuffer* newRBufferSnapshot() const;
SkStreamAsset* newStreamSnapshot() const;

Просмотреть файл

@ -390,10 +390,8 @@ struct SK_API SkIRect {
struct SK_API SkRect {
SkScalar fLeft, fTop, fRight, fBottom;
static SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
SkRect r;
r.setEmpty();
return r;
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {
return SkRect{0, 0, 0, 0};
}
static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
@ -420,10 +418,9 @@ struct SK_API SkRect {
return r;
}
static SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
SkRect rect;
rect.set(l, t, r, b);
return rect;
static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,
SkScalar b) {
return SkRect {l, t, r, b};
}
static SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {
@ -442,6 +439,10 @@ struct SK_API SkRect {
return r;
}
static SkRect Make(const SkISize& size) {
return MakeIWH(size.width(), size.height());
}
static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {
SkRect r;
r.set(SkIntToScalar(irect.fLeft),
@ -506,7 +507,7 @@ struct SK_API SkRect {
/** Set this rectangle to the empty rectangle (0,0,0,0)
*/
void setEmpty() { memset(this, 0, sizeof(*this)); }
void setEmpty() { *this = MakeEmpty(); }
void set(const SkIRect& src) {
fLeft = SkIntToScalar(src.fLeft);

Просмотреть файл

@ -8,11 +8,12 @@
#ifndef SkRefCnt_DEFINED
#define SkRefCnt_DEFINED
#include "../private/SkAtomics.h"
#include "../private/SkTLogic.h"
#include "SkTypes.h"
#include <atomic>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#define SK_SUPPORT_TRANSITION_TO_SP_INTERFACES
@ -37,19 +38,28 @@ public:
*/
virtual ~SkRefCntBase() {
#ifdef SK_DEBUG
SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt);
fRefCnt = 0; // illegal value, to catch us if we reuse after delete
SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt());
// illegal value, to catch us if we reuse after delete
fRefCnt.store(0, std::memory_order_relaxed);
#endif
}
/** Return the reference count. Use only for debugging. */
int32_t getRefCnt() const { return fRefCnt; }
int32_t getRefCnt() const {
return fRefCnt.load(std::memory_order_relaxed);
}
#ifdef SK_DEBUG
void validate() const {
SkASSERT(getRefCnt() > 0);
}
#endif
/** May return true if the caller is the only owner.
* Ensures that all previous owner's actions are complete.
*/
bool unique() const {
if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) {
if (1 == fRefCnt.load(std::memory_order_acquire)) {
// The acquire barrier is only really needed if we return true. It
// prevents code conditioned on the result of unique() from running
// until previous owners are all totally done calling unref().
@ -66,11 +76,12 @@ public:
// go to zero, but not below, prior to reusing the object. This breaks
// the use of unique() on such objects and as such should be removed
// once the Android code is fixed.
SkASSERT(fRefCnt >= 0);
SkASSERT(getRefCnt() >= 0);
#else
SkASSERT(fRefCnt > 0);
SkASSERT(getRefCnt() > 0);
#endif
(void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No barrier required.
// No barrier required.
(void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
}
/** Decrement the reference count. If the reference count is 1 before the
@ -78,33 +89,24 @@ public:
the object needs to have been allocated via new, and not on the stack.
*/
void unref() const {
SkASSERT(fRefCnt > 0);
SkASSERT(getRefCnt() > 0);
// A release here acts in place of all releases we "should" have been doing in ref().
if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
// Like unique(), the acquire is only needed on success, to make sure
// code in internal_dispose() doesn't happen before the decrement.
this->internal_dispose();
}
}
#ifdef SK_DEBUG
void validate() const {
SkASSERT(fRefCnt > 0);
}
#endif
protected:
/**
* Allow subclasses to call this if they've overridden internal_dispose
* so they can reset fRefCnt before the destructor is called. Should only
* be called right before calling through to inherited internal_dispose()
* or before calling the destructor.
* so they can reset fRefCnt before the destructor is called or if they
* choose not to call the destructor (e.g. using a free list).
*/
void internal_dispose_restore_refcnt_to_1() const {
#ifdef SK_DEBUG
SkASSERT(0 == fRefCnt);
fRefCnt = 1;
#endif
SkASSERT(0 == getRefCnt());
fRefCnt.store(1, std::memory_order_relaxed);
}
private:
@ -120,7 +122,7 @@ private:
// and conditionally call SkRefCnt::internal_dispose().
friend class SkWeakRefCnt;
mutable int32_t fRefCnt;
mutable std::atomic<int32_t> fRefCnt;
typedef SkNoncopyable INHERITED;
};
@ -130,7 +132,13 @@ private:
// This SkRefCnt should normally derive from SkRefCntBase.
#include SK_REF_CNT_MIXIN_INCLUDE
#else
class SK_API SkRefCnt : public SkRefCntBase { };
class SK_API SkRefCnt : public SkRefCntBase {
// "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
#if defined(GOOGLE3)
public:
void deref() const { this->unref(); }
#endif
};
#endif
///////////////////////////////////////////////////////////////////////////////
@ -213,25 +221,29 @@ template <typename Derived>
class SkNVRefCnt : SkNoncopyable {
public:
SkNVRefCnt() : fRefCnt(1) {}
~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); }
~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt()); }
// Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
// - unique() needs acquire when it returns true, and no barrier if it returns false;
// - ref() doesn't need any barrier;
// - unref() needs a release barrier, and an acquire if it's going to call delete.
bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); }
void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); }
bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
void unref() const {
if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert
if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
// restore the 1 for our destructor's assert
SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));
delete (const Derived*)this;
}
}
void deref() const { this->unref(); }
private:
mutable int32_t fRefCnt;
mutable std::atomic<int32_t> fRefCnt;
int32_t getRefCnt() const {
return fRefCnt.load(std::memory_order_relaxed);
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -249,15 +261,15 @@ template <typename T> class sk_sp {
public:
using element_type = T;
sk_sp() : fPtr(nullptr) {}
sk_sp(std::nullptr_t) : fPtr(nullptr) {}
constexpr sk_sp() : fPtr(nullptr) {}
constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}
/**
* Shares the underlying object by calling ref(), so that both the argument and the newly
* created sk_sp both have a reference to it.
*/
sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>>
template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
/**
@ -266,7 +278,7 @@ public:
* No call to ref() or unref() will be made.
*/
sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>>
template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
/**
@ -294,7 +306,7 @@ public:
this->reset(SkSafeRef(that.get()));
return *this;
}
template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>>
template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
sk_sp<T>& operator=(const sk_sp<U>& that) {
this->reset(SkSafeRef(that.get()));
return *this;
@ -309,7 +321,7 @@ public:
this->reset(that.release());
return *this;
}
template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>>
template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
sk_sp<T>& operator=(sk_sp<U>&& that) {
this->reset(that.release());
return *this;
@ -391,7 +403,7 @@ template <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const
// Provide defined total order on sk_sp.
// http://wg21.cmeerw.net/lwg/issue1297
// http://wg21.cmeerw.net/lwg/issue1401 .
return std::less<void*>()((void*)a.get(), (void*)b.get());
return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get());
}
template <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) {
return std::less<T*>()(a.get(), nullptr);
@ -432,7 +444,7 @@ template <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b)
template <typename T, typename... Args>
sk_sp<T> sk_make_sp(Args&&... args) {
return sk_sp<T>(new T(std__forward<Args>(args)...));
return sk_sp<T>(new T(std::forward<Args>(args)...));
}
#ifdef SK_SUPPORT_TRANSITION_TO_SP_INTERFACES

Просмотреть файл

@ -255,7 +255,15 @@ public:
* 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); }
bool op(const SkIRect& rect, Op op) {
if (this->isRect() && kIntersect_Op == op) {
if (!fBounds.intersect(rect)) {
return this->setEmpty();
}
return true;
}
return this->op(*this, rect, op);
}
/**
* Set this region to the result of applying the Op to this region and the

Просмотреть файл

@ -101,6 +101,7 @@ typedef double SkScalar;
//////////////////////////////////////////////////////////////////////////////////////////////////
#define SkIntToScalar(x) static_cast<SkScalar>(x)
#define SkIntToFloat(x) static_cast<float>(x)
#define SkScalarTruncToInt(x) static_cast<int>(x)
#define SkScalarToFloat(x) static_cast<float>(x)

Просмотреть файл

@ -17,6 +17,8 @@
#include "../gpu/GrColor.h"
class SkColorFilter;
class SkColorSpace;
class SkImage;
class SkPath;
class SkPicture;
class SkXfermode;
@ -227,6 +229,7 @@ public:
*/
size_t contextSize(const ContextRec&) const;
#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
/**
* Returns true if this shader is just a bitmap, and if not null, returns the bitmap,
* localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the
@ -239,6 +242,19 @@ public:
bool isABitmap() const {
return this->isABitmap(nullptr, nullptr, nullptr);
}
#endif
/**
* Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this
* if they want to keep it longer than the lifetime of the shader). If not, return nullptr.
*/
SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const {
return this->onIsAImage(localMatrix, xy);
}
bool isAImage() const {
return this->isAImage(nullptr, nullptr) != nullptr;
}
/**
* If the shader subclass can be represented as a gradient, asAGradient
@ -309,6 +325,28 @@ public:
virtual bool asACompose(ComposeRec*) const { return false; }
#if SK_SUPPORT_GPU
struct AsFPArgs {
AsFPArgs(GrContext* context,
const SkMatrix* viewMatrix,
const SkMatrix* localMatrix,
SkFilterQuality filterQuality,
SkColorSpace* dstColorSpace,
SkSourceGammaTreatment gammaTreatment)
: fContext(context)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix)
, fFilterQuality(filterQuality)
, fDstColorSpace(dstColorSpace)
, fGammaTreatment(gammaTreatment) {}
GrContext* fContext;
const SkMatrix* fViewMatrix;
const SkMatrix* fLocalMatrix;
SkFilterQuality fFilterQuality;
SkColorSpace* fDstColorSpace;
SkSourceGammaTreatment fGammaTreatment;
};
/**
* Returns a GrFragmentProcessor that implements the shader for the GPU backend. NULL is
@ -323,10 +361,8 @@ public:
* The returned GrFragmentProcessor should expect an unpremultiplied input color and
* produce a premultiplied output.
*/
virtual const GrFragmentProcessor* asFragmentProcessor(GrContext*,
const SkMatrix& viewMatrix,
const SkMatrix* localMatrix,
SkFilterQuality) const;
virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const;
#endif
/**
* If the shader can represent its "average" luminance in a single color, return true and
@ -375,6 +411,14 @@ public:
*/
static sk_sp<SkShader> MakeColorShader(SkColor);
/**
* Create a shader that draws the specified color (in the specified colorspace).
*
* This works around the limitation that SkPaint::setColor() only takes byte values, and does
* not support specific colorspaces.
*/
static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);
static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
SkXfermode::Mode);
@ -457,6 +501,7 @@ public:
SK_TO_STRING_VIRT()
SK_DEFINE_FLATTENABLE_TYPE(SkShader)
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
protected:
void flatten(SkWriteBuffer&) const override;
@ -479,9 +524,15 @@ protected:
return false;
}
#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
virtual bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode[2]) const {
return false;
}
#endif
virtual SkImage* onIsAImage(SkMatrix*, TileMode[2]) const {
return nullptr;
}
private:
// This is essentially const, but not officially so it can be modified in
@ -490,7 +541,7 @@ private:
// So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
friend class SkLocalMatrixShader;
friend class SkBitmapProcShader; // for computeTotalInverse()
friend class SkBitmapProcLegacyShader; // for computeTotalInverse()
typedef SkFlattenable INHERITED;
};

Просмотреть файл

@ -40,11 +40,9 @@ public:
virtual ~SkStream() {}
/**
* Attempts to open the specified file, and return a stream to it (using
* mmap if available). On success, the caller is responsible for deleting.
* On failure, returns NULL.
* Attempts to open the specified file as a stream, returns nullptr on failure.
*/
static SkStreamAsset* NewFromFile(const char path[]);
static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);
/** Reads or skips size number of bytes.
* If buffer == NULL, skip size bytes, return how many were skipped.
@ -200,7 +198,10 @@ public:
bool write16(U16CPU);
bool write32(uint32_t);
bool writeText(const char text[]);
bool writeText(const char text[]) {
SkASSERT(text);
return this->write(text, strlen(text));
}
bool writeDecAsText(int32_t);
bool writeBigDecAsText(int64_t, int minDigits = 0);
bool writeHexAsText(uint32_t, int minDigits = 0);
@ -288,11 +289,13 @@ public:
/** If copyData is true, the stream makes a private copy of the data. */
SkMemoryStream(const void* data, size_t length, bool copyData = false);
#ifdef SK_SUPPORT_LEGACY_STREAM_DATA
/** Use the specified data as the memory for this stream.
* The stream will call ref() on the data (assuming it is not NULL).
* DEPRECATED
*/
SkMemoryStream(SkData*);
#endif
/** Creates the stream to read from the specified data */
SkMemoryStream(sk_sp<SkData>);
@ -309,17 +312,24 @@ public:
*/
void setMemoryOwned(const void* data, size_t length);
sk_sp<SkData> asData() const { return fData; }
void setData(sk_sp<SkData>);
#ifdef SK_SUPPORT_LEGACY_STREAM_DATA
/** Return the stream's data in a SkData.
* The caller must call unref() when it is finished using the data.
*/
SkData* copyToData() const;
SkData* copyToData() const { return asData().release(); }
/**
* Use the specified data as the memory for this stream.
* The stream will call ref() on the data (assuming it is not NULL).
* The function returns the data parameter as a convenience.
*/
SkData* setData(SkData*);
SkData* setData(SkData* data) {
this->setData(sk_ref_sp(data));
return data;
}
#endif
void skipToAlign4();
const void* getAtPos();
@ -401,11 +411,18 @@ public:
void copyTo(void* dst) const;
void writeToStream(SkWStream* dst) const;
sk_sp<SkData> snapshotAsData() const;
// Return the contents as SkData, and then reset the stream.
sk_sp<SkData> detachAsData();
#ifdef SK_SUPPORT_LEGACY_STREAM_DATA
/**
* Return a copy of the data written so far. This call is responsible for
* calling unref() when they are finished with the data.
*/
SkData* copyToData() const;
SkData* copyToData() const {
return snapshotAsData().release();
}
#endif
/** Reset, returning a reader stream with the current content. */
SkStreamAsset* detachAsStream();

Просмотреть файл

@ -98,6 +98,22 @@ public:
*/
void applyToPaint(SkPaint* paint) const;
/**
* Gives a conservative value for the outset that should applied to a
* geometries bounds to account for any inflation due to applying this
* strokeRec to the geometry.
*/
SkScalar getInflationRadius() const;
/**
* Equivalent to:
* SkStrokeRec rec(paint, style);
* rec.getInflationRadius();
* This does not account for other effects on the paint (i.e. path
* effect).
*/
static SkScalar GetInflationRadius(const SkPaint&, SkPaint::Style);
/**
* Compare if two SkStrokeRecs have an equal effect on a path.
* Equal SkStrokeRecs produce equal paths. Equality of produced

Просмотреть файл

@ -36,6 +36,8 @@ public:
*
* If the requested surface cannot be created, or the request is not a
* supported configuration, NULL will be returned.
*
* Callers are responsible for initialiazing the surface pixels.
*/
static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
const SkSurfaceProps* = nullptr);
@ -49,11 +51,15 @@ public:
void* context, const SkSurfaceProps* = nullptr);
/**
* Return a new surface, with the memory for the pixels automatically allocated, but respecting
* Return a new surface, with the memory for the pixels automatically allocated but respecting
* the specified rowBytes. If rowBytes==0, then a default value will be chosen. If a non-zero
* rowBytes is specified, then any images snapped off of this surface (via newImageSnapshot())
* rowBytes is specified, then any images snapped off of this surface (via makeImageSnapshot())
* are guaranteed to have the same rowBytes.
*
* If the requested alpha type is not opaque, then the surface's pixel memory will be
* zero-initialized. If it is opaque, then it will be left uninitialized, and the caller is
* responsible for initially clearing the surface.
*
* If the requested surface cannot be created, or the request is not a
* supported configuration, NULL will be returned.
*/
@ -62,7 +68,10 @@ public:
/**
* Allocate a new surface, automatically computing the rowBytes.
*/
static sk_sp<SkSurface> MakeRaster(const SkImageInfo&, const SkSurfaceProps* = nullptr);
static sk_sp<SkSurface> MakeRaster(const SkImageInfo& info,
const SkSurfaceProps* props = nullptr) {
return MakeRaster(info, 0, props);
}
/**
* Helper version of NewRaster. It creates a SkImageInfo with the
@ -74,12 +83,6 @@ public:
return MakeRaster(SkImageInfo::MakeN32Premul(width, height), props);
}
/**
* Return a new surface using the specified render target.
*/
static sk_sp<SkSurface> MakeRenderTargetDirect(GrRenderTarget*,
const SkSurfaceProps* = nullptr);
/**
* Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag
* must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
@ -87,7 +90,7 @@ public:
* SkSurface.
*/
static sk_sp<SkSurface> MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
const SkSurfaceProps*);
sk_sp<SkColorSpace>, const SkSurfaceProps*);
/**
* Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume
@ -96,6 +99,7 @@ public:
*/
static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext*,
const GrBackendRenderTargetDesc&,
sk_sp<SkColorSpace>,
const SkSurfaceProps*);
/**
@ -107,21 +111,46 @@ public:
* SkSurface.
*/
static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(
GrContext*, const GrBackendTextureDesc&, const SkSurfaceProps*);
GrContext*, const GrBackendTextureDesc&, sk_sp<SkColorSpace>, const SkSurfaceProps*);
/**
* Legacy versions of the above factories, without color space support. These create "legacy"
* surfaces that operate without gamma correction or color management.
*/
static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
const SkSurfaceProps* props) {
return MakeFromBackendTexture(ctx, desc, nullptr, props);
}
static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* ctx,
const GrBackendRenderTargetDesc& desc,
const SkSurfaceProps* props) {
return MakeFromBackendRenderTarget(ctx, desc, nullptr, props);
}
static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(
GrContext* ctx, const GrBackendTextureDesc& desc, const SkSurfaceProps* props) {
return MakeFromBackendTextureAsRenderTarget(ctx, desc, nullptr, props);
}
/**
* Return a new surface whose contents will be drawn to an offscreen
* render target, allocated by the surface.
*
* The GrTextureStorageAllocator will be reused if SkImage snapshots create
* additional textures.
*/
static sk_sp<SkSurface> MakeRenderTarget(
GrContext*, SkBudgeted, const SkImageInfo&, int sampleCount, const SkSurfaceProps*,
GrTextureStorageAllocator = GrTextureStorageAllocator());
static sk_sp<SkSurface> MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
int sampleCount, GrSurfaceOrigin,
const SkSurfaceProps*);
static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
const SkImageInfo& info, int sampleCount,
const SkSurfaceProps* props) {
return MakeRenderTarget(context, budgeted, info, sampleCount,
kBottomLeft_GrSurfaceOrigin, props);
}
static sk_sp<SkSurface> MakeRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
return MakeRenderTarget(gr, b, info, 0, nullptr);
return MakeRenderTarget(gr, b, info, 0, kBottomLeft_GrSurfaceOrigin, nullptr);
}
#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
@ -147,12 +176,6 @@ public:
const SkSurfaceProps* props = NULL) {
return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
}
static SkSurface* NewRenderTargetDirect(GrRenderTarget* rt, const SkSurfaceProps* props) {
return MakeRenderTargetDirect(rt, props).release();
}
static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
return NewRenderTargetDirect(target, NULL);
}
static SkSurface* NewFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
const SkSurfaceProps* props) {
return MakeFromBackendTexture(ctx, desc, props).release();
@ -172,9 +195,8 @@ public:
return MakeFromBackendTextureAsRenderTarget(ctx, desc, props).release();
}
static SkSurface* NewRenderTarget(GrContext* ctx, SkBudgeted b, const SkImageInfo& info,
int sampleCount, const SkSurfaceProps* props = NULL,
GrTextureStorageAllocator a = GrTextureStorageAllocator()) {
return MakeRenderTarget(ctx, b, info, sampleCount, props, a).release();
int sampleCount, const SkSurfaceProps* props = NULL) {
return MakeRenderTarget(ctx, b, info, sampleCount, props).release();
}
static SkSurface* NewRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
return NewRenderTarget(gr, b, info, 0);

Просмотреть файл

@ -51,20 +51,7 @@ static inline bool SkPixelGeometryIsV(SkPixelGeometry geo) {
class SK_API SkSurfaceProps {
public:
enum Flags {
kDisallowAntiAlias_Flag = 1 << 0,
kDisallowDither_Flag = 1 << 1,
kUseDeviceIndependentFonts_Flag = 1 << 2,
/**
* This flag causes sRGB inputs to the color pipeline (images and other sRGB-tagged
* colors) to be gamma-corrected (converted to linear) before use. Without this flag,
* texture scaling and filtering is not gamma correct, preserving the behavior of Skia
* up through 2015.
*
* It is recommended to enable this flag when rendering to an sRGB or floating point
* surface.
*/
kAllowSRGBInputs_Flag = 1 << 3,
kUseDeviceIndependentFonts_Flag = 1 << 0,
};
/** Deprecated alias used by Chromium. Will be removed. */
static const Flags kUseDistanceFieldFonts_Flag = kUseDeviceIndependentFonts_Flag;
@ -81,12 +68,9 @@ public:
uint32_t flags() const { return fFlags; }
SkPixelGeometry pixelGeometry() const { return fPixelGeometry; }
bool isDisallowAA() const { return SkToBool(fFlags & kDisallowAntiAlias_Flag); }
bool isDisallowDither() const { return SkToBool(fFlags & kDisallowDither_Flag); }
bool isUseDeviceIndependentFonts() const {
return SkToBool(fFlags & kUseDeviceIndependentFonts_Flag);
}
bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); }
private:
SkSurfaceProps();

Просмотреть файл

@ -19,21 +19,12 @@
*/
template <typename T> class SkTLazy {
public:
SkTLazy() : fPtr(NULL) {}
SkTLazy() : fPtr(nullptr) {}
explicit SkTLazy(const T* src) : fPtr(NULL) {
if (src) {
fPtr = new (fStorage.get()) T(*src);
}
}
explicit SkTLazy(const T* src)
: fPtr(src ? new (fStorage.get()) T(*src) : nullptr) {}
SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) {
if (src.isValid()) {
fPtr = new (fStorage.get()) T(*src.get());
} else {
fPtr = NULL;
}
}
SkTLazy(const SkTLazy& src) : fPtr(nullptr) { *this = src; }
~SkTLazy() {
if (this->isValid()) {
@ -41,6 +32,15 @@ public:
}
}
SkTLazy& operator=(const SkTLazy& src) {
if (src.isValid()) {
this->set(*src.get());
} else {
this->reset();
}
return *this;
}
/**
* Return a pointer to an instance of the class initialized with 'args'.
* If a previous instance had been initialized (either from init() or
@ -51,7 +51,7 @@ public:
if (this->isValid()) {
fPtr->~T();
}
fPtr = new (SkTCast<T*>(fStorage.get())) T(std__forward<Args>(args)...);
fPtr = new (SkTCast<T*>(fStorage.get())) T(std::forward<Args>(args)...);
return fPtr;
}
@ -76,7 +76,7 @@ public:
void reset() {
if (this->isValid()) {
fPtr->~T();
fPtr = NULL;
fPtr = nullptr;
}
}
@ -94,13 +94,13 @@ public:
/**
* Like above but doesn't assert if object isn't initialized (in which case
* NULL is returned).
* nullptr is returned).
*/
T* getMaybeNull() const { return fPtr; }
private:
T* fPtr; // NULL or fStorage
SkAlignedSTStorage<1, T> fStorage;
T* fPtr; // nullptr or fStorage
};
/**
@ -134,11 +134,11 @@ public:
SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}
// Constructor for delayed initialization.
SkTCopyOnFirstWrite() : fObj(NULL) {}
SkTCopyOnFirstWrite() : fObj(nullptr) {}
// Should only be called once, and only if the default constructor was used.
void init(const T& initial) {
SkASSERT(NULL == fObj);
SkASSERT(nullptr == fObj);
SkASSERT(!fLazy.isValid());
fObj = &initial;
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "../private/SkTemplates.h"
#include "SkPaint.h"
#include "SkString.h"
#include "SkRefCnt.h"
class SkReadBuffer;
@ -19,7 +20,7 @@ class SkWriteBuffer;
SkTextBlob combines multiple text runs into an immutable, ref-counted structure.
*/
class SK_API SkTextBlob : public SkRefCnt {
class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {
public:
/**
* Returns a conservative blob bounding box.
@ -43,20 +44,25 @@ public:
* @return A new SkTextBlob representing the serialized data, or NULL if the buffer is
* invalid.
*/
static const SkTextBlob* CreateFromBuffer(SkReadBuffer&);
static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);
enum GlyphPositioning {
static const SkTextBlob* CreateFromBuffer(SkReadBuffer& buffer) {
return MakeFromBuffer(buffer).release();
}
enum GlyphPositioning : uint8_t {
kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph.
kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph.
kFull_Positioning = 2 // Point positioning -- two scalars per glyph.
};
private:
friend class SkNVRefCnt<SkTextBlob>;
class RunRecord;
SkTextBlob(int runCount, const SkRect& bounds);
virtual ~SkTextBlob();
~SkTextBlob();
// Memory for objects of this class is created with sk_malloc rather than operator new and must
// be freed with sk_free.
@ -98,16 +104,40 @@ public:
* Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and
* can be reused.
*/
const SkTextBlob* build();
sk_sp<SkTextBlob> make();
#ifdef SK_SUPPORT_LEGACY_TEXTBLOB_BUILDER
const SkTextBlob* build() {
return this->make().release();
}
#endif
/**
* Glyph and position buffers associated with a run.
*
* A run is a sequence of glyphs sharing the same font metrics and positioning mode.
* A run is a sequence of glyphs sharing the same font metrics
* and positioning mode.
*
* If textByteCount is 0, utf8text and clusters will be NULL (no
* character information will be associated with the glyphs).
*
* utf8text will point to a buffer of size textByteCount bytes.
*
* clusters (if not NULL) will point to an array of size count.
* For each glyph, give the byte-offset into the text for the
* first byte in the first character in that glyph's cluster.
* Each value in the array should be an integer less than
* textByteCount. Values in the array should either be
* monotonically increasing (left-to-right text) or monotonically
* decreasing (right-to-left text). This definiton is conviently
* the same as used by Harfbuzz's hb_glyph_info_t::cluster field,
* except that Harfbuzz interleaves glyphs and clusters.
*/
struct RunBuffer {
uint16_t* glyphs;
SkGlyphID* glyphs;
SkScalar* pos;
char* utf8text;
uint32_t* clusters;
};
/**
@ -117,14 +147,27 @@ public:
* @param font The font to be used for this run.
* @param count Number of glyphs.
* @param x,y Position within the blob.
* @param textByteCount length of the original UTF-8 text that
* corresponds to this sequence of glyphs. If 0,
* text will not be included in the textblob.
* @param lang Language code, currently unimplemented.
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
* be used when computing the blob bounds, to avoid re-measuring.
*
* @return A writable glyph buffer, valid until the next allocRun() or
* build() call. The buffer is guaranteed to hold @count@ glyphs.
*/
const RunBuffer& allocRunText(const SkPaint& font,
int count,
SkScalar x,
SkScalar y,
int textByteCount,
SkString lang,
const SkRect* bounds = NULL);
const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,
const SkRect* bounds = NULL);
const SkRect* bounds = NULL) {
return this->allocRunText(font, count, x, y, 0, SkString(), bounds);
}
/**
* Allocates a new horizontally-positioned run and returns its writable glyph and position
@ -133,14 +176,23 @@ public:
* @param font The font to be used for this run.
* @param count Number of glyphs.
* @param y Vertical offset within the blob.
* @param textByteCount length of the original UTF-8 text that
* corresponds to this sequence of glyphs. If 0,
* text will not be included in the textblob.
* @param lang Language code, currently unimplemented.
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
* be used when computing the blob bounds, to avoid re-measuring.
*
* @return Writable glyph and position buffers, valid until the next allocRun()
* or build() call. The buffers are guaranteed to hold @count@ elements.
*/
const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y,
int textByteCount, SkString lang,
const SkRect* bounds = NULL);
const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,
const SkRect* bounds = NULL);
const SkRect* bounds = NULL) {
return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds);
}
/**
* Allocates a new fully-positioned run and returns its writable glyph and position
@ -148,6 +200,10 @@ public:
*
* @param font The font to be used for this run.
* @param count Number of glyphs.
* @param textByteCount length of the original UTF-8 text that
* corresponds to this sequence of glyphs. If 0,
* text will not be included in the textblob.
* @param lang Language code, currently unimplemented.
* @param bounds Optional run bounding box. If known in advance (!= NULL), it will
* be used when computing the blob bounds, to avoid re-measuring.
*
@ -155,12 +211,18 @@ public:
* or build() call. The glyph buffer and position buffer are
* guaranteed to hold @count@ and 2 * @count@ elements, respectively.
*/
const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL);
const RunBuffer& allocRunTextPos(const SkPaint& font, int count,
int textByteCount, SkString lang,
const SkRect* bounds = NULL);
const RunBuffer& allocRunPos(const SkPaint& font, int count,
const SkRect* bounds = NULL) {
return this->allocRunTextPos(font, count, 0, SkString(), bounds);
}
private:
void reserve(size_t size);
void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
int count, SkPoint offset, const SkRect* bounds);
int count, int textBytes, SkPoint offset, const SkRect* bounds);
bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,
int count, SkPoint offset);
void updateDeferredBounds();

Просмотреть файл

@ -17,7 +17,7 @@ class SkString;
/** \class SkTime
Platform-implemented utilities to return time of day, and millisecond counter.
*/
class SkTime {
class SK_API SkTime {
public:
struct DateTime {
int16_t fTimeZoneMinutes; // The number of minutes that GetDateTime()

Просмотреть файл

@ -1,4 +1,3 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -6,11 +5,11 @@
* found in the LICENSE file.
*/
#ifndef SkTypeface_DEFINED
#define SkTypeface_DEFINED
#include "../private/SkOncePtr.h"
#include "../private/SkBitmaskEnum.h"
#include "../private/SkOnce.h"
#include "../private/SkWeakRefCnt.h"
#include "SkFontStyle.h"
#include "SkRect.h"
@ -21,6 +20,7 @@ class SkFontData;
class SkFontDescriptor;
class SkScalerContext;
struct SkScalerContextRec;
struct SkScalerContextEffects;
class SkStream;
class SkStreamAsset;
class SkAdvancedTypefaceMetrics;
@ -93,51 +93,66 @@ public:
*/
static bool Equal(const SkTypeface* facea, const SkTypeface* faceb);
/**
* Returns a ref() to the default typeface. The caller must call unref()
* when they are done referencing the object. Never returns NULL.
*/
static SkTypeface* RefDefault(Style style = SkTypeface::kNormal);
/** Returns the default typeface, which is never nullptr. */
static sk_sp<SkTypeface> MakeDefault(Style style = SkTypeface::kNormal);
#ifdef SK_SUPPORT_LEGACY_TYPEFACE_PTR
static SkTypeface* RefDefault(Style style = SkTypeface::kNormal) {
return MakeDefault(style).release();
}
#endif
/** Return a new reference to the typeface that most closely matches the
requested familyName and style. Pass null as the familyName to return
the default font for the requested style. Will never return null
/** Creates a new reference to the typeface that most closely matches the
requested familyName and fontStyle. This method allows extended font
face specifiers as in the SkFontStyle type. Will never return null.
@param familyName May be NULL. The name of the font family.
@param style The style (normal, bold, italic) of the typeface.
@return reference to the closest-matching typeface. Call must call
unref() when they are done.
@param familyName May be NULL. The name of the font family.
@param fontStyle The style of the typeface.
@return reference to the closest-matching typeface. Call must call
unref() when they are done.
*/
static SkTypeface* CreateFromName(const char familyName[], Style style);
static sk_sp<SkTypeface> MakeFromName(const char familyName[], SkFontStyle fontStyle);
/** Return a new reference to the typeface that most closely matches the
requested typeface and specified Style. Use this call if you want to
pick a new style from the same family of the existing typeface.
If family is NULL, this selects from the default font's family.
#ifdef SK_SUPPORT_LEGACY_TYPEFACE_PTR
static SkTypeface* CreateFromName(const char familyName[], Style style) {
return MakeFromName(familyName, SkFontStyle::FromOldStyle(style)).release();
}
#endif
/** Return the typeface that most closely matches the requested typeface and style.
Use this to pick a new style from the same family of the existing typeface.
If family is nullptr, this selects from the default font's family.
@param family May be NULL. The name of the existing type face.
@param s The style (normal, bold, italic) of the type face.
@return reference to the closest-matching typeface. Call must call
unref() when they are done.
@return the closest-matching typeface.
*/
static SkTypeface* CreateFromTypeface(const SkTypeface* family, Style s);
static sk_sp<SkTypeface> MakeFromTypeface(SkTypeface* family, Style);
/** Return a new typeface given a file. If the file does not exist, or is
not a valid font file, returns null.
not a valid font file, returns nullptr.
*/
static SkTypeface* CreateFromFile(const char path[], int index = 0);
static sk_sp<SkTypeface> MakeFromFile(const char path[], int index = 0);
#ifdef SK_SUPPORT_LEGACY_TYPEFACE_PTR
static SkTypeface* CreateFromFile(const char path[], int index = 0) {
return MakeFromFile(path, index).release();
}
#endif
/** Return a new typeface given a stream. If the stream is
not a valid font file, returns null. Ownership of the stream is
not a valid font file, returns nullptr. Ownership of the stream is
transferred, so the caller must not reference it again.
*/
static SkTypeface* CreateFromStream(SkStreamAsset* stream, int index = 0);
static sk_sp<SkTypeface> MakeFromStream(SkStreamAsset* stream, int index = 0);
#ifdef SK_SUPPORT_LEGACY_TYPEFACE_PTR
static SkTypeface* CreateFromStream(SkStreamAsset* stream, int index = 0) {
return MakeFromStream(stream, index).release();
}
#endif
/** Return a new typeface given font data and configuration. If the data
is not valid font data, returns null. Ownership of the font data is
transferred, so the caller must not reference it again.
is not valid font data, returns nullptr.
*/
static SkTypeface* CreateFromFontData(SkFontData*);
static sk_sp<SkTypeface> MakeFromFontData(std::unique_ptr<SkFontData>);
/** Write a unique signature to a stream, sufficient to reconstruct a
typeface referencing the same font when Deserialize is called.
@ -145,12 +160,11 @@ public:
void serialize(SkWStream*) const;
/** Given the data previously written by serialize(), return a new instance
to a typeface referring to the same font. If that font is not available,
return null. If an instance is returned, the caller is responsible for
calling unref() when they are done with it.
of a typeface referring to the same font. If that font is not available,
return nullptr.
Does not affect ownership of SkStream.
*/
static SkTypeface* Deserialize(SkStream*);
static sk_sp<SkTypeface> MakeDeserialize(SkStream*);
enum Encoding {
kUTF8_Encoding,
@ -174,7 +188,7 @@ public:
* from the beginning of chars. This value is valid, even if the
* glyphs parameter is NULL.
*/
int charsToGlyphs(const void* chars, Encoding encoding, uint16_t glyphs[],
int charsToGlyphs(const void* chars, Encoding encoding, SkGlyphID glyphs[],
int glyphCount) const;
/**
@ -248,7 +262,7 @@ public:
* array will be in an undefined state (possibly some values may have been
* written, but none of them should be interpreted as valid values).
*/
bool getKerningPairAdjustments(const uint16_t glyphs[], int count,
bool getKerningPairAdjustments(const SkGlyphID glyphs[], int count,
int32_t adjustments[]) const;
struct LocalizedString {
@ -285,17 +299,16 @@ public:
SkStreamAsset* openStream(int* ttcIndex) const;
/**
* Return the font data, or NULL on failure.
* The caller is responsible for deleting the font data.
* Return the font data, or nullptr on failure.
*/
SkFontData* createFontData() const;
std::unique_ptr<SkFontData> makeFontData() const;
/**
* Return a scalercontext for the given descriptor. If this fails, then
* if allowFailure is true, this returns NULL, else it returns a
* dummy scalercontext that will not crash, but will draw nothing.
*/
SkScalerContext* createScalerContext(const SkDescriptor*,
SkScalerContext* createScalerContext(const SkScalerContextEffects&, const SkDescriptor*,
bool allowFailure = false) const;
/**
@ -324,25 +337,26 @@ protected:
// The type of advance data wanted.
enum PerGlyphInfo {
kNo_PerGlyphInfo = 0x0, // Don't populate any per glyph info.
kHAdvance_PerGlyphInfo = 0x1, // Populate horizontal advance data.
kVAdvance_PerGlyphInfo = 0x2, // Populate vertical advance data.
kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only).
kToUnicode_PerGlyphInfo = 0x8 // Populate ToUnicode table, ignored
// for Type 1 fonts
kGlyphNames_PerGlyphInfo = 0x1, // Populate glyph names (Type 1 only).
kToUnicode_PerGlyphInfo = 0x2 // Populate ToUnicode table, ignored
// for Type 1 fonts
};
/** uniqueID must be unique and non-zero
*/
SkTypeface(const SkFontStyle& style, SkFontID uniqueID, bool isFixedPitch = false);
SkTypeface(const SkFontStyle& style, bool isFixedPitch = false);
virtual ~SkTypeface();
/** Sets the fixedPitch bit. If used, must be called in the constructor. */
void setIsFixedPitch(bool isFixedPitch) { fIsFixedPitch = isFixedPitch; }
/** Sets the font style. If used, must be called in the constructor. */
void setFontStyle(SkFontStyle style) { fStyle = style; }
friend class SkScalerContext;
static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);
virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const = 0;
virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
const SkDescriptor*) const = 0;
virtual void onFilterRec(SkScalerContextRec*) const = 0;
virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
PerGlyphInfo,
@ -351,16 +365,16 @@ protected:
virtual SkStreamAsset* onOpenStream(int* ttcIndex) const = 0;
// TODO: make pure virtual.
virtual SkFontData* onCreateFontData() const;
virtual std::unique_ptr<SkFontData> onMakeFontData() const;
virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0;
virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[],
virtual int onCharsToGlyphs(const void* chars, Encoding, SkGlyphID glyphs[],
int glyphCount) const = 0;
virtual int onCountGlyphs() const = 0;
virtual int onGetUPEM() const = 0;
virtual bool onGetKerningPairAdjustments(const uint16_t glyphs[], int count,
virtual bool onGetKerningPairAdjustments(const SkGlyphID glyphs[], int count,
int32_t adjustments[]) const;
/** Returns the family name of the typeface as known by its font manager.
@ -381,7 +395,6 @@ private:
friend class SkGTypeface;
friend class SkRandomTypeface;
friend class SkPDFFont;
friend class SkPDFCIDFont;
friend class GrPathRendering;
friend class GrGLPathRendering;
@ -401,12 +414,10 @@ private:
uint32_t glyphIDsCount = 0) const;
private:
static SkTypeface* CreateDefault(int style); // SkLazyPtr requires an int, not a Style.
static void DeleteDefault(SkTypeface*);
SkOncePtr<SkRect> fLazyBounds;
SkFontID fUniqueID;
SkFontStyle fStyle;
mutable SkRect fBounds;
mutable SkOnce fBoundsOnce;
bool fIsFixedPitch;
friend class SkPaint;
@ -415,4 +426,8 @@ private:
typedef SkWeakRefCnt INHERITED;
};
namespace skstd {
template <> struct is_bitmask_enum<SkTypeface::PerGlyphInfo> : std::true_type {};
}
#endif

Просмотреть файл

@ -17,7 +17,11 @@
// before #including <memory>. This makes no sense. I'm not very interested in
// understanding why... these are old, bizarre platform configuration that we
// should just let die.
#if defined(MOZ_B2G) && defined(__GNUC__) && __GNUC__ == 4
// See https://llvm.org/bugs/show_bug.cgi?id=25608 .
#include <ciso646> // Include something innocuous to define _LIBCPP_VERISON if it's libc++.
#if defined(__GNUC__) && __GNUC__ == 4 \
&& ((defined(__arm__) && (defined(__ARM_NEON__) || defined(__ARM_NEON))) || defined(__aarch64__)) \
&& defined(_LIBCPP_VERSION)
typedef float float32_t;
#include <memory>
#endif
@ -27,12 +31,6 @@
#include "SkPostConfig.h"
#include <stddef.h>
#include <stdint.h>
#if defined(SK_ARM_HAS_NEON)
#include <arm_neon.h>
#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
#include <immintrin.h>
#endif
// IWYU pragma: end_exports
#include <string.h>
@ -141,45 +139,45 @@ inline void operator delete(void* p) {
SK_API void SkDebugf(const char format[], ...);
#endif
#define SkASSERT_RELEASE(cond) if(!(cond)) { SK_ABORT(#cond); }
#define SkREQUIRE_SEMICOLON_AFTER(code) do { code } while (false)
#define SkASSERT_RELEASE(cond) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { SK_ABORT(#cond); } )
#ifdef SK_DEBUG
#define SkASSERT(cond) SkASSERT_RELEASE(cond)
#define SkDEBUGFAIL(message) SkASSERT(false && message)
#define SkASSERT(cond) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { SK_ABORT("assert(" #cond ")"); })
#define SkASSERTF(cond, fmt, ...) \
SkREQUIRE_SEMICOLON_AFTER(if (!(cond)) { \
SkDebugf(fmt"\n", __VA_ARGS__); \
SK_ABORT("assert(" #cond ")"); \
})
#define SkDEBUGFAIL(message) SK_ABORT(message)
#define SkDEBUGFAILF(fmt, ...) SkASSERTF(false, fmt, ##__VA_ARGS__)
#define SkDEBUGCODE(code) code
#define SkDEBUGCODE(...) __VA_ARGS__
#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 SkASSERTF(cond, fmt, ...)
#define SkDEBUGFAIL(message)
#define SkDEBUGCODE(code)
#define SkDEBUGFAILF(fmt, ...)
#define SkDEBUGCODE(...)
#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
// unlike SkASSERT, this guy executes its condition in the non-debug build.
// The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
#define SkAssertResult(cond) if (cond) {} do {} while(false)
#endif
// Legacy macro names for SK_ABORT
#define SkFAIL(message) SK_ABORT(message)
#define sk_throw() SK_ABORT("sk_throw")
// We want to evaluate cond only once, and inside the SkASSERT somewhere so we see its string form.
// So we use the comma operator to make an SkDebugf that always returns false: we'll evaluate cond,
// and if it's true the assert passes; if it's false, we'll print the message and the assert fails.
#define SkASSERTF(cond, fmt, ...) SkASSERT((cond) || (SkDebugf(fmt"\n", __VA_ARGS__), false))
#ifdef SK_DEVELOPER
#define SkDEVCODE(code) code
#else
#define SkDEVCODE(code)
#endif
#ifdef SK_IGNORE_TO_STRING
#define SK_TO_STRING_NONVIRT()
#define SK_TO_STRING_VIRT()
@ -286,7 +284,7 @@ template <typename D, typename S> D SkTo(S s) {
/** Returns 0 or 1 based on the condition
*/
#define SkToBool(cond) (!!(cond))
#define SkToBool(cond) ((cond) != 0)
#define SK_MaxS16 32767
#define SK_MinS16 -32767
@ -356,6 +354,10 @@ typedef uint32_t SkFourByteTag;
*/
typedef int32_t SkUnichar;
/** 16 bit unsigned integer to hold a glyph index
*/
typedef uint16_t SkGlyphID;
/** 32 bit value to hold a millisecond duration
* Note that SK_MSecMax is about 25 days.
*/
@ -387,7 +389,7 @@ typedef uint32_t SkMSec;
/** Faster than SkToBool for integral conditions. Returns 0 or 1
*/
static inline int Sk32ToBool(uint32_t n) {
static inline constexpr int Sk32ToBool(uint32_t n) {
return (n | (0-n)) >> 31;
}
@ -426,11 +428,11 @@ static inline int32_t SkMin32(int32_t a, int32_t b) {
return a;
}
template <typename T> const T& SkTMin(const T& a, const T& b) {
template <typename T> constexpr const T& SkTMin(const T& a, const T& b) {
return (a < b) ? a : b;
}
template <typename T> const T& SkTMax(const T& a, const T& b) {
template <typename T> constexpr const T& SkTMax(const T& a, const T& b) {
return (b < a) ? a : b;
}
@ -446,7 +448,7 @@ static inline int32_t SkFastMin32(int32_t value, int32_t max) {
}
/** Returns value pinned between min and max, inclusively. */
template <typename T> static inline const T& SkTPin(const T& value, const T& min, const T& max) {
template <typename T> static constexpr const T& SkTPin(const T& value, const T& min, const T& max) {
return SkTMax(SkTMin(value, max), min);
}
@ -461,6 +463,15 @@ enum class SkBudgeted : bool {
kYes = true
};
/**
* Indicates whether a backing store needs to be an exact match or can be larger
* than is strictly necessary
*/
enum class SkBackingFit {
kApprox,
kExact
};
///////////////////////////////////////////////////////////////////////////////
/** Use to combine multiple bits in a bitmask in a type safe way.

Просмотреть файл

@ -16,85 +16,120 @@
#include "SkPixelSerializer.h"
#include "SkRefCnt.h"
#include "SkWriter32.h"
#include "../private/SkTHash.h"
class SkBitmap;
class SkBitmapHeap;
class SkDeduper;
class SkFactorySet;
class SkFlattenable;
class SkNamedFactorySet;
class SkRefCntSet;
class SkWriteBuffer {
public:
SkWriteBuffer() {}
virtual ~SkWriteBuffer() {}
virtual bool isCrossProcess() const = 0;
virtual void writeByteArray(const void* data, size_t size) = 0;
void writeDataAsByteArray(SkData* data) {
this->writeByteArray(data->data(), data->size());
}
virtual void writeBool(bool value) = 0;
virtual void writeScalar(SkScalar value) = 0;
virtual void writeScalarArray(const SkScalar* value, uint32_t count) = 0;
virtual void writeInt(int32_t value) = 0;
virtual void writeIntArray(const int32_t* value, uint32_t count) = 0;
virtual void writeUInt(uint32_t value) = 0;
void write32(int32_t value) {
this->writeInt(value);
}
virtual void writeString(const char* value) = 0;
virtual void writeFlattenable(const SkFlattenable* flattenable) = 0;
virtual void writeColor(SkColor color) = 0;
virtual void writeColorArray(const SkColor* color, uint32_t count) = 0;
virtual void writeColor4f(const SkColor4f& color) = 0;
virtual void writeColor4fArray(const SkColor4f* color, uint32_t count) = 0;
virtual void writePoint(const SkPoint& point) = 0;
virtual void writePointArray(const SkPoint* point, uint32_t count) = 0;
virtual void writeMatrix(const SkMatrix& matrix) = 0;
virtual void writeIRect(const SkIRect& rect) = 0;
virtual void writeRect(const SkRect& rect) = 0;
virtual void writeRegion(const SkRegion& region) = 0;
virtual void writePath(const SkPath& path) = 0;
virtual size_t writeStream(SkStream* stream, size_t length) = 0;
virtual void writeBitmap(const SkBitmap& bitmap) = 0;
virtual void writeImage(const SkImage*) = 0;
virtual void writeTypeface(SkTypeface* typeface) = 0;
virtual void writePaint(const SkPaint& paint) = 0;
void setDeduper(SkDeduper* deduper) { fDeduper = deduper; }
protected:
SkDeduper* fDeduper = nullptr;
};
/**
* Concrete implementation that serializes to a flat binary blob.
*/
class SkBinaryWriteBuffer : public SkWriteBuffer {
public:
enum Flags {
kCrossProcess_Flag = 1 << 0,
kValidation_Flag = 1 << 1,
kCrossProcess_Flag = 1 << 0,
};
SkWriteBuffer(uint32_t flags = 0);
SkWriteBuffer(void* initialStorage, size_t storageSize, uint32_t flags = 0);
~SkWriteBuffer();
SkBinaryWriteBuffer(uint32_t flags = 0);
SkBinaryWriteBuffer(void* initialStorage, size_t storageSize, uint32_t flags = 0);
~SkBinaryWriteBuffer();
bool isCrossProcess() const {
return this->isValidating() || SkToBool(fFlags & kCrossProcess_Flag);
bool isCrossProcess() const override {
return SkToBool(fFlags & kCrossProcess_Flag);
}
void write(const void* buffer, size_t bytes) {
fWriter.write(buffer, bytes);
}
SkWriter32* getWriter32() { return &fWriter; }
void reset(void* storage = NULL, size_t storageSize = 0) {
fWriter.reset(storage, storageSize);
}
uint32_t* reserve(size_t size) { return fWriter.reserve(size); }
size_t bytesWritten() const { return fWriter.bytesWritten(); }
void writeByteArray(const void* data, size_t size);
void writeDataAsByteArray(SkData* data) { this->writeByteArray(data->data(), data->size()); }
void writeBool(bool value);
void writeScalar(SkScalar value);
void writeScalarArray(const SkScalar* value, uint32_t count);
void writeInt(int32_t value);
void writeIntArray(const int32_t* value, uint32_t count);
void writeUInt(uint32_t value);
void write32(int32_t value);
void writeString(const char* value);
void writeEncodedString(const void* value, size_t byteLength, SkPaint::TextEncoding encoding);
void writeFunctionPtr(void* ptr) { fWriter.writePtr(ptr); }
void writeByteArray(const void* data, size_t size) override;
void writeBool(bool value) override;
void writeScalar(SkScalar value) override;
void writeScalarArray(const SkScalar* value, uint32_t count) override;
void writeInt(int32_t value) override;
void writeIntArray(const int32_t* value, uint32_t count) override;
void writeUInt(uint32_t value) override;
void writeString(const char* value) override;
void writeFlattenable(const SkFlattenable* flattenable);
void writeColor(const SkColor& color);
void writeColorArray(const SkColor* color, uint32_t count);
void writePoint(const SkPoint& point);
void writePointArray(const SkPoint* point, uint32_t count);
void writeMatrix(const SkMatrix& matrix);
void writeIRect(const SkIRect& rect);
void writeRect(const SkRect& rect);
void writeRegion(const SkRegion& region);
void writePath(const SkPath& path);
size_t writeStream(SkStream* stream, size_t length);
void writeBitmap(const SkBitmap& bitmap);
void writeImage(const SkImage*);
void writeTypeface(SkTypeface* typeface);
void writePaint(const SkPaint& paint) { paint.flatten(*this); }
void writeFlattenable(const SkFlattenable* flattenable) override;
void writeColor(SkColor color) override;
void writeColorArray(const SkColor* color, uint32_t count) override;
void writeColor4f(const SkColor4f& color) override;
void writeColor4fArray(const SkColor4f* color, uint32_t count) override;
void writePoint(const SkPoint& point) override;
void writePointArray(const SkPoint* point, uint32_t count) override;
void writeMatrix(const SkMatrix& matrix) override;
void writeIRect(const SkIRect& rect) override;
void writeRect(const SkRect& rect) override;
void writeRegion(const SkRegion& region) override;
void writePath(const SkPath& path) override;
size_t writeStream(SkStream* stream, size_t length) override;
void writeBitmap(const SkBitmap& bitmap) override;
void writeImage(const SkImage*) override;
void writeTypeface(SkTypeface* typeface) override;
void writePaint(const SkPaint& paint) override;
bool writeToStream(SkWStream*);
void writeToMemory(void* dst) { fWriter.flatten(dst); }
SkFactorySet* setFactoryRecorder(SkFactorySet*);
SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
/**
* Set an SkBitmapHeap to store bitmaps rather than flattening.
*
* Incompatible with an SkPixelSerializer. If an SkPixelSerializer is set,
* setting an SkBitmapHeap will set the SkPixelSerializer to NULL in release
* and crash in debug.
*/
void setBitmapHeap(SkBitmapHeap*);
/**
* Set an SkPixelSerializer to store an encoded representation of pixels,
* e.g. SkBitmaps.
@ -102,25 +137,21 @@ public:
* Calls ref() on the serializer.
*
* TODO: Encode SkImage pixels as well.
*
* Incompatible with the SkBitmapHeap. If an encoder is set fBitmapHeap will
* be set to NULL in release and crash in debug.
*/
void setPixelSerializer(SkPixelSerializer*);
SkPixelSerializer* getPixelSerializer() const { return fPixelSerializer; }
private:
bool isValidating() const { return SkToBool(fFlags & kValidation_Flag); }
const uint32_t fFlags;
SkFactorySet* fFactorySet;
SkNamedFactorySet* fNamedFactorySet;
SkWriter32 fWriter;
SkBitmapHeap* fBitmapHeap;
SkRefCntSet* fTFSet;
SkAutoTUnref<SkPixelSerializer> fPixelSerializer;
// Only used if we do not have an fFactorySet
SkTHashMap<SkString, uint32_t> fFlattenableDict;
};
#endif // SkWriteBuffer_DEFINED

Просмотреть файл

@ -51,12 +51,6 @@ public:
fExternal = external;
}
// Returns the current buffer.
// The pointer may be invalidated by any future write calls.
const uint32_t* contiguousArray() const {
return (uint32_t*)fData;
}
// size MUST be multiple of 4
uint32_t* reserve(size_t size) {
SkASSERT(SkAlign4(size) == size);

Просмотреть файл

@ -1,4 +1,3 @@
/*
* Copyright 2006 The Android Open Source Project
*
@ -6,18 +5,21 @@
* found in the LICENSE file.
*/
#ifndef SkXfermode_DEFINED
#define SkXfermode_DEFINED
#include "SkFlattenable.h"
#include "SkBlendMode.h"
#include "SkColor.h"
#include "SkFlattenable.h"
class GrFragmentProcessor;
class GrTexture;
class GrXPFactory;
class SkRasterPipeline;
class SkString;
struct SkArithmeticParams;
struct SkPM4f;
typedef SkPM4f (*SkXfermodeProc4f)(const SkPM4f& src, const SkPM4f& dst);
@ -113,6 +115,9 @@ public:
* Gets the name of the Mode as a string.
*/
static const char* ModeName(Mode);
static const char* ModeName(SkBlendMode mode) {
return ModeName(Mode(mode));
}
/**
* If the xfermode is one of the modes in the Mode enum, then asMode()
@ -158,6 +163,31 @@ public:
}
#endif
/**
* Skia maintains global xfermode objects corresponding to each BlendMode. This returns a
* ptr to that global xfermode (or null if the mode is srcover). Thus the caller may use
* the returned ptr, but it should leave its refcnt untouched.
*/
static SkXfermode* Peek(SkBlendMode mode) {
sk_sp<SkXfermode> xfer = Make(mode);
if (!xfer) {
SkASSERT(SkBlendMode::kSrcOver == mode);
return nullptr;
}
SkASSERT(!xfer->unique());
return xfer.get();
}
static sk_sp<SkXfermode> Make(SkBlendMode bm) {
return Make((Mode)bm);
}
SkBlendMode blend() const {
Mode mode;
SkAssertResult(this->asMode(&mode));
return (SkBlendMode)mode;
}
/** Return a function pointer to a routine that applies the specified
porter-duff transfer mode.
*/
@ -166,6 +196,8 @@ public:
virtual SkXfermodeProc4f getProc4f() const;
bool appendStages(SkRasterPipeline*) const;
/**
* If the specified mode can be represented by a pair of Coeff, then return
* true and set (if not NULL) the corresponding coeffs. If the mode is
@ -214,22 +246,23 @@ public:
static bool IsOpaque(const sk_sp<SkXfermode>& xfer, SrcColorOpacity opacityType) {
return IsOpaque(xfer.get(), opacityType);
}
static bool IsOpaque(SkBlendMode, SrcColorOpacity);
#if SK_SUPPORT_GPU
/** Used by the SkXfermodeImageFilter to blend two colors via a GrFragmentProcessor.
The input to the returned FP is the src color. The dst color is
provided by the dst param which becomes a child FP of the returned FP.
provided by the dst param which becomes a child FP of the returned FP.
It is legal for the function to return a null output. This indicates that
the output of the blend is simply the src color.
*/
virtual const GrFragmentProcessor* getFragmentProcessorForImageFilter(
const GrFragmentProcessor* dst) const;
virtual sk_sp<GrFragmentProcessor> makeFragmentProcessorForImageFilter(
sk_sp<GrFragmentProcessor> dst) const;
/** A subclass must implement this factory function to work with the GPU backend.
The xfermode will return a factory for which the caller will get a ref. It is up
/** A subclass must implement this factory function to work with the GPU backend.
The xfermode will return a factory for which the caller will get a ref. It is up
to the caller to install it. XferProcessors cannot use a background texture.
*/
virtual GrXPFactory* asXPFactory() const;
virtual sk_sp<GrXPFactory> asXPFactory() const;
#endif
SK_TO_STRING_PUREVIRT()
@ -248,27 +281,28 @@ public:
return GetD32Proc(xfer.get(), flags);
}
enum D64Flags {
kSrcIsOpaque_D64Flag = 1 << 0,
kSrcIsSingle_D64Flag = 1 << 1,
kDstIsFloat16_D64Flag = 1 << 2, // else U16 bit components
enum F16Flags {
kSrcIsOpaque_F16Flag = 1 << 0,
kSrcIsSingle_F16Flag = 1 << 1,
};
typedef void (*D64Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
typedef void (*F16Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
const SkAlpha coverage[]);
static D64Proc GetD64Proc(SkXfermode*, uint32_t flags);
static D64Proc GetD64Proc(const sk_sp<SkXfermode>& xfer, uint32_t flags) {
return GetD64Proc(xfer.get(), flags);
static F16Proc GetF16Proc(SkXfermode*, uint32_t flags);
static F16Proc GetF16Proc(const sk_sp<SkXfermode>& xfer, uint32_t flags) {
return GetF16Proc(xfer.get(), flags);
}
enum LCDFlags {
kSrcIsOpaque_LCDFlag = 1 << 0, // else src(s) may have alpha < 1
kSrcIsSingle_LCDFlag = 1 << 1, // else src[count]
kDstIsLinearInt_LCDFlag = 1 << 2, // else srgb/half-float
kDstIsSRGB_LCDFlag = 1 << 2, // else l32 or f16
};
typedef void (*LCD32Proc)(uint32_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
typedef void (*LCD64Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
typedef void (*LCDF16Proc)(uint64_t* dst, const SkPM4f* src, int count, const uint16_t lcd[]);
static LCD32Proc GetLCD32Proc(uint32_t flags);
static LCD64Proc GetLCD64Proc(uint32_t) { return nullptr; }
static LCDF16Proc GetLCDF16Proc(uint32_t) { return nullptr; }
virtual bool isArithmetic(SkArithmeticParams*) const { return false; }
protected:
SkXfermode() {}
@ -283,7 +317,8 @@ protected:
virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
virtual D32Proc onGetD32Proc(uint32_t flags) const;
virtual D64Proc onGetD64Proc(uint32_t flags) const;
virtual F16Proc onGetF16Proc(uint32_t flags) const;
virtual bool onAppendStages(SkRasterPipeline*) const;
private:
enum {

Просмотреть файл

@ -9,7 +9,8 @@
#define SkAlphaThresholdFilter_DEFINED
#include "SkImageFilter.h"
#include "SkRegion.h"
class SkRegion;
class SK_API SkAlphaThresholdFilter {
public:
@ -21,7 +22,8 @@ public:
* source image.
*/
static sk_sp<SkImageFilter> Make(const SkRegion& region, SkScalar innerMin,
SkScalar outerMax, sk_sp<SkImageFilter> input);
SkScalar outerMax, sk_sp<SkImageFilter> input,
const SkImageFilter::CropRect* cropRect = nullptr);
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR

Просмотреть файл

@ -12,6 +12,8 @@
#include "SkScalar.h"
#include "SkXfermode.h"
#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE
class SK_API SkArithmeticMode {
public:
/**
@ -38,3 +40,5 @@ private:
};
#endif
#endif

Просмотреть файл

@ -9,44 +9,23 @@
#define SkBlurImageFilter_DEFINED
#include "SkImageFilter.h"
#include "SkSize.h"
class SK_API SkBlurImageFilter : public SkImageFilter {
class SK_API SkBlurImageFilter {
public:
static sk_sp<SkImageFilter> Make(SkScalar sigmaX, SkScalar sigmaY, sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr) {
if (0 == sigmaX && 0 == sigmaY && nullptr == cropRect) {
return input;
}
return sk_sp<SkImageFilter>(new SkBlurImageFilter(sigmaX, sigmaY, input, cropRect));
static sk_sp<SkImageFilter> Make(SkScalar sigmaX, SkScalar sigmaY,
sk_sp<SkImageFilter> input,
const SkImageFilter::CropRect* cropRect = nullptr) {
return SkImageFilter::MakeBlur(sigmaX, sigmaY, input, cropRect);
}
SkRect computeFastBounds(const SkRect&) const override;
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input = nullptr,
const CropRect* cropRect = nullptr) {
return Make(sigmaX, sigmaY, sk_ref_sp<SkImageFilter>(input), cropRect).release();
static SkImageFilter* Create(SkScalar sigmaX, SkScalar sigmaY,
SkImageFilter * input = nullptr,
const SkImageFilter::CropRect* cropRect = nullptr) {
return SkImageFilter::MakeBlur(sigmaX, sigmaY, sk_ref_sp<SkImageFilter>(input),
cropRect).release();
}
#endif
protected:
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
SkIRect onFilterNodeBounds(const SkIRect& src, const SkMatrix&, MapDirection) const override;
private:
SkBlurImageFilter(SkScalar sigmaX,
SkScalar sigmaY,
sk_sp<SkImageFilter> input,
const CropRect* cropRect);
SkSize fSigma;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -32,13 +32,21 @@ public:
};
/** Create a blur maskfilter.
* @param style The SkBlurStyle to use
* @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
* @param flags Flags to use - defaults to none
* @param style The SkBlurStyle to use
* @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
* @param occluder The rect for which no pixels need be drawn (b.c. it will be overdrawn
* with some opaque object. This is just a hint which backends are free to
* ignore.
* @param flags Flags to use - defaults to none
* @return The new blur maskfilter
*/
static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma,
uint32_t flags = kNone_BlurFlag);
const SkRect& occluder, uint32_t flags = kNone_BlurFlag);
static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma,
uint32_t flags = kNone_BlurFlag) {
return Make(style, sigma, SkRect::MakeEmpty(), flags);
}
/** Create an emboss maskfilter
@param blurSigma standard deviation of the Gaussian blur to apply
@ -65,6 +73,28 @@ public:
SkScalar blurRadius);
#endif
static const int kMaxDivisions = 6;
// This method computes all the parameters for drawing a partially occluded nine-patched
// blurred rrect mask:
// rrectToDraw - the integerized rrect to draw in the mask
// widthHeight - how large to make the mask (rrectToDraw will be centered in this coord sys)
// rectXs, rectYs - the x & y coordinates of the covering geometry lattice
// texXs, texYs - the texture coordinate at each point in rectXs & rectYs
// numXs, numYs - number of coordinates in the x & y directions
// skipMask - bit mask that contains a 1-bit whenever one of the cells is occluded
// It returns true if 'devRRect' is nine-patchable
static bool ComputeBlurredRRectParams(const SkRRect& srcRRect, const SkRRect& devRRect,
const SkRect& occluder,
SkScalar sigma, SkScalar xformedSigma,
SkRRect* rrectToDraw,
SkISize* widthHeight,
SkScalar rectXs[kMaxDivisions],
SkScalar rectYs[kMaxDivisions],
SkScalar texXs[kMaxDivisions],
SkScalar texYs[kMaxDivisions],
int* numXs, int* numYs, uint32_t* skipMask);
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
private:

Просмотреть файл

@ -10,7 +10,7 @@
#include "SkColorFilter.h"
#include "SkData.h"
#include "../private/SkMutex.h"
#include "../private/SkOnce.h"
#include "../private/SkTemplates.h"
class SK_API SkColorCubeFilter : public SkColorFilter {
@ -30,7 +30,7 @@ public:
uint32_t getFlags() const override;
#if SK_SUPPORT_GPU
const GrFragmentProcessor* asFragmentProcessor(GrContext*) const override;
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
#endif
SK_TO_STRING_OVERRIDE()
@ -65,8 +65,7 @@ private:
const int fCubeDimension;
// Make sure we only initialize the caches once.
SkMutex fLutsMutex;
bool fLutsInited;
SkOnce fLutsInitOnce;
static void initProcessingLuts(ColorCubeProcesingCache* cache);
};

Просмотреть файл

@ -33,9 +33,10 @@ public:
protected:
void flatten(SkWriteBuffer&) const override;
bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
SkIPoint* loc) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
bool onIsColorFilterNode(SkColorFilter**) const override;
bool onCanHandleComplexCTM() const override { return true; }
bool affectsTransparentBlack() const override;
private:

Просмотреть файл

@ -12,16 +12,8 @@
class SK_API SkComposeImageFilter : public SkImageFilter {
public:
static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner) {
if (!outer) {
return inner;
}
if (!inner) {
return outer;
}
sk_sp<SkImageFilter> inputs[2] = { std::move(outer), std::move(inner) };
return sk_sp<SkImageFilter>(new SkComposeImageFilter(inputs));
}
static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner);
SkRect computeFastBounds(const SkRect& src) const override;
SK_TO_STRING_OVERRIDE()
@ -42,6 +34,7 @@ protected:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
bool onCanHandleComplexCTM() const override { return true; }
private:
typedef SkImageFilter INHERITED;

Просмотреть файл

@ -9,7 +9,6 @@
#define SkDisplacementMapEffect_DEFINED
#include "SkImageFilter.h"
#include "SkBitmap.h"
class SK_API SkDisplacementMapEffect : public SkImageFilter {
public:
@ -21,39 +20,45 @@ public:
kA_ChannelSelectorType
};
~SkDisplacementMapEffect();
~SkDisplacementMapEffect() override;
static SkImageFilter* Create(ChannelSelectorType xChannelSelector,
ChannelSelectorType yChannelSelector,
SkScalar scale, SkImageFilter* displacement,
SkImageFilter* color = NULL,
const CropRect* cropRect = NULL);
static sk_sp<SkImageFilter> Make(ChannelSelectorType xChannelSelector,
ChannelSelectorType yChannelSelector,
SkScalar scale,
sk_sp<SkImageFilter> displacement,
sk_sp<SkImageFilter> color,
const CropRect* cropRect = nullptr);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDisplacementMapEffect)
bool onFilterImageDeprecated(Proxy* proxy,
const SkBitmap& src,
const Context& ctx,
SkBitmap* dst,
SkIPoint* offset) const override;
SkRect computeFastBounds(const SkRect& src) const override;
virtual SkIRect onFilterBounds(const SkIRect& src, const SkMatrix&,
MapDirection) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
#if SK_SUPPORT_GPU
bool canFilterImageGPU() const override { return true; }
bool filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, const Context& ctx,
SkBitmap* result, SkIPoint* offset) const override;
#endif
SK_TO_STRING_OVERRIDE()
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(ChannelSelectorType xChannelSelector,
ChannelSelectorType yChannelSelector,
SkScalar scale, SkImageFilter* displacement,
SkImageFilter* color = nullptr,
const CropRect* cropRect = nullptr) {
return Make(xChannelSelector, yChannelSelector, scale,
sk_ref_sp<SkImageFilter>(displacement),
sk_ref_sp<SkImageFilter>(color),
cropRect).release();
}
#endif
protected:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
ChannelSelectorType yChannelSelector,
SkScalar scale, SkImageFilter* inputs[2],
SkScalar scale, sk_sp<SkImageFilter> inputs[2],
const CropRect* cropRect);
void flatten(SkWriteBuffer&) const override;

Просмотреть файл

@ -26,12 +26,7 @@ public:
static sk_sp<SkImageFilter> Make(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY,
SkColor color, ShadowMode shadowMode,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr) {
return sk_sp<SkImageFilter>(new SkDropShadowImageFilter(dx, dy, sigmaX, sigmaY,
color, shadowMode,
std::move(input),
cropRect));
}
const CropRect* cropRect = nullptr);
SkRect computeFastBounds(const SkRect&) const override;
SK_TO_STRING_OVERRIDE()

Просмотреть файл

@ -0,0 +1,48 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkGammaColorFilter_DEFINED
#define SkGammaColorFilter_DEFINED
#include "SkColorFilter.h"
#include "SkRefCnt.h"
// This colorfilter can be used to perform pixel-by-pixel conversion between linear and
// power-law color spaces. A gamma of 2.2 is interpreted to mean convert from sRGB to linear
// while a gamma of 1/2.2 is interpreted to mean convert from linear to sRGB. Any other
// values are just directly applied (i.e., out = in^gamma)
//
// More complicated color space mapping (i.e., ICC profiles) should be handled via the
// SkColorSpace object.
class SK_API SkGammaColorFilter : public SkColorFilter {
public:
static sk_sp<SkColorFilter> Make(SkScalar gamma);
#ifdef SK_SUPPORT_LEGACY_COLORFILTER_PTR
static SkColorFilter* Create(SkScalar gamma) { return Make(gamma).release(); }
#endif
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
#endif
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLumaColorFilter)
protected:
void flatten(SkWriteBuffer&) const override;
private:
SkGammaColorFilter(SkScalar gamma);
SkScalar fGamma;
typedef SkColorFilter INHERITED;
};
#endif

Просмотреть файл

@ -0,0 +1,27 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkGaussianEdgeShader_DEFINED
#define SkGaussianEdgeShader_DEFINED
#include "SkShader.h"
class SK_API SkGaussianEdgeShader {
public:
/** Returns a shader that applies a Gaussian blur depending on distance to the edge
* Currently this is only useable with Circle and RRect shapes on the GPU backend.
* Raster will draw nothing.
*/
static sk_sp<SkShader> Make();
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
private:
SkGaussianEdgeShader(); // can't be instantiated
};
#endif

Просмотреть файл

@ -26,13 +26,9 @@ public:
kInterpolateColorsInPremul_Flag = 1 << 0,
};
/** Returns a shader that generates a linear gradient between the two
specified points.
/** Returns a shader that generates a linear gradient between the two specified points.
<p />
CreateLinear returns a shader with a reference count of 1.
The caller should decrement the shader's reference count when done with the shader.
It is an error for count to be < 2.
@param pts The start and end points for the gradient.
@param pts The start and end points for the gradient.
@param colors The array[count] of colors, to be distributed between the two points
@param pos May be NULL. array[count] of SkScalars, or NULL, of the relative position of
each corresponding color in the colors array. If this is NULL,
@ -52,11 +48,30 @@ public:
return MakeLinear(pts, colors, pos, count, mode, 0, NULL);
}
/** Returns a shader that generates a linear gradient between the two specified points.
<p />
@param pts The start and end points for the gradient.
@param colors The array[count] of colors, to be distributed between the two points
@param pos May be NULL. array[count] of SkScalars, or NULL, of the relative position of
each corresponding color in the colors array. If this is NULL,
the the colors are distributed evenly between the start and end point.
If this is not null, the values must begin with 0, end with 1.0, and
intermediate values must be strictly increasing.
@param count Must be >=2. The number of colors (and pos if not NULL) entries.
@param mode The tiling mode
*/
static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count, SkShader::TileMode mode,
uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count, SkShader::TileMode mode) {
return MakeLinear(pts, colors, std::move(colorSpace), pos, count, mode, 0, NULL);
}
/** Returns a shader that generates a radial gradient given the center and radius.
<p />
CreateRadial returns a shader with a reference count of 1.
The caller should decrement the shader's reference count when done with the shader.
It is an error for colorCount to be < 2, or for radius to be <= 0.
@param center The center of the circle for this gradient
@param radius Must be positive. The radius of the circle for this gradient
@param colors The array[count] of colors, to be distributed between the center and edge of the circle
@ -78,6 +93,29 @@ public:
return MakeRadial(center, radius, colors, pos, count, mode, 0, NULL);
}
/** Returns a shader that generates a radial gradient given the center and radius.
<p />
@param center The center of the circle for this gradient
@param radius Must be positive. The radius of the circle for this gradient
@param colors The array[count] of colors, to be distributed between the center and edge of the circle
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
each corresponding color in the colors array. If this is NULL,
the the colors are distributed evenly between the center and edge of the circle.
If this is not null, the values must begin with 0, end with 1.0, and
intermediate values must be strictly increasing.
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
@param mode The tiling mode
*/
static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count, SkShader::TileMode mode,
uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count, SkShader::TileMode mode) {
return MakeRadial(center, radius, colors, std::move(colorSpace), pos, count, mode, 0, NULL);
}
/**
* Returns a shader that generates a conical gradient given two circles, or
* returns NULL if the inputs are invalid. The gradient interprets the
@ -97,11 +135,29 @@ public:
0, NULL);
}
/**
* Returns a shader that generates a conical gradient given two circles, or
* returns NULL if the inputs are invalid. The gradient interprets the
* two circles according to the following HTML spec.
* http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
*/
static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
const SkColor4f colors[],
sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
int count, SkShader::TileMode mode,
uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
const SkColor4f colors[],
sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],
int count, SkShader::TileMode mode) {
return MakeTwoPointConical(start, startRadius, end, endRadius, colors,
std::move(colorSpace), pos, count, mode, 0, NULL);
}
/** Returns a shader that generates a sweep gradient given a center.
<p />
CreateSweep returns a shader with a reference count of 1.
The caller should decrement the shader's reference count when done with the shader.
It is an error for colorCount to be < 2.
@param cx The X coordinate of the center of the sweep
@param cx The Y coordinate of the center of the sweep
@param colors The array[count] of colors, to be distributed around the center.
@ -120,6 +176,28 @@ public:
return MakeSweep(cx, cy, colors, pos, count, 0, NULL);
}
/** Returns a shader that generates a sweep gradient given a center.
<p />
@param cx The X coordinate of the center of the sweep
@param cx The Y coordinate of the center of the sweep
@param colors The array[count] of colors, to be distributed around the center.
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
each corresponding color in the colors array. If this is NULL,
the the colors are distributed evenly between the center and edge of the circle.
If this is not null, the values must begin with 0, end with 1.0, and
intermediate values must be strictly increasing.
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
*/
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count,
uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count) {
return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, 0, NULL);
}
#ifdef SK_SUPPORT_LEGACY_CREATESHADER_PTR
static SkShader* CreateLinear(const SkPoint pts[2],
const SkColor colors[], const SkScalar pos[], int count,

Просмотреть файл

@ -13,25 +13,11 @@
class SK_API SkImageSource : public SkImageFilter {
public:
static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image) {
if (!image) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkImageSource(std::move(image)));
}
static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image);
static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image,
const SkRect& srcRect,
const SkRect& dstRect,
SkFilterQuality filterQuality) {
if (!image) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkImageSource(std::move(image),
srcRect, dstRect,
filterQuality));
}
SkFilterQuality filterQuality);
SkRect computeFastBounds(const SkRect& src) const override;

Просмотреть файл

@ -17,34 +17,77 @@ struct SkPoint3;
class SK_API SkLightingImageFilter : public SkImageFilter {
public:
static SkImageFilter* CreateDistantLitDiffuse(const SkPoint3& direction,
static sk_sp<SkImageFilter> MakeDistantLitDiffuse(const SkPoint3& direction,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
static SkImageFilter* CreatePointLitDiffuse(const SkPoint3& location,
sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> MakePointLitDiffuse(const SkPoint3& location,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
static SkImageFilter* CreateSpotLitDiffuse(const SkPoint3& location,
sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> MakeSpotLitDiffuse(const SkPoint3& location,
const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
static SkImageFilter* CreateDistantLitSpecular(const SkPoint3& direction,
sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> MakeDistantLitSpecular(const SkPoint3& direction,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
static SkImageFilter* CreatePointLitSpecular(const SkPoint3& location,
SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> MakePointLitSpecular(const SkPoint3& location,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
static SkImageFilter* CreateSpotLitSpecular(const SkPoint3& location,
SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> MakeSpotLitSpecular(const SkPoint3& location,
const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
~SkLightingImageFilter();
SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);
~SkLightingImageFilter() override;
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* CreateDistantLitDiffuse(const SkPoint3& direction,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakeDistantLitDiffuse(direction, lightColor, surfaceScale, kd,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
static SkImageFilter* CreatePointLitDiffuse(const SkPoint3& location,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakePointLitDiffuse(location, lightColor, surfaceScale, kd,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
static SkImageFilter* CreateSpotLitDiffuse(const SkPoint3& location,
const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakeSpotLitDiffuse(location, target, specularExponent, cutoffAngle,
lightColor, surfaceScale, kd,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
static SkImageFilter* CreateDistantLitSpecular(const SkPoint3& direction,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakeDistantLitSpecular(direction, lightColor, surfaceScale, ks, shininess,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
static SkImageFilter* CreatePointLitSpecular(const SkPoint3& location,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakePointLitSpecular(location, lightColor, surfaceScale, ks, shininess,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
static SkImageFilter* CreateSpotLitSpecular(const SkPoint3& location,
const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL) {
return MakeSpotLitSpecular(location, target, specularExponent, cutoffAngle,
lightColor, surfaceScale, ks, shininess,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
#endif
protected:
SkLightingImageFilter(SkImageFilterLight* light,
SkLightingImageFilter(sk_sp<SkImageFilterLight> light,
SkScalar surfaceScale,
SkImageFilter* input,
sk_sp<SkImageFilter> input,
const CropRect* cropRect);
void flatten(SkWriteBuffer&) const override;
const SkImageFilterLight* light() const { return fLight.get(); }
@ -52,9 +95,10 @@ protected:
bool affectsTransparentBlack() const override { return true; }
private:
typedef SkImageFilter INHERITED;
SkAutoTUnref<SkImageFilterLight> fLight;
sk_sp<SkImageFilterLight> fLight;
SkScalar fSurfaceScale;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -9,6 +9,7 @@
#define SkLumaColorFilter_DEFINED
#include "SkColorFilter.h"
#include "SkRefCnt.h"
/**
* Luminance-to-alpha color filter, as defined in
@ -32,7 +33,7 @@ public:
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU
const GrFragmentProcessor* asFragmentProcessor(GrContext*) const override;
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
#endif
SK_TO_STRING_OVERRIDE()

Просмотреть файл

@ -14,7 +14,9 @@
class SK_API SkMagnifierImageFilter : public SkImageFilter {
public:
static sk_sp<SkImageFilter> Make(const SkRect& src, SkScalar inset, sk_sp<SkImageFilter> input);
static sk_sp<SkImageFilter> Make(const SkRect& src, SkScalar inset,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMagnifierImageFilter)
@ -27,15 +29,14 @@ public:
#endif
protected:
SkMagnifierImageFilter(const SkRect& srcRect, SkScalar inset, sk_sp<SkImageFilter> input);
SkMagnifierImageFilter(const SkRect& srcRect,
SkScalar inset,
sk_sp<SkImageFilter> input,
const CropRect* cropRect);
void flatten(SkWriteBuffer&) const override;
bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* offset) const override;
#if SK_SUPPORT_GPU
bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
const SkIRect& bounds) const override;
#endif
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
private:
SkRect fSrcRect;

Просмотреть файл

@ -13,6 +13,8 @@
#include "SkSize.h"
#include "SkPoint.h"
class SkBitmap;
/*! \class SkMatrixConvolutionImageFilter
Matrix convolution image filter. This filter applies an NxM image
processing kernel to a given input image. This can be used to produce
@ -29,7 +31,7 @@ public:
kMax_TileMode = kClampToBlack_TileMode
};
virtual ~SkMatrixConvolutionImageFilter();
~SkMatrixConvolutionImageFilter() override;
/** Construct a matrix convolution image filter.
@param kernelSize The kernel size in pixels, in each dimension (N by M).
@ -52,6 +54,20 @@ public:
passed to filterImage() is used instead.
@param cropRect The rectangle to which the output processing will be limited.
*/
static sk_sp<SkImageFilter> Make(const SkISize& kernelSize,
const SkScalar* kernel,
SkScalar gain,
SkScalar bias,
const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter)
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(const SkISize& kernelSize,
const SkScalar* kernel,
SkScalar gain,
@ -60,10 +76,11 @@ public:
TileMode tileMode,
bool convolveAlpha,
SkImageFilter* input = NULL,
const CropRect* cropRect = NULL);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMatrixConvolutionImageFilter)
const CropRect* cropRect = NULL) {
return Make(kernelSize, kernel, gain, bias, kernelOffset, tileMode, convolveAlpha,
sk_ref_sp<SkImageFilter>(input), cropRect).release();
}
#endif
protected:
SkMatrixConvolutionImageFilter(const SkISize& kernelSize,
@ -73,20 +90,15 @@ protected:
const SkIPoint& kernelOffset,
TileMode tileMode,
bool convolveAlpha,
SkImageFilter* input,
sk_sp<SkImageFilter> input,
const CropRect* cropRect);
void flatten(SkWriteBuffer&) const override;
bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
SkBitmap* result, SkIPoint* loc) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
bool affectsTransparentBlack() const override;
#if SK_SUPPORT_GPU
bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
const SkIRect& bounds) const override;
#endif
private:
SkISize fKernelSize;
SkScalar* fKernel;
@ -95,7 +107,6 @@ private:
SkIPoint fKernelOffset;
TileMode fTileMode;
bool fConvolveAlpha;
typedef SkImageFilter INHERITED;
template <class PixelFetcher, bool convolveAlpha>
void filterPixels(const SkBitmap& src,
@ -115,6 +126,8 @@ private:
SkBitmap* result,
const SkIRect& rect,
const SkIRect& bounds) const;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -18,18 +18,11 @@ public:
static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> first, sk_sp<SkImageFilter> second,
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode,
const CropRect* cropRect = nullptr) {
sk_sp<SkImageFilter> inputs[2] = { first, second };
SkXfermode::Mode modes[2] = { mode, mode };
return sk_sp<SkImageFilter>(new SkMergeImageFilter(inputs, 2, modes, cropRect));
}
const CropRect* cropRect = nullptr);
static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> filters[],
int count,
const SkXfermode::Mode modes[] = nullptr,
const CropRect* cropRect = nullptr) {
return sk_sp<SkImageFilter>(new SkMergeImageFilter(filters, count, modes, cropRect));
}
const CropRect* cropRect = nullptr);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMergeImageFilter)
@ -58,6 +51,7 @@ protected:
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
bool onCanHandleComplexCTM() const override { return true; }
private:
SkMergeImageFilter(sk_sp<SkImageFilter> filters[], int count, const SkXfermode::Mode modes[],

Просмотреть файл

@ -57,14 +57,7 @@ class SK_API SkDilateImageFilter : public SkMorphologyImageFilter {
public:
static sk_sp<SkImageFilter> Make(int radiusX, int radiusY,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr) {
if (radiusX < 0 || radiusY < 0) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkDilateImageFilter(radiusX, radiusY,
std::move(input),
cropRect));
}
const CropRect* cropRect = nullptr);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter)
@ -96,14 +89,7 @@ class SK_API SkErodeImageFilter : public SkMorphologyImageFilter {
public:
static sk_sp<SkImageFilter> Make(int radiusX, int radiusY,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr) {
if (radiusX < 0 || radiusY < 0) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkErodeImageFilter(radiusX, radiusY,
std::move(input),
cropRect));
}
const CropRect* cropRect = nullptr);
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter)

Просмотреть файл

@ -15,13 +15,7 @@ class SK_API SkOffsetImageFilter : public SkImageFilter {
public:
static sk_sp<SkImageFilter> Make(SkScalar dx, SkScalar dy,
sk_sp<SkImageFilter> input,
const CropRect* cropRect = nullptr) {
if (!SkScalarIsFinite(dx) || !SkScalarIsFinite(dy)) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkOffsetImageFilter(dx, dy, std::move(input), cropRect));
}
const CropRect* cropRect = nullptr);
SkRect computeFastBounds(const SkRect& src) const override;

Просмотреть файл

@ -22,9 +22,7 @@ public:
* not specified, the source primitive's bounds are used
* instead.
*/
static sk_sp<SkImageFilter> Make(const SkPaint& paint, const CropRect* cropRect = nullptr) {
return sk_sp<SkImageFilter>(new SkPaintImageFilter(paint, cropRect));
}
static sk_sp<SkImageFilter> Make(const SkPaint& paint, const CropRect* cropRect = nullptr);
bool affectsTransparentBlack() const override;

Просмотреть файл

@ -102,8 +102,7 @@ public:
};
#if SK_SUPPORT_GPU
const GrFragmentProcessor* asFragmentProcessor(GrContext* context, const SkMatrix& viewM,
const SkMatrix*, SkFilterQuality) const override;
sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
#endif
SK_TO_STRING_OVERRIDE()

Просмотреть файл

@ -16,20 +16,13 @@ public:
/**
* Refs the passed-in picture.
*/
static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture) {
return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture)));
}
static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture);
/**
* Refs the passed-in picture. cropRect can be used to crop or expand the destination rect when
* the picture is drawn. (No scaling is implied by the dest rect; only the CTM is applied.)
*/
static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture, const SkRect& cropRect) {
return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture),
cropRect,
kDeviceSpace_PictureResolution,
kLow_SkFilterQuality));
}
static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture, const SkRect& cropRect);
/**
* Refs the passed-in picture. The picture is rasterized at a resolution that matches the
@ -40,12 +33,7 @@ public:
*/
static sk_sp<SkImageFilter> MakeForLocalSpace(sk_sp<SkPicture> picture,
const SkRect& cropRect,
SkFilterQuality filterQuality) {
return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture),
cropRect,
kLocalSpace_PictureResolution,
filterQuality));
}
SkFilterQuality filterQuality);
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(const SkPicture* picture) {
@ -79,17 +67,20 @@ protected:
* @param SkReadBuffer Serialized picture data.
*/
void flatten(SkWriteBuffer&) const override;
bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result,
SkIPoint* offset) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
private:
explicit SkPictureImageFilter(sk_sp<SkPicture> picture);
SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
PictureResolution, SkFilterQuality);
void drawPictureAtDeviceResolution(SkBaseDevice*, const SkIRect& deviceBounds,
void drawPictureAtDeviceResolution(SkCanvas* canvas,
const SkIRect& deviceBounds,
const Context&) const;
void drawPictureAtLocalResolution(Proxy*, SkBaseDevice*, const SkIRect& deviceBounds,
void drawPictureAtLocalResolution(SkSpecialImage* source,
SkCanvas*,
const SkIRect& deviceBounds,
const Context&) const;
sk_sp<SkPicture> fPicture;

Просмотреть файл

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkRRectsGaussianEdgeShader_DEFINED
#define SkRRectsGaussianEdgeShader_DEFINED
#include "SkShader.h"
class SkRRect;
class SK_API SkRRectsGaussianEdgeShader {
public:
/** Returns a shader that applies a Gaussian blur depending on distance to the edge
* of the intersection of two round rects.
* Currently this is only useable with round rects that have the same radii at
* all the corners and for which the x & y radii are equal.
* Raster will draw nothing.
*
* The coverage geometry that should be drawn should be no larger than the intersection
* of the bounding boxes of the two round rects. Ambitious users can omit the center
* area of the coverage geometry if it is known to be occluded.
*/
static sk_sp<SkShader> Make(const SkRRect& first,
const SkRRect& second,
SkScalar radius, SkScalar unused = 0.0f);
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
private:
SkRRectsGaussianEdgeShader(); // can't be instantiated
};
#endif

Просмотреть файл

@ -1,52 +0,0 @@
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef _SkTestImageFilters_h
#define _SkTestImageFilters_h
#include "SkImageFilter.h"
#include "SkPoint.h"
// Fun mode that scales down (only) and then scales back up to look pixelated
class SK_API SkDownSampleImageFilter : public SkImageFilter {
public:
static sk_sp<SkImageFilter> Make(SkScalar scale, sk_sp<SkImageFilter> input) {
if (!SkScalarIsFinite(scale)) {
return nullptr;
}
// we don't support scale in this range
if (scale > SK_Scalar1 || scale <= 0) {
return nullptr;
}
return sk_sp<SkImageFilter>(new SkDownSampleImageFilter(scale, std::move(input)));
}
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDownSampleImageFilter)
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(SkScalar scale, SkImageFilter* input = nullptr) {
return Make(scale, sk_ref_sp<SkImageFilter>(input)).release();
}
#endif
protected:
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
private:
SkDownSampleImageFilter(SkScalar scale, sk_sp<SkImageFilter> input)
: INHERITED(&input, 1, nullptr), fScale(scale) {}
SkScalar fScale;
typedef SkImageFilter INHERITED;
};
#endif

Просмотреть файл

@ -11,18 +11,16 @@
#include "SkImageFilter.h"
class SK_API SkTileImageFilter : public SkImageFilter {
typedef SkImageFilter INHERITED;
public:
/** Create a tile image filter
@param src Defines the pixels to tile
@param dst Defines the pixels where tiles are drawn
@param input Input from which the subregion defined by srcRect will be tiled
*/
static SkImageFilter* Create(const SkRect& src, const SkRect& dst, SkImageFilter* input);
static sk_sp<SkImageFilter> Make(const SkRect& src,
const SkRect& dst,
sk_sp<SkImageFilter> input);
bool onFilterImageDeprecated(Proxy* proxy, const SkBitmap& src, const Context& ctx,
SkBitmap* dst, SkIPoint* offset) const override;
SkIRect onFilterBounds(const SkIRect& src, const SkMatrix&, MapDirection) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
SkRect computeFastBounds(const SkRect& src) const override;
@ -30,15 +28,26 @@ public:
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTileImageFilter)
#ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_PTR
static SkImageFilter* Create(const SkRect& src, const SkRect& dst, SkImageFilter* input) {
return Make(src, dst, sk_ref_sp<SkImageFilter>(input)).release();
}
#endif
protected:
void flatten(SkWriteBuffer& buffer) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
private:
SkTileImageFilter(const SkRect& srcRect, const SkRect& dstRect, SkImageFilter* input)
: INHERITED(1, &input, NULL), fSrcRect(srcRect), fDstRect(dstRect) {}
SkTileImageFilter(const SkRect& srcRect, const SkRect& dstRect, sk_sp<SkImageFilter> input)
: INHERITED(&input, 1, nullptr), fSrcRect(srcRect), fDstRect(dstRect) {}
SkRect fSrcRect;
SkRect fDstRect;
typedef SkImageFilter INHERITED;
};
#endif

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше