mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Lottie experiments
This commit is contained in:
parent
5b08504388
commit
992bfbde1e
@ -201,6 +201,7 @@ ios_application(
|
||||
resources = [
|
||||
"//Tests/Common:LaunchScreen",
|
||||
":TestDataBundle",
|
||||
"//Tests/LottieMetalTest/skia",
|
||||
],
|
||||
frameworks = [
|
||||
],
|
||||
|
@ -25,6 +25,8 @@ objc_library(
|
||||
deps = [
|
||||
"//submodules/LottieCpp",
|
||||
"//Tests/LottieMetalTest/thorvg",
|
||||
"//Tests/LottieMetalTest/skia",
|
||||
"//Tests/LottieMetalTest/skia:libskia"
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
|
@ -0,0 +1,316 @@
|
||||
#include "SkiaCanvasImpl.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkFont.h"
|
||||
#include "include/core/SkFontTypes.h"
|
||||
#include "include/core/SkGraphics.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkShader.h"
|
||||
#include "include/core/SkString.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/core/SkTileMode.h"
|
||||
#include "include/core/SkPath.h"
|
||||
#include "include/core/SkPathEffect.h"
|
||||
#include "include/effects/SkDashPathEffect.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
|
||||
namespace lottie {
|
||||
|
||||
namespace {
|
||||
|
||||
SkColor skColor(Color const &color) {
|
||||
return SkColorSetARGB((uint8_t)(color.a * 255.0), (uint8_t)(color.r * 255.0), (uint8_t)(color.g * 255.0), (uint8_t)(color.b * 255.0));
|
||||
}
|
||||
|
||||
void skPath(CanvasPathEnumerator const &enumeratePath, SkPath &nativePath) {
|
||||
enumeratePath([&](PathCommand const &command) {
|
||||
switch (command.type) {
|
||||
case PathCommandType::MoveTo: {
|
||||
nativePath.moveTo(command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::LineTo: {
|
||||
nativePath.lineTo(command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::CurveTo: {
|
||||
nativePath.cubicTo(command.points[0].x, command.points[0].y, command.points[1].x, command.points[1].y, command.points[2].x, command.points[2].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::Close: {
|
||||
nativePath.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SkiaCanvasImpl::SkiaCanvasImpl(int width, int height) :
|
||||
_width(width), _height(height) {
|
||||
int bytesPerRow = width * 4;
|
||||
_pixelData = malloc(bytesPerRow * height);
|
||||
_ownsPixelData = true;
|
||||
|
||||
_surface = SkSurfaces::WrapPixels(
|
||||
SkImageInfo::MakeN32Premul(width, height),
|
||||
_pixelData,
|
||||
bytesPerRow,
|
||||
nullptr
|
||||
);
|
||||
|
||||
_canvas = _surface->getCanvas();
|
||||
_canvas->resetMatrix();
|
||||
_canvas->clear(SkColorSetARGB(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
SkiaCanvasImpl::SkiaCanvasImpl(int width, int height, int bytesPerRow, void *pixelData) {
|
||||
_pixelData = pixelData;
|
||||
_ownsPixelData = false;
|
||||
|
||||
_surface = SkSurfaces::WrapPixels(
|
||||
SkImageInfo::MakeN32Premul(width, height),
|
||||
_pixelData,
|
||||
bytesPerRow,
|
||||
nullptr
|
||||
);
|
||||
|
||||
_canvas = _surface->getCanvas();
|
||||
_canvas->resetMatrix();
|
||||
_canvas->clear(SkColorSetARGB(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
SkiaCanvasImpl::~SkiaCanvasImpl() {
|
||||
if (_ownsPixelData) {
|
||||
free(_pixelData);
|
||||
}
|
||||
}
|
||||
|
||||
int SkiaCanvasImpl::width() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
int SkiaCanvasImpl::height() const {
|
||||
return _height;
|
||||
}
|
||||
|
||||
std::shared_ptr<Canvas> SkiaCanvasImpl::makeLayer(int width, int height) {
|
||||
return std::make_shared<SkiaCanvasImpl>(width, height);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::saveState() {
|
||||
_canvas->save();
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::restoreState() {
|
||||
_canvas->restore();
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
SkPaint paint;
|
||||
paint.setColor(skColor(color));
|
||||
paint.setAlphaf(_alpha);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setBlendMode(_blendMode);
|
||||
|
||||
SkPath nativePath;
|
||||
skPath(enumeratePath, nativePath);
|
||||
nativePath.setFillType(fillRule == FillRule::EvenOdd ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding);
|
||||
|
||||
_canvas->drawPath(nativePath, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setBlendMode(_blendMode);
|
||||
paint.setDither(false);
|
||||
paint.setStyle(SkPaint::Style::kFill_Style);
|
||||
|
||||
SkPoint linearPoints[2] = {
|
||||
SkPoint::Make(start.x, start.y),
|
||||
SkPoint::Make(end.x, end.y)
|
||||
};
|
||||
|
||||
std::vector<SkColor> colors;
|
||||
for (const auto &color : gradient.colors()) {
|
||||
colors.push_back(skColor(Color(color.r, color.g, color.b, color.a * _alpha)));
|
||||
}
|
||||
|
||||
std::vector<SkScalar> locations;
|
||||
for (auto location : gradient.locations()) {
|
||||
locations.push_back(location);
|
||||
}
|
||||
|
||||
paint.setShader(SkGradientShader::MakeLinear(linearPoints, colors.data(), locations.data(), (int)colors.size(), SkTileMode::kMirror));
|
||||
|
||||
SkPath nativePath;
|
||||
skPath(enumeratePath, nativePath);
|
||||
nativePath.setFillType(fillRule == FillRule::EvenOdd ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding);
|
||||
|
||||
_canvas->drawPath(nativePath, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setBlendMode(_blendMode);
|
||||
paint.setDither(false);
|
||||
paint.setStyle(SkPaint::Style::kFill_Style);
|
||||
|
||||
std::vector<SkColor> colors;
|
||||
for (const auto &color : gradient.colors()) {
|
||||
colors.push_back(skColor(Color(color.r, color.g, color.b, color.a * _alpha)));
|
||||
}
|
||||
|
||||
std::vector<SkScalar> locations;
|
||||
for (auto location : gradient.locations()) {
|
||||
locations.push_back(location);
|
||||
}
|
||||
|
||||
paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(startCenter.x, startCenter.y), endRadius, colors.data(), locations.data(), (int)colors.size(), SkTileMode::kMirror));
|
||||
|
||||
SkPath nativePath;
|
||||
skPath(enumeratePath, nativePath);
|
||||
nativePath.setFillType(fillRule == FillRule::EvenOdd ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding);
|
||||
|
||||
_canvas->drawPath(nativePath, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setBlendMode(_blendMode);
|
||||
paint.setColor(skColor(color));
|
||||
paint.setAlphaf(_alpha);
|
||||
paint.setStyle(SkPaint::Style::kStroke_Style);
|
||||
|
||||
paint.setStrokeWidth(lineWidth);
|
||||
switch (lineJoin) {
|
||||
case LineJoin::Miter: {
|
||||
paint.setStrokeJoin(SkPaint::Join::kMiter_Join);
|
||||
break;
|
||||
}
|
||||
case LineJoin::Round: {
|
||||
paint.setStrokeJoin(SkPaint::Join::kRound_Join);
|
||||
break;
|
||||
}
|
||||
case LineJoin::Bevel: {
|
||||
paint.setStrokeJoin(SkPaint::Join::kBevel_Join);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
paint.setStrokeJoin(SkPaint::Join::kBevel_Join);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lineCap) {
|
||||
case LineCap::Butt: {
|
||||
paint.setStrokeCap(SkPaint::Cap::kButt_Cap);
|
||||
break;
|
||||
}
|
||||
case LineCap::Round: {
|
||||
paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
|
||||
break;
|
||||
}
|
||||
case LineCap::Square: {
|
||||
paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dashPattern.empty()) {
|
||||
std::vector<SkScalar> intervals;
|
||||
intervals.reserve(dashPattern.size());
|
||||
for (auto value : dashPattern) {
|
||||
intervals.push_back(value);
|
||||
}
|
||||
paint.setPathEffect(SkDashPathEffect::Make(intervals.data(), (int)intervals.size(), dashPhase));
|
||||
}
|
||||
|
||||
SkPath nativePath;
|
||||
skPath(enumeratePath, nativePath);
|
||||
|
||||
_canvas->drawPath(nativePath, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setColor(skColor(fillColor));
|
||||
paint.setAlphaf(_alpha);
|
||||
paint.setBlendMode(_blendMode);
|
||||
|
||||
_canvas->drawRect(SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::setBlendMode(BlendMode blendMode) {
|
||||
switch (blendMode) {
|
||||
case BlendMode::Normal: {
|
||||
_blendMode = SkBlendMode::kSrcOver;
|
||||
break;
|
||||
}
|
||||
case BlendMode::DestinationIn: {
|
||||
_blendMode = SkBlendMode::kDstIn;
|
||||
break;
|
||||
}
|
||||
case BlendMode::DestinationOut: {
|
||||
_blendMode = SkBlendMode::kDstOut;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
_blendMode = SkBlendMode::kSrcOver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::setAlpha(float alpha) {
|
||||
_alpha = alpha;
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||
SkScalar m9[9] = {
|
||||
transform.rows().columns[0][0], transform.rows().columns[1][0], transform.rows().columns[2][0],
|
||||
transform.rows().columns[0][1], transform.rows().columns[1][1], transform.rows().columns[2][1],
|
||||
transform.rows().columns[0][2], transform.rows().columns[1][2], transform.rows().columns[2][2]
|
||||
};
|
||||
SkMatrix matrix;
|
||||
matrix.set9(m9);
|
||||
_canvas->concat(matrix);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
||||
SkiaCanvasImpl *impl = (SkiaCanvasImpl *)other.get();
|
||||
auto image = impl->surface()->makeImageSnapshot();
|
||||
SkPaint paint;
|
||||
paint.setBlendMode(_blendMode);
|
||||
paint.setAlphaf(_alpha);
|
||||
_canvas->drawImageRect(image.get(), SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), SkSamplingOptions(SkFilterMode::kLinear), &paint);
|
||||
}
|
||||
|
||||
void SkiaCanvasImpl::flush() {
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> SkiaCanvasImpl::surface() const {
|
||||
return _surface;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
#ifndef SkiaCanvasImpl_h
|
||||
#define SkiaCanvasImpl_h
|
||||
|
||||
#include <LottieCpp/LottieCpp.h>
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
|
||||
namespace lottie {
|
||||
|
||||
class SkiaCanvasImpl: public Canvas {
|
||||
public:
|
||||
SkiaCanvasImpl(int width, int height);
|
||||
SkiaCanvasImpl(int width, int height, int bytesPerRow, void *pixelData);
|
||||
virtual ~SkiaCanvasImpl();
|
||||
|
||||
virtual int width() const override;
|
||||
virtual int height() const override;
|
||||
|
||||
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
||||
|
||||
virtual void saveState() override;
|
||||
virtual void restoreState() override;
|
||||
|
||||
virtual void fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override;
|
||||
|
||||
virtual void setBlendMode(BlendMode blendMode) override;
|
||||
|
||||
virtual void setAlpha(float alpha) override;
|
||||
|
||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
||||
void flush();
|
||||
sk_sp<SkSurface> surface() const;
|
||||
|
||||
private:
|
||||
void *_pixelData = nullptr;
|
||||
bool _ownsPixelData = false;
|
||||
int _width = 0;
|
||||
int _height = 0;
|
||||
sk_sp<SkSurface> _surface;
|
||||
SkCanvas *_canvas = nullptr;
|
||||
SkBlendMode _blendMode = SkBlendMode::kSrcOver;
|
||||
double _alpha = 1.0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -5,11 +5,14 @@
|
||||
|
||||
#import "CoreGraphicsCanvasImpl.h"
|
||||
#import "ThorVGCanvasImpl.h"
|
||||
#import "SkiaCanvasImpl.h"
|
||||
|
||||
#include <LottieCpp/RenderTreeNode.h>
|
||||
#include <LottieCpp/CGPathCocoa.h>
|
||||
#include <LottieCpp/VectorsCocoa.h>
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
auto rect = calculatePathBoundingBox(path);
|
||||
return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
||||
@ -69,7 +72,84 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
|
||||
return [[UIImage alloc] initWithCGImage:std::static_pointer_cast<lottie::CanvasImpl::Image>(image)->nativeImage()];
|
||||
} else {
|
||||
if ((int64_t)"" < 0) {
|
||||
if ((int64_t)"" > 0) {
|
||||
/*auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul((int)size.width, (int)size.height));
|
||||
|
||||
int bytesPerRow = ((int)size.width) * 4;
|
||||
void *pixelData = malloc(bytesPerRow * (int)size.height);
|
||||
|
||||
sk_sp<SkSurface> surface2 = SkSurfaces::WrapPixels(
|
||||
SkImageInfo::MakeN32Premul((int)size.width, (int)size.height),
|
||||
pixelData,
|
||||
bytesPerRow,
|
||||
nullptr
|
||||
);
|
||||
|
||||
SkCanvas *canvas = surface->getCanvas();
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
SkPath path;
|
||||
path.moveTo(124, 108);
|
||||
path.lineTo(172, 24);
|
||||
path.addCircle(50, 50, 30);
|
||||
path.moveTo(36, 148);
|
||||
path.quadTo(66, 188, 120, 136);
|
||||
canvas->drawPath(path, paint);
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
paint.setColor(SK_ColorBLUE);
|
||||
paint.setStrokeWidth(3);
|
||||
canvas->drawPath(path, paint);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||
|
||||
CGContextRef targetContext = CGBitmapContextCreate(pixelData, (int)size.width, (int)size.height, 8, bytesPerRow, colorSpace, bitmapInfo);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
CGImageRef bitmapImage = CGBitmapContextCreateImage(targetContext);
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:bitmapImage scale:1.0f orientation:UIImageOrientationDownMirrored];
|
||||
CGImageRelease(bitmapImage);
|
||||
|
||||
CGContextRelease(targetContext);
|
||||
|
||||
free(pixelData);
|
||||
|
||||
return image;*/
|
||||
|
||||
int bytesPerRow = ((int)size.width) * 4;
|
||||
void *pixelData = malloc(bytesPerRow * (int)size.height);
|
||||
auto context = std::make_shared<lottie::SkiaCanvasImpl>((int)size.width, (int)size.height, bytesPerRow, pixelData);
|
||||
|
||||
_canvasRenderer->render(_renderer, context, lottie::Vector2D(size.width, size.height));
|
||||
|
||||
context->flush();
|
||||
|
||||
vImage_Buffer src;
|
||||
src.data = (void *)pixelData;
|
||||
src.width = (int)size.width;
|
||||
src.height = (int)size.height;
|
||||
src.rowBytes = bytesPerRow;
|
||||
|
||||
uint8_t permuteMap[4] = {2, 1, 0, 3};
|
||||
vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, kvImageDoNotTile);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||
|
||||
CGContextRef targetContext = CGBitmapContextCreate(pixelData, (int)size.width, (int)size.height, 8, bytesPerRow, colorSpace, bitmapInfo);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
|
||||
CGImageRef bitmapImage = CGBitmapContextCreateImage(targetContext);
|
||||
UIImage *image = [[UIImage alloc] initWithCGImage:bitmapImage scale:1.0f orientation:UIImageOrientationDownMirrored];
|
||||
CGImageRelease(bitmapImage);
|
||||
|
||||
CGContextRelease(targetContext);
|
||||
|
||||
free(pixelData);
|
||||
|
||||
return image;
|
||||
} else if ((int64_t)"" < 0) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
lottie::ThorVGCanvasImpl::initializeOnce();
|
||||
|
@ -113,15 +113,15 @@ public final class ViewController: UIViewController {
|
||||
SharedDisplayLinkDriver.shared.updateForegroundState(true)
|
||||
|
||||
let bundlePath = Bundle.main.path(forResource: "TestDataBundle", ofType: "bundle")!
|
||||
let filePath = bundlePath + "/fireworks.json"
|
||||
let filePath = bundlePath + "/fire.json"
|
||||
|
||||
let performanceFrameSize = 8
|
||||
let performanceFrameSize = 512
|
||||
|
||||
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
|
||||
|
||||
if "".isEmpty {
|
||||
if !"".isEmpty {
|
||||
if #available(iOS 13.0, *) {
|
||||
self.test = ReferenceCompareTest(view: self.view, testNonReference: false)
|
||||
self.test = ReferenceCompareTest(view: self.view, testNonReference: true)
|
||||
}
|
||||
} else if !"".isEmpty {
|
||||
/*let cachedAnimation = cacheLottieMetalAnimation(path: filePath)!
|
||||
|
43
Tests/LottieMetalTest/skia/BUILD
Normal file
43
Tests/LottieMetalTest/skia/BUILD
Normal file
@ -0,0 +1,43 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
load("@build_bazel_rules_apple//apple:apple.bzl",
|
||||
"apple_dynamic_framework_import",
|
||||
)
|
||||
|
||||
|
||||
apple_dynamic_framework_import(
|
||||
name = "libskia",
|
||||
framework_imports = glob([
|
||||
"libskia.framework/**"
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "skia",
|
||||
enable_modules = True,
|
||||
module_name = "skia",
|
||||
srcs = glob([
|
||||
]),
|
||||
copts = [
|
||||
"-I{}/PublicHeaders/skia".format(package_name()),
|
||||
],
|
||||
linkopts = [
|
||||
"-Wl,-rpath,@loader_path/Frameworks/libskia.framework",
|
||||
],
|
||||
hdrs = glob([
|
||||
"PublicHeaders/**/*.h",
|
||||
]),
|
||||
includes = [
|
||||
"PublicHeaders",
|
||||
"PublicHeaders/skia",
|
||||
],
|
||||
deps = [
|
||||
":libskia",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"Foundation",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
15
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/OWNERS
Normal file
15
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/OWNERS
Normal file
@ -0,0 +1,15 @@
|
||||
set noparent
|
||||
|
||||
# Include one of the following reviewers for CLs that add or change Skia's public API:
|
||||
brianosman@google.com
|
||||
egdaniel@google.com
|
||||
fmalita@google.com
|
||||
fmalita@chromium.org
|
||||
hcm@google.com
|
||||
herb@google.com
|
||||
robertphillips@google.com
|
||||
|
||||
per-file BUILD.bazel=bungeman@google.com
|
||||
per-file BUILD.bazel=jcgregorio@google.com
|
||||
per-file BUILD.bazel=kjlubick@google.com
|
||||
per-file BUILD.bazel=lovisolo@google.com
|
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* 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 SkAndroidCodec_DEFINED
|
||||
#define SkAndroidCodec_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkColorSpace.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/SkEncodedInfo.h"
|
||||
#include "include/private/base/SkNoncopyable.h"
|
||||
#include "modules/skcms/skcms.h"
|
||||
|
||||
// TODO(kjlubick, bungeman) Replace these includes with forward declares
|
||||
#include "include/codec/SkEncodedImageFormat.h" // IWYU pragma: keep
|
||||
#include "include/core/SkAlphaType.h" // IWYU pragma: keep
|
||||
#include "include/core/SkColorType.h" // IWYU pragma: keep
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
class SkData;
|
||||
class SkPngChunkReader;
|
||||
class SkStream;
|
||||
struct SkGainmapInfo;
|
||||
struct SkIRect;
|
||||
|
||||
/**
|
||||
* Abstract interface defining image codec functionality that is necessary for
|
||||
* Android.
|
||||
*/
|
||||
class SK_API SkAndroidCodec : SkNoncopyable {
|
||||
public:
|
||||
/**
|
||||
* Deprecated.
|
||||
*
|
||||
* Now that SkAndroidCodec supports multiframe images, there are multiple
|
||||
* ways to handle compositing an oriented frame on top of an oriented frame
|
||||
* with different tradeoffs. SkAndroidCodec now ignores the orientation and
|
||||
* forces the client to handle it.
|
||||
*/
|
||||
enum class ExifOrientationBehavior {
|
||||
kIgnore,
|
||||
kRespect,
|
||||
};
|
||||
|
||||
/**
|
||||
* Pass ownership of an SkCodec to a newly-created SkAndroidCodec.
|
||||
*/
|
||||
static std::unique_ptr<SkAndroidCodec> MakeFromCodec(std::unique_ptr<SkCodec>);
|
||||
|
||||
/**
|
||||
* If this stream represents an encoded image that we know how to decode,
|
||||
* return an SkAndroidCodec that can decode it. Otherwise return NULL.
|
||||
*
|
||||
* The SkPngChunkReader handles unknown chunks in PNGs.
|
||||
* See SkCodec.h for more details.
|
||||
*
|
||||
* If NULL is returned, the stream is deleted immediately. Otherwise, the
|
||||
* SkCodec takes ownership of it, and will delete it when done with it.
|
||||
*/
|
||||
static std::unique_ptr<SkAndroidCodec> MakeFromStream(std::unique_ptr<SkStream>,
|
||||
SkPngChunkReader* = nullptr);
|
||||
|
||||
/**
|
||||
* If this data represents an encoded image that we know how to decode,
|
||||
* return an SkAndroidCodec that can decode it. Otherwise return NULL.
|
||||
*
|
||||
* The SkPngChunkReader handles unknown chunks in PNGs.
|
||||
* See SkCodec.h for more details.
|
||||
*/
|
||||
static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
|
||||
|
||||
virtual ~SkAndroidCodec();
|
||||
|
||||
// TODO: fInfo is now just a cache of SkCodec's SkImageInfo. No need to
|
||||
// cache and return a reference here, once Android call-sites are updated.
|
||||
const SkImageInfo& getInfo() const { return fInfo; }
|
||||
|
||||
/**
|
||||
* Return the ICC profile of the encoded data.
|
||||
*/
|
||||
const skcms_ICCProfile* getICCProfile() const {
|
||||
return fCodec->getEncodedInfo().profile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format of the encoded data.
|
||||
*/
|
||||
SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
|
||||
|
||||
/**
|
||||
* @param requestedColorType Color type requested by the client
|
||||
*
|
||||
* |requestedColorType| may be overriden. We will default to kF16
|
||||
* for high precision images.
|
||||
*
|
||||
* In the general case, if it is possible to decode to
|
||||
* |requestedColorType|, this returns |requestedColorType|.
|
||||
* Otherwise, this returns a color type that is an appropriate
|
||||
* match for the the encoded data.
|
||||
*/
|
||||
SkColorType computeOutputColorType(SkColorType requestedColorType);
|
||||
|
||||
/**
|
||||
* @param requestedUnpremul Indicates if the client requested
|
||||
* unpremultiplied output
|
||||
*
|
||||
* Returns the appropriate alpha type to decode to. If the image
|
||||
* has alpha, the value of requestedUnpremul will be honored.
|
||||
*/
|
||||
SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
|
||||
|
||||
/**
|
||||
* @param outputColorType Color type that the client will decode to.
|
||||
* @param prefColorSpace Preferred color space to decode to.
|
||||
* This may not return |prefColorSpace| for
|
||||
* specific color types.
|
||||
*
|
||||
* Returns the appropriate color space to decode to.
|
||||
*/
|
||||
sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
|
||||
sk_sp<SkColorSpace> prefColorSpace = nullptr);
|
||||
|
||||
/**
|
||||
* Compute the appropriate sample size to get to |size|.
|
||||
*
|
||||
* @param size As an input parameter, the desired output size of
|
||||
* the decode. As an output parameter, the smallest sampled size
|
||||
* larger than the input.
|
||||
* @return the sample size to set AndroidOptions::fSampleSize to decode
|
||||
* to the output |size|.
|
||||
*/
|
||||
int computeSampleSize(SkISize* size) const;
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the scaled output image, for an input
|
||||
* sampleSize.
|
||||
*
|
||||
* When the sample size divides evenly into the original dimensions, the
|
||||
* scaled output dimensions will simply be equal to the original
|
||||
* dimensions divided by the sample size.
|
||||
*
|
||||
* When the sample size does not divide even into the original
|
||||
* dimensions, the codec may round up or down, depending on what is most
|
||||
* efficient to decode.
|
||||
*
|
||||
* Finally, the codec will always recommend a non-zero output, so the output
|
||||
* dimension will always be one if the sampleSize is greater than the
|
||||
* original dimension.
|
||||
*/
|
||||
SkISize getSampledDimensions(int sampleSize) const;
|
||||
|
||||
/**
|
||||
* Return (via desiredSubset) a subset which can decoded from this codec,
|
||||
* or false if the input subset is invalid.
|
||||
*
|
||||
* @param desiredSubset in/out parameter
|
||||
* As input, a desired subset of the original bounds
|
||||
* (as specified by getInfo).
|
||||
* As output, if true is returned, desiredSubset may
|
||||
* have been modified to a subset which is
|
||||
* supported. Although a particular change may have
|
||||
* been made to desiredSubset to create something
|
||||
* supported, it is possible other changes could
|
||||
* result in a valid subset. If false is returned,
|
||||
* desiredSubset's value is undefined.
|
||||
* @return true If the input desiredSubset is valid.
|
||||
* desiredSubset may be modified to a subset
|
||||
* supported by the codec.
|
||||
* false If desiredSubset is invalid (NULL or not fully
|
||||
* contained within the image).
|
||||
*/
|
||||
bool getSupportedSubset(SkIRect* desiredSubset) const;
|
||||
// TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the scaled, partial output image, for an
|
||||
* input sampleSize and subset.
|
||||
*
|
||||
* @param sampleSize Factor to scale down by.
|
||||
* @param subset Must be a valid subset of the original image
|
||||
* dimensions and a subset supported by SkAndroidCodec.
|
||||
* getSubset() can be used to obtain a subset supported
|
||||
* by SkAndroidCodec.
|
||||
* @return Size of the scaled partial image. Or zero size
|
||||
* if either of the inputs is invalid.
|
||||
*/
|
||||
SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
|
||||
|
||||
/**
|
||||
* Additional options to pass to getAndroidPixels().
|
||||
*/
|
||||
// FIXME: It's a bit redundant to name these AndroidOptions when this class is already
|
||||
// called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
|
||||
// these Options when SkCodec has a slightly different set of Options. Maybe these
|
||||
// should be DecodeOptions or SamplingOptions?
|
||||
struct AndroidOptions : public SkCodec::Options {
|
||||
AndroidOptions()
|
||||
: SkCodec::Options()
|
||||
, fSampleSize(1)
|
||||
{}
|
||||
|
||||
/**
|
||||
* The client may provide an integer downscale factor for the decode.
|
||||
* The codec may implement this downscaling by sampling or another
|
||||
* method if it is more efficient.
|
||||
*
|
||||
* The default is 1, representing no downscaling.
|
||||
*/
|
||||
int fSampleSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode into the given pixels, a block of memory of size at
|
||||
* least (info.fHeight - 1) * rowBytes + (info.fWidth *
|
||||
* bytesPerPixel)
|
||||
*
|
||||
* Repeated calls to this function should give the same results,
|
||||
* allowing the PixelRef to be immutable.
|
||||
*
|
||||
* @param info A description of the format (config, size)
|
||||
* expected by the caller. This can simply be identical
|
||||
* to the info returned by getInfo().
|
||||
*
|
||||
* This contract also allows the caller to specify
|
||||
* different output-configs, which the implementation can
|
||||
* decide to support or not.
|
||||
*
|
||||
* A size that does not match getInfo() implies a request
|
||||
* to scale or subset. If the codec cannot perform this
|
||||
* scaling or subsetting, it will return an error code.
|
||||
*
|
||||
* The AndroidOptions object is also used to specify any requested scaling or subsetting
|
||||
* using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
|
||||
* for AndroidOptions) are used.
|
||||
*
|
||||
* @return Result kSuccess, or another value explaining the type of failure.
|
||||
*/
|
||||
// FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
|
||||
// called SkAndroidCodec. On the other hand, it's may be a bit confusing to call
|
||||
// this getPixels() when it is a slightly different API than SkCodec's getPixels().
|
||||
// Maybe this should be decode() or decodeSubset()?
|
||||
SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
|
||||
const AndroidOptions* options);
|
||||
|
||||
/**
|
||||
* Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
|
||||
* specified above for AndroidOptions. It will not perform any scaling or subsetting.
|
||||
*/
|
||||
SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
|
||||
|
||||
SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
|
||||
return this->getAndroidPixels(info, pixels, rowBytes);
|
||||
}
|
||||
|
||||
SkCodec* codec() const { return fCodec.get(); }
|
||||
|
||||
/**
|
||||
* Retrieve the gainmap for an image.
|
||||
*
|
||||
* @param outInfo On success, this is populated with the parameters for
|
||||
* rendering this gainmap. This parameter must be non-nullptr.
|
||||
*
|
||||
* @param outGainmapImageStream On success, this is populated with a stream from which the
|
||||
* gainmap image may be decoded. This parameter is optional, and
|
||||
* may be set to nullptr.
|
||||
*
|
||||
* @return If this has a gainmap image and that gainmap image was
|
||||
* successfully extracted then return true. Otherwise return
|
||||
* false.
|
||||
*/
|
||||
bool getAndroidGainmap(SkGainmapInfo* outInfo,
|
||||
std::unique_ptr<SkStream>* outGainmapImageStream);
|
||||
|
||||
protected:
|
||||
SkAndroidCodec(SkCodec*);
|
||||
|
||||
virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
|
||||
|
||||
virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
|
||||
|
||||
virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
|
||||
size_t rowBytes, const AndroidOptions& options) = 0;
|
||||
|
||||
private:
|
||||
const SkImageInfo fInfo;
|
||||
std::unique_ptr<SkCodec> fCodec;
|
||||
};
|
||||
#endif // SkAndroidCodec_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkAvifDecoder_DEFINED
|
||||
#define SkAvifDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkAvifDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a AVIF image. */
|
||||
SK_API bool IsAvif(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a AVIF.
|
||||
*
|
||||
* If the bytes are not a AVIF, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "avif", IsAvif, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkAvifDecoder
|
||||
|
||||
#endif // SkAvifDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkBmpDecoder_DEFINED
|
||||
#define SkBmpDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkBmpDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a BMP image. */
|
||||
SK_API bool IsBmp(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a BMP.
|
||||
*
|
||||
* If the bytes are not a BMP, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "bmp", IsBmp, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkBmpDecoder
|
||||
|
||||
#endif // SkBmpDecoder_DEFINED
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 SkCodecAnimation_DEFINED
|
||||
#define SkCodecAnimation_DEFINED
|
||||
|
||||
namespace SkCodecAnimation {
|
||||
/**
|
||||
* This specifies how the next frame is based on this frame.
|
||||
*
|
||||
* Names are based on the GIF 89a spec.
|
||||
*
|
||||
* The numbers correspond to values in a GIF.
|
||||
*/
|
||||
enum class DisposalMethod {
|
||||
/**
|
||||
* The next frame should be drawn on top of this one.
|
||||
*
|
||||
* In a GIF, a value of 0 (not specified) is also treated as Keep.
|
||||
*/
|
||||
kKeep = 1,
|
||||
|
||||
/**
|
||||
* Similar to Keep, except the area inside this frame's rectangle
|
||||
* should be cleared to the BackGround color (transparent) before
|
||||
* drawing the next frame.
|
||||
*/
|
||||
kRestoreBGColor = 2,
|
||||
|
||||
/**
|
||||
* The next frame should be drawn on top of the previous frame - i.e.
|
||||
* disregarding this one.
|
||||
*
|
||||
* In a GIF, a value of 4 is also treated as RestorePrevious.
|
||||
*/
|
||||
kRestorePrevious = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* How to blend the current frame.
|
||||
*/
|
||||
enum class Blend {
|
||||
/**
|
||||
* Blend with the prior frame as if using SkBlendMode::kSrcOver.
|
||||
*/
|
||||
kSrcOver,
|
||||
|
||||
/**
|
||||
* Blend with the prior frame as if using SkBlendMode::kSrc.
|
||||
*
|
||||
* This frame's pixels replace the destination pixels.
|
||||
*/
|
||||
kSrc,
|
||||
};
|
||||
|
||||
} // namespace SkCodecAnimation
|
||||
#endif // SkCodecAnimation_DEFINED
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 SkEncodedImageFormat_DEFINED
|
||||
#define SkEncodedImageFormat_DEFINED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Enum describing format of encoded data.
|
||||
*/
|
||||
enum class SkEncodedImageFormat {
|
||||
kBMP,
|
||||
kGIF,
|
||||
kICO,
|
||||
kJPEG,
|
||||
kPNG,
|
||||
kWBMP,
|
||||
kWEBP,
|
||||
kPKM,
|
||||
kKTX,
|
||||
kASTC,
|
||||
kDNG,
|
||||
kHEIF,
|
||||
kAVIF,
|
||||
kJPEGXL,
|
||||
};
|
||||
|
||||
#endif // SkEncodedImageFormat_DEFINED
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkEncodedOrigin_DEFINED
|
||||
#define SkEncodedOrigin_DEFINED
|
||||
|
||||
#include "include/core/SkMatrix.h"
|
||||
|
||||
// These values match the orientation www.exif.org/Exif2-2.PDF.
|
||||
enum SkEncodedOrigin {
|
||||
kTopLeft_SkEncodedOrigin = 1, // Default
|
||||
kTopRight_SkEncodedOrigin = 2, // Reflected across y-axis
|
||||
kBottomRight_SkEncodedOrigin = 3, // Rotated 180
|
||||
kBottomLeft_SkEncodedOrigin = 4, // Reflected across x-axis
|
||||
kLeftTop_SkEncodedOrigin = 5, // Reflected across x-axis, Rotated 90 CCW
|
||||
kRightTop_SkEncodedOrigin = 6, // Rotated 90 CW
|
||||
kRightBottom_SkEncodedOrigin = 7, // Reflected across x-axis, Rotated 90 CW
|
||||
kLeftBottom_SkEncodedOrigin = 8, // Rotated 90 CCW
|
||||
kDefault_SkEncodedOrigin = kTopLeft_SkEncodedOrigin,
|
||||
kLast_SkEncodedOrigin = kLeftBottom_SkEncodedOrigin,
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an encoded origin and the width and height of the source data, returns a matrix
|
||||
* that transforms the source rectangle with upper left corner at [0, 0] and origin to a correctly
|
||||
* oriented destination rectangle of [0, 0, w, h].
|
||||
*/
|
||||
static inline SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h) {
|
||||
switch (origin) {
|
||||
case kTopLeft_SkEncodedOrigin: return SkMatrix::I();
|
||||
case kTopRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, 1, 0, 0, 0, 1);
|
||||
case kBottomRight_SkEncodedOrigin: return SkMatrix::MakeAll(-1, 0, w, 0, -1, h, 0, 0, 1);
|
||||
case kBottomLeft_SkEncodedOrigin: return SkMatrix::MakeAll( 1, 0, 0, 0, -1, h, 0, 0, 1);
|
||||
case kLeftTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, 1, 0, 0, 0, 0, 1);
|
||||
case kRightTop_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, w, 1, 0, 0, 0, 0, 1);
|
||||
case kRightBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, -1, w, -1, 0, h, 0, 0, 1);
|
||||
case kLeftBottom_SkEncodedOrigin: return SkMatrix::MakeAll( 0, 1, 0, -1, 0, h, 0, 0, 1);
|
||||
}
|
||||
SK_ABORT("Unexpected origin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the encoded origin includes a 90 degree rotation, in which case the width
|
||||
* and height of the source data are swapped relative to a correctly oriented destination.
|
||||
*/
|
||||
static inline bool SkEncodedOriginSwapsWidthHeight(SkEncodedOrigin origin) {
|
||||
return origin >= kLeftTop_SkEncodedOrigin;
|
||||
}
|
||||
|
||||
#endif // SkEncodedOrigin_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkGifDecoder_DEFINED
|
||||
#define SkGifDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkGifDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a GIF image. */
|
||||
SK_API bool IsGif(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a GIF.
|
||||
*
|
||||
* If the bytes are not a GIF, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "gif", IsGif, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkGifDecoder
|
||||
|
||||
#endif // SkGifDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkIcoDecoder_DEFINED
|
||||
#define SkIcoDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkIcoDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a ICO image. */
|
||||
SK_API bool IsIco(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a ICO.
|
||||
*
|
||||
* If the bytes are not a ICO, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "ico", IsIco, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkIcoDecoder
|
||||
|
||||
#endif // SkIcoDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkJpegDecoder_DEFINED
|
||||
#define SkJpegDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkJpegDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a JPEG image. */
|
||||
SK_API bool IsJpeg(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a JPEG.
|
||||
*
|
||||
* If the bytes are not a JPEG, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "jpeg", IsJpeg, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkJpegDecoder
|
||||
|
||||
#endif // SkJpegDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkJpegxlDecoder_DEFINED
|
||||
#define SkJpegxlDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkJpegxlDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a JPEGXL image. */
|
||||
SK_API bool IsJpegxl(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a JPEGXL.
|
||||
*
|
||||
* If the bytes are not a JPEGXL, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "jpegxl", IsJpegxl, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkJpegxlDecoder
|
||||
|
||||
#endif // SkJpegxlDecoder_DEFINED
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkPixmapUtils_DEFINED
|
||||
#define SkPixmapUtils_DEFINED
|
||||
|
||||
#include "include/codec/SkEncodedOrigin.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkPixmap;
|
||||
|
||||
namespace SkPixmapUtils {
|
||||
/**
|
||||
* Copy the pixels in src into dst, applying the orientation transformations specified
|
||||
* by origin. If the inputs are invalid, this returns false and no copy is made.
|
||||
*/
|
||||
SK_API bool Orient(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin);
|
||||
|
||||
/**
|
||||
* Return a copy of the provided ImageInfo with the width and height swapped.
|
||||
*/
|
||||
SK_API SkImageInfo SwapWidthHeight(const SkImageInfo& info);
|
||||
|
||||
} // namespace SkPixmapUtils
|
||||
|
||||
#endif // SkPixmapUtils_DEFINED
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 SkPngChunkReader_DEFINED
|
||||
#define SkPngChunkReader_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/**
|
||||
* SkPngChunkReader
|
||||
*
|
||||
* Base class for optional callbacks to retrieve meta/chunk data out of a PNG
|
||||
* encoded image as it is being decoded.
|
||||
* Used by SkCodec.
|
||||
*/
|
||||
class SkPngChunkReader : public SkRefCnt {
|
||||
public:
|
||||
/**
|
||||
* This will be called by the decoder when it sees an unknown chunk.
|
||||
*
|
||||
* Use by SkCodec:
|
||||
* Depending on the location of the unknown chunks, this callback may be
|
||||
* called by
|
||||
* - the factory (NewFromStream/NewFromData)
|
||||
* - getPixels
|
||||
* - startScanlineDecode
|
||||
* - the first call to getScanlines/skipScanlines
|
||||
* The callback may be called from a different thread (e.g. if the SkCodec
|
||||
* is passed to another thread), and it may be called multiple times, if
|
||||
* the SkCodec is used multiple times.
|
||||
*
|
||||
* @param tag Name for this type of chunk.
|
||||
* @param data Data to be interpreted by the subclass.
|
||||
* @param length Number of bytes of data in the chunk.
|
||||
* @return true to continue decoding, or false to indicate an error, which
|
||||
* will cause the decoder to not return the image.
|
||||
*/
|
||||
virtual bool readChunk(const char tag[], const void* data, size_t length) = 0;
|
||||
};
|
||||
#endif // SkPngChunkReader_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkPngDecoder_DEFINED
|
||||
#define SkPngDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkPngDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a PNG image. */
|
||||
SK_API bool IsPng(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a PNG.
|
||||
*
|
||||
* If the bytes are not a PNG, returns nullptr.
|
||||
*
|
||||
* DecodeContext, if non-null, is expected to be a SkPngChunkReader*
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "png", IsPng, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkPngDecoder
|
||||
|
||||
#endif // SkPngDecoder_DEFINED
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkRawDecoder_DEFINED
|
||||
#define SkRawDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkRawDecoder {
|
||||
|
||||
inline bool IsRaw(const void*, size_t) {
|
||||
// Raw formats are tricky to detect just by reading in the first several bytes.
|
||||
// For example, PIEX might need to read 10k bytes to detect Sony's arw format
|
||||
// https://github.com/google/piex/blob/f1e15dd837c04347504149f71db67a78fbeddc73/src/image_type_recognition/image_type_recognition_lite.cc#L152
|
||||
// Thus, we just assume everything might be a RAW file and check it last.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a raw image.
|
||||
*
|
||||
* If the bytes are not a raw, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
// This decoder will always be checked last, no matter when it is registered.
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "raw", IsRaw, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkRawDecoder
|
||||
|
||||
#endif // SkRawDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkWbmpDecoder_DEFINED
|
||||
#define SkWbmpDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkWbmpDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a WBMP image. */
|
||||
SK_API bool IsWbmp(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a WBMP.
|
||||
*
|
||||
* If the bytes are not a WBMP, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "wbmp", IsWbmp, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkWbmpDecoder
|
||||
|
||||
#endif // SkWbmpDecoder_DEFINED
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkWebpDecoder_DEFINED
|
||||
#define SkWebpDecoder_DEFINED
|
||||
|
||||
#include "include/codec/SkCodec.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkData;
|
||||
class SkStream;
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SkWebpDecoder {
|
||||
|
||||
/** Returns true if this data claims to be a WEBP image. */
|
||||
SK_API bool IsWebp(const void*, size_t);
|
||||
|
||||
/**
|
||||
* Attempts to decode the given bytes as a WEBP.
|
||||
*
|
||||
* If the bytes are not a WEBP, returns nullptr.
|
||||
*
|
||||
* DecodeContext is ignored
|
||||
*/
|
||||
SK_API std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
SK_API std::unique_ptr<SkCodec> Decode(sk_sp<SkData>,
|
||||
SkCodec::Result*,
|
||||
SkCodecs::DecodeContext = nullptr);
|
||||
|
||||
inline constexpr SkCodecs::Decoder Decoder() {
|
||||
return { "webp", IsWebp, Decode };
|
||||
}
|
||||
|
||||
} // namespace SkWebpDecoder
|
||||
|
||||
#endif // SkWebpDecoder_DEFINED
|
@ -0,0 +1,2 @@
|
||||
bungeman@google.com
|
||||
kjlubick@google.com
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 SkUserConfig_DEFINED
|
||||
#define SkUserConfig_DEFINED
|
||||
|
||||
/* SkTypes.h, the root of the public header files, includes this file
|
||||
SkUserConfig.h after first initializing certain Skia defines, letting
|
||||
this file change or augment those flags.
|
||||
|
||||
Below are optional defines that add, subtract, or change default behavior
|
||||
in Skia. Your port can locally edit this file to enable/disable flags as
|
||||
you choose, or these can be declared on your command line (i.e. -Dfoo).
|
||||
|
||||
By default, this #include file will always default to having all the flags
|
||||
commented out, so including it will have no effect.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Skia has lots of debug-only code. Often this is just null checks or other
|
||||
parameter checking, but sometimes it can be quite intrusive (e.g. check that
|
||||
each 32bit pixel is in premultiplied form). This code can be very useful
|
||||
during development, but will slow things down in a shipping product.
|
||||
|
||||
By default, these mutually exclusive flags are defined in SkTypes.h,
|
||||
based on the presence or absence of NDEBUG, but that decision can be changed
|
||||
here.
|
||||
*/
|
||||
//#define SK_DEBUG
|
||||
//#define SK_RELEASE
|
||||
|
||||
/* To write debug messages to a console, skia will call SkDebugf(...) following
|
||||
printf conventions (e.g. const char* format, ...). If you want to redirect
|
||||
this to something other than printf, define yours here
|
||||
*/
|
||||
//#define SkDebugf(...) MyFunction(__VA_ARGS__)
|
||||
|
||||
/* Skia has both debug and release asserts. When an assert fails SK_ABORT will
|
||||
be used to report an abort message. SK_ABORT is expected not to return. Skia
|
||||
provides a default implementation which will print the message with SkDebugf
|
||||
and then call sk_abort_no_print.
|
||||
*/
|
||||
//#define SK_ABORT(message, ...)
|
||||
|
||||
/* To specify a different default font strike cache memory limit, define this. If this is
|
||||
undefined, skia will use a built-in value.
|
||||
*/
|
||||
//#define SK_DEFAULT_FONT_CACHE_LIMIT (1024 * 1024)
|
||||
|
||||
/* To specify a different default font strike cache count limit, define this. If this is
|
||||
undefined, skia will use a built-in value.
|
||||
*/
|
||||
// #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 2048
|
||||
|
||||
/* To specify the default size of the image cache, undefine this and set it to
|
||||
the desired value (in bytes). SkGraphics.h as a runtime API to set this
|
||||
value as well. If this is undefined, a built-in value will be used.
|
||||
*/
|
||||
//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
|
||||
|
||||
/* 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
|
||||
improving readability. If this is undefined, Skia will use its default
|
||||
value (e.g. 48)
|
||||
*/
|
||||
//#define SK_MAX_SIZE_FOR_LCDTEXT 48
|
||||
|
||||
/* Change the kN32_SkColorType ordering to BGRA to work in X windows.
|
||||
*/
|
||||
//#define SK_R32_SHIFT 16
|
||||
|
||||
/* Determines whether to build code that supports the Ganesh GPU backend. Some classes
|
||||
that are not GPU-specific, such as SkShader subclasses, have optional code
|
||||
that is used allows them to interact with this GPU backend. If you'd like to
|
||||
include this code, include -DSK_GANESH in your cflags or uncomment below.
|
||||
Defaults to not set (No Ganesh GPU backend).
|
||||
This define affects the ABI of Skia, so make sure it matches the client which uses
|
||||
the compiled version of Skia.
|
||||
*/
|
||||
//#define SK_GANESH
|
||||
|
||||
/* Skia makes use of histogram logging macros to trace the frequency of
|
||||
events. By default, Skia provides no-op versions of these macros.
|
||||
Skia consumers can provide their own definitions of these macros to
|
||||
integrate with their histogram collection backend.
|
||||
*/
|
||||
//#define SK_HISTOGRAM_BOOLEAN(name, sample)
|
||||
//#define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
|
||||
//#define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
|
||||
//#define SK_HISTOGRAM_MEMORY_KB(name, sample)
|
||||
|
||||
// To use smaller but slower mipmap builder
|
||||
//#define SK_USE_DRAWING_MIPMAP_DOWNSAMPLER
|
||||
|
||||
/* Skia tries to make use of some non-standard C++ language extensions.
|
||||
By default, Skia provides msvc and clang/gcc versions of these macros.
|
||||
Skia consumers can provide their own definitions of these macros to
|
||||
integrate with their own compilers and build system.
|
||||
*/
|
||||
//#define SK_ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
//#define SK_NEVER_INLINE __attribute__((noinline))
|
||||
//#define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
|
||||
//#define SK_NO_SANITIZE(A) __attribute__((no_sanitize(A)))
|
||||
//#define SK_TRIVIAL_ABI [[clang::trivial_abi]]
|
||||
|
||||
/*
|
||||
* If compiling Skia as a DLL, public APIs should be exported. Skia will set
|
||||
* SK_API to something sensible for Clang and MSVC, but if clients need to
|
||||
* customize it for their build system or compiler, they may.
|
||||
* If a client needs to use SK_API (e.g. overriding SK_ABORT), then they
|
||||
* *must* define their own, the default will not be defined prior to loading
|
||||
* this file.
|
||||
*/
|
||||
//#define SK_API __declspec(dllexport)
|
||||
|
||||
#endif
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkAlphaType_DEFINED
|
||||
#define SkAlphaType_DEFINED
|
||||
|
||||
/** \enum SkAlphaType
|
||||
Describes how to interpret the alpha component of a pixel. A pixel may
|
||||
be opaque, or alpha, describing multiple levels of transparency.
|
||||
|
||||
In simple blending, alpha weights the draw color and the destination
|
||||
color to create a new color. If alpha describes a weight from zero to one:
|
||||
|
||||
new color = draw color * alpha + destination color * (1 - alpha)
|
||||
|
||||
In practice alpha is encoded in two or more bits, where 1.0 equals all bits set.
|
||||
|
||||
RGB may have alpha included in each component value; the stored
|
||||
value is the original RGB multiplied by alpha. Premultiplied color
|
||||
components improve performance.
|
||||
*/
|
||||
enum SkAlphaType : int {
|
||||
kUnknown_SkAlphaType, //!< uninitialized
|
||||
kOpaque_SkAlphaType, //!< pixel is opaque
|
||||
kPremul_SkAlphaType, //!< pixel components are premultiplied by alpha
|
||||
kUnpremul_SkAlphaType, //!< pixel components are independent of alpha
|
||||
kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value
|
||||
};
|
||||
|
||||
/** Returns true if SkAlphaType equals kOpaque_SkAlphaType.
|
||||
|
||||
kOpaque_SkAlphaType is a hint that the SkColorType is opaque, or that all
|
||||
alpha values are set to their 1.0 equivalent. If SkAlphaType is
|
||||
kOpaque_SkAlphaType, and SkColorType is not opaque, then the result of
|
||||
drawing any pixel with a alpha value less than 1.0 is undefined.
|
||||
*/
|
||||
static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
|
||||
return kOpaque_SkAlphaType == at;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkAnnotation_DEFINED
|
||||
#define SkAnnotation_DEFINED
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
class SkData;
|
||||
struct SkPoint;
|
||||
struct SkRect;
|
||||
class SkCanvas;
|
||||
|
||||
/**
|
||||
* Annotate the canvas by associating the specified URL with the
|
||||
* specified rectangle (in local coordinates, just like drawRect).
|
||||
*
|
||||
* The URL is expected to be escaped and be valid 7-bit ASCII.
|
||||
*
|
||||
* If the backend of this canvas does not support annotations, this call is
|
||||
* safely ignored.
|
||||
*
|
||||
* The caller is responsible for managing its ownership of the SkData.
|
||||
*/
|
||||
SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);
|
||||
|
||||
/**
|
||||
* Annotate the canvas by associating a name with the specified point.
|
||||
*
|
||||
* If the backend of this canvas does not support annotations, this call is
|
||||
* safely ignored.
|
||||
*
|
||||
* The caller is responsible for managing its ownership of the SkData.
|
||||
*/
|
||||
SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*);
|
||||
|
||||
/**
|
||||
* Annotate the canvas by making the specified rectangle link to a named
|
||||
* destination.
|
||||
*
|
||||
* If the backend of this canvas does not support annotations, this call is
|
||||
* safely ignored.
|
||||
*
|
||||
* The caller is responsible for managing its ownership of the SkData.
|
||||
*/
|
||||
SK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*);
|
||||
|
||||
#endif
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkArc_DEFINED
|
||||
#define SkArc_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
|
||||
// Represents an arc along an oval boundary, or a closed wedge of the oval.
|
||||
struct SkArc {
|
||||
enum class Type : bool {
|
||||
kArc, // An arc along the perimeter of the oval
|
||||
kWedge // A closed wedge that includes the oval's center
|
||||
};
|
||||
|
||||
SkArc() = default;
|
||||
SkArc(const SkArc& arc) = default;
|
||||
SkArc& operator=(const SkArc& arc) = default;
|
||||
|
||||
const SkRect& oval() const { return fOval; }
|
||||
SkScalar startAngle() const { return fStartAngle; }
|
||||
SkScalar sweepAngle() const { return fSweepAngle; }
|
||||
bool isWedge() const { return fType == Type::kWedge; }
|
||||
|
||||
friend bool operator==(const SkArc& a, const SkArc& b) {
|
||||
return a.fOval == b.fOval && a.fStartAngle == b.fStartAngle &&
|
||||
a.fSweepAngle == b.fSweepAngle && a.fType == b.fType;
|
||||
}
|
||||
|
||||
friend bool operator!=(const SkArc& a, const SkArc& b) { return !(a == b); }
|
||||
|
||||
// Preferred factory that explicitly states which type of arc
|
||||
static SkArc Make(const SkRect& oval,
|
||||
SkScalar startAngleDegrees,
|
||||
SkScalar sweepAngleDegrees,
|
||||
Type type) {
|
||||
return SkArc(oval, startAngleDegrees, sweepAngleDegrees, type);
|
||||
}
|
||||
|
||||
// Deprecated factory to assist with legacy code based on `useCenter`
|
||||
static SkArc Make(const SkRect& oval,
|
||||
SkScalar startAngleDegrees,
|
||||
SkScalar sweepAngleDegrees,
|
||||
bool useCenter) {
|
||||
return SkArc(
|
||||
oval, startAngleDegrees, sweepAngleDegrees, useCenter ? Type::kWedge : Type::kArc);
|
||||
}
|
||||
|
||||
// Bounds of oval containing the arc.
|
||||
SkRect fOval = SkRect::MakeEmpty();
|
||||
|
||||
// Angle in degrees where the arc begins. Zero means horizontally to the right.
|
||||
SkScalar fStartAngle = 0;
|
||||
// Sweep angle in degrees; positive is clockwise.
|
||||
SkScalar fSweepAngle = 0;
|
||||
|
||||
Type fType = Type::kArc;
|
||||
|
||||
private:
|
||||
SkArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, Type type)
|
||||
: fOval(oval), fStartAngle(startAngle), fSweepAngle(sweepAngle), fType(type) {}
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkBBHFactory_DEFINED
|
||||
#define SkBBHFactory_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
// TODO(kjlubick) fix client users and then make this a forward declare
|
||||
#include "include/core/SkRect.h" // IWYU pragma: keep
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
class SkBBoxHierarchy : public SkRefCnt {
|
||||
public:
|
||||
struct Metadata {
|
||||
bool isDraw; // The corresponding SkRect bounds a draw command, not a pure state change.
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert N bounding boxes into the hierarchy.
|
||||
*/
|
||||
virtual void insert(const SkRect[], int N) = 0;
|
||||
virtual void insert(const SkRect[], const Metadata[], int N);
|
||||
|
||||
/**
|
||||
* Populate results with the indices of bounding boxes intersecting that query.
|
||||
*/
|
||||
virtual void search(const SkRect& query, std::vector<int>* results) const = 0;
|
||||
|
||||
/**
|
||||
* Return approximate size in memory of *this.
|
||||
*/
|
||||
virtual size_t bytesUsed() const = 0;
|
||||
|
||||
protected:
|
||||
SkBBoxHierarchy() = default;
|
||||
SkBBoxHierarchy(const SkBBoxHierarchy&) = delete;
|
||||
SkBBoxHierarchy& operator=(const SkBBoxHierarchy&) = delete;
|
||||
};
|
||||
|
||||
class SK_API SkBBHFactory {
|
||||
public:
|
||||
/**
|
||||
* Allocate a new SkBBoxHierarchy. Return NULL on failure.
|
||||
*/
|
||||
virtual sk_sp<SkBBoxHierarchy> operator()() const = 0;
|
||||
virtual ~SkBBHFactory() {}
|
||||
|
||||
protected:
|
||||
SkBBHFactory() = default;
|
||||
SkBBHFactory(const SkBBHFactory&) = delete;
|
||||
SkBBHFactory& operator=(const SkBBHFactory&) = delete;
|
||||
};
|
||||
|
||||
class SK_API SkRTreeFactory : public SkBBHFactory {
|
||||
public:
|
||||
sk_sp<SkBBoxHierarchy> operator()() const override;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/**
|
||||
* Blends are operators that take in two colors (source, destination) and return a new color.
|
||||
* Many of these operate the same on all 4 components: red, green, blue, alpha. For these,
|
||||
* we just document what happens to one component, rather than naming each one separately.
|
||||
*
|
||||
* Different SkColorTypes have different representations for color components:
|
||||
* 8-bit: 0..255
|
||||
* 6-bit: 0..63
|
||||
* 5-bit: 0..31
|
||||
* 4-bit: 0..15
|
||||
* floats: 0...1
|
||||
*
|
||||
* The documentation is expressed as if the component values are always 0..1 (floats).
|
||||
*
|
||||
* For brevity, the documentation uses the following abbreviations
|
||||
* s : source
|
||||
* d : destination
|
||||
* sa : source alpha
|
||||
* da : destination alpha
|
||||
*
|
||||
* Results are abbreviated
|
||||
* r : if all 4 components are computed in the same manner
|
||||
* ra : result alpha component
|
||||
* rc : result "color": red, green, blue components
|
||||
*/
|
||||
enum class SkBlendMode {
|
||||
kClear, //!< r = 0
|
||||
kSrc, //!< r = s
|
||||
kDst, //!< r = d
|
||||
kSrcOver, //!< r = s + (1-sa)*d
|
||||
kDstOver, //!< r = d + (1-da)*s
|
||||
kSrcIn, //!< r = s * da
|
||||
kDstIn, //!< r = d * sa
|
||||
kSrcOut, //!< r = s * (1-da)
|
||||
kDstOut, //!< r = d * (1-sa)
|
||||
kSrcATop, //!< r = s*da + d*(1-sa)
|
||||
kDstATop, //!< r = d*sa + s*(1-da)
|
||||
kXor, //!< r = s*(1-da) + d*(1-sa)
|
||||
kPlus, //!< r = min(s + d, 1)
|
||||
kModulate, //!< r = s*d
|
||||
kScreen, //!< r = s + d - s*d
|
||||
|
||||
kOverlay, //!< multiply or screen, depending on destination
|
||||
kDarken, //!< rc = s + d - max(s*da, d*sa), ra = kSrcOver
|
||||
kLighten, //!< rc = s + d - min(s*da, d*sa), ra = kSrcOver
|
||||
kColorDodge, //!< brighten destination to reflect source
|
||||
kColorBurn, //!< darken destination to reflect source
|
||||
kHardLight, //!< multiply or screen, depending on source
|
||||
kSoftLight, //!< lighten or darken, depending on source
|
||||
kDifference, //!< rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
|
||||
kExclusion, //!< rc = s + d - two(s*d), ra = kSrcOver
|
||||
kMultiply, //!< r = s*(1-da) + d*(1-sa) + s*d
|
||||
|
||||
kHue, //!< hue of source with saturation and luminosity of destination
|
||||
kSaturation, //!< saturation of source with hue and luminosity of destination
|
||||
kColor, //!< hue and saturation of source with luminosity of destination
|
||||
kLuminosity, //!< luminosity of source with hue and saturation of destination
|
||||
|
||||
kLastCoeffMode = kScreen, //!< last porter duff blend mode
|
||||
kLastSeparableMode = kMultiply, //!< last blend mode operating separately on components
|
||||
kLastMode = kLuminosity, //!< last valid value
|
||||
};
|
||||
|
||||
static constexpr int kSkBlendModeCount = static_cast<int>(SkBlendMode::kLastMode) + 1;
|
||||
|
||||
/**
|
||||
* For Porter-Duff SkBlendModes (those <= kLastCoeffMode), these coefficients describe the blend
|
||||
* equation used. Coefficient-based blend modes specify an equation:
|
||||
* ('dstCoeff' * dst + 'srcCoeff' * src), where the coefficient values are constants, functions of
|
||||
* the src or dst alpha, or functions of the src or dst color.
|
||||
*/
|
||||
enum class SkBlendModeCoeff {
|
||||
kZero, /** 0 */
|
||||
kOne, /** 1 */
|
||||
kSC, /** src color */
|
||||
kISC, /** inverse src color (i.e. 1 - sc) */
|
||||
kDC, /** dst color */
|
||||
kIDC, /** inverse dst color (i.e. 1 - dc) */
|
||||
kSA, /** src alpha */
|
||||
kISA, /** inverse src alpha (i.e. 1 - sa) */
|
||||
kDA, /** dst alpha */
|
||||
kIDA, /** inverse dst alpha (i.e. 1 - da) */
|
||||
|
||||
kCoeffCount
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if 'mode' is a coefficient-based blend mode (<= kLastCoeffMode). If true is
|
||||
* returned, the mode's src and dst coefficient functions are set in 'src' and 'dst'.
|
||||
*/
|
||||
SK_API bool SkBlendMode_AsCoeff(SkBlendMode mode, SkBlendModeCoeff* src, SkBlendModeCoeff* dst);
|
||||
|
||||
|
||||
/** Returns name of blendMode as null-terminated C string.
|
||||
|
||||
@return C string
|
||||
*/
|
||||
SK_API const char* SkBlendMode_Name(SkBlendMode blendMode);
|
||||
|
||||
#endif
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkBlender_DEFINED
|
||||
#define SkBlender_DEFINED
|
||||
|
||||
#include "include/core/SkBlendMode.h"
|
||||
#include "include/core/SkFlattenable.h"
|
||||
|
||||
/**
|
||||
* SkBlender represents a custom blend function in the Skia pipeline. When an SkBlender is
|
||||
* present in a paint, the SkBlendMode is ignored. A blender combines a source color (the
|
||||
* result of our paint) and destination color (from the canvas) into a final color.
|
||||
*/
|
||||
class SK_API SkBlender : public SkFlattenable {
|
||||
public:
|
||||
/**
|
||||
* Create a blender that implements the specified BlendMode.
|
||||
*/
|
||||
static sk_sp<SkBlender> Mode(SkBlendMode mode);
|
||||
|
||||
private:
|
||||
SkBlender() = default;
|
||||
friend class SkBlenderBase;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkBlurTypes_DEFINED
|
||||
#define SkBlurTypes_DEFINED
|
||||
|
||||
enum SkBlurStyle : int {
|
||||
kNormal_SkBlurStyle, //!< fuzzy inside and outside
|
||||
kSolid_SkBlurStyle, //!< solid inside, fuzzy outside
|
||||
kOuter_SkBlurStyle, //!< nothing inside, fuzzy outside
|
||||
kInner_SkBlurStyle, //!< fuzzy inside, nothing outside
|
||||
|
||||
kLastEnum_SkBlurStyle = kInner_SkBlurStyle,
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkCanvasVirtualEnforcer_DEFINED
|
||||
#define SkCanvasVirtualEnforcer_DEFINED
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
|
||||
// If you would ordinarily want to inherit from Base (eg SkCanvas, SkNWayCanvas), instead
|
||||
// inherit from SkCanvasVirtualEnforcer<Base>, which will make the build fail if you forget
|
||||
// to override one of SkCanvas' key virtual hooks.
|
||||
template <typename Base>
|
||||
class SkCanvasVirtualEnforcer : public Base {
|
||||
public:
|
||||
using Base::Base;
|
||||
|
||||
protected:
|
||||
void onDrawPaint(const SkPaint& paint) override = 0;
|
||||
void onDrawBehind(const SkPaint&) override {} // make zero after android updates
|
||||
void onDrawRect(const SkRect& rect, const SkPaint& paint) override = 0;
|
||||
void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override = 0;
|
||||
void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
|
||||
const SkPaint& paint) override = 0;
|
||||
void onDrawOval(const SkRect& rect, const SkPaint& paint) override = 0;
|
||||
void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
|
||||
const SkPaint& paint) override = 0;
|
||||
void onDrawPath(const SkPath& path, const SkPaint& paint) override = 0;
|
||||
void onDrawRegion(const SkRegion& region, const SkPaint& paint) override = 0;
|
||||
|
||||
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
const SkPaint& paint) override = 0;
|
||||
|
||||
void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
|
||||
const SkPoint texCoords[4], SkBlendMode mode,
|
||||
const SkPaint& paint) override = 0;
|
||||
void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
|
||||
const SkPaint& paint) override = 0;
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
// This is under active development for Chrome and not used in Android. Hold off on adding
|
||||
// implementations in Android's SkCanvas subclasses until this stabilizes.
|
||||
void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
|
||||
SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override {}
|
||||
#else
|
||||
void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
|
||||
SkCanvas::QuadAAFlags aaFlags, const SkColor4f& color, SkBlendMode mode) override = 0;
|
||||
#endif
|
||||
|
||||
void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override = 0;
|
||||
void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override = 0;
|
||||
|
||||
void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override = 0;
|
||||
void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
|
||||
const SkPaint* paint) override = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkCapabilities_DEFINED
|
||||
#define SkCapabilities_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/sksl/SkSLVersion.h"
|
||||
|
||||
namespace SkSL { struct ShaderCaps; }
|
||||
|
||||
#if defined(SK_GRAPHITE)
|
||||
namespace skgpu::graphite { class Caps; }
|
||||
#endif
|
||||
|
||||
class SK_API SkCapabilities : public SkRefCnt {
|
||||
public:
|
||||
static sk_sp<const SkCapabilities> RasterBackend();
|
||||
|
||||
SkSL::Version skslVersion() const { return fSkSLVersion; }
|
||||
|
||||
protected:
|
||||
#if defined(SK_GRAPHITE)
|
||||
friend class skgpu::graphite::Caps; // for ctor
|
||||
#endif
|
||||
|
||||
SkCapabilities() = default;
|
||||
|
||||
void initSkCaps(const SkSL::ShaderCaps*);
|
||||
|
||||
SkSL::Version fSkSLVersion = SkSL::Version::k100;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 "include/core/SkTypes.h"
|
||||
|
||||
enum class SkClipOp {
|
||||
kDifference = 0,
|
||||
kIntersect = 1,
|
||||
kMax_EnumValue = kIntersect
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,447 @@
|
||||
/*
|
||||
* 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 SkColor_DEFINED
|
||||
#define SkColor_DEFINED
|
||||
|
||||
#include "include/core/SkAlphaType.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkCPUTypes.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
/** \file SkColor.h
|
||||
|
||||
Types, consts, functions, and macros for colors.
|
||||
*/
|
||||
|
||||
/** 8-bit type for an alpha value. 255 is 100% opaque, zero is 100% transparent.
|
||||
*/
|
||||
typedef uint8_t SkAlpha;
|
||||
|
||||
/** 32-bit ARGB color value, unpremultiplied. Color components are always in
|
||||
a known order. This is different from SkPMColor, which has its bytes in a configuration
|
||||
dependent order, to match the format of kBGRA_8888_SkColorType bitmaps. SkColor
|
||||
is the type used to specify colors in SkPaint and in gradients.
|
||||
|
||||
Color that is premultiplied has the same component values as color
|
||||
that is unpremultiplied if alpha is 255, fully opaque, although may have the
|
||||
component values in a different order.
|
||||
*/
|
||||
typedef uint32_t SkColor;
|
||||
|
||||
/** Returns color value from 8-bit component values. Asserts if SK_DEBUG is defined
|
||||
if a, r, g, or b exceed 255. Since color is unpremultiplied, a may be smaller
|
||||
than the largest of r, g, and b.
|
||||
|
||||
@param a amount of alpha, from fully transparent (0) to fully opaque (255)
|
||||
@param r amount of red, from no red (0) to full red (255)
|
||||
@param g amount of green, from no green (0) to full green (255)
|
||||
@param b amount of blue, from no blue (0) to full blue (255)
|
||||
@return color and alpha, unpremultiplied
|
||||
*/
|
||||
static constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
return SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255),
|
||||
(a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
|
||||
/** Returns color value from 8-bit component values, with alpha set
|
||||
fully opaque to 255.
|
||||
*/
|
||||
#define SkColorSetRGB(r, g, b) SkColorSetARGB(0xFF, r, g, b)
|
||||
|
||||
/** Returns alpha byte from color value.
|
||||
*/
|
||||
#define SkColorGetA(color) (((color) >> 24) & 0xFF)
|
||||
|
||||
/** Returns red component of color, from zero to 255.
|
||||
*/
|
||||
#define SkColorGetR(color) (((color) >> 16) & 0xFF)
|
||||
|
||||
/** Returns green component of color, from zero to 255.
|
||||
*/
|
||||
#define SkColorGetG(color) (((color) >> 8) & 0xFF)
|
||||
|
||||
/** Returns blue component of color, from zero to 255.
|
||||
*/
|
||||
#define SkColorGetB(color) (((color) >> 0) & 0xFF)
|
||||
|
||||
/** Returns unpremultiplied color with red, blue, and green set from c; and alpha set
|
||||
from a. Alpha component of c is ignored and is replaced by a in result.
|
||||
|
||||
@param c packed RGB, eight bits per component
|
||||
@param a alpha: transparent at zero, fully opaque at 255
|
||||
@return color with transparency
|
||||
*/
|
||||
[[nodiscard]] static constexpr inline SkColor SkColorSetA(SkColor c, U8CPU a) {
|
||||
return (c & 0x00FFFFFF) | (a << 24);
|
||||
}
|
||||
|
||||
/** Represents fully transparent SkAlpha value. SkAlpha ranges from zero,
|
||||
fully transparent; to 255, fully opaque.
|
||||
*/
|
||||
constexpr SkAlpha SK_AlphaTRANSPARENT = 0x00;
|
||||
|
||||
/** Represents fully opaque SkAlpha value. SkAlpha ranges from zero,
|
||||
fully transparent; to 255, fully opaque.
|
||||
*/
|
||||
constexpr SkAlpha SK_AlphaOPAQUE = 0xFF;
|
||||
|
||||
/** Represents fully transparent SkColor. May be used to initialize a destination
|
||||
containing a mask or a non-rectangular image.
|
||||
*/
|
||||
constexpr SkColor SK_ColorTRANSPARENT = SkColorSetARGB(0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
/** Represents fully opaque black.
|
||||
*/
|
||||
constexpr SkColor SK_ColorBLACK = SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
|
||||
|
||||
/** Represents fully opaque dark gray.
|
||||
Note that SVG dark gray is equivalent to 0xFFA9A9A9.
|
||||
*/
|
||||
constexpr SkColor SK_ColorDKGRAY = SkColorSetARGB(0xFF, 0x44, 0x44, 0x44);
|
||||
|
||||
/** Represents fully opaque gray.
|
||||
Note that HTML gray is equivalent to 0xFF808080.
|
||||
*/
|
||||
constexpr SkColor SK_ColorGRAY = SkColorSetARGB(0xFF, 0x88, 0x88, 0x88);
|
||||
|
||||
/** Represents fully opaque light gray. HTML silver is equivalent to 0xFFC0C0C0.
|
||||
Note that SVG light gray is equivalent to 0xFFD3D3D3.
|
||||
*/
|
||||
constexpr SkColor SK_ColorLTGRAY = SkColorSetARGB(0xFF, 0xCC, 0xCC, 0xCC);
|
||||
|
||||
/** Represents fully opaque white.
|
||||
*/
|
||||
constexpr SkColor SK_ColorWHITE = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
/** Represents fully opaque red.
|
||||
*/
|
||||
constexpr SkColor SK_ColorRED = SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00);
|
||||
|
||||
/** Represents fully opaque green. HTML lime is equivalent.
|
||||
Note that HTML green is equivalent to 0xFF008000.
|
||||
*/
|
||||
constexpr SkColor SK_ColorGREEN = SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00);
|
||||
|
||||
/** Represents fully opaque blue.
|
||||
*/
|
||||
constexpr SkColor SK_ColorBLUE = SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF);
|
||||
|
||||
/** Represents fully opaque yellow.
|
||||
*/
|
||||
constexpr SkColor SK_ColorYELLOW = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0x00);
|
||||
|
||||
/** Represents fully opaque cyan. HTML aqua is equivalent.
|
||||
*/
|
||||
constexpr SkColor SK_ColorCYAN = SkColorSetARGB(0xFF, 0x00, 0xFF, 0xFF);
|
||||
|
||||
/** Represents fully opaque magenta. HTML fuchsia is equivalent.
|
||||
*/
|
||||
constexpr SkColor SK_ColorMAGENTA = SkColorSetARGB(0xFF, 0xFF, 0x00, 0xFF);
|
||||
|
||||
/** Converts RGB to its HSV components.
|
||||
hsv[0] contains hsv hue, a value from zero to less than 360.
|
||||
hsv[1] contains hsv saturation, a value from zero to one.
|
||||
hsv[2] contains hsv value, a value from zero to one.
|
||||
|
||||
@param red red component value from zero to 255
|
||||
@param green green component value from zero to 255
|
||||
@param blue blue component value from zero to 255
|
||||
@param hsv three element array which holds the resulting HSV components
|
||||
*/
|
||||
SK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
|
||||
|
||||
/** Converts ARGB to its HSV components. Alpha in ARGB is ignored.
|
||||
hsv[0] contains hsv hue, and is assigned a value from zero to less than 360.
|
||||
hsv[1] contains hsv saturation, a value from zero to one.
|
||||
hsv[2] contains hsv value, a value from zero to one.
|
||||
|
||||
@param color ARGB color to convert
|
||||
@param hsv three element array which holds the resulting HSV components
|
||||
*/
|
||||
static inline void SkColorToHSV(SkColor color, SkScalar hsv[3]) {
|
||||
SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
|
||||
}
|
||||
|
||||
/** Converts HSV components to an ARGB color. Alpha is passed through unchanged.
|
||||
hsv[0] represents hsv hue, an angle from zero to less than 360.
|
||||
hsv[1] represents hsv saturation, and varies from zero to one.
|
||||
hsv[2] represents hsv value, and varies from zero to one.
|
||||
|
||||
Out of range hsv values are pinned.
|
||||
|
||||
@param alpha alpha component of the returned ARGB color
|
||||
@param hsv three element array which holds the input HSV components
|
||||
@return ARGB equivalent to HSV
|
||||
*/
|
||||
SK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
|
||||
|
||||
/** Converts HSV components to an ARGB color. Alpha is set to 255.
|
||||
hsv[0] represents hsv hue, an angle from zero to less than 360.
|
||||
hsv[1] represents hsv saturation, and varies from zero to one.
|
||||
hsv[2] represents hsv value, and varies from zero to one.
|
||||
|
||||
Out of range hsv values are pinned.
|
||||
|
||||
@param hsv three element array which holds the input HSV components
|
||||
@return RGB equivalent to HSV
|
||||
*/
|
||||
static inline SkColor SkHSVToColor(const SkScalar hsv[3]) {
|
||||
return SkHSVToColor(0xFF, hsv);
|
||||
}
|
||||
|
||||
/** 32-bit ARGB color value, premultiplied. The byte order for this value is
|
||||
configuration dependent, matching the format of kBGRA_8888_SkColorType bitmaps.
|
||||
This is different from SkColor, which is unpremultiplied, and is always in the
|
||||
same byte order.
|
||||
*/
|
||||
typedef uint32_t SkPMColor;
|
||||
|
||||
/** Returns a SkPMColor value from unpremultiplied 8-bit component values.
|
||||
|
||||
@param a amount of alpha, from fully transparent (0) to fully opaque (255)
|
||||
@param r amount of red, from no red (0) to full red (255)
|
||||
@param g amount of green, from no green (0) to full green (255)
|
||||
@param b amount of blue, from no blue (0) to full blue (255)
|
||||
@return premultiplied color
|
||||
*/
|
||||
SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
|
||||
|
||||
/** Returns pmcolor closest to color c. Multiplies c RGB components by the c alpha,
|
||||
and arranges the bytes to match the format of kN32_SkColorType.
|
||||
|
||||
@param c unpremultiplied ARGB color
|
||||
@return premultiplied color
|
||||
*/
|
||||
SK_API SkPMColor SkPreMultiplyColor(SkColor c);
|
||||
|
||||
/** \enum SkColorChannel
|
||||
Describes different color channels one can manipulate
|
||||
*/
|
||||
enum class SkColorChannel {
|
||||
kR, // the red channel
|
||||
kG, // the green channel
|
||||
kB, // the blue channel
|
||||
kA, // the alpha channel
|
||||
|
||||
kLastEnum = kA,
|
||||
};
|
||||
|
||||
/** Used to represent the channels available in a color type or texture format as a mask. */
|
||||
enum SkColorChannelFlag : uint32_t {
|
||||
kRed_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kR),
|
||||
kGreen_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kG),
|
||||
kBlue_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kB),
|
||||
kAlpha_SkColorChannelFlag = 1 << static_cast<uint32_t>(SkColorChannel::kA),
|
||||
kGray_SkColorChannelFlag = 0x10,
|
||||
// Convenience values
|
||||
kGrayAlpha_SkColorChannelFlags = kGray_SkColorChannelFlag | kAlpha_SkColorChannelFlag,
|
||||
kRG_SkColorChannelFlags = kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag,
|
||||
kRGB_SkColorChannelFlags = kRG_SkColorChannelFlags | kBlue_SkColorChannelFlag,
|
||||
kRGBA_SkColorChannelFlags = kRGB_SkColorChannelFlags | kAlpha_SkColorChannelFlag,
|
||||
};
|
||||
static_assert(0 == (kGray_SkColorChannelFlag & kRGBA_SkColorChannelFlags), "bitfield conflict");
|
||||
|
||||
/** \struct SkRGBA4f
|
||||
RGBA color value, holding four floating point components. Color components are always in
|
||||
a known order. kAT determines if the SkRGBA4f's R, G, and B components are premultiplied
|
||||
by alpha or not.
|
||||
|
||||
Skia's public API always uses unpremultiplied colors, which can be stored as
|
||||
SkRGBA4f<kUnpremul_SkAlphaType>. For convenience, this type can also be referred to
|
||||
as SkColor4f.
|
||||
*/
|
||||
template <SkAlphaType kAT>
|
||||
struct SkRGBA4f {
|
||||
float fR; //!< red component
|
||||
float fG; //!< green component
|
||||
float fB; //!< blue component
|
||||
float fA; //!< alpha component
|
||||
|
||||
/** Compares SkRGBA4f with other, and returns true if all components are equal.
|
||||
|
||||
@param other SkRGBA4f to compare
|
||||
@return true if SkRGBA4f equals other
|
||||
*/
|
||||
bool operator==(const SkRGBA4f& other) const {
|
||||
return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;
|
||||
}
|
||||
|
||||
/** Compares SkRGBA4f with other, and returns true if not all components are equal.
|
||||
|
||||
@param other SkRGBA4f to compare
|
||||
@return true if SkRGBA4f is not equal to other
|
||||
*/
|
||||
bool operator!=(const SkRGBA4f& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/** Returns SkRGBA4f multiplied by scale.
|
||||
|
||||
@param scale value to multiply by
|
||||
@return SkRGBA4f as (fR * scale, fG * scale, fB * scale, fA * scale)
|
||||
*/
|
||||
SkRGBA4f operator*(float scale) const {
|
||||
return { fR * scale, fG * scale, fB * scale, fA * scale };
|
||||
}
|
||||
|
||||
/** Returns SkRGBA4f multiplied component-wise by scale.
|
||||
|
||||
@param scale SkRGBA4f to multiply by
|
||||
@return SkRGBA4f as (fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA)
|
||||
*/
|
||||
SkRGBA4f operator*(const SkRGBA4f& scale) const {
|
||||
return { fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA };
|
||||
}
|
||||
|
||||
/** Returns a pointer to components of SkRGBA4f, for array access.
|
||||
|
||||
@return pointer to array [fR, fG, fB, fA]
|
||||
*/
|
||||
const float* vec() const { return &fR; }
|
||||
|
||||
/** Returns a pointer to components of SkRGBA4f, for array access.
|
||||
|
||||
@return pointer to array [fR, fG, fB, fA]
|
||||
*/
|
||||
float* vec() { return &fR; }
|
||||
|
||||
/** As a std::array<float, 4> */
|
||||
std::array<float, 4> array() const { return {fR, fG, fB, fA}; }
|
||||
|
||||
/** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
|
||||
|
||||
@param index one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
|
||||
@return value corresponding to index
|
||||
*/
|
||||
float operator[](int index) const {
|
||||
SkASSERT(index >= 0 && index < 4);
|
||||
return this->vec()[index];
|
||||
}
|
||||
|
||||
/** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
|
||||
|
||||
@param index one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
|
||||
@return value corresponding to index
|
||||
*/
|
||||
float& operator[](int index) {
|
||||
SkASSERT(index >= 0 && index < 4);
|
||||
return this->vec()[index];
|
||||
}
|
||||
|
||||
/** Returns true if SkRGBA4f is an opaque color. Asserts if fA is out of range and
|
||||
SK_DEBUG is defined.
|
||||
|
||||
@return true if SkRGBA4f is opaque
|
||||
*/
|
||||
bool isOpaque() const {
|
||||
SkASSERT(fA <= 1.0f && fA >= 0.0f);
|
||||
return fA == 1.0f;
|
||||
}
|
||||
|
||||
/** Returns true if all channels are in [0, 1]. */
|
||||
bool fitsInBytes() const {
|
||||
SkASSERT(fA >= 0.0f && fA <= 1.0f);
|
||||
return fR >= 0.0f && fR <= 1.0f &&
|
||||
fG >= 0.0f && fG <= 1.0f &&
|
||||
fB >= 0.0f && fB <= 1.0f;
|
||||
}
|
||||
|
||||
/** Returns closest SkRGBA4f to SkColor. Only allowed if SkRGBA4f is unpremultiplied.
|
||||
|
||||
@param color Color with Alpha, red, blue, and green components
|
||||
@return SkColor as SkRGBA4f
|
||||
|
||||
example: https://fiddle.skia.org/c/@RGBA4f_FromColor
|
||||
*/
|
||||
static SkRGBA4f FromColor(SkColor color); // impl. depends on kAT
|
||||
|
||||
/** Returns closest SkColor to SkRGBA4f. Only allowed if SkRGBA4f is unpremultiplied.
|
||||
|
||||
@return color as SkColor
|
||||
|
||||
example: https://fiddle.skia.org/c/@RGBA4f_toSkColor
|
||||
*/
|
||||
SkColor toSkColor() const; // impl. depends on kAT
|
||||
|
||||
/** Returns closest SkRGBA4f to SkPMColor. Only allowed if SkRGBA4f is premultiplied.
|
||||
|
||||
@return SkPMColor as SkRGBA4f
|
||||
*/
|
||||
static SkRGBA4f FromPMColor(SkPMColor); // impl. depends on kAT
|
||||
|
||||
/** Returns SkRGBA4f premultiplied by alpha. Asserts at compile time if SkRGBA4f is
|
||||
already premultiplied.
|
||||
|
||||
@return premultiplied color
|
||||
*/
|
||||
SkRGBA4f<kPremul_SkAlphaType> premul() const {
|
||||
static_assert(kAT == kUnpremul_SkAlphaType, "");
|
||||
return { fR * fA, fG * fA, fB * fA, fA };
|
||||
}
|
||||
|
||||
/** Returns SkRGBA4f unpremultiplied by alpha. Asserts at compile time if SkRGBA4f is
|
||||
already unpremultiplied.
|
||||
|
||||
@return unpremultiplied color
|
||||
*/
|
||||
SkRGBA4f<kUnpremul_SkAlphaType> unpremul() const {
|
||||
static_assert(kAT == kPremul_SkAlphaType, "");
|
||||
|
||||
if (fA == 0.0f) {
|
||||
return { 0, 0, 0, 0 };
|
||||
} else {
|
||||
float invAlpha = 1 / fA;
|
||||
return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA };
|
||||
}
|
||||
}
|
||||
|
||||
// This produces bytes in RGBA order (eg GrColor). Impl. is the same, regardless of kAT
|
||||
uint32_t toBytes_RGBA() const;
|
||||
static SkRGBA4f FromBytes_RGBA(uint32_t color);
|
||||
|
||||
/**
|
||||
Returns a copy of the SkRGBA4f but with alpha component set to 1.0f.
|
||||
|
||||
@return opaque color
|
||||
*/
|
||||
SkRGBA4f makeOpaque() const {
|
||||
return { fR, fG, fB, 1.0f };
|
||||
}
|
||||
};
|
||||
|
||||
/** \struct SkColor4f
|
||||
RGBA color value, holding four floating point components. Color components are always in
|
||||
a known order, and are unpremultiplied.
|
||||
|
||||
This is a specialization of SkRGBA4f. For details, @see SkRGBA4f.
|
||||
*/
|
||||
using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>;
|
||||
|
||||
template <> SK_API SkColor4f SkColor4f::FromColor(SkColor);
|
||||
template <> SK_API SkColor SkColor4f::toSkColor() const;
|
||||
template <> SK_API uint32_t SkColor4f::toBytes_RGBA() const;
|
||||
template <> SK_API SkColor4f SkColor4f::FromBytes_RGBA(uint32_t color);
|
||||
|
||||
namespace SkColors {
|
||||
constexpr SkColor4f kTransparent = {0, 0, 0, 0};
|
||||
constexpr SkColor4f kBlack = {0, 0, 0, 1};
|
||||
constexpr SkColor4f kDkGray = {0.25f, 0.25f, 0.25f, 1};
|
||||
constexpr SkColor4f kGray = {0.50f, 0.50f, 0.50f, 1};
|
||||
constexpr SkColor4f kLtGray = {0.75f, 0.75f, 0.75f, 1};
|
||||
constexpr SkColor4f kWhite = {1, 1, 1, 1};
|
||||
constexpr SkColor4f kRed = {1, 0, 0, 1};
|
||||
constexpr SkColor4f kGreen = {0, 1, 0, 1};
|
||||
constexpr SkColor4f kBlue = {0, 0, 1, 1};
|
||||
constexpr SkColor4f kYellow = {1, 1, 0, 1};
|
||||
constexpr SkColor4f kCyan = {0, 1, 1, 1};
|
||||
constexpr SkColor4f kMagenta = {1, 0, 1, 1};
|
||||
} // namespace SkColors
|
||||
#endif
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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 SkColorFilter_DEFINED
|
||||
#define SkColorFilter_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
class SkColorMatrix;
|
||||
class SkColorSpace;
|
||||
class SkColorTable;
|
||||
|
||||
enum class SkBlendMode;
|
||||
struct SkDeserialProcs;
|
||||
|
||||
/**
|
||||
* ColorFilters are optional objects in the drawing pipeline. When present in
|
||||
* a paint, they are called with the "src" colors, and return new colors, which
|
||||
* are then passed onto the next stage (either ImageFilter or Xfermode).
|
||||
*
|
||||
* All subclasses are required to be reentrant-safe : it must be legal to share
|
||||
* the same instance between several threads.
|
||||
*/
|
||||
class SK_API SkColorFilter : public SkFlattenable {
|
||||
public:
|
||||
/** If the filter can be represented by a source color plus Mode, this
|
||||
* returns true, and sets (if not NULL) the color and mode appropriately.
|
||||
* If not, this returns false and ignores the parameters.
|
||||
*/
|
||||
bool asAColorMode(SkColor* color, SkBlendMode* mode) const;
|
||||
|
||||
/** If the filter can be represented by a 5x4 matrix, this
|
||||
* returns true, and sets the matrix appropriately.
|
||||
* If not, this returns false and ignores the parameter.
|
||||
*/
|
||||
bool asAColorMatrix(float matrix[20]) const;
|
||||
|
||||
// Returns true if the filter is guaranteed to never change the alpha of a color it filters.
|
||||
bool isAlphaUnchanged() const;
|
||||
|
||||
/**
|
||||
* Applies this filter to the input color. This function does no color management.
|
||||
*
|
||||
* DEPRECATED: Please use filterColor4f instead. That function supports higher precision,
|
||||
* wide-gamut color, and is explicit about the color space of the input and output.
|
||||
*/
|
||||
SkColor filterColor(SkColor) const;
|
||||
|
||||
/**
|
||||
* Converts the src color (in src colorspace), into the dst colorspace,
|
||||
* then applies this filter to it, returning the filtered color in the dst colorspace.
|
||||
*/
|
||||
SkColor4f filterColor4f(const SkColor4f& srcColor, SkColorSpace* srcCS,
|
||||
SkColorSpace* dstCS) const;
|
||||
|
||||
/** Construct a colorfilter whose effect is to first apply the inner filter and then apply
|
||||
* this filter, applied to the output of the inner filter.
|
||||
*
|
||||
* result = this(inner(...))
|
||||
*/
|
||||
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const;
|
||||
|
||||
/** Return a colorfilter that will compute this filter in a specific color space. By default all
|
||||
* filters operate in the destination (surface) color space. This allows filters like Blend and
|
||||
* Matrix, or runtime color filters to perform their math in a known space.
|
||||
*/
|
||||
sk_sp<SkColorFilter> makeWithWorkingColorSpace(sk_sp<SkColorSpace>) const;
|
||||
|
||||
static sk_sp<SkColorFilter> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
private:
|
||||
SkColorFilter() = default;
|
||||
friend class SkColorFilterBase;
|
||||
|
||||
using INHERITED = SkFlattenable;
|
||||
};
|
||||
|
||||
class SK_API SkColorFilters {
|
||||
public:
|
||||
static sk_sp<SkColorFilter> Compose(const sk_sp<SkColorFilter>& outer,
|
||||
sk_sp<SkColorFilter> inner) {
|
||||
return outer ? outer->makeComposed(std::move(inner))
|
||||
: std::move(inner);
|
||||
}
|
||||
|
||||
// Blends between the constant color (src) and input color (dst) based on the SkBlendMode.
|
||||
// If the color space is null, the constant color is assumed to be defined in sRGB.
|
||||
static sk_sp<SkColorFilter> Blend(const SkColor4f& c, sk_sp<SkColorSpace>, SkBlendMode mode);
|
||||
static sk_sp<SkColorFilter> Blend(SkColor c, SkBlendMode mode);
|
||||
|
||||
static sk_sp<SkColorFilter> Matrix(const SkColorMatrix&);
|
||||
static sk_sp<SkColorFilter> Matrix(const float rowMajor[20]);
|
||||
|
||||
// A version of Matrix which operates in HSLA space instead of RGBA.
|
||||
// I.e. HSLA-to-RGBA(Matrix(RGBA-to-HSLA(input))).
|
||||
static sk_sp<SkColorFilter> HSLAMatrix(const SkColorMatrix&);
|
||||
static sk_sp<SkColorFilter> HSLAMatrix(const float rowMajor[20]);
|
||||
|
||||
static sk_sp<SkColorFilter> LinearToSRGBGamma();
|
||||
static sk_sp<SkColorFilter> SRGBToLinearGamma();
|
||||
static sk_sp<SkColorFilter> Lerp(float t, sk_sp<SkColorFilter> dst, sk_sp<SkColorFilter> src);
|
||||
|
||||
/**
|
||||
* Create a table colorfilter, copying the table into the filter, and
|
||||
* applying it to all 4 components.
|
||||
* a' = table[a];
|
||||
* r' = table[r];
|
||||
* g' = table[g];
|
||||
* b' = table[b];
|
||||
* Components are operated on in unpremultiplied space. If the incomming
|
||||
* colors are premultiplied, they are temporarily unpremultiplied, then
|
||||
* the table is applied, and then the result is remultiplied.
|
||||
*/
|
||||
static sk_sp<SkColorFilter> Table(const uint8_t table[256]);
|
||||
|
||||
/**
|
||||
* Create a table colorfilter, with a different table for each
|
||||
* component [A, R, G, B]. If a given table is NULL, then it is
|
||||
* treated as identity, with the component left unchanged. If a table
|
||||
* is not null, then its contents are copied into the filter.
|
||||
*/
|
||||
static sk_sp<SkColorFilter> TableARGB(const uint8_t tableA[256],
|
||||
const uint8_t tableR[256],
|
||||
const uint8_t tableG[256],
|
||||
const uint8_t tableB[256]);
|
||||
|
||||
/**
|
||||
* Create a table colorfilter that holds a ref to the shared color table.
|
||||
*/
|
||||
static sk_sp<SkColorFilter> Table(sk_sp<SkColorTable> table);
|
||||
|
||||
/**
|
||||
* Create a colorfilter that multiplies the RGB channels by one color, and
|
||||
* then adds a second color, pinning the result for each component to
|
||||
* [0..255]. The alpha components of the mul and add arguments
|
||||
* are ignored.
|
||||
*/
|
||||
static sk_sp<SkColorFilter> Lighting(SkColor mul, SkColor add);
|
||||
|
||||
private:
|
||||
SkColorFilters() = delete;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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 SkColorPriv_DEFINED
|
||||
#define SkColorPriv_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/private/base/SkMath.h"
|
||||
#include "include/private/base/SkTPin.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
|
||||
byte into a scale value, so that we can say scale * value >> 8 instead of
|
||||
alpha * value / 255.
|
||||
|
||||
In debugging, asserts that alpha is 0..255
|
||||
*/
|
||||
static inline unsigned SkAlpha255To256(U8CPU alpha) {
|
||||
SkASSERT(SkToU8(alpha) == alpha);
|
||||
// this one assues that blending on top of an opaque dst keeps it that way
|
||||
// even though it is less accurate than a+(a>>7) for non-opaque dsts
|
||||
return alpha + 1;
|
||||
}
|
||||
|
||||
/** Multiplify value by 0..256, and shift the result down 8
|
||||
(i.e. return (value * alpha256) >> 8)
|
||||
*/
|
||||
#define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
|
||||
|
||||
static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
|
||||
return static_cast<U8CPU>(SkTPin(x, 0.0f, 1.0f) * 255 + 0.5);
|
||||
}
|
||||
|
||||
#define SK_A32_BITS 8
|
||||
#define SK_R32_BITS 8
|
||||
#define SK_G32_BITS 8
|
||||
#define SK_B32_BITS 8
|
||||
|
||||
#define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
|
||||
#define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
|
||||
#define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
|
||||
#define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
|
||||
|
||||
/*
|
||||
* Skia's 32bit backend only supports 1 swizzle order at a time (compile-time).
|
||||
* This is specified by SK_R32_SHIFT=0 or SK_R32_SHIFT=16.
|
||||
*
|
||||
* For easier compatibility with Skia's GPU backend, we further restrict these
|
||||
* to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
|
||||
* not directly correspond to the same shift-order, since we have to take endianess
|
||||
* into account.
|
||||
*
|
||||
* Here we enforce this constraint.
|
||||
*/
|
||||
|
||||
#define SK_RGBA_R32_SHIFT 0
|
||||
#define SK_RGBA_G32_SHIFT 8
|
||||
#define SK_RGBA_B32_SHIFT 16
|
||||
#define SK_RGBA_A32_SHIFT 24
|
||||
|
||||
#define SK_BGRA_B32_SHIFT 0
|
||||
#define SK_BGRA_G32_SHIFT 8
|
||||
#define SK_BGRA_R32_SHIFT 16
|
||||
#define SK_BGRA_A32_SHIFT 24
|
||||
|
||||
#if defined(SK_PMCOLOR_IS_RGBA) || defined(SK_PMCOLOR_IS_BGRA)
|
||||
#error "Configure PMCOLOR by setting SK_R32_SHIFT."
|
||||
#endif
|
||||
|
||||
// Deduce which SK_PMCOLOR_IS_ to define from the _SHIFT defines
|
||||
|
||||
#if (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
|
||||
SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
|
||||
SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
|
||||
SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
|
||||
#define SK_PMCOLOR_IS_RGBA
|
||||
#elif (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
|
||||
SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
|
||||
SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
|
||||
SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
|
||||
#define SK_PMCOLOR_IS_BGRA
|
||||
#else
|
||||
#error "need 32bit packing to be either RGBA or BGRA"
|
||||
#endif
|
||||
|
||||
#define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
|
||||
#define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
|
||||
#define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
|
||||
#define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
|
||||
|
||||
#define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
|
||||
#define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
|
||||
#define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
|
||||
#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
|
||||
|
||||
/**
|
||||
* Pack the components into a SkPMColor, checking (in the debug version) that
|
||||
* the components are 0..255, and are already premultiplied (i.e. alpha >= color)
|
||||
*/
|
||||
static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
SkA32Assert(a);
|
||||
SkASSERT(r <= a);
|
||||
SkASSERT(g <= a);
|
||||
SkASSERT(b <= a);
|
||||
|
||||
return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
|
||||
(g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as SkPackARGB32, but this version guarantees to not check that the
|
||||
* values are premultiplied in the debug version.
|
||||
*/
|
||||
static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
|
||||
(g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
|
||||
}
|
||||
|
||||
static inline
|
||||
SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
|
||||
SkA32Assert(a);
|
||||
SkR32Assert(r);
|
||||
SkG32Assert(g);
|
||||
SkB32Assert(b);
|
||||
|
||||
if (a != 255) {
|
||||
r = SkMulDiv255Round(r, a);
|
||||
g = SkMulDiv255Round(g, a);
|
||||
b = SkMulDiv255Round(b, a);
|
||||
}
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
|
||||
// inlined; forcing inlining significantly improves performance.
|
||||
static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
|
||||
uint32_t mask = 0xFF00FF;
|
||||
|
||||
uint32_t rb = ((c & mask) * scale) >> 8;
|
||||
uint32_t ag = ((c >> 8) & mask) * scale;
|
||||
return (rb & mask) | (ag & ~mask);
|
||||
}
|
||||
|
||||
static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
|
||||
uint32_t scale = SkAlpha255To256(255 - SkGetPackedA32(src));
|
||||
|
||||
uint32_t mask = 0xFF00FF;
|
||||
uint32_t rb = (((dst & mask) * scale) >> 8) & mask;
|
||||
uint32_t ag = (((dst >> 8) & mask) * scale) & ~mask;
|
||||
|
||||
rb += (src & mask);
|
||||
ag += (src & ~mask);
|
||||
|
||||
// Color channels (but not alpha) can overflow, so we have to saturate to 0xFF in each lane.
|
||||
return std::min(rb & 0x000001FF, 0x000000FFU) |
|
||||
std::min(ag & 0x0001FF00, 0x0000FF00U) |
|
||||
std::min(rb & 0x01FF0000, 0x00FF0000U) |
|
||||
(ag & 0xFF000000);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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 "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkFixed.h"
|
||||
#include "include/private/base/SkOnce.h"
|
||||
#include "modules/skcms/skcms.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class SkData;
|
||||
|
||||
/**
|
||||
* Describes a color gamut with primaries and a white point.
|
||||
*/
|
||||
struct SK_API SkColorSpacePrimaries {
|
||||
float fRX;
|
||||
float fRY;
|
||||
float fGX;
|
||||
float fGY;
|
||||
float fBX;
|
||||
float fBY;
|
||||
float fWX;
|
||||
float fWY;
|
||||
|
||||
/**
|
||||
* Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
|
||||
* representation of SkColorSpace.
|
||||
*/
|
||||
bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
|
||||
};
|
||||
|
||||
namespace SkNamedTransferFn {
|
||||
|
||||
// Like SkNamedGamut::kSRGB, keeping this bitwise exactly the same as skcms makes things fastest.
|
||||
static constexpr skcms_TransferFunction kSRGB =
|
||||
{ 2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0.0f, 0.0f };
|
||||
|
||||
static constexpr skcms_TransferFunction k2Dot2 =
|
||||
{ 2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
static constexpr skcms_TransferFunction kLinear =
|
||||
{ 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
static constexpr skcms_TransferFunction kRec2020 =
|
||||
{2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0};
|
||||
|
||||
static constexpr skcms_TransferFunction kPQ =
|
||||
{-2.0f, -107/128.0f, 1.0f, 32/2523.0f, 2413/128.0f, -2392/128.0f, 8192/1305.0f };
|
||||
|
||||
static constexpr skcms_TransferFunction kHLG =
|
||||
{-3.0f, 2.0f, 2.0f, 1/0.17883277f, 0.28466892f, 0.55991073f, 0.0f };
|
||||
|
||||
} // namespace SkNamedTransferFn
|
||||
|
||||
namespace SkNamedGamut {
|
||||
|
||||
static constexpr skcms_Matrix3x3 kSRGB = {{
|
||||
// ICC fixed-point (16.16) representation, taken from skcms. Please keep them exactly in sync.
|
||||
// 0.436065674f, 0.385147095f, 0.143066406f,
|
||||
// 0.222488403f, 0.716873169f, 0.060607910f,
|
||||
// 0.013916016f, 0.097076416f, 0.714096069f,
|
||||
{ SkFixedToFloat(0x6FA2), SkFixedToFloat(0x6299), SkFixedToFloat(0x24A0) },
|
||||
{ SkFixedToFloat(0x38F5), SkFixedToFloat(0xB785), SkFixedToFloat(0x0F84) },
|
||||
{ SkFixedToFloat(0x0390), SkFixedToFloat(0x18DA), SkFixedToFloat(0xB6CF) },
|
||||
}};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kAdobeRGB = {{
|
||||
// ICC fixed-point (16.16) repesentation of:
|
||||
// 0.60974, 0.20528, 0.14919,
|
||||
// 0.31111, 0.62567, 0.06322,
|
||||
// 0.01947, 0.06087, 0.74457,
|
||||
{ SkFixedToFloat(0x9c18), SkFixedToFloat(0x348d), SkFixedToFloat(0x2631) },
|
||||
{ SkFixedToFloat(0x4fa5), SkFixedToFloat(0xa02c), SkFixedToFloat(0x102f) },
|
||||
{ SkFixedToFloat(0x04fc), SkFixedToFloat(0x0f95), SkFixedToFloat(0xbe9c) },
|
||||
}};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kDisplayP3 = {{
|
||||
{ 0.515102f, 0.291965f, 0.157153f },
|
||||
{ 0.241182f, 0.692236f, 0.0665819f },
|
||||
{ -0.00104941f, 0.0418818f, 0.784378f },
|
||||
}};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kRec2020 = {{
|
||||
{ 0.673459f, 0.165661f, 0.125100f },
|
||||
{ 0.279033f, 0.675338f, 0.0456288f },
|
||||
{ -0.00193139f, 0.0299794f, 0.797162f },
|
||||
}};
|
||||
|
||||
static constexpr skcms_Matrix3x3 kXYZ = {{
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
}};
|
||||
|
||||
} // namespace SkNamedGamut
|
||||
|
||||
class SK_API SkColorSpace : public SkNVRefCnt<SkColorSpace> {
|
||||
public:
|
||||
/**
|
||||
* Create the sRGB color space.
|
||||
*/
|
||||
static sk_sp<SkColorSpace> MakeSRGB();
|
||||
|
||||
/**
|
||||
* Colorspace with the sRGB primaries, but a linear (1.0) gamma.
|
||||
*/
|
||||
static sk_sp<SkColorSpace> MakeSRGBLinear();
|
||||
|
||||
/**
|
||||
* Create an SkColorSpace from a transfer function and a row-major 3x3 transformation to XYZ.
|
||||
*/
|
||||
static sk_sp<SkColorSpace> MakeRGB(const skcms_TransferFunction& transferFn,
|
||||
const skcms_Matrix3x3& toXYZ);
|
||||
|
||||
/**
|
||||
* Create an SkColorSpace from a parsed (skcms) ICC profile.
|
||||
*/
|
||||
static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);
|
||||
|
||||
/**
|
||||
* Convert this color space to an skcms ICC profile struct.
|
||||
*/
|
||||
void toProfile(skcms_ICCProfile*) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Sets |fn| to the transfer function from this color space. Returns true if the transfer
|
||||
* function can be represented as coefficients to the standard ICC 7-parameter equation.
|
||||
* Returns false otherwise (eg, PQ, HLG).
|
||||
*/
|
||||
bool isNumericalTransferFn(skcms_TransferFunction* fn) const;
|
||||
|
||||
/**
|
||||
* Returns true and sets |toXYZD50|.
|
||||
*/
|
||||
bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
|
||||
|
||||
/**
|
||||
* Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking
|
||||
* of gamuts, at the (very small) risk of collision.
|
||||
*/
|
||||
uint32_t toXYZD50Hash() const { return fToXYZD50Hash; }
|
||||
|
||||
/**
|
||||
* Returns a color space with the same gamut as this one, but with a linear gamma.
|
||||
*/
|
||||
sk_sp<SkColorSpace> makeLinearGamma() const;
|
||||
|
||||
/**
|
||||
* Returns a color space with the same gamut as this one, but with the sRGB transfer
|
||||
* function.
|
||||
*/
|
||||
sk_sp<SkColorSpace> makeSRGBGamma() const;
|
||||
|
||||
/**
|
||||
* Returns a color space with the same transfer function as this one, but with the primary
|
||||
* colors rotated. In other words, this produces a new color space that maps RGB to GBR
|
||||
* (when applied to a source), and maps RGB to BRG (when applied to a destination).
|
||||
*
|
||||
* This is used for testing, to construct color spaces that have severe and testable behavior.
|
||||
*/
|
||||
sk_sp<SkColorSpace> makeColorSpin() const;
|
||||
|
||||
/**
|
||||
* Returns true if the color space is sRGB.
|
||||
* Returns false otherwise.
|
||||
*
|
||||
* This allows a little bit of tolerance, given that we might see small numerical error
|
||||
* in some cases: converting ICC fixed point to float, converting white point to D50,
|
||||
* rounding decisions on transfer function and matrix.
|
||||
*
|
||||
* This does not consider a 2.2f exponential transfer function to be sRGB. While these
|
||||
* functions are similar (and it is sometimes useful to consider them together), this
|
||||
* function checks for logical equality.
|
||||
*/
|
||||
bool isSRGB() const;
|
||||
|
||||
/**
|
||||
* Returns a serialized representation of this color space.
|
||||
*/
|
||||
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*, const SkColorSpace*);
|
||||
|
||||
void transferFn(float gabcdef[7]) const; // DEPRECATED: Remove when webview usage is gone
|
||||
void transferFn(skcms_TransferFunction* fn) const;
|
||||
void invTransferFn(skcms_TransferFunction* fn) const;
|
||||
void gamutTransformTo(const SkColorSpace* dst, skcms_Matrix3x3* src_to_dst) const;
|
||||
|
||||
uint32_t transferFnHash() const { return fTransferFnHash; }
|
||||
uint64_t hash() const { return (uint64_t)fTransferFnHash << 32 | fToXYZD50Hash; }
|
||||
|
||||
private:
|
||||
friend class SkColorSpaceSingletonFactory;
|
||||
|
||||
SkColorSpace(const skcms_TransferFunction& transferFn, const skcms_Matrix3x3& toXYZ);
|
||||
|
||||
void computeLazyDstFields() const;
|
||||
|
||||
uint32_t fTransferFnHash;
|
||||
uint32_t fToXYZD50Hash;
|
||||
|
||||
skcms_TransferFunction fTransferFn;
|
||||
skcms_Matrix3x3 fToXYZD50;
|
||||
|
||||
mutable skcms_TransferFunction fInvTransferFn;
|
||||
mutable skcms_Matrix3x3 fFromXYZD50;
|
||||
mutable SkOnce fLazyDstFieldsOnce;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkColorTable_DEFINED
|
||||
#define SkColorTable_DEFINED
|
||||
|
||||
#include "include/core/SkBitmap.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class SkReadBuffer;
|
||||
class SkWriteBuffer;
|
||||
|
||||
/**
|
||||
* SkColorTable holds the lookup tables for each channel (ARGB) used to define the filter behavior
|
||||
* of `SkColorFilters::Table`, and provides a way to share the table data between client code and
|
||||
* the returned SkColorFilter. Once created, an SkColorTable is immutable.
|
||||
*/
|
||||
class SK_API SkColorTable : public SkRefCnt {
|
||||
public:
|
||||
// Creates a new SkColorTable with 'table' used for all four channels. The table is copied into
|
||||
// the SkColorTable.
|
||||
static sk_sp<SkColorTable> Make(const uint8_t table[256]) {
|
||||
return Make(table, table, table, table);
|
||||
}
|
||||
|
||||
// Creates a new SkColorTable with the per-channel lookup tables. Each non-null table is copied
|
||||
// into the SkColorTable. Null parameters are interpreted as the identity table.
|
||||
static sk_sp<SkColorTable> Make(const uint8_t tableA[256],
|
||||
const uint8_t tableR[256],
|
||||
const uint8_t tableG[256],
|
||||
const uint8_t tableB[256]);
|
||||
|
||||
// Per-channel constant value lookup (0-255).
|
||||
const uint8_t* alphaTable() const { return fTable.getAddr8(0, 0); }
|
||||
const uint8_t* redTable() const { return fTable.getAddr8(0, 1); }
|
||||
const uint8_t* greenTable() const { return fTable.getAddr8(0, 2); }
|
||||
const uint8_t* blueTable() const { return fTable.getAddr8(0, 3); }
|
||||
|
||||
void flatten(SkWriteBuffer& buffer) const;
|
||||
|
||||
static sk_sp<SkColorTable> Deserialize(SkReadBuffer& buffer);
|
||||
|
||||
private:
|
||||
friend class SkTableColorFilter; // for bitmap()
|
||||
|
||||
SkColorTable(const SkBitmap& table) : fTable(table) {}
|
||||
|
||||
// The returned SkBitmap is immutable; attempting to modify its pixel data will trigger asserts
|
||||
// in debug builds and cause undefined behavior in release builds.
|
||||
const SkBitmap& bitmap() const { return fTable; }
|
||||
|
||||
SkBitmap fTable; // A 256x4 A8 image
|
||||
};
|
||||
|
||||
#endif // SkColorTable_DEFINED
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkColorType_DEFINED
|
||||
#define SkColorType_DEFINED
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/** \enum SkColorType
|
||||
Describes how pixel bits encode color. A pixel may be an alpha mask, a grayscale, RGB, or ARGB.
|
||||
|
||||
kN32_SkColorType selects the native 32-bit ARGB format for the current configuration. This can
|
||||
lead to inconsistent results across platforms, so use with caution.
|
||||
*/
|
||||
enum SkColorType : int {
|
||||
kUnknown_SkColorType, //!< uninitialized
|
||||
kAlpha_8_SkColorType, //!< pixel with alpha in 8-bit byte
|
||||
kRGB_565_SkColorType, //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
|
||||
kARGB_4444_SkColorType, //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word
|
||||
kRGBA_8888_SkColorType, //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word
|
||||
kRGB_888x_SkColorType, //!< pixel with 8 bits each for red, green, blue; in 32-bit word
|
||||
kBGRA_8888_SkColorType, //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word
|
||||
kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
|
||||
kBGRA_1010102_SkColorType, //!< 10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
|
||||
kRGB_101010x_SkColorType, //!< pixel with 10 bits each for red, green, blue; in 32-bit word
|
||||
kBGR_101010x_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word
|
||||
kBGR_101010x_XR_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
|
||||
kBGRA_10101010_XR_SkColorType, //!< pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
|
||||
kRGBA_10x6_SkColorType, //!< pixel with 10 used bits (most significant) followed by 6 unused
|
||||
// bits for red, green, blue, alpha; in 64-bit word
|
||||
kGray_8_SkColorType, //!< pixel with grayscale level in 8-bit byte
|
||||
kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha;
|
||||
// in 64-bit word
|
||||
kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha;
|
||||
// in 64-bit word
|
||||
kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word
|
||||
|
||||
// The following 6 colortypes are just for reading from - not for rendering to
|
||||
kR8G8_unorm_SkColorType, //!< pixel with a uint8_t for red and green
|
||||
|
||||
kA16_float_SkColorType, //!< pixel with a half float for alpha
|
||||
kR16G16_float_SkColorType, //!< pixel with a half float for red and green
|
||||
|
||||
kA16_unorm_SkColorType, //!< pixel with a little endian uint16_t for alpha
|
||||
kR16G16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red and green
|
||||
kR16G16B16A16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red, green, blue
|
||||
// and alpha
|
||||
|
||||
kSRGBA_8888_SkColorType,
|
||||
kR8_unorm_SkColorType,
|
||||
|
||||
kLastEnum_SkColorType = kR8_unorm_SkColorType, //!< last valid value
|
||||
|
||||
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
|
||||
kN32_SkColorType = kBGRA_8888_SkColorType,//!< native 32-bit BGRA encoding
|
||||
|
||||
#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
|
||||
kN32_SkColorType = kRGBA_8888_SkColorType,//!< native 32-bit RGBA encoding
|
||||
|
||||
#else
|
||||
#error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
|
||||
#endif
|
||||
};
|
||||
static constexpr int kSkColorTypeCnt = static_cast<int>(kLastEnum_SkColorType) + 1;
|
||||
|
||||
#endif
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkContourMeasure_DEFINED
|
||||
#define SkContourMeasure_DEFINED
|
||||
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkTDArray.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class SkMatrix;
|
||||
class SkPath;
|
||||
|
||||
class SK_API SkContourMeasure : public SkRefCnt {
|
||||
public:
|
||||
/** Return the length of the contour.
|
||||
*/
|
||||
SkScalar length() const { return fLength; }
|
||||
|
||||
/** Pins distance to 0 <= distance <= length(), and then computes the corresponding
|
||||
* position and tangent.
|
||||
*/
|
||||
[[nodiscard]] bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent) const;
|
||||
|
||||
enum MatrixFlags {
|
||||
kGetPosition_MatrixFlag = 0x01,
|
||||
kGetTangent_MatrixFlag = 0x02,
|
||||
kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
|
||||
};
|
||||
|
||||
/** Pins distance to 0 <= distance <= getLength(), and then computes
|
||||
the corresponding matrix (by calling getPosTan).
|
||||
Returns false if there is no path, or a zero-length path was specified, in which case
|
||||
matrix is unchanged.
|
||||
*/
|
||||
[[nodiscard]] bool getMatrix(SkScalar distance, SkMatrix* matrix,
|
||||
MatrixFlags flags = kGetPosAndTan_MatrixFlag) const;
|
||||
|
||||
/** Given a start and stop distance, return in dst the intervening segment(s).
|
||||
If the segment is zero-length, return false, else return true.
|
||||
startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
|
||||
then return false (and leave dst untouched).
|
||||
Begin the segment with a moveTo if startWithMoveTo is true
|
||||
*/
|
||||
[[nodiscard]] bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
|
||||
bool startWithMoveTo) const;
|
||||
|
||||
/** Return true if the contour is closed()
|
||||
*/
|
||||
bool isClosed() const { return fIsClosed; }
|
||||
|
||||
private:
|
||||
struct Segment {
|
||||
SkScalar fDistance; // total distance up to this point
|
||||
unsigned fPtIndex; // index into the fPts array
|
||||
unsigned fTValue : 30;
|
||||
unsigned fType : 2; // actually the enum SkSegType
|
||||
// See SkPathMeasurePriv.h
|
||||
|
||||
SkScalar getScalarT() const;
|
||||
|
||||
static const Segment* Next(const Segment* seg) {
|
||||
unsigned ptIndex = seg->fPtIndex;
|
||||
do {
|
||||
++seg;
|
||||
} while (seg->fPtIndex == ptIndex);
|
||||
return seg;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const SkTDArray<Segment> fSegments;
|
||||
const SkTDArray<SkPoint> fPts; // Points used to define the segments
|
||||
|
||||
const SkScalar fLength;
|
||||
const bool fIsClosed;
|
||||
|
||||
SkContourMeasure(SkTDArray<Segment>&& segs, SkTDArray<SkPoint>&& pts,
|
||||
SkScalar length, bool isClosed);
|
||||
~SkContourMeasure() override {}
|
||||
|
||||
const Segment* distanceToSegment(SkScalar distance, SkScalar* t) const;
|
||||
|
||||
friend class SkContourMeasureIter;
|
||||
friend class SkPathMeasurePriv;
|
||||
};
|
||||
|
||||
class SK_API SkContourMeasureIter {
|
||||
public:
|
||||
SkContourMeasureIter();
|
||||
/**
|
||||
* Initialize the Iter with a path.
|
||||
* The parts of the path that are needed are copied, so the client is free to modify/delete
|
||||
* the path after this call.
|
||||
*
|
||||
* resScale controls the precision of the measure. values > 1 increase the
|
||||
* precision (and possibly slow down the computation).
|
||||
*/
|
||||
SkContourMeasureIter(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
|
||||
~SkContourMeasureIter();
|
||||
|
||||
SkContourMeasureIter(SkContourMeasureIter&&);
|
||||
SkContourMeasureIter& operator=(SkContourMeasureIter&&);
|
||||
|
||||
/**
|
||||
* Reset the Iter with a path.
|
||||
* The parts of the path that are needed are copied, so the client is free to modify/delete
|
||||
* the path after this call.
|
||||
*/
|
||||
void reset(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
|
||||
|
||||
/**
|
||||
* Iterates through contours in path, returning a contour-measure object for each contour
|
||||
* in the path. Returns null when it is done.
|
||||
*
|
||||
* This only returns non-zero length contours, where a contour is the segments between
|
||||
* a kMove_Verb and either ...
|
||||
* - the next kMove_Verb
|
||||
* - kClose_Verb (1 or more)
|
||||
* - kDone_Verb
|
||||
* If it encounters a zero-length contour, it is skipped.
|
||||
*/
|
||||
sk_sp<SkContourMeasure> next();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> fImpl;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkCoverageMode_DEFINED
|
||||
#define SkCoverageMode_DEFINED
|
||||
|
||||
/**
|
||||
* Describes geometric operations (ala SkRegion::Op) that can be applied to coverage bytes.
|
||||
* These can be thought of as variants of porter-duff (SkBlendMode) modes, but only applied
|
||||
* to the alpha channel.
|
||||
*
|
||||
* See SkMaskFilter for ways to use these when combining two different masks.
|
||||
*/
|
||||
enum class SkCoverageMode {
|
||||
kUnion, // A ∪ B A+B-A*B
|
||||
kIntersect, // A ∩ B A*B
|
||||
kDifference, // A - B A*(1-B)
|
||||
kReverseDifference, // B - A B*(1-A)
|
||||
kXor, // A ⊕ B A+B-2*A*B
|
||||
|
||||
kLast = kXor,
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkCubicMap_DEFINED
|
||||
#define SkCubicMap_DEFINED
|
||||
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/**
|
||||
* Fast evaluation of a cubic ease-in / ease-out curve. This is defined as a parametric cubic
|
||||
* curve inside the unit square.
|
||||
*
|
||||
* pt[0] is implicitly { 0, 0 }
|
||||
* pt[3] is implicitly { 1, 1 }
|
||||
* pts[1,2].X are inside the unit [0..1]
|
||||
*/
|
||||
class SK_API SkCubicMap {
|
||||
public:
|
||||
SkCubicMap(SkPoint p1, SkPoint p2);
|
||||
|
||||
static bool IsLinear(SkPoint p1, SkPoint p2) {
|
||||
return SkScalarNearlyEqual(p1.fX, p1.fY) && SkScalarNearlyEqual(p2.fX, p2.fY);
|
||||
}
|
||||
|
||||
float computeYFromX(float x) const;
|
||||
|
||||
SkPoint computeFromT(float t) const;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
kLine_Type, // x == y
|
||||
kCubeRoot_Type, // At^3 == x
|
||||
kSolver_Type, // general monotonic cubic solver
|
||||
};
|
||||
|
||||
SkPoint fCoeff[3];
|
||||
Type fType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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 SkData_DEFINED
|
||||
#define SkData_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkAssert.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
class SkStream;
|
||||
|
||||
/**
|
||||
* 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 final : public SkNVRefCnt<SkData> {
|
||||
public:
|
||||
/**
|
||||
* Returns the number of bytes stored.
|
||||
*/
|
||||
size_t size() const { return fSize; }
|
||||
|
||||
bool isEmpty() const { return 0 == fSize; }
|
||||
|
||||
/**
|
||||
* Returns the ptr to the data.
|
||||
*/
|
||||
const void* data() const { return fPtr; }
|
||||
|
||||
/**
|
||||
* Like data(), returns a read-only ptr into the data, but in this case
|
||||
* it is cast to uint8_t*, to make it easy to add an offset to it.
|
||||
*/
|
||||
const uint8_t* bytes() const {
|
||||
return reinterpret_cast<const uint8_t*>(fPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* USE WITH CAUTION.
|
||||
* This call will assert that the refcnt is 1, as a precaution against modifying the
|
||||
* contents when another client/thread has access to the data.
|
||||
*/
|
||||
void* writable_data() {
|
||||
if (fSize) {
|
||||
// only assert we're unique if we're not empty
|
||||
SkASSERT(this->unique());
|
||||
}
|
||||
return const_cast<void*>(fPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to copy a range of the data into a caller-provided buffer.
|
||||
* Returns the actual number of bytes copied, after clamping offset and
|
||||
* length to the size of the data. If buffer is NULL, it is ignored, and
|
||||
* only the computed number of bytes is returned.
|
||||
*/
|
||||
size_t copyRange(size_t offset, size_t length, void* buffer) const;
|
||||
|
||||
/**
|
||||
* Returns true if these two objects have the same length and contents,
|
||||
* effectively returning 0 == memcmp(...)
|
||||
*/
|
||||
bool equals(const SkData* other) const;
|
||||
|
||||
/**
|
||||
* Function that, if provided, will be called when the SkData goes out
|
||||
* of scope, allowing for custom allocation/freeing of the data's contents.
|
||||
*/
|
||||
typedef void (*ReleaseProc)(const void* ptr, void* context);
|
||||
|
||||
/**
|
||||
* Create a new dataref by copying the specified data
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
static sk_sp<SkData> MakeUninitialized(size_t length);
|
||||
|
||||
/**
|
||||
* Create a new data with zero-initialized contents. The caller should call writable_data()
|
||||
* to write into the buffer, but this must be done before another ref() is made.
|
||||
*/
|
||||
static sk_sp<SkData> MakeZeroInitialized(size_t length);
|
||||
|
||||
/**
|
||||
* Create a new dataref by copying the specified c-string
|
||||
* (a null-terminated array of bytes). The returned SkData will have size()
|
||||
* equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
|
||||
* as "".
|
||||
*/
|
||||
static sk_sp<SkData> MakeWithCString(const char cstr[]);
|
||||
|
||||
/**
|
||||
* Create a new dataref, taking the ptr as is, and using the
|
||||
* releaseproc to free it. The proc may be NULL.
|
||||
*/
|
||||
static sk_sp<SkData> MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx);
|
||||
|
||||
/**
|
||||
* Call this when the data parameter is already const and will outlive the lifetime of the
|
||||
* SkData. Suitable for with const globals.
|
||||
*/
|
||||
static sk_sp<SkData> MakeWithoutCopy(const void* data, size_t length) {
|
||||
return MakeWithProc(data, length, NoopReleaseProc, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new dataref from a pointer allocated by malloc. The Data object
|
||||
* takes ownership of that allocation, and will handling calling sk_free.
|
||||
*/
|
||||
static sk_sp<SkData> MakeFromMalloc(const void* data, size_t length);
|
||||
|
||||
/**
|
||||
* Create a new dataref the file with the specified path.
|
||||
* If the file cannot be opened, this returns NULL.
|
||||
*/
|
||||
static sk_sp<SkData> MakeFromFileName(const char path[]);
|
||||
|
||||
/**
|
||||
* Create a new dataref from a stdio FILE.
|
||||
* This does not take ownership of the FILE, nor close it.
|
||||
* The caller is free to close the FILE at its convenience.
|
||||
* The FILE must be open for reading only.
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
static sk_sp<SkData> MakeFromFILE(FILE* f);
|
||||
|
||||
/**
|
||||
* Create a new dataref from a file descriptor.
|
||||
* This does not take ownership of the file descriptor, nor close it.
|
||||
* The caller is free to close the file descriptor at its convenience.
|
||||
* The file descriptor must be open for reading only.
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
static sk_sp<SkData> MakeFromFD(int fd);
|
||||
|
||||
/**
|
||||
* Attempt to read size bytes into a SkData. If the read succeeds, return the data,
|
||||
* else return NULL. Either way the stream's cursor may have been changed as a result
|
||||
* of calling read().
|
||||
*/
|
||||
static sk_sp<SkData> MakeFromStream(SkStream*, size_t size);
|
||||
|
||||
/**
|
||||
* Create a new dataref using a subset of the data in the specified
|
||||
* src dataref.
|
||||
*/
|
||||
static sk_sp<SkData> MakeSubset(const SkData* src, size_t offset, size_t length);
|
||||
|
||||
/**
|
||||
* Returns a new empty dataref (or a reference to a shared empty dataref).
|
||||
* New or shared, the caller must see that unref() is eventually called.
|
||||
*/
|
||||
static sk_sp<SkData> MakeEmpty();
|
||||
|
||||
private:
|
||||
friend class SkNVRefCnt<SkData>;
|
||||
ReleaseProc fReleaseProc;
|
||||
void* fReleaseProcContext;
|
||||
const void* fPtr;
|
||||
size_t fSize;
|
||||
|
||||
SkData(const void* ptr, size_t size, ReleaseProc, void* context);
|
||||
explicit SkData(size_t size); // inplace new/delete
|
||||
~SkData();
|
||||
|
||||
// Ensure the unsized delete is called.
|
||||
void operator delete(void* p);
|
||||
|
||||
// shared internal factory
|
||||
static sk_sp<SkData> PrivateNewWithCopy(const void* srcOrNull, size_t length);
|
||||
|
||||
static void NoopReleaseProc(const void*, void*); // {}
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkDataTable_DEFINED
|
||||
#define SkDataTable_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkAssert.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
/**
|
||||
* Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
|
||||
* organized into a table of entries, each with a length, so the entries are
|
||||
* not required to all be the same size.
|
||||
*/
|
||||
class SK_API SkDataTable : public SkRefCnt {
|
||||
public:
|
||||
/**
|
||||
* Returns true if the table is empty (i.e. has no entries).
|
||||
*/
|
||||
bool isEmpty() const { return 0 == fCount; }
|
||||
|
||||
/**
|
||||
* Return the number of entries in the table. 0 for an empty table
|
||||
*/
|
||||
int count() const { return fCount; }
|
||||
|
||||
/**
|
||||
* Return the size of the index'th entry in the table. The caller must
|
||||
* ensure that index is valid for this table.
|
||||
*/
|
||||
size_t atSize(int index) const;
|
||||
|
||||
/**
|
||||
* Return a pointer to the data of the index'th entry in the table.
|
||||
* The caller must ensure that index is valid for this table.
|
||||
*
|
||||
* @param size If non-null, this returns the byte size of this entry. This
|
||||
* will be the same value that atSize(index) would return.
|
||||
*/
|
||||
const void* at(int index, size_t* size = nullptr) const;
|
||||
|
||||
template <typename T>
|
||||
const T* atT(int index, size_t* size = nullptr) const {
|
||||
return reinterpret_cast<const T*>(this->at(index, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index'th entry as a c-string, and assumes that the trailing
|
||||
* null byte had been copied into the table as well.
|
||||
*/
|
||||
const char* atStr(int index) const {
|
||||
size_t size;
|
||||
const char* str = this->atT<const char>(index, &size);
|
||||
SkASSERT(strlen(str) + 1 == size);
|
||||
return str;
|
||||
}
|
||||
|
||||
typedef void (*FreeProc)(void* context);
|
||||
|
||||
static sk_sp<SkDataTable> MakeEmpty();
|
||||
|
||||
/**
|
||||
* Return a new DataTable that contains a copy of the data stored in each
|
||||
* "array".
|
||||
*
|
||||
* @param ptrs array of points to each element to be copied into the table.
|
||||
* @param sizes array of byte-lengths for each entry in the corresponding
|
||||
* ptrs[] array.
|
||||
* @param count the number of array elements in ptrs[] and sizes[] to copy.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param array contiguous array of data for all elements to be copied.
|
||||
* @param elemSize byte-length for a given element.
|
||||
* @param count the number of entries to be copied out of array. The number
|
||||
* of bytes that will be copied is count * elemSize.
|
||||
*/
|
||||
static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);
|
||||
|
||||
static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,
|
||||
FreeProc proc, void* context);
|
||||
|
||||
private:
|
||||
struct Dir {
|
||||
const void* fPtr;
|
||||
uintptr_t fSize;
|
||||
};
|
||||
|
||||
int fCount;
|
||||
size_t fElemSize;
|
||||
union {
|
||||
const Dir* fDir;
|
||||
const char* fElems;
|
||||
} fU;
|
||||
|
||||
FreeProc fFreeProc;
|
||||
void* fFreeProcContext;
|
||||
|
||||
SkDataTable();
|
||||
SkDataTable(const void* array, size_t elemSize, int count,
|
||||
FreeProc, void* context);
|
||||
SkDataTable(const Dir*, int count, FreeProc, void* context);
|
||||
~SkDataTable() override;
|
||||
|
||||
friend class SkDataTableBuilder; // access to Dir
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkDocument_DEFINED
|
||||
#define SkDocument_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkCanvas;
|
||||
class SkWStream;
|
||||
struct SkRect;
|
||||
|
||||
/** SK_ScalarDefaultDPI is 72 dots per inch. */
|
||||
static constexpr SkScalar SK_ScalarDefaultRasterDPI = 72.0f;
|
||||
|
||||
/**
|
||||
* High-level API for creating a document-based canvas. To use..
|
||||
*
|
||||
* 1. Create a document, specifying a stream to store the output.
|
||||
* 2. For each "page" of content:
|
||||
* a. canvas = doc->beginPage(...)
|
||||
* b. draw_my_content(canvas);
|
||||
* c. doc->endPage();
|
||||
* 3. Close the document with doc->close().
|
||||
*/
|
||||
class SK_API SkDocument : public SkRefCnt {
|
||||
public:
|
||||
|
||||
/**
|
||||
* 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
|
||||
* scope when endPage() or close() is called, or the document is deleted.
|
||||
* This will call endPage() if there is a currently active page.
|
||||
*/
|
||||
SkCanvas* beginPage(SkScalar width, SkScalar height, const SkRect* content = nullptr);
|
||||
|
||||
/**
|
||||
* Call endPage() when the content for the current page has been drawn
|
||||
* (into the canvas returned by beginPage()). After this call the canvas
|
||||
* returned by beginPage() will be out-of-scope.
|
||||
*/
|
||||
void endPage();
|
||||
|
||||
/**
|
||||
* Call close() when all pages have been drawn. This will close the file
|
||||
* 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.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Call abort() to stop producing the document immediately.
|
||||
* The stream output must be ignored, and should not be trusted.
|
||||
*/
|
||||
void abort();
|
||||
|
||||
protected:
|
||||
SkDocument(SkWStream*);
|
||||
|
||||
// note: subclasses must call close() in their destructor, as the base class
|
||||
// cannot do this for them.
|
||||
~SkDocument() override;
|
||||
|
||||
virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height) = 0;
|
||||
virtual void onEndPage() = 0;
|
||||
virtual void onClose(SkWStream*) = 0;
|
||||
virtual void onAbort() = 0;
|
||||
|
||||
// Allows subclasses to write to the stream as pages are written.
|
||||
SkWStream* getStream() { return fStream; }
|
||||
|
||||
enum State {
|
||||
kBetweenPages_State,
|
||||
kInPage_State,
|
||||
kClosed_State
|
||||
};
|
||||
State getState() const { return fState; }
|
||||
|
||||
private:
|
||||
SkWStream* fStream;
|
||||
State fState;
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkDrawable_DEFINED
|
||||
#define SkDrawable_DEFINED
|
||||
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class GrBackendDrawableInfo;
|
||||
class SkCanvas;
|
||||
class SkMatrix;
|
||||
class SkPicture;
|
||||
enum class GrBackendApi : unsigned int;
|
||||
struct SkDeserialProcs;
|
||||
struct SkIRect;
|
||||
struct SkImageInfo;
|
||||
struct SkRect;
|
||||
|
||||
/**
|
||||
* Base-class for objects that draw into SkCanvas.
|
||||
*
|
||||
* The object has a generation ID, which is guaranteed to be unique across all drawables. To
|
||||
* 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 SK_API SkDrawable : public SkFlattenable {
|
||||
public:
|
||||
/**
|
||||
* Draws into the specified content. The drawing sequence will be balanced upon return
|
||||
* (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
|
||||
* and the current matrix and clip settings will not be changed.
|
||||
*/
|
||||
void draw(SkCanvas*, const SkMatrix* = nullptr);
|
||||
void draw(SkCanvas*, SkScalar x, SkScalar y);
|
||||
|
||||
/**
|
||||
* When using the GPU backend it is possible for a drawable to execute using the underlying 3D
|
||||
* API rather than the SkCanvas API. It does so by creating a GpuDrawHandler. The GPU backend
|
||||
* is deferred so the handler will be given access to the 3D API at the correct point in the
|
||||
* drawing stream as the GPU backend flushes. Since the drawable may mutate, each time it is
|
||||
* drawn to a GPU-backed canvas a new handler is snapped, representing the drawable's state at
|
||||
* the time of the snap.
|
||||
*
|
||||
* When the GPU backend flushes to the 3D API it will call the draw method on the
|
||||
* GpuDrawHandler. At this time the drawable may add commands to the stream of GPU commands for
|
||||
* the unerlying 3D API. The draw function takes a GrBackendDrawableInfo which contains
|
||||
* information about the current state of 3D API which the caller must respect. See
|
||||
* GrBackendDrawableInfo for more specific details on what information is sent and the
|
||||
* requirements for different 3D APIs.
|
||||
*
|
||||
* Additionaly there may be a slight delay from when the drawable adds its commands to when
|
||||
* those commands are actually submitted to the GPU. Thus the drawable or GpuDrawHandler is
|
||||
* required to keep any resources that are used by its added commands alive and valid until
|
||||
* those commands are submitted to the GPU. The GpuDrawHandler will be kept alive and then
|
||||
* deleted once the commands are submitted to the GPU. The dtor of the GpuDrawHandler is the
|
||||
* signal to the drawable that the commands have all been submitted. Different 3D APIs may have
|
||||
* additional requirements for certain resources which require waiting for the GPU to finish
|
||||
* all work on those resources before reusing or deleting them. In this case, the drawable can
|
||||
* use the dtor call of the GpuDrawHandler to add a fence to the GPU to track when the GPU work
|
||||
* has completed.
|
||||
*
|
||||
* Currently this is only supported for the GPU Vulkan backend.
|
||||
*/
|
||||
|
||||
class GpuDrawHandler {
|
||||
public:
|
||||
virtual ~GpuDrawHandler() {}
|
||||
|
||||
virtual void draw(const GrBackendDrawableInfo&) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Snaps off a GpuDrawHandler to represent the state of the SkDrawable at the time the snap is
|
||||
* called. This is used for executing GPU backend specific draws intermixed with normal Skia GPU
|
||||
* draws. The GPU API, which will be used for the draw, as well as the full matrix, device clip
|
||||
* bounds and imageInfo of the target buffer are passed in as inputs.
|
||||
*/
|
||||
std::unique_ptr<GpuDrawHandler> snapGpuDrawHandler(GrBackendApi backendApi,
|
||||
const SkMatrix& matrix,
|
||||
const SkIRect& clipBounds,
|
||||
const SkImageInfo& bufferInfo) {
|
||||
return this->onSnapGpuDrawHandler(backendApi, matrix, clipBounds, bufferInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an SkPicture with the contents of this SkDrawable.
|
||||
*/
|
||||
sk_sp<SkPicture> makePictureSnapshot();
|
||||
|
||||
/**
|
||||
* Return a unique value for this instance. If two calls to this return the same value,
|
||||
* it is presumed that calling the draw() method will render the same thing as well.
|
||||
*
|
||||
* Subclasses that change their state should call notifyDrawingChanged() to ensure that
|
||||
* a new value will be returned the next time it is called.
|
||||
*/
|
||||
uint32_t getGenerationID();
|
||||
|
||||
/**
|
||||
* Return the (conservative) bounds of what the drawable will draw. If the drawable can
|
||||
* change what it draws (e.g. animation or in response to some external change), then this
|
||||
* must return a bounds that is always valid for all possible states.
|
||||
*/
|
||||
SkRect getBounds();
|
||||
|
||||
/**
|
||||
* Return approximately how many bytes would be freed if this drawable is destroyed.
|
||||
* The base implementation returns 0 to indicate that this is unknown.
|
||||
*/
|
||||
size_t approximateBytesUsed();
|
||||
|
||||
/**
|
||||
* Calling this invalidates the previous generation ID, and causes a new one to be computed
|
||||
* the next time getGenerationID() is called. Typically this is called by the object itself,
|
||||
* in response to its internal state changing.
|
||||
*/
|
||||
void notifyDrawingChanged();
|
||||
|
||||
static SkFlattenable::Type GetFlattenableType() {
|
||||
return kSkDrawable_Type;
|
||||
}
|
||||
|
||||
SkFlattenable::Type getFlattenableType() const override {
|
||||
return kSkDrawable_Type;
|
||||
}
|
||||
|
||||
static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr) {
|
||||
return sk_sp<SkDrawable>(static_cast<SkDrawable*>(
|
||||
SkFlattenable::Deserialize(
|
||||
kSkDrawable_Type, data, size, procs).release()));
|
||||
}
|
||||
|
||||
Factory getFactory() const override { return nullptr; }
|
||||
const char* getTypeName() const override { return nullptr; }
|
||||
|
||||
protected:
|
||||
SkDrawable();
|
||||
|
||||
virtual SkRect onGetBounds() = 0;
|
||||
virtual size_t onApproximateBytesUsed();
|
||||
virtual void onDraw(SkCanvas*) = 0;
|
||||
|
||||
virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&,
|
||||
const SkIRect& /*clipBounds*/,
|
||||
const SkImageInfo&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: Delete this once Android gets updated to take the clipBounds version above.
|
||||
virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
|
||||
* may override if they have a more efficient way to return a picture for the current state
|
||||
* of their drawable. Note: this picture must draw the same as what would be drawn from
|
||||
* onDraw().
|
||||
*/
|
||||
virtual sk_sp<SkPicture> onMakePictureSnapshot();
|
||||
|
||||
private:
|
||||
int32_t fGenerationID;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkExecutor_DEFINED
|
||||
#define SkExecutor_DEFINED
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
class SK_API SkExecutor {
|
||||
public:
|
||||
virtual ~SkExecutor();
|
||||
|
||||
// Create a thread pool SkExecutor with a fixed thread count, by default the number of cores.
|
||||
static std::unique_ptr<SkExecutor> MakeFIFOThreadPool(int threads = 0,
|
||||
bool allowBorrowing = true);
|
||||
static std::unique_ptr<SkExecutor> MakeLIFOThreadPool(int threads = 0,
|
||||
bool allowBorrowing = true);
|
||||
|
||||
// There is always a default SkExecutor available by calling SkExecutor::GetDefault().
|
||||
static SkExecutor& GetDefault();
|
||||
static void SetDefault(SkExecutor*); // Does not take ownership. Not thread safe.
|
||||
|
||||
// Add work to execute.
|
||||
virtual void add(std::function<void(void)>) = 0;
|
||||
|
||||
// If it makes sense for this executor, use this thread to execute work for a little while.
|
||||
virtual void borrow() {}
|
||||
|
||||
protected:
|
||||
SkExecutor() = default;
|
||||
SkExecutor(const SkExecutor&) = delete;
|
||||
SkExecutor& operator=(const SkExecutor&) = delete;
|
||||
};
|
||||
|
||||
#endif//SkExecutor_DEFINED
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 SkFlattenable_DEFINED
|
||||
#define SkFlattenable_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class SkData;
|
||||
class SkReadBuffer;
|
||||
class SkWriteBuffer;
|
||||
struct SkDeserialProcs;
|
||||
struct SkSerialProcs;
|
||||
|
||||
/** \class SkFlattenable
|
||||
|
||||
SkFlattenable is the base class for objects that need to be flattened
|
||||
into a data stream for either transport or as part of the key to the
|
||||
font cache.
|
||||
*/
|
||||
class SK_API SkFlattenable : public SkRefCnt {
|
||||
public:
|
||||
enum Type {
|
||||
kSkColorFilter_Type,
|
||||
kSkBlender_Type,
|
||||
kSkDrawable_Type,
|
||||
kSkDrawLooper_Type, // no longer supported by Skia
|
||||
kSkImageFilter_Type,
|
||||
kSkMaskFilter_Type,
|
||||
kSkPathEffect_Type,
|
||||
kSkShader_Type,
|
||||
};
|
||||
|
||||
typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);
|
||||
|
||||
SkFlattenable() {}
|
||||
|
||||
/** Implement this to return a factory function pointer that can be called
|
||||
to recreate your class given a buffer (previously written to by your
|
||||
override of flatten().
|
||||
*/
|
||||
virtual Factory getFactory() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the name of the object's class.
|
||||
*/
|
||||
virtual const char* getTypeName() const = 0;
|
||||
|
||||
static Factory NameToFactory(const char name[]);
|
||||
static const char* FactoryToName(Factory);
|
||||
|
||||
static void Register(const char name[], Factory);
|
||||
|
||||
/**
|
||||
* Override this if your subclass needs to record data that it will need to recreate itself
|
||||
* from its CreateProc (returned by getFactory()).
|
||||
*
|
||||
* DEPRECATED public : will move to protected ... use serialize() instead
|
||||
*/
|
||||
virtual void flatten(SkWriteBuffer&) const {}
|
||||
|
||||
virtual Type getFlattenableType() const = 0;
|
||||
|
||||
//
|
||||
// public ways to serialize / deserialize
|
||||
//
|
||||
sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;
|
||||
size_t serialize(void* memory, size_t memory_size,
|
||||
const SkSerialProcs* = nullptr) const;
|
||||
static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
protected:
|
||||
class PrivateInitializer {
|
||||
public:
|
||||
static void InitEffects();
|
||||
static void InitImageFilters();
|
||||
};
|
||||
|
||||
private:
|
||||
static void RegisterFlattenablesIfNeeded();
|
||||
static void Finalize();
|
||||
|
||||
friend class SkGraphics;
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#if defined(SK_DISABLE_EFFECT_DESERIALIZATION)
|
||||
#define SK_REGISTER_FLATTENABLE(type) do{}while(false)
|
||||
|
||||
#define SK_FLATTENABLE_HOOKS(type) \
|
||||
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
|
||||
friend class SkFlattenable::PrivateInitializer; \
|
||||
Factory getFactory() const override { return nullptr; } \
|
||||
const char* getTypeName() const override { return #type; }
|
||||
#else
|
||||
#define SK_REGISTER_FLATTENABLE(type) \
|
||||
SkFlattenable::Register(#type, type::CreateProc)
|
||||
|
||||
#define SK_FLATTENABLE_HOOKS(type) \
|
||||
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&); \
|
||||
friend class SkFlattenable::PrivateInitializer; \
|
||||
Factory getFactory() const override { return type::CreateProc; } \
|
||||
const char* getTypeName() const override { return #type; }
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFont_DEFINED
|
||||
#define SkFont_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypeface.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
#include "include/private/base/SkTypeTraits.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
class SkMatrix;
|
||||
class SkPaint;
|
||||
class SkPath;
|
||||
enum class SkFontHinting;
|
||||
enum class SkTextEncoding;
|
||||
struct SkFontMetrics;
|
||||
struct SkPoint;
|
||||
|
||||
/** \class SkFont
|
||||
SkFont controls options applied when drawing and measuring text.
|
||||
*/
|
||||
class SK_API SkFont {
|
||||
public:
|
||||
/** Whether edge pixels draw opaque or with partial transparency.
|
||||
*/
|
||||
enum class Edging {
|
||||
kAlias, //!< no transparent pixels on glyph edges
|
||||
kAntiAlias, //!< may have transparent pixels on glyph edges
|
||||
kSubpixelAntiAlias, //!< glyph positioned in pixel using transparency
|
||||
};
|
||||
|
||||
/** Constructs SkFont with default values.
|
||||
|
||||
@return default initialized SkFont
|
||||
*/
|
||||
SkFont();
|
||||
|
||||
/** Constructs SkFont with default values with SkTypeface and size in points.
|
||||
|
||||
@param typeface font and style used to draw and measure text
|
||||
@param size typographic height of text
|
||||
@return initialized SkFont
|
||||
*/
|
||||
SkFont(sk_sp<SkTypeface> typeface, SkScalar size);
|
||||
|
||||
/** Constructs SkFont with default values with SkTypeface.
|
||||
|
||||
@param typeface font and style used to draw and measure text
|
||||
@return initialized SkFont
|
||||
*/
|
||||
explicit SkFont(sk_sp<SkTypeface> typeface);
|
||||
|
||||
|
||||
/** Constructs SkFont with default values with SkTypeface and size in points,
|
||||
horizontal scale, and horizontal skew. Horizontal scale emulates condensed
|
||||
and expanded fonts. Horizontal skew emulates oblique fonts.
|
||||
|
||||
@param typeface font and style used to draw and measure text
|
||||
@param size typographic height of text
|
||||
@param scaleX text horizontal scale
|
||||
@param skewX additional shear on x-axis relative to y-axis
|
||||
@return initialized SkFont
|
||||
*/
|
||||
SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
|
||||
|
||||
|
||||
/** Compares SkFont and font, and returns true if they are equivalent.
|
||||
May return false if SkTypeface has identical contents but different pointers.
|
||||
|
||||
@param font font to compare
|
||||
@return true if SkFont pair are equivalent
|
||||
*/
|
||||
bool operator==(const SkFont& font) const;
|
||||
|
||||
/** Compares SkFont and font, and returns true if they are not equivalent.
|
||||
May return true if SkTypeface has identical contents but different pointers.
|
||||
|
||||
@param font font to compare
|
||||
@return true if SkFont pair are not equivalent
|
||||
*/
|
||||
bool operator!=(const SkFont& font) const { return !(*this == font); }
|
||||
|
||||
/** If true, instructs the font manager to always hint glyphs.
|
||||
Returned value is only meaningful if platform uses FreeType as the font manager.
|
||||
|
||||
@return true if all glyphs are hinted
|
||||
*/
|
||||
bool isForceAutoHinting() const { return SkToBool(fFlags & kForceAutoHinting_PrivFlag); }
|
||||
|
||||
/** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
|
||||
|
||||
@return true if glyphs may be font bitmaps
|
||||
*/
|
||||
bool isEmbeddedBitmaps() const { return SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag); }
|
||||
|
||||
/** Returns true if glyphs may be drawn at sub-pixel offsets.
|
||||
|
||||
@return true if glyphs may be drawn at sub-pixel offsets.
|
||||
*/
|
||||
bool isSubpixel() const { return SkToBool(fFlags & kSubpixel_PrivFlag); }
|
||||
|
||||
/** Returns true if font and glyph metrics are requested to be linearly scalable.
|
||||
|
||||
@return true if font and glyph metrics are requested to be linearly scalable.
|
||||
*/
|
||||
bool isLinearMetrics() const { return SkToBool(fFlags & kLinearMetrics_PrivFlag); }
|
||||
|
||||
/** Returns true if bold is approximated by increasing the stroke width when creating glyph
|
||||
bitmaps from outlines.
|
||||
|
||||
@return bold is approximated through stroke width
|
||||
*/
|
||||
bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
|
||||
|
||||
/** Returns true if baselines will be snapped to pixel positions when the current transformation
|
||||
matrix is axis aligned.
|
||||
|
||||
@return baselines may be snapped to pixels
|
||||
*/
|
||||
bool isBaselineSnap() const { return SkToBool(fFlags & kBaselineSnap_PrivFlag); }
|
||||
|
||||
/** Sets whether to always hint glyphs.
|
||||
If forceAutoHinting is set, instructs the font manager to always hint glyphs.
|
||||
|
||||
Only affects platforms that use FreeType as the font manager.
|
||||
|
||||
@param forceAutoHinting setting to always hint glyphs
|
||||
*/
|
||||
void setForceAutoHinting(bool forceAutoHinting);
|
||||
|
||||
/** Requests, but does not require, to use bitmaps in fonts instead of outlines.
|
||||
|
||||
@param embeddedBitmaps setting to use bitmaps in fonts
|
||||
*/
|
||||
void setEmbeddedBitmaps(bool embeddedBitmaps);
|
||||
|
||||
/** Requests, but does not require, that glyphs respect sub-pixel positioning.
|
||||
|
||||
@param subpixel setting for sub-pixel positioning
|
||||
*/
|
||||
void setSubpixel(bool subpixel);
|
||||
|
||||
/** Requests, but does not require, linearly scalable font and glyph metrics.
|
||||
|
||||
For outline fonts 'true' means font and glyph metrics should ignore hinting and rounding.
|
||||
Note that some bitmap formats may not be able to scale linearly and will ignore this flag.
|
||||
|
||||
@param linearMetrics setting for linearly scalable font and glyph metrics.
|
||||
*/
|
||||
void setLinearMetrics(bool linearMetrics);
|
||||
|
||||
/** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
|
||||
|
||||
@param embolden setting for bold approximation
|
||||
*/
|
||||
void setEmbolden(bool embolden);
|
||||
|
||||
/** Requests that baselines be snapped to pixels when the current transformation matrix is axis
|
||||
aligned.
|
||||
|
||||
@param baselineSnap setting for baseline snapping to pixels
|
||||
*/
|
||||
void setBaselineSnap(bool baselineSnap);
|
||||
|
||||
/** Whether edge pixels draw opaque or with partial transparency.
|
||||
*/
|
||||
Edging getEdging() const { return (Edging)fEdging; }
|
||||
|
||||
/** Requests, but does not require, that edge pixels draw opaque or with
|
||||
partial transparency.
|
||||
*/
|
||||
void setEdging(Edging edging);
|
||||
|
||||
/** Sets level of glyph outline adjustment.
|
||||
Does not check for valid values of hintingLevel.
|
||||
*/
|
||||
void setHinting(SkFontHinting hintingLevel);
|
||||
|
||||
/** Returns level of glyph outline adjustment.
|
||||
*/
|
||||
SkFontHinting getHinting() const { return (SkFontHinting)fHinting; }
|
||||
|
||||
/** Returns a font with the same attributes of this font, but with the specified size.
|
||||
Returns nullptr if size is less than zero, infinite, or NaN.
|
||||
|
||||
@param size typographic height of text
|
||||
@return initialized SkFont
|
||||
*/
|
||||
SkFont makeWithSize(SkScalar size) const;
|
||||
|
||||
/** Does not alter SkTypeface SkRefCnt.
|
||||
|
||||
@return non-null SkTypeface
|
||||
*/
|
||||
SkTypeface* getTypeface() const {
|
||||
SkASSERT(fTypeface);
|
||||
return fTypeface.get();
|
||||
}
|
||||
|
||||
/** Returns text size in points.
|
||||
|
||||
@return typographic height of text
|
||||
*/
|
||||
SkScalar getSize() const { return fSize; }
|
||||
|
||||
/** Returns text scale on x-axis.
|
||||
Default value is 1.
|
||||
|
||||
@return text horizontal scale
|
||||
*/
|
||||
SkScalar getScaleX() const { return fScaleX; }
|
||||
|
||||
/** Returns text skew on x-axis.
|
||||
Default value is zero.
|
||||
|
||||
@return additional shear on x-axis relative to y-axis
|
||||
*/
|
||||
SkScalar getSkewX() const { return fSkewX; }
|
||||
|
||||
/** Increases SkTypeface SkRefCnt by one.
|
||||
|
||||
@return A non-null SkTypeface.
|
||||
*/
|
||||
sk_sp<SkTypeface> refTypeface() const {
|
||||
SkASSERT(fTypeface);
|
||||
return fTypeface;
|
||||
}
|
||||
|
||||
/** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
|
||||
Pass nullptr to clear SkTypeface and use an empty typeface (which draws nothing).
|
||||
Increments tf SkRefCnt by one.
|
||||
|
||||
@param tf font and style used to draw text
|
||||
*/
|
||||
void setTypeface(sk_sp<SkTypeface> tf);
|
||||
|
||||
/** Sets text size in points.
|
||||
Has no effect if textSize is not greater than or equal to zero.
|
||||
|
||||
@param textSize typographic height of text
|
||||
*/
|
||||
void setSize(SkScalar textSize);
|
||||
|
||||
/** Sets text scale on x-axis.
|
||||
Default value is 1.
|
||||
|
||||
@param scaleX text horizontal scale
|
||||
*/
|
||||
void setScaleX(SkScalar scaleX);
|
||||
|
||||
/** Sets text skew on x-axis.
|
||||
Default value is zero.
|
||||
|
||||
@param skewX additional shear on x-axis relative to y-axis
|
||||
*/
|
||||
void setSkewX(SkScalar skewX);
|
||||
|
||||
/** Converts text into glyph indices.
|
||||
Returns the number of glyph indices represented by text.
|
||||
SkTextEncoding specifies how text represents characters or glyphs.
|
||||
glyphs may be nullptr, to compute the glyph count.
|
||||
|
||||
Does not check text for valid character codes or valid glyph indices.
|
||||
|
||||
If byteLength equals zero, returns zero.
|
||||
If byteLength includes a partial character, the partial character is ignored.
|
||||
|
||||
If encoding is SkTextEncoding::kUTF8 and text contains an invalid UTF-8 sequence,
|
||||
zero is returned.
|
||||
|
||||
When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
|
||||
SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
|
||||
single glyph. This function uses the default character-to-glyph
|
||||
mapping from the SkTypeface and maps characters not found in the
|
||||
SkTypeface to zero.
|
||||
|
||||
If maxGlyphCount is not sufficient to store all the glyphs, no glyphs are copied.
|
||||
The total glyph count is returned for subsequent buffer reallocation.
|
||||
|
||||
@param text character storage encoded with SkTextEncoding
|
||||
@param byteLength length of character storage in bytes
|
||||
@param glyphs storage for glyph indices; may be nullptr
|
||||
@param maxGlyphCount storage capacity
|
||||
@return number of glyphs represented by text of length byteLength
|
||||
*/
|
||||
int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
|
||||
SkGlyphID glyphs[], int maxGlyphCount) const;
|
||||
|
||||
/** Returns glyph index for Unicode character.
|
||||
|
||||
If the character is not supported by the SkTypeface, returns 0.
|
||||
|
||||
@param uni Unicode character
|
||||
@return glyph index
|
||||
*/
|
||||
SkGlyphID unicharToGlyph(SkUnichar uni) const;
|
||||
|
||||
void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const;
|
||||
|
||||
/** Returns number of glyphs represented by text.
|
||||
|
||||
If encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
|
||||
SkTextEncoding::kUTF32; then each Unicode codepoint is mapped to a
|
||||
single glyph.
|
||||
|
||||
@param text character storage encoded with SkTextEncoding
|
||||
@param byteLength length of character storage in bytes
|
||||
@return number of glyphs represented by text of length byteLength
|
||||
*/
|
||||
int countText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
|
||||
return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
|
||||
}
|
||||
|
||||
/** Returns the advance width of text.
|
||||
The advance is the normal distance to move before drawing additional text.
|
||||
Returns the bounding box of text if bounds is not nullptr.
|
||||
|
||||
@param text character storage encoded with SkTextEncoding
|
||||
@param byteLength length of character storage in bytes
|
||||
@param bounds returns bounding box relative to (0, 0) if not nullptr
|
||||
@return the sum of the default advance widths
|
||||
*/
|
||||
SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
|
||||
SkRect* bounds = nullptr) const {
|
||||
return this->measureText(text, byteLength, encoding, bounds, nullptr);
|
||||
}
|
||||
|
||||
/** Returns the advance width of text.
|
||||
The advance is the normal distance to move before drawing additional text.
|
||||
Returns the bounding box of text if bounds is not nullptr. The paint
|
||||
stroke settings, mask filter, or path effect may modify the bounds.
|
||||
|
||||
@param text character storage encoded with SkTextEncoding
|
||||
@param byteLength length of character storage in bytes
|
||||
@param bounds returns bounding box relative to (0, 0) if not nullptr
|
||||
@param paint optional; may be nullptr
|
||||
@return the sum of the default advance widths
|
||||
*/
|
||||
SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
|
||||
SkRect* bounds, const SkPaint* paint) const;
|
||||
|
||||
/** DEPRECATED
|
||||
Retrieves the advance and bounds for each glyph in glyphs.
|
||||
Both widths and bounds may be nullptr.
|
||||
If widths is not nullptr, widths must be an array of count entries.
|
||||
if bounds is not nullptr, bounds must be an array of count entries.
|
||||
|
||||
@param glyphs array of glyph indices to be measured
|
||||
@param count number of glyphs
|
||||
@param widths returns text advances for each glyph; may be nullptr
|
||||
@param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
|
||||
*/
|
||||
void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[]) const {
|
||||
this->getWidthsBounds(glyphs, count, widths, bounds, nullptr);
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[], std::nullptr_t) const {
|
||||
this->getWidths(glyphs, count, widths);
|
||||
}
|
||||
|
||||
/** Retrieves the advance and bounds for each glyph in glyphs.
|
||||
Both widths and bounds may be nullptr.
|
||||
If widths is not nullptr, widths must be an array of count entries.
|
||||
if bounds is not nullptr, bounds must be an array of count entries.
|
||||
|
||||
@param glyphs array of glyph indices to be measured
|
||||
@param count number of glyphs
|
||||
@param widths returns text advances for each glyph
|
||||
*/
|
||||
void getWidths(const SkGlyphID glyphs[], int count, SkScalar widths[]) const {
|
||||
this->getWidthsBounds(glyphs, count, widths, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/** Retrieves the advance and bounds for each glyph in glyphs.
|
||||
Both widths and bounds may be nullptr.
|
||||
If widths is not nullptr, widths must be an array of count entries.
|
||||
if bounds is not nullptr, bounds must be an array of count entries.
|
||||
|
||||
@param glyphs array of glyph indices to be measured
|
||||
@param count number of glyphs
|
||||
@param widths returns text advances for each glyph; may be nullptr
|
||||
@param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
|
||||
@param paint optional, specifies stroking, SkPathEffect and SkMaskFilter
|
||||
*/
|
||||
void getWidthsBounds(const SkGlyphID glyphs[], int count, SkScalar widths[], SkRect bounds[],
|
||||
const SkPaint* paint) const;
|
||||
|
||||
|
||||
/** Retrieves the bounds for each glyph in glyphs.
|
||||
bounds must be an array of count entries.
|
||||
If paint is not nullptr, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
|
||||
|
||||
@param glyphs array of glyph indices to be measured
|
||||
@param count number of glyphs
|
||||
@param bounds returns bounds for each glyph relative to (0, 0); may be nullptr
|
||||
@param paint optional, specifies stroking, SkPathEffect, and SkMaskFilter
|
||||
*/
|
||||
void getBounds(const SkGlyphID glyphs[], int count, SkRect bounds[],
|
||||
const SkPaint* paint) const {
|
||||
this->getWidthsBounds(glyphs, count, nullptr, bounds, paint);
|
||||
}
|
||||
|
||||
/** Retrieves the positions for each glyph, beginning at the specified origin. The caller
|
||||
must allocated at least count number of elements in the pos[] array.
|
||||
|
||||
@param glyphs array of glyph indices to be positioned
|
||||
@param count number of glyphs
|
||||
@param pos returns glyphs positions
|
||||
@param origin location of the first glyph. Defaults to {0, 0}.
|
||||
*/
|
||||
void getPos(const SkGlyphID glyphs[], int count, SkPoint pos[], SkPoint origin = {0, 0}) const;
|
||||
|
||||
/** Retrieves the x-positions for each glyph, beginning at the specified origin. The caller
|
||||
must allocated at least count number of elements in the xpos[] array.
|
||||
|
||||
@param glyphs array of glyph indices to be positioned
|
||||
@param count number of glyphs
|
||||
@param xpos returns glyphs x-positions
|
||||
@param origin x-position of the first glyph. Defaults to 0.
|
||||
*/
|
||||
void getXPos(const SkGlyphID glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
|
||||
|
||||
/** Returns intervals [start, end] describing lines parallel to the advance that intersect
|
||||
* with the glyphs.
|
||||
*
|
||||
* @param glyphs the glyphs to intersect
|
||||
* @param count the number of glyphs and positions
|
||||
* @param pos the position of each glyph
|
||||
* @param top the top of the line intersecting
|
||||
* @param bottom the bottom of the line intersecting
|
||||
@return array of pairs of x values [start, end]. May be empty.
|
||||
*/
|
||||
std::vector<SkScalar> getIntercepts(const SkGlyphID glyphs[], int count, const SkPoint pos[],
|
||||
SkScalar top, SkScalar bottom,
|
||||
const SkPaint* = nullptr) const;
|
||||
|
||||
/** Modifies path to be the outline of the glyph.
|
||||
If the glyph has an outline, modifies path to be the glyph's outline and returns true.
|
||||
The glyph outline may be empty. Degenerate contours in the glyph outline will be skipped.
|
||||
If glyph is described by a bitmap, returns false and ignores path parameter.
|
||||
|
||||
@param glyphID index of glyph
|
||||
@param path pointer to existing SkPath
|
||||
@return true if glyphID is described by path
|
||||
*/
|
||||
bool getPath(SkGlyphID glyphID, SkPath* path) const;
|
||||
|
||||
/** Returns path corresponding to glyph array.
|
||||
|
||||
@param glyphIDs array of glyph indices
|
||||
@param count number of glyphs
|
||||
@param glyphPathProc function returning one glyph description as path
|
||||
@param ctx function context
|
||||
*/
|
||||
void getPaths(const SkGlyphID glyphIDs[], int count,
|
||||
void (*glyphPathProc)(const SkPath* pathOrNull, const SkMatrix& mx, void* ctx),
|
||||
void* ctx) const;
|
||||
|
||||
/** Returns SkFontMetrics associated with SkTypeface.
|
||||
The return value is the recommended spacing between lines: the sum of metrics
|
||||
descent, ascent, and leading.
|
||||
If metrics is not nullptr, SkFontMetrics is copied to metrics.
|
||||
Results are scaled by text size but does not take into account
|
||||
dimensions required by text scale, text skew, fake bold,
|
||||
style stroke, and SkPathEffect.
|
||||
|
||||
@param metrics storage for SkFontMetrics; may be nullptr
|
||||
@return recommended spacing between lines
|
||||
*/
|
||||
SkScalar getMetrics(SkFontMetrics* metrics) const;
|
||||
|
||||
/** Returns the recommended spacing between lines: the sum of metrics
|
||||
descent, ascent, and leading.
|
||||
Result is scaled by text size but does not take into account
|
||||
dimensions required by stroking and SkPathEffect.
|
||||
Returns the same result as getMetrics().
|
||||
|
||||
@return recommended spacing between lines
|
||||
*/
|
||||
SkScalar getSpacing() const { return this->getMetrics(nullptr); }
|
||||
|
||||
/** Dumps fields of the font to SkDebugf. May change its output over time, so clients should
|
||||
* not rely on this for anything specific. Used to aid in debugging.
|
||||
*/
|
||||
void dump() const;
|
||||
|
||||
using sk_is_trivially_relocatable = std::true_type;
|
||||
|
||||
private:
|
||||
enum PrivFlags {
|
||||
kForceAutoHinting_PrivFlag = 1 << 0,
|
||||
kEmbeddedBitmaps_PrivFlag = 1 << 1,
|
||||
kSubpixel_PrivFlag = 1 << 2,
|
||||
kLinearMetrics_PrivFlag = 1 << 3,
|
||||
kEmbolden_PrivFlag = 1 << 4,
|
||||
kBaselineSnap_PrivFlag = 1 << 5,
|
||||
};
|
||||
|
||||
static constexpr unsigned kAllFlags = kForceAutoHinting_PrivFlag
|
||||
| kEmbeddedBitmaps_PrivFlag
|
||||
| kSubpixel_PrivFlag
|
||||
| kLinearMetrics_PrivFlag
|
||||
| kEmbolden_PrivFlag
|
||||
| kBaselineSnap_PrivFlag;
|
||||
|
||||
sk_sp<SkTypeface> fTypeface;
|
||||
SkScalar fSize;
|
||||
SkScalar fScaleX;
|
||||
SkScalar fSkewX;
|
||||
uint8_t fFlags;
|
||||
uint8_t fEdging;
|
||||
uint8_t fHinting;
|
||||
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fTypeface)>::value);
|
||||
|
||||
SkScalar setupForAsPaths(SkPaint*);
|
||||
bool hasSomeAntiAliasing() const;
|
||||
|
||||
friend class SkFontPriv;
|
||||
friend class SkGlyphRunListPainterCPU;
|
||||
friend class SkStrikeSpec;
|
||||
friend class SkRemoteGlyphCacheTest;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontArguments_DEFINED
|
||||
#define SkFontArguments_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/** Represents a set of actual arguments for a font. */
|
||||
struct SkFontArguments {
|
||||
struct VariationPosition {
|
||||
struct Coordinate {
|
||||
SkFourByteTag axis;
|
||||
float value;
|
||||
};
|
||||
const Coordinate* coordinates;
|
||||
int coordinateCount;
|
||||
};
|
||||
|
||||
/** Specify a palette to use and overrides for palette entries.
|
||||
*
|
||||
* `overrides` is a list of pairs of palette entry index and color.
|
||||
* The overriden palette entries will use the associated color.
|
||||
* Override pairs with palette entry indices out of range will not be applied.
|
||||
* Later override entries override earlier ones.
|
||||
*/
|
||||
struct Palette {
|
||||
struct Override {
|
||||
uint16_t index;
|
||||
SkColor color;
|
||||
};
|
||||
int index;
|
||||
const Override* overrides;
|
||||
int overrideCount;
|
||||
};
|
||||
|
||||
SkFontArguments()
|
||||
: fCollectionIndex(0)
|
||||
, fVariationDesignPosition{nullptr, 0}
|
||||
, fPalette{0, nullptr, 0} {}
|
||||
|
||||
/** Specify the index of the desired font.
|
||||
*
|
||||
* Font formats like ttc, dfont, cff, cid, pfr, t42, t1, and fon may actually be indexed
|
||||
* collections of fonts.
|
||||
*/
|
||||
SkFontArguments& setCollectionIndex(int collectionIndex) {
|
||||
fCollectionIndex = collectionIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Specify a position in the variation design space.
|
||||
*
|
||||
* Any axis not specified will use the default value.
|
||||
* Any specified axis not actually present in the font will be ignored.
|
||||
*
|
||||
* @param position not copied. The value must remain valid for life of SkFontArguments.
|
||||
*/
|
||||
SkFontArguments& setVariationDesignPosition(VariationPosition position) {
|
||||
fVariationDesignPosition.coordinates = position.coordinates;
|
||||
fVariationDesignPosition.coordinateCount = position.coordinateCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int getCollectionIndex() const {
|
||||
return fCollectionIndex;
|
||||
}
|
||||
|
||||
VariationPosition getVariationDesignPosition() const {
|
||||
return fVariationDesignPosition;
|
||||
}
|
||||
|
||||
SkFontArguments& setPalette(Palette palette) {
|
||||
fPalette.index = palette.index;
|
||||
fPalette.overrides = palette.overrides;
|
||||
fPalette.overrideCount = palette.overrideCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Palette getPalette() const { return fPalette; }
|
||||
|
||||
private:
|
||||
int fCollectionIndex;
|
||||
VariationPosition fVariationDesignPosition;
|
||||
Palette fPalette;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontMetrics_DEFINED
|
||||
#define SkFontMetrics_DEFINED
|
||||
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
/** \class SkFontMetrics
|
||||
The metrics of an SkFont.
|
||||
The metric values are consistent with the Skia y-down coordinate system.
|
||||
*/
|
||||
struct SK_API SkFontMetrics {
|
||||
bool operator==(const SkFontMetrics& that) const {
|
||||
return
|
||||
this->fFlags == that.fFlags &&
|
||||
this->fTop == that.fTop &&
|
||||
this->fAscent == that.fAscent &&
|
||||
this->fDescent == that.fDescent &&
|
||||
this->fBottom == that.fBottom &&
|
||||
this->fLeading == that.fLeading &&
|
||||
this->fAvgCharWidth == that.fAvgCharWidth &&
|
||||
this->fMaxCharWidth == that.fMaxCharWidth &&
|
||||
this->fXMin == that.fXMin &&
|
||||
this->fXMax == that.fXMax &&
|
||||
this->fXHeight == that.fXHeight &&
|
||||
this->fCapHeight == that.fCapHeight &&
|
||||
this->fUnderlineThickness == that.fUnderlineThickness &&
|
||||
this->fUnderlinePosition == that.fUnderlinePosition &&
|
||||
this->fStrikeoutThickness == that.fStrikeoutThickness &&
|
||||
this->fStrikeoutPosition == that.fStrikeoutPosition;
|
||||
}
|
||||
|
||||
/** \enum FontMetricsFlags
|
||||
FontMetricsFlags indicate when certain metrics are valid;
|
||||
the underline or strikeout metrics may be valid and zero.
|
||||
Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
|
||||
*/
|
||||
enum FontMetricsFlags {
|
||||
kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
|
||||
kUnderlinePositionIsValid_Flag = 1 << 1, //!< set if fUnderlinePosition is valid
|
||||
kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
|
||||
kStrikeoutPositionIsValid_Flag = 1 << 3, //!< set if fStrikeoutPosition is valid
|
||||
kBoundsInvalid_Flag = 1 << 4, //!< set if fTop, fBottom, fXMin, fXMax invalid
|
||||
};
|
||||
|
||||
uint32_t fFlags; //!< FontMetricsFlags indicating which metrics are valid
|
||||
SkScalar fTop; //!< greatest extent above origin of any glyph bounding box, typically negative; deprecated with variable fonts
|
||||
SkScalar fAscent; //!< distance to reserve above baseline, typically negative
|
||||
SkScalar fDescent; //!< distance to reserve below baseline, typically positive
|
||||
SkScalar fBottom; //!< greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable fonts
|
||||
SkScalar fLeading; //!< distance to add between lines, typically positive or zero
|
||||
SkScalar fAvgCharWidth; //!< average character width, zero if unknown
|
||||
SkScalar fMaxCharWidth; //!< maximum character width, zero if unknown
|
||||
SkScalar fXMin; //!< greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with variable fonts
|
||||
SkScalar fXMax; //!< greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with variable fonts
|
||||
SkScalar fXHeight; //!< height of lower-case 'x', zero if unknown, typically negative
|
||||
SkScalar fCapHeight; //!< height of an upper-case letter, zero if unknown, typically negative
|
||||
SkScalar fUnderlineThickness; //!< underline thickness
|
||||
SkScalar fUnderlinePosition; //!< distance from baseline to top of stroke, typically positive
|
||||
SkScalar fStrikeoutThickness; //!< strikeout thickness
|
||||
SkScalar fStrikeoutPosition; //!< distance from baseline to bottom of stroke, typically negative
|
||||
|
||||
/** Returns true if SkFontMetrics has a valid underline thickness, and sets
|
||||
thickness to that value. If the underline thickness is not valid,
|
||||
return false, and ignore thickness.
|
||||
|
||||
@param thickness storage for underline width
|
||||
@return true if font specifies underline width
|
||||
*/
|
||||
bool hasUnderlineThickness(SkScalar* thickness) const {
|
||||
if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
|
||||
*thickness = fUnderlineThickness;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if SkFontMetrics has a valid underline position, and sets
|
||||
position to that value. If the underline position is not valid,
|
||||
return false, and ignore position.
|
||||
|
||||
@param position storage for underline position
|
||||
@return true if font specifies underline position
|
||||
*/
|
||||
bool hasUnderlinePosition(SkScalar* position) const {
|
||||
if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
|
||||
*position = fUnderlinePosition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if SkFontMetrics has a valid strikeout thickness, and sets
|
||||
thickness to that value. If the underline thickness is not valid,
|
||||
return false, and ignore thickness.
|
||||
|
||||
@param thickness storage for strikeout width
|
||||
@return true if font specifies strikeout width
|
||||
*/
|
||||
bool hasStrikeoutThickness(SkScalar* thickness) const {
|
||||
if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
|
||||
*thickness = fStrikeoutThickness;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if SkFontMetrics has a valid strikeout position, and sets
|
||||
position to that value. If the underline position is not valid,
|
||||
return false, and ignore position.
|
||||
|
||||
@param position storage for strikeout position
|
||||
@return true if font specifies strikeout position
|
||||
*/
|
||||
bool hasStrikeoutPosition(SkScalar* position) const {
|
||||
if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
|
||||
*position = fStrikeoutPosition;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if SkFontMetrics has a valid fTop, fBottom, fXMin, and fXMax.
|
||||
If the bounds are not valid, return false.
|
||||
|
||||
@return true if font specifies maximum glyph bounds
|
||||
*/
|
||||
bool hasBounds() const {
|
||||
return !SkToBool(fFlags & kBoundsInvalid_Flag);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontMgr_DEFINED
|
||||
#define SkFontMgr_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class SkData;
|
||||
class SkFontStyle;
|
||||
class SkStreamAsset;
|
||||
class SkString;
|
||||
class SkTypeface;
|
||||
struct SkFontArguments;
|
||||
|
||||
class SK_API SkFontStyleSet : public SkRefCnt {
|
||||
public:
|
||||
virtual int count() = 0;
|
||||
virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
|
||||
virtual sk_sp<SkTypeface> createTypeface(int index) = 0;
|
||||
virtual sk_sp<SkTypeface> matchStyle(const SkFontStyle& pattern) = 0;
|
||||
|
||||
static sk_sp<SkFontStyleSet> CreateEmpty();
|
||||
|
||||
protected:
|
||||
sk_sp<SkTypeface> matchStyleCSS3(const SkFontStyle& pattern);
|
||||
};
|
||||
|
||||
class SK_API SkFontMgr : public SkRefCnt {
|
||||
public:
|
||||
int countFamilies() const;
|
||||
void getFamilyName(int index, SkString* familyName) const;
|
||||
sk_sp<SkFontStyleSet> createStyleSet(int index) const;
|
||||
|
||||
/**
|
||||
* The caller must call unref() on the returned object.
|
||||
* Never returns NULL; will return an empty set if the name is not found.
|
||||
*
|
||||
* Passing nullptr as the parameter will return the default system family.
|
||||
* Note that most systems don't have a default system family, so passing nullptr will often
|
||||
* result in the empty set.
|
||||
*
|
||||
* It is possible that this will return a style set not accessible from
|
||||
* createStyleSet(int) due to hidden or auto-activated fonts.
|
||||
*/
|
||||
sk_sp<SkFontStyleSet> matchFamily(const char familyName[]) const;
|
||||
|
||||
/**
|
||||
* Find the closest matching typeface to the specified familyName and style
|
||||
* and return a ref to it. The caller must call unref() on the returned
|
||||
* object. Will return nullptr if no 'good' match is found.
|
||||
*
|
||||
* Passing |nullptr| as the parameter for |familyName| will return the
|
||||
* default system font.
|
||||
*
|
||||
* It is possible that this will return a style set not accessible from
|
||||
* createStyleSet(int) or matchFamily(const char[]) due to hidden or
|
||||
* auto-activated fonts.
|
||||
*/
|
||||
sk_sp<SkTypeface> matchFamilyStyle(const char familyName[], const SkFontStyle&) const;
|
||||
|
||||
/**
|
||||
* Use the system fallback to find a typeface for the given character.
|
||||
* Note that bcp47 is a combination of ISO 639, 15924, and 3166-1 codes,
|
||||
* so it is fine to just pass a ISO 639 here.
|
||||
*
|
||||
* Will return NULL if no family can be found for the character
|
||||
* in the system fallback.
|
||||
*
|
||||
* Passing |nullptr| as the parameter for |familyName| will return the
|
||||
* default system font.
|
||||
*
|
||||
* bcp47[0] is the least significant fallback, bcp47[bcp47Count-1] is the
|
||||
* most significant. If no specified bcp47 codes match, any font with the
|
||||
* requested character will be matched.
|
||||
*/
|
||||
sk_sp<SkTypeface> matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
|
||||
const char* bcp47[], int bcp47Count,
|
||||
SkUnichar character) const;
|
||||
|
||||
/**
|
||||
* Create a typeface for the specified data and TTC index (pass 0 for none)
|
||||
* or NULL if the data is not recognized. The caller must call unref() on
|
||||
* the returned object if it is not null.
|
||||
*/
|
||||
sk_sp<SkTypeface> makeFromData(sk_sp<SkData>, int ttcIndex = 0) const;
|
||||
|
||||
/**
|
||||
* Create a typeface for the specified stream and TTC index
|
||||
* (pass 0 for none) or NULL if the stream is not recognized. The caller
|
||||
* must call unref() on the returned object if it is not null.
|
||||
*/
|
||||
sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, int ttcIndex = 0) const;
|
||||
|
||||
/* Experimental, API subject to change. */
|
||||
sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const;
|
||||
|
||||
/**
|
||||
* Create a typeface for the specified fileName and TTC index
|
||||
* (pass 0 for none) or NULL if the file is not found, or its contents are
|
||||
* not recognized. The caller must call unref() on the returned object
|
||||
* if it is not null.
|
||||
*/
|
||||
sk_sp<SkTypeface> makeFromFile(const char path[], int ttcIndex = 0) const;
|
||||
|
||||
sk_sp<SkTypeface> legacyMakeTypeface(const char familyName[], SkFontStyle style) const;
|
||||
|
||||
/* Returns an empty font manager without any typeface dependencies */
|
||||
static sk_sp<SkFontMgr> RefEmpty();
|
||||
|
||||
protected:
|
||||
virtual int onCountFamilies() const = 0;
|
||||
virtual void onGetFamilyName(int index, SkString* familyName) const = 0;
|
||||
virtual sk_sp<SkFontStyleSet> onCreateStyleSet(int index)const = 0;
|
||||
|
||||
/** May return NULL if the name is not found. */
|
||||
virtual sk_sp<SkFontStyleSet> onMatchFamily(const char familyName[]) const = 0;
|
||||
|
||||
virtual sk_sp<SkTypeface> onMatchFamilyStyle(const char familyName[],
|
||||
const SkFontStyle&) const = 0;
|
||||
virtual sk_sp<SkTypeface> onMatchFamilyStyleCharacter(const char familyName[],
|
||||
const SkFontStyle&,
|
||||
const char* bcp47[], int bcp47Count,
|
||||
SkUnichar character) const = 0;
|
||||
|
||||
virtual sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const = 0;
|
||||
virtual sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
|
||||
int ttcIndex) const = 0;
|
||||
virtual sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
|
||||
const SkFontArguments&) const = 0;
|
||||
virtual sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const = 0;
|
||||
|
||||
virtual sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontParameters_DEFINED
|
||||
#define SkFontParameters_DEFINED
|
||||
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
struct SkFontParameters {
|
||||
struct Variation {
|
||||
// Parameters in a variation font axis.
|
||||
struct Axis {
|
||||
constexpr Axis() : tag(0), min(0), def(0), max(0), flags(0) {}
|
||||
constexpr Axis(SkFourByteTag tag, float min, float def, float max, bool hidden) :
|
||||
tag(tag), min(min), def(def), max(max), flags(hidden ? HIDDEN : 0) {}
|
||||
|
||||
// Four character identifier of the font axis (weight, width, slant, italic...).
|
||||
SkFourByteTag tag;
|
||||
// Minimum value supported by this axis.
|
||||
float min;
|
||||
// Default value set by this axis.
|
||||
float def;
|
||||
// Maximum value supported by this axis. The maximum can equal the minimum.
|
||||
float max;
|
||||
// Return whether this axis is recommended to be remain hidden in user interfaces.
|
||||
bool isHidden() const { return flags & HIDDEN; }
|
||||
// Set this axis to be remain hidden in user interfaces.
|
||||
void setHidden(bool hidden) { flags = hidden ? (flags | HIDDEN) : (flags & ~HIDDEN); }
|
||||
private:
|
||||
static constexpr uint16_t HIDDEN = 0x0001;
|
||||
// Attributes for a font axis.
|
||||
uint16_t flags;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontStyle_DEFINED
|
||||
#define SkFontStyle_DEFINED
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkTPin.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class SK_API SkFontStyle {
|
||||
public:
|
||||
enum Weight {
|
||||
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 {
|
||||
kUltraCondensed_Width = 1,
|
||||
kExtraCondensed_Width = 2,
|
||||
kCondensed_Width = 3,
|
||||
kSemiCondensed_Width = 4,
|
||||
kNormal_Width = 5,
|
||||
kSemiExpanded_Width = 6,
|
||||
kExpanded_Width = 7,
|
||||
kExtraExpanded_Width = 8,
|
||||
kUltraExpanded_Width = 9,
|
||||
};
|
||||
|
||||
enum Slant {
|
||||
kUpright_Slant,
|
||||
kItalic_Slant,
|
||||
kOblique_Slant,
|
||||
};
|
||||
|
||||
constexpr SkFontStyle(int weight, int width, Slant slant) : fValue(
|
||||
(SkTPin<int>(weight, kInvisible_Weight, kExtraBlack_Weight)) +
|
||||
(SkTPin<int>(width, kUltraCondensed_Width, kUltraExpanded_Width) << 16) +
|
||||
(SkTPin<int>(slant, kUpright_Slant, kOblique_Slant) << 24)
|
||||
) { }
|
||||
|
||||
constexpr SkFontStyle() : SkFontStyle{kNormal_Weight, kNormal_Width, kUpright_Slant} { }
|
||||
|
||||
bool operator==(const SkFontStyle& rhs) const {
|
||||
return fValue == rhs.fValue;
|
||||
}
|
||||
|
||||
int weight() const { return fValue & 0xFFFF; }
|
||||
int width() const { return (fValue >> 16) & 0xFF; }
|
||||
Slant slant() const { return (Slant)((fValue >> 24) & 0xFF); }
|
||||
|
||||
static constexpr SkFontStyle Normal() {
|
||||
return SkFontStyle(kNormal_Weight, kNormal_Width, kUpright_Slant);
|
||||
}
|
||||
static constexpr SkFontStyle Bold() {
|
||||
return SkFontStyle(kBold_Weight, kNormal_Width, kUpright_Slant);
|
||||
}
|
||||
static constexpr SkFontStyle Italic() {
|
||||
return SkFontStyle(kNormal_Weight, kNormal_Width, kItalic_Slant );
|
||||
}
|
||||
static constexpr SkFontStyle BoldItalic() {
|
||||
return SkFontStyle(kBold_Weight, kNormal_Width, kItalic_Slant );
|
||||
}
|
||||
|
||||
private:
|
||||
friend class SkTypefaceProxyPrototype; // To serialize fValue
|
||||
int32_t fValue;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkFontTypes_DEFINED
|
||||
#define SkFontTypes_DEFINED
|
||||
|
||||
enum class SkTextEncoding {
|
||||
kUTF8, //!< uses bytes to represent UTF-8 or ASCII
|
||||
kUTF16, //!< uses two byte words to represent most of Unicode
|
||||
kUTF32, //!< uses four byte words to represent all of Unicode
|
||||
kGlyphID, //!< uses two byte words to represent glyph indices
|
||||
};
|
||||
|
||||
enum class SkFontHinting {
|
||||
kNone, //!< glyph outlines unchanged
|
||||
kSlight, //!< minimal modification to improve constrast
|
||||
kNormal, //!< glyph outlines modified to improve constrast
|
||||
kFull, //!< modifies glyph outlines for maximum constrast
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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 SkGraphics_DEFINED
|
||||
#define SkGraphics_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class SkData;
|
||||
class SkImageGenerator;
|
||||
class SkOpenTypeSVGDecoder;
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
class SK_API SkGraphics {
|
||||
public:
|
||||
/**
|
||||
* Call this at process initialization time if your environment does not
|
||||
* permit static global initializers that execute code.
|
||||
* Init() is thread-safe and idempotent.
|
||||
*/
|
||||
static void Init();
|
||||
|
||||
/**
|
||||
* Return the max number of bytes that should be used by the font cache.
|
||||
* If the cache needs to allocate more, it will purge previous entries.
|
||||
* This max can be changed by calling SetFontCacheLimit().
|
||||
*/
|
||||
static size_t GetFontCacheLimit();
|
||||
|
||||
/**
|
||||
* Specify the max number of bytes that should be used by the font cache.
|
||||
* If the cache needs to allocate more, it will purge previous entries.
|
||||
*
|
||||
* This function returns the previous setting, as if GetFontCacheLimit()
|
||||
* had be called before the new limit was set.
|
||||
*/
|
||||
static size_t SetFontCacheLimit(size_t bytes);
|
||||
|
||||
/**
|
||||
* Return the number of bytes currently used by the font cache.
|
||||
*/
|
||||
static size_t GetFontCacheUsed();
|
||||
|
||||
/**
|
||||
* Return the number of entries in the font cache.
|
||||
* A cache "entry" is associated with each typeface + pointSize + matrix.
|
||||
*/
|
||||
static int GetFontCacheCountUsed();
|
||||
|
||||
/**
|
||||
* Return the current limit to the number of entries in the font cache.
|
||||
* A cache "entry" is associated with each typeface + pointSize + matrix.
|
||||
*/
|
||||
static int GetFontCacheCountLimit();
|
||||
|
||||
/**
|
||||
* Set the limit to the number of entries in the font cache, and return
|
||||
* the previous value. If this new value is lower than the previous,
|
||||
* it will automatically try to purge entries to meet the new limit.
|
||||
*/
|
||||
static int SetFontCacheCountLimit(int count);
|
||||
|
||||
/**
|
||||
* Return the current limit to the number of entries in the typeface cache.
|
||||
* A cache "entry" is associated with each typeface.
|
||||
*/
|
||||
static int GetTypefaceCacheCountLimit();
|
||||
|
||||
/**
|
||||
* Set the limit to the number of entries in the typeface cache, and return
|
||||
* the previous value. Changes to this only take effect the next time
|
||||
* each cache object is modified.
|
||||
*/
|
||||
static int SetTypefaceCacheCountLimit(int count);
|
||||
|
||||
/**
|
||||
* For debugging purposes, this will attempt to purge the font cache. It
|
||||
* does not change the limit, but will cause subsequent font measures and
|
||||
* draws to be recreated, since they will no longer be in the cache.
|
||||
*/
|
||||
static void PurgeFontCache();
|
||||
|
||||
/**
|
||||
* If the strike cache is above the cache limit, attempt to purge strikes
|
||||
* with pinners. This should be called after clients release locks on
|
||||
* pinned strikes.
|
||||
*/
|
||||
static void PurgePinnedFontCache();
|
||||
|
||||
/**
|
||||
* This function returns the memory used for temporary images and other resources.
|
||||
*/
|
||||
static size_t GetResourceCacheTotalBytesUsed();
|
||||
|
||||
/**
|
||||
* These functions get/set the memory usage limit for the resource cache, used for temporary
|
||||
* bitmaps and other resources. Entries are purged from the cache when the memory useage
|
||||
* exceeds this limit.
|
||||
*/
|
||||
static size_t GetResourceCacheTotalByteLimit();
|
||||
static size_t SetResourceCacheTotalByteLimit(size_t newLimit);
|
||||
|
||||
/**
|
||||
* For debugging purposes, this will attempt to purge the resource cache. It
|
||||
* does not change the limit.
|
||||
*/
|
||||
static void PurgeResourceCache();
|
||||
|
||||
/**
|
||||
* When the cachable entry is very lage (e.g. a large scaled bitmap), adding it to the cache
|
||||
* can cause most/all of the existing entries to be purged. To avoid the, the client can set
|
||||
* a limit for a single allocation. If a cacheable entry would have been cached, but its size
|
||||
* exceeds this limit, then we do not attempt to cache it at all.
|
||||
*
|
||||
* Zero is the default value, meaning we always attempt to cache entries.
|
||||
*/
|
||||
static size_t GetResourceCacheSingleAllocationByteLimit();
|
||||
static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit);
|
||||
|
||||
/**
|
||||
* Dumps memory usage of caches using the SkTraceMemoryDump interface. See SkTraceMemoryDump
|
||||
* for usage of this method.
|
||||
*/
|
||||
static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
|
||||
|
||||
/**
|
||||
* Free as much globally cached memory as possible. This will purge all private caches in Skia,
|
||||
* including font and image caches.
|
||||
*
|
||||
* If there are caches associated with GPU context, those will not be affected by this call.
|
||||
*/
|
||||
static void PurgeAllCaches();
|
||||
|
||||
typedef std::unique_ptr<SkImageGenerator>
|
||||
(*ImageGeneratorFromEncodedDataFactory)(sk_sp<SkData>);
|
||||
|
||||
/**
|
||||
* To instantiate images from encoded data, first looks at this runtime function-ptr. If it
|
||||
* exists, it is called to create an SkImageGenerator from SkData. If there is no function-ptr
|
||||
* or there is, but it returns NULL, then skia will call its internal default implementation.
|
||||
*
|
||||
* Returns the previous factory (which could be NULL).
|
||||
*/
|
||||
static ImageGeneratorFromEncodedDataFactory
|
||||
SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory);
|
||||
|
||||
/**
|
||||
* To draw OpenType SVG data, Skia will look at this runtime function pointer. If this function
|
||||
* pointer is set, the SkTypeface implementations which support OpenType SVG will call this
|
||||
* function to create an SkOpenTypeSVGDecoder to decode the OpenType SVG and draw it as needed.
|
||||
* If this function is not set, the SkTypeface implementations will generally not support
|
||||
* OpenType SVG and attempt to use other glyph representations if available.
|
||||
*/
|
||||
using OpenTypeSVGDecoderFactory =
|
||||
std::unique_ptr<SkOpenTypeSVGDecoder> (*)(const uint8_t* svg, size_t length);
|
||||
static OpenTypeSVGDecoderFactory SetOpenTypeSVGDecoderFactory(OpenTypeSVGDecoderFactory);
|
||||
static OpenTypeSVGDecoderFactory GetOpenTypeSVGDecoderFactory();
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,948 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkImage_DEFINED
|
||||
#define SkImage_DEFINED
|
||||
|
||||
#include "include/core/SkAlphaType.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
class GrDirectContext;
|
||||
class GrRecordingContext;
|
||||
class SkBitmap;
|
||||
class SkColorSpace;
|
||||
class SkData;
|
||||
class SkImage;
|
||||
class SkImageFilter;
|
||||
class SkImageGenerator;
|
||||
class SkMatrix;
|
||||
class SkMipmap;
|
||||
class SkPaint;
|
||||
class SkPicture;
|
||||
class SkPixmap;
|
||||
class SkShader;
|
||||
class SkSurfaceProps;
|
||||
enum SkColorType : int;
|
||||
enum class SkTextureCompressionType;
|
||||
enum class SkTileMode;
|
||||
|
||||
struct SkIPoint;
|
||||
struct SkSamplingOptions;
|
||||
|
||||
namespace skgpu::graphite { class Recorder; }
|
||||
|
||||
namespace SkImages {
|
||||
|
||||
/** Caller data passed to RasterReleaseProc; may be nullptr. */
|
||||
using ReleaseContext = void*;
|
||||
/** Function called when SkImage no longer shares pixels. ReleaseContext is
|
||||
provided by caller when SkImage is created, and may be nullptr.
|
||||
*/
|
||||
using RasterReleaseProc = void(const void* pixels, ReleaseContext);
|
||||
|
||||
/** Creates a CPU-backed SkImage from bitmap, sharing or copying bitmap pixels. If the bitmap
|
||||
is marked immutable, and its pixel memory is shareable, it may be shared
|
||||
instead of copied.
|
||||
|
||||
SkImage is returned if bitmap is valid. Valid SkBitmap parameters include:
|
||||
dimensions are greater than zero;
|
||||
each dimension fits in 29 bits;
|
||||
SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
|
||||
row bytes are large enough to hold one row of pixels;
|
||||
pixel address is not nullptr.
|
||||
|
||||
@param bitmap SkImageInfo, row bytes, and pixels
|
||||
@return created SkImage, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> RasterFromBitmap(const SkBitmap& bitmap);
|
||||
|
||||
/** Creates a CPU-backed SkImage from compressed data.
|
||||
|
||||
This method will decompress the compressed data and create an image wrapping
|
||||
it. Any mipmap levels present in the compressed data are discarded.
|
||||
|
||||
@param data compressed data to store in SkImage
|
||||
@param width width of full SkImage
|
||||
@param height height of full SkImage
|
||||
@param type type of compression used
|
||||
@return created SkImage, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> RasterFromCompressedTextureData(sk_sp<SkData> data,
|
||||
int width,
|
||||
int height,
|
||||
SkTextureCompressionType type);
|
||||
|
||||
/**
|
||||
* Return a SkImage using the encoded data, but attempts to defer decoding until the
|
||||
* image is actually used/drawn. This deferral allows the system to cache the result, either on the
|
||||
* CPU or on the GPU, depending on where the image is drawn. If memory is low, the cache may
|
||||
* be purged, causing the next draw of the image to have to re-decode.
|
||||
*
|
||||
* If alphaType is nullopt, the image's alpha type will be chosen automatically based on the
|
||||
* image format. Transparent images will default to kPremul_SkAlphaType. If alphaType contains
|
||||
* kPremul_SkAlphaType or kUnpremul_SkAlphaType, that alpha type will be used. Forcing opaque
|
||||
* (passing kOpaque_SkAlphaType) is not allowed, and will return nullptr.
|
||||
*
|
||||
* If the encoded format is not supported, nullptr is returned.
|
||||
*
|
||||
* If possible, clients should use SkCodecs::DeferredImage instead.
|
||||
*
|
||||
* @param encoded the encoded data
|
||||
* @return created SkImage, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_DeferredFromEncodedData
|
||||
*/
|
||||
SK_API sk_sp<SkImage> DeferredFromEncodedData(sk_sp<SkData> encoded,
|
||||
std::optional<SkAlphaType> alphaType = std::nullopt);
|
||||
|
||||
/** Creates SkImage from data returned by imageGenerator. The image data will not be created
|
||||
(on either the CPU or GPU) until the image is actually drawn.
|
||||
Generated data is owned by SkImage and may not be shared or accessed.
|
||||
|
||||
SkImage is returned if generator data is valid. Valid data parameters vary by type of data
|
||||
and platform.
|
||||
|
||||
imageGenerator may wrap SkPicture data, codec data, or custom data.
|
||||
|
||||
@param imageGenerator stock or custom routines to retrieve SkImage
|
||||
@return created SkImage, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> DeferredFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator);
|
||||
|
||||
enum class BitDepth {
|
||||
kU8, //!< uses 8-bit unsigned int per color component
|
||||
kF16, //!< uses 16-bit float per color component
|
||||
};
|
||||
|
||||
/** Creates SkImage from picture. Returned SkImage width and height are set by dimensions.
|
||||
SkImage draws picture with matrix and paint, set to bitDepth and colorSpace.
|
||||
|
||||
The Picture data is not turned into an image (CPU or GPU) until it is drawn.
|
||||
|
||||
If matrix is nullptr, draws with identity SkMatrix. If paint is nullptr, draws
|
||||
with default SkPaint. colorSpace may be nullptr.
|
||||
|
||||
@param picture stream of drawing commands
|
||||
@param dimensions width and height
|
||||
@param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
|
||||
@param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
|
||||
@param bitDepth 8-bit integer or 16-bit float: per component
|
||||
@param colorSpace range of colors; may be nullptr
|
||||
@param props props to use when rasterizing the picture
|
||||
@return created SkImage, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> DeferredFromPicture(sk_sp<SkPicture> picture,
|
||||
const SkISize& dimensions,
|
||||
const SkMatrix* matrix,
|
||||
const SkPaint* paint,
|
||||
BitDepth bitDepth,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
SkSurfaceProps props);
|
||||
SK_API sk_sp<SkImage> DeferredFromPicture(sk_sp<SkPicture> picture,
|
||||
const SkISize& dimensions,
|
||||
const SkMatrix* matrix,
|
||||
const SkPaint* paint,
|
||||
BitDepth bitDepth,
|
||||
sk_sp<SkColorSpace> colorSpace);
|
||||
|
||||
/** Creates a CPU-backed SkImage from pixmap, copying the pixel data.
|
||||
As a result, pixmap pixels may be modified or deleted without affecting SkImage.
|
||||
|
||||
SkImage is returned if SkPixmap is valid. Valid SkPixmap parameters include:
|
||||
dimensions are greater than zero;
|
||||
each dimension fits in 29 bits;
|
||||
SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
|
||||
row bytes are large enough to hold one row of pixels;
|
||||
pixel address is not nullptr.
|
||||
|
||||
@param pixmap SkImageInfo, pixel address, and row bytes
|
||||
@return copy of SkPixmap pixels, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_RasterFromPixmapCopy
|
||||
*/
|
||||
SK_API sk_sp<SkImage> RasterFromPixmapCopy(const SkPixmap& pixmap);
|
||||
|
||||
/** Creates CPU-backed SkImage from pixmap, sharing SkPixmap pixels. Pixels must remain valid and
|
||||
unchanged until rasterReleaseProc is called. rasterReleaseProc is passed
|
||||
releaseContext when SkImage is deleted or no longer refers to pixmap pixels.
|
||||
|
||||
Pass nullptr for rasterReleaseProc to share SkPixmap without requiring a callback
|
||||
when SkImage is released. Pass nullptr for releaseContext if rasterReleaseProc
|
||||
does not require state.
|
||||
|
||||
SkImage is returned if pixmap is valid. Valid SkPixmap parameters include:
|
||||
dimensions are greater than zero;
|
||||
each dimension fits in 29 bits;
|
||||
SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
|
||||
row bytes are large enough to hold one row of pixels;
|
||||
pixel address is not nullptr.
|
||||
|
||||
@param pixmap SkImageInfo, pixel address, and row bytes
|
||||
@param rasterReleaseProc function called when pixels can be released; or nullptr
|
||||
@param releaseContext state passed to rasterReleaseProc; or nullptr
|
||||
@return SkImage sharing pixmap
|
||||
*/
|
||||
SK_API sk_sp<SkImage> RasterFromPixmap(const SkPixmap& pixmap,
|
||||
RasterReleaseProc rasterReleaseProc,
|
||||
ReleaseContext releaseContext);
|
||||
|
||||
/** Creates CPU-backed SkImage from pixel data described by info.
|
||||
The pixels data will *not* be copied.
|
||||
|
||||
SkImage is returned if SkImageInfo is valid. Valid SkImageInfo parameters include:
|
||||
dimensions are greater than zero;
|
||||
each dimension fits in 29 bits;
|
||||
SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
|
||||
rowBytes are large enough to hold one row of pixels;
|
||||
pixels is not nullptr, and contains enough data for SkImage.
|
||||
|
||||
@param info contains width, height, SkAlphaType, SkColorType, SkColorSpace
|
||||
@param pixels address or pixel storage
|
||||
@param rowBytes size of pixel row or larger
|
||||
@return SkImage sharing pixels, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> RasterFromData(const SkImageInfo& info,
|
||||
sk_sp<SkData> pixels,
|
||||
size_t rowBytes);
|
||||
|
||||
/** Creates a filtered SkImage on the CPU. filter processes the src image, potentially changing
|
||||
the color, position, and size. subset is the bounds of src that are processed
|
||||
by filter. clipBounds is the expected bounds of the filtered SkImage. outSubset
|
||||
is required storage for the actual bounds of the filtered SkImage. offset is
|
||||
required storage for translation of returned SkImage.
|
||||
|
||||
Returns nullptr a filtered result could not be created. If nullptr is returned, outSubset
|
||||
and offset are undefined.
|
||||
|
||||
Useful for animation of SkImageFilter that varies size from frame to frame.
|
||||
outSubset describes the valid bounds of returned image. offset translates the returned SkImage
|
||||
to keep subsequent animation frames aligned with respect to each other.
|
||||
|
||||
@param src the image to be filtered
|
||||
@param filter the image filter to be applied
|
||||
@param subset bounds of SkImage processed by filter
|
||||
@param clipBounds expected bounds of filtered SkImage
|
||||
@param outSubset storage for returned SkImage bounds
|
||||
@param offset storage for returned SkImage translation
|
||||
@return filtered SkImage, or nullptr
|
||||
*/
|
||||
SK_API sk_sp<SkImage> MakeWithFilter(sk_sp<SkImage> src,
|
||||
const SkImageFilter* filter,
|
||||
const SkIRect& subset,
|
||||
const SkIRect& clipBounds,
|
||||
SkIRect* outSubset,
|
||||
SkIPoint* offset);
|
||||
|
||||
} // namespace SkImages
|
||||
|
||||
/** \class SkImage
|
||||
SkImage describes a two dimensional array of pixels to draw. The pixels may be
|
||||
decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,
|
||||
or located in GPU memory as a GPU texture.
|
||||
|
||||
SkImage cannot be modified after it is created. SkImage may allocate additional
|
||||
storage as needed; for instance, an encoded SkImage may decode when drawn.
|
||||
|
||||
SkImage width and height are greater than zero. Creating an SkImage with zero width
|
||||
or height returns SkImage equal to nullptr.
|
||||
|
||||
SkImage may be created from SkBitmap, SkPixmap, SkSurface, SkPicture, encoded streams,
|
||||
GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported
|
||||
include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details
|
||||
vary with platform.
|
||||
|
||||
See SkImages namespace for the static factory methods to make SkImages.
|
||||
|
||||
Clients should *not* subclass SkImage as there is a lot of internal machinery that is
|
||||
not publicly accessible.
|
||||
*/
|
||||
class SK_API SkImage : public SkRefCnt {
|
||||
public:
|
||||
/** Returns a SkImageInfo describing the width, height, color type, alpha type, and color space
|
||||
of the SkImage.
|
||||
|
||||
@return image info of SkImage.
|
||||
*/
|
||||
const SkImageInfo& imageInfo() const { return fInfo; }
|
||||
|
||||
/** Returns pixel count in each row.
|
||||
|
||||
@return pixel width in SkImage
|
||||
*/
|
||||
int width() const { return fInfo.width(); }
|
||||
|
||||
/** Returns pixel row count.
|
||||
|
||||
@return pixel height in SkImage
|
||||
*/
|
||||
int height() const { return fInfo.height(); }
|
||||
|
||||
/** Returns SkISize { width(), height() }.
|
||||
|
||||
@return integral size of width() and height()
|
||||
*/
|
||||
SkISize dimensions() const { return SkISize::Make(fInfo.width(), fInfo.height()); }
|
||||
|
||||
/** Returns SkIRect { 0, 0, width(), height() }.
|
||||
|
||||
@return integral rectangle from origin to width() and height()
|
||||
*/
|
||||
SkIRect bounds() const { return SkIRect::MakeWH(fInfo.width(), fInfo.height()); }
|
||||
|
||||
/** Returns value unique to image. SkImage contents cannot change after SkImage is
|
||||
created. Any operation to create a new SkImage will receive generate a new
|
||||
unique number.
|
||||
|
||||
@return unique identifier
|
||||
*/
|
||||
uint32_t uniqueID() const { return fUniqueID; }
|
||||
|
||||
/** Returns SkAlphaType.
|
||||
|
||||
SkAlphaType returned was a parameter to an SkImage constructor,
|
||||
or was parsed from encoded data.
|
||||
|
||||
@return SkAlphaType in SkImage
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_alphaType
|
||||
*/
|
||||
SkAlphaType alphaType() const;
|
||||
|
||||
/** Returns SkColorType if known; otherwise, returns kUnknown_SkColorType.
|
||||
|
||||
@return SkColorType of SkImage
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_colorType
|
||||
*/
|
||||
SkColorType colorType() const;
|
||||
|
||||
/** Returns SkColorSpace, the range of colors, associated with SkImage. The
|
||||
reference count of SkColorSpace is unchanged. The returned SkColorSpace is
|
||||
immutable.
|
||||
|
||||
SkColorSpace returned was passed to an SkImage constructor,
|
||||
or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
|
||||
is drawn, depending on the capabilities of the SkSurface receiving the drawing.
|
||||
|
||||
@return SkColorSpace in SkImage, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_colorSpace
|
||||
*/
|
||||
SkColorSpace* colorSpace() const;
|
||||
|
||||
/** Returns a smart pointer to SkColorSpace, the range of colors, associated with
|
||||
SkImage. The smart pointer tracks the number of objects sharing this
|
||||
SkColorSpace reference so the memory is released when the owners destruct.
|
||||
|
||||
The returned SkColorSpace is immutable.
|
||||
|
||||
SkColorSpace returned was passed to an SkImage constructor,
|
||||
or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
|
||||
is drawn, depending on the capabilities of the SkSurface receiving the drawing.
|
||||
|
||||
@return SkColorSpace in SkImage, or nullptr, wrapped in a smart pointer
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_refColorSpace
|
||||
*/
|
||||
sk_sp<SkColorSpace> refColorSpace() const;
|
||||
|
||||
/** Returns true if SkImage pixels represent transparency only. If true, each pixel
|
||||
is packed in 8 bits as defined by kAlpha_8_SkColorType.
|
||||
|
||||
@return true if pixels represent a transparency mask
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_isAlphaOnly
|
||||
*/
|
||||
bool isAlphaOnly() const;
|
||||
|
||||
/** Returns true if pixels ignore their alpha value and are treated as fully opaque.
|
||||
|
||||
@return true if SkAlphaType is kOpaque_SkAlphaType
|
||||
*/
|
||||
bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }
|
||||
|
||||
/**
|
||||
* Make a shader with the specified tiling and mipmap sampling.
|
||||
*/
|
||||
sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
|
||||
const SkMatrix* localMatrix = nullptr) const;
|
||||
sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
|
||||
const SkMatrix& lm) const;
|
||||
/** Defaults to clamp in both X and Y. */
|
||||
sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
|
||||
sk_sp<SkShader> makeShader(const SkSamplingOptions& sampling,
|
||||
const SkMatrix* lm = nullptr) const;
|
||||
|
||||
/**
|
||||
* makeRawShader functions like makeShader, but for images that contain non-color data.
|
||||
* This includes images encoding things like normals, material properties (eg, roughness),
|
||||
* heightmaps, or any other purely mathematical data that happens to be stored in an image.
|
||||
* These types of images are useful with some programmable shaders (see: SkRuntimeEffect).
|
||||
*
|
||||
* Raw image shaders work like regular image shaders (including filtering and tiling), with
|
||||
* a few major differences:
|
||||
* - No color space transformation is ever applied (the color space of the image is ignored).
|
||||
* - Images with an alpha type of kUnpremul are *not* automatically premultiplied.
|
||||
* - Bicubic filtering is not supported. If SkSamplingOptions::useCubic is true, these
|
||||
* factories will return nullptr.
|
||||
*/
|
||||
sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions&,
|
||||
const SkMatrix* localMatrix = nullptr) const;
|
||||
sk_sp<SkShader> makeRawShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
|
||||
const SkMatrix& lm) const;
|
||||
/** Defaults to clamp in both X and Y. */
|
||||
sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling, const SkMatrix& lm) const;
|
||||
sk_sp<SkShader> makeRawShader(const SkSamplingOptions& sampling,
|
||||
const SkMatrix* lm = nullptr) const;
|
||||
|
||||
/** Copies SkImage pixel address, row bytes, and SkImageInfo to pixmap, if address
|
||||
is available, and returns true. If pixel address is not available, return
|
||||
false and leave pixmap unchanged.
|
||||
|
||||
@param pixmap storage for pixel state if pixels are readable; otherwise, ignored
|
||||
@return true if SkImage has direct access to pixels
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_peekPixels
|
||||
*/
|
||||
bool peekPixels(SkPixmap* pixmap) const;
|
||||
|
||||
/** Returns true if the contents of SkImage was created on or uploaded to GPU memory,
|
||||
and is available as a GPU texture.
|
||||
|
||||
@return true if SkImage is a GPU texture
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_isTextureBacked
|
||||
*/
|
||||
virtual bool isTextureBacked() const = 0;
|
||||
|
||||
/** Returns an approximation of the amount of texture memory used by the image. Returns
|
||||
zero if the image is not texture backed or if the texture has an external format.
|
||||
*/
|
||||
virtual size_t textureSize() const = 0;
|
||||
|
||||
/** Returns true if SkImage can be drawn on either raster surface or GPU surface.
|
||||
If context is nullptr, tests if SkImage draws on raster surface;
|
||||
otherwise, tests if SkImage draws on GPU surface associated with context.
|
||||
|
||||
SkImage backed by GPU texture may become invalid if associated context is
|
||||
invalid. lazy image may be invalid and may not draw to raster surface or
|
||||
GPU surface or both.
|
||||
|
||||
@param context GPU context
|
||||
@return true if SkImage can be drawn
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_isValid
|
||||
*/
|
||||
virtual bool isValid(GrRecordingContext* context) const = 0;
|
||||
|
||||
/** \enum SkImage::CachingHint
|
||||
CachingHint selects whether Skia may internally cache SkBitmap generated by
|
||||
decoding SkImage, or by copying SkImage from GPU to CPU. The default behavior
|
||||
allows caching SkBitmap.
|
||||
|
||||
Choose kDisallow_CachingHint if SkImage pixels are to be used only once, or
|
||||
if SkImage pixels reside in a cache outside of Skia, or to reduce memory pressure.
|
||||
|
||||
Choosing kAllow_CachingHint does not ensure that pixels will be cached.
|
||||
SkImage pixels may not be cached if memory requirements are too large or
|
||||
pixels are not accessible.
|
||||
*/
|
||||
enum CachingHint {
|
||||
kAllow_CachingHint, //!< allows internally caching decoded and copied pixels
|
||||
kDisallow_CachingHint, //!< disallows internally caching decoded and copied pixels
|
||||
};
|
||||
|
||||
/** Copies SkRect of pixels from SkImage to dstPixels. Copy starts at offset (srcX, srcY),
|
||||
and does not exceed SkImage (width(), height()).
|
||||
|
||||
dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
|
||||
destination. dstRowBytes specifies the gap from one destination row to the next.
|
||||
Returns true if pixels are copied. Returns false if:
|
||||
- dstInfo.addr() equals nullptr
|
||||
- dstRowBytes is less than dstInfo.minRowBytes()
|
||||
- SkPixelRef is nullptr
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
|
||||
If SkImage SkColorType is kGray_8_SkColorType, dstInfo.colorSpace() must match.
|
||||
If SkImage SkAlphaType is kOpaque_SkAlphaType, dstInfo.alphaType() must
|
||||
match. If SkImage SkColorSpace is nullptr, dstInfo.colorSpace() must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
srcX and srcY may be negative to copy only top or left of source. Returns
|
||||
false if width() or height() is zero or negative.
|
||||
Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
|
||||
|
||||
If cachingHint is kAllow_CachingHint, pixels may be retained locally.
|
||||
If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
|
||||
|
||||
@param context the GrDirectContext in play, if it exists
|
||||
@param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
|
||||
@param dstPixels destination pixel storage
|
||||
@param dstRowBytes destination row length
|
||||
@param srcX column index whose absolute value is less than width()
|
||||
@param srcY row index whose absolute value is less than height()
|
||||
@param cachingHint whether the pixels should be cached locally
|
||||
@return true if pixels are copied to dstPixels
|
||||
*/
|
||||
bool readPixels(GrDirectContext* context,
|
||||
const SkImageInfo& dstInfo,
|
||||
void* dstPixels,
|
||||
size_t dstRowBytes,
|
||||
int srcX, int srcY,
|
||||
CachingHint cachingHint = kAllow_CachingHint) const;
|
||||
|
||||
/** Copies a SkRect of pixels from SkImage to dst. Copy starts at (srcX, srcY), and
|
||||
does not exceed SkImage (width(), height()).
|
||||
|
||||
dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
|
||||
and row bytes of destination. dst.rowBytes() specifics the gap from one destination
|
||||
row to the next. Returns true if pixels are copied. Returns false if:
|
||||
- dst pixel storage equals nullptr
|
||||
- dst.rowBytes is less than SkImageInfo::minRowBytes
|
||||
- SkPixelRef is nullptr
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
|
||||
If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
|
||||
If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
|
||||
match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
srcX and srcY may be negative to copy only top or left of source. Returns
|
||||
false if width() or height() is zero or negative.
|
||||
Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
|
||||
|
||||
If cachingHint is kAllow_CachingHint, pixels may be retained locally.
|
||||
If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
|
||||
|
||||
@param context the GrDirectContext in play, if it exists
|
||||
@param dst destination SkPixmap: SkImageInfo, pixels, row bytes
|
||||
@param srcX column index whose absolute value is less than width()
|
||||
@param srcY row index whose absolute value is less than height()
|
||||
@param cachingHint whether the pixels should be cached locallyZ
|
||||
@return true if pixels are copied to dst
|
||||
*/
|
||||
bool readPixels(GrDirectContext* context,
|
||||
const SkPixmap& dst,
|
||||
int srcX,
|
||||
int srcY,
|
||||
CachingHint cachingHint = kAllow_CachingHint) const;
|
||||
|
||||
#if defined(GRAPHITE_TEST_UTILS)
|
||||
bool readPixelsGraphite(skgpu::graphite::Recorder*,
|
||||
const SkPixmap& dst,
|
||||
int srcX,
|
||||
int srcY) const;
|
||||
#endif
|
||||
|
||||
#ifndef SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API
|
||||
/** Deprecated. Use the variants that accept a GrDirectContext. */
|
||||
bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
|
||||
int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
|
||||
bool readPixels(const SkPixmap& dst, int srcX, int srcY,
|
||||
CachingHint cachingHint = kAllow_CachingHint) const;
|
||||
#endif
|
||||
|
||||
/** The result from asyncRescaleAndReadPixels() or asyncRescaleAndReadPixelsYUV420(). */
|
||||
class AsyncReadResult {
|
||||
public:
|
||||
AsyncReadResult(const AsyncReadResult&) = delete;
|
||||
AsyncReadResult(AsyncReadResult&&) = delete;
|
||||
AsyncReadResult& operator=(const AsyncReadResult&) = delete;
|
||||
AsyncReadResult& operator=(AsyncReadResult&&) = delete;
|
||||
|
||||
virtual ~AsyncReadResult() = default;
|
||||
virtual int count() const = 0;
|
||||
virtual const void* data(int i) const = 0;
|
||||
virtual size_t rowBytes(int i) const = 0;
|
||||
|
||||
protected:
|
||||
AsyncReadResult() = default;
|
||||
};
|
||||
|
||||
/** Client-provided context that is passed to client-provided ReadPixelsContext. */
|
||||
using ReadPixelsContext = void*;
|
||||
|
||||
/** Client-provided callback to asyncRescaleAndReadPixels() or
|
||||
asyncRescaleAndReadPixelsYUV420() that is called when read result is ready or on failure.
|
||||
*/
|
||||
using ReadPixelsCallback = void(ReadPixelsContext, std::unique_ptr<const AsyncReadResult>);
|
||||
|
||||
enum class RescaleGamma : bool { kSrc, kLinear };
|
||||
|
||||
enum class RescaleMode {
|
||||
kNearest,
|
||||
kLinear,
|
||||
kRepeatedLinear,
|
||||
kRepeatedCubic,
|
||||
};
|
||||
|
||||
/** Makes image pixel data available to caller, possibly asynchronously. It can also rescale
|
||||
the image pixels.
|
||||
|
||||
Currently asynchronous reads are only supported on the GPU backend and only when the
|
||||
underlying 3D API supports transfer buffers and CPU/GPU synchronization primitives. In all
|
||||
other cases this operates synchronously.
|
||||
|
||||
Data is read from the source sub-rectangle, is optionally converted to a linear gamma, is
|
||||
rescaled to the size indicated by 'info', is then converted to the color space, color type,
|
||||
and alpha type of 'info'. A 'srcRect' that is not contained by the bounds of the image
|
||||
causes failure.
|
||||
|
||||
When the pixel data is ready the caller's ReadPixelsCallback is called with a
|
||||
AsyncReadResult containing pixel data in the requested color type, alpha type, and color
|
||||
space. The AsyncReadResult will have count() == 1. Upon failure the callback is called with
|
||||
nullptr for AsyncReadResult. For a GPU image this flushes work but a submit must occur to
|
||||
guarantee a finite time before the callback is called.
|
||||
|
||||
The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
|
||||
is GPU-backed the data is immediately invalidated if the context is abandoned or
|
||||
destroyed.
|
||||
|
||||
@param info info of the requested pixels
|
||||
@param srcRect subrectangle of image to read
|
||||
@param rescaleGamma controls whether rescaling is done in the image's gamma or whether
|
||||
the source data is transformed to a linear gamma before rescaling.
|
||||
@param rescaleMode controls the technique (and cost) of the rescaling
|
||||
@param callback function to call with result of the read
|
||||
@param context passed to callback
|
||||
*/
|
||||
void asyncRescaleAndReadPixels(const SkImageInfo& info,
|
||||
const SkIRect& srcRect,
|
||||
RescaleGamma rescaleGamma,
|
||||
RescaleMode rescaleMode,
|
||||
ReadPixelsCallback callback,
|
||||
ReadPixelsContext context) const;
|
||||
|
||||
/**
|
||||
Similar to asyncRescaleAndReadPixels but performs an additional conversion to YUV. The
|
||||
RGB->YUV conversion is controlled by 'yuvColorSpace'. The YUV data is returned as three
|
||||
planes ordered y, u, v. The u and v planes are half the width and height of the resized
|
||||
rectangle. The y, u, and v values are single bytes. Currently this fails if 'dstSize'
|
||||
width and height are not even. A 'srcRect' that is not contained by the bounds of the
|
||||
image causes failure.
|
||||
|
||||
When the pixel data is ready the caller's ReadPixelsCallback is called with a
|
||||
AsyncReadResult containing the planar data. The AsyncReadResult will have count() == 3.
|
||||
Upon failure the callback is called with nullptr for AsyncReadResult. For a GPU image this
|
||||
flushes work but a submit must occur to guarantee a finite time before the callback is
|
||||
called.
|
||||
|
||||
The data is valid for the lifetime of AsyncReadResult with the exception that if the SkImage
|
||||
is GPU-backed the data is immediately invalidated if the context is abandoned or
|
||||
destroyed.
|
||||
|
||||
@param yuvColorSpace The transformation from RGB to YUV. Applied to the resized image
|
||||
after it is converted to dstColorSpace.
|
||||
@param dstColorSpace The color space to convert the resized image to, after rescaling.
|
||||
@param srcRect The portion of the image to rescale and convert to YUV planes.
|
||||
@param dstSize The size to rescale srcRect to
|
||||
@param rescaleGamma controls whether rescaling is done in the image's gamma or whether
|
||||
the source data is transformed to a linear gamma before rescaling.
|
||||
@param rescaleMode controls the technique (and cost) of the rescaling
|
||||
@param callback function to call with the planar read result
|
||||
@param context passed to callback
|
||||
*/
|
||||
void asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
|
||||
sk_sp<SkColorSpace> dstColorSpace,
|
||||
const SkIRect& srcRect,
|
||||
const SkISize& dstSize,
|
||||
RescaleGamma rescaleGamma,
|
||||
RescaleMode rescaleMode,
|
||||
ReadPixelsCallback callback,
|
||||
ReadPixelsContext context) const;
|
||||
|
||||
/**
|
||||
* Identical to asyncRescaleAndReadPixelsYUV420 but a fourth plane is returned in the
|
||||
* AsyncReadResult passed to 'callback'. The fourth plane contains the alpha chanel at the
|
||||
* same full resolution as the Y plane.
|
||||
*/
|
||||
void asyncRescaleAndReadPixelsYUVA420(SkYUVColorSpace yuvColorSpace,
|
||||
sk_sp<SkColorSpace> dstColorSpace,
|
||||
const SkIRect& srcRect,
|
||||
const SkISize& dstSize,
|
||||
RescaleGamma rescaleGamma,
|
||||
RescaleMode rescaleMode,
|
||||
ReadPixelsCallback callback,
|
||||
ReadPixelsContext context) const;
|
||||
|
||||
/** Copies SkImage to dst, scaling pixels to fit dst.width() and dst.height(), and
|
||||
converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
|
||||
pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is
|
||||
less than dst SkImageInfo::minRowBytes.
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
|
||||
If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
|
||||
If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
|
||||
match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
If cachingHint is kAllow_CachingHint, pixels may be retained locally.
|
||||
If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
|
||||
|
||||
@param dst destination SkPixmap: SkImageInfo, pixels, row bytes
|
||||
@return true if pixels are scaled to fit dst
|
||||
*/
|
||||
bool scalePixels(const SkPixmap& dst, const SkSamplingOptions&,
|
||||
CachingHint cachingHint = kAllow_CachingHint) const;
|
||||
|
||||
/** Returns encoded SkImage pixels as SkData, if SkImage was created from supported
|
||||
encoded stream format. Platform support for formats vary and may require building
|
||||
with one or more of: SK_ENCODE_JPEG, SK_ENCODE_PNG, SK_ENCODE_WEBP.
|
||||
|
||||
Returns nullptr if SkImage contents are not encoded.
|
||||
|
||||
@return encoded SkImage, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_refEncodedData
|
||||
*/
|
||||
sk_sp<SkData> refEncodedData() const;
|
||||
|
||||
/** Returns subset of this image.
|
||||
|
||||
Returns nullptr if any of the following are true:
|
||||
- Subset is empty
|
||||
- Subset is not contained inside the image's bounds
|
||||
- Pixels in the source image could not be read or copied
|
||||
- This image is texture-backed and the provided context is null or does not match
|
||||
the source image's context.
|
||||
|
||||
If the source image was texture-backed, the resulting image will be texture-backed also.
|
||||
Otherwise, the returned image will be raster-backed.
|
||||
|
||||
@param direct the GrDirectContext of the source image (nullptr is ok if the source image
|
||||
is not texture-backed).
|
||||
@param subset bounds of returned SkImage
|
||||
@return the subsetted image, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_makeSubset
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeSubset(GrDirectContext* direct, const SkIRect& subset) const = 0;
|
||||
|
||||
struct RequiredProperties {
|
||||
bool fMipmapped;
|
||||
|
||||
bool operator==(const RequiredProperties& other) const {
|
||||
return fMipmapped == other.fMipmapped;
|
||||
}
|
||||
|
||||
bool operator!=(const RequiredProperties& other) const { return !(*this == other); }
|
||||
|
||||
bool operator<(const RequiredProperties& other) const {
|
||||
return fMipmapped < other.fMipmapped;
|
||||
}
|
||||
};
|
||||
|
||||
/** Returns subset of this image.
|
||||
|
||||
Returns nullptr if any of the following are true:
|
||||
- Subset is empty
|
||||
- Subset is not contained inside the image's bounds
|
||||
- Pixels in the image could not be read or copied
|
||||
- This image is texture-backed and the provided context is null or does not match
|
||||
the source image's context.
|
||||
|
||||
If the source image was texture-backed, the resulting image will be texture-backed also.
|
||||
Otherwise, the returned image will be raster-backed.
|
||||
|
||||
@param recorder the recorder of the source image (nullptr is ok if the
|
||||
source image was texture-backed).
|
||||
@param subset bounds of returned SkImage
|
||||
@param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps)
|
||||
@return the subsetted image, or nullptr
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeSubset(skgpu::graphite::Recorder*,
|
||||
const SkIRect& subset,
|
||||
RequiredProperties) const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the image has mipmap levels.
|
||||
*/
|
||||
bool hasMipmaps() const;
|
||||
|
||||
/**
|
||||
* Returns true if the image holds protected content.
|
||||
*/
|
||||
bool isProtected() const;
|
||||
|
||||
/**
|
||||
* Returns an image with the same "base" pixels as the this image, but with mipmap levels
|
||||
* automatically generated and attached.
|
||||
*/
|
||||
sk_sp<SkImage> withDefaultMipmaps() const;
|
||||
|
||||
/** Returns raster image or lazy image. Copies SkImage backed by GPU texture into
|
||||
CPU memory if needed. Returns original SkImage if decoded in raster bitmap,
|
||||
or if encoded in a stream.
|
||||
|
||||
Returns nullptr if backed by GPU texture and copy fails.
|
||||
|
||||
@return raster image, lazy image, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_makeNonTextureImage
|
||||
*/
|
||||
sk_sp<SkImage> makeNonTextureImage(GrDirectContext* = nullptr) const;
|
||||
|
||||
/** Returns raster image. Copies SkImage backed by GPU texture into CPU memory,
|
||||
or decodes SkImage from lazy image. Returns original SkImage if decoded in
|
||||
raster bitmap.
|
||||
|
||||
Returns nullptr if copy, decode, or pixel read fails.
|
||||
|
||||
If cachingHint is kAllow_CachingHint, pixels may be retained locally.
|
||||
If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
|
||||
|
||||
@return raster image, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_makeRasterImage
|
||||
*/
|
||||
sk_sp<SkImage> makeRasterImage(GrDirectContext*,
|
||||
CachingHint cachingHint = kDisallow_CachingHint) const;
|
||||
|
||||
#if !defined(SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API)
|
||||
sk_sp<SkImage> makeRasterImage(CachingHint cachingHint = kDisallow_CachingHint) const {
|
||||
return this->makeRasterImage(nullptr, cachingHint);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Deprecated.
|
||||
*/
|
||||
enum LegacyBitmapMode {
|
||||
kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable
|
||||
};
|
||||
|
||||
/** Deprecated.
|
||||
Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
|
||||
kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.
|
||||
Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if
|
||||
SkBitmap write did not succeed.
|
||||
|
||||
@param bitmap storage for legacy SkBitmap
|
||||
@param legacyBitmapMode bitmap is read-only and immutable
|
||||
@return true if SkBitmap was created
|
||||
*/
|
||||
bool asLegacyBitmap(SkBitmap* bitmap,
|
||||
LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
|
||||
|
||||
/** Returns true if SkImage is backed by an image-generator or other service that creates
|
||||
and caches its pixels or texture on-demand.
|
||||
|
||||
@return true if SkImage is created as needed
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_isLazyGenerated_a
|
||||
example: https://fiddle.skia.org/c/@Image_isLazyGenerated_b
|
||||
*/
|
||||
virtual bool isLazyGenerated() const = 0;
|
||||
|
||||
/** Creates SkImage in target SkColorSpace.
|
||||
Returns nullptr if SkImage could not be created.
|
||||
|
||||
Returns original SkImage if it is in target SkColorSpace.
|
||||
Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
|
||||
If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
|
||||
|
||||
If this image is texture-backed, the context parameter is required and must match the
|
||||
context of the source image.
|
||||
|
||||
@param direct The GrDirectContext in play, if it exists
|
||||
@param target SkColorSpace describing color range of returned SkImage
|
||||
@return created SkImage in target SkColorSpace
|
||||
|
||||
example: https://fiddle.skia.org/c/@Image_makeColorSpace
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeColorSpace(GrDirectContext* direct,
|
||||
sk_sp<SkColorSpace> target) const = 0;
|
||||
|
||||
/** Creates SkImage in target SkColorSpace.
|
||||
Returns nullptr if SkImage could not be created.
|
||||
|
||||
Returns original SkImage if it is in target SkColorSpace.
|
||||
Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
|
||||
If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
|
||||
|
||||
If this image is graphite-backed, the recorder parameter is required.
|
||||
|
||||
@param targetColorSpace SkColorSpace describing color range of returned SkImage
|
||||
@param recorder The Recorder in which to create the new image
|
||||
@param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps)
|
||||
@return created SkImage in target SkColorSpace
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeColorSpace(skgpu::graphite::Recorder*,
|
||||
sk_sp<SkColorSpace> targetColorSpace,
|
||||
RequiredProperties) const = 0;
|
||||
|
||||
/** Experimental.
|
||||
Creates SkImage in target SkColorType and SkColorSpace.
|
||||
Returns nullptr if SkImage could not be created.
|
||||
|
||||
Returns original SkImage if it is in target SkColorType and SkColorSpace.
|
||||
|
||||
If this image is texture-backed, the context parameter is required and must match the
|
||||
context of the source image.
|
||||
|
||||
@param direct The GrDirectContext in play, if it exists
|
||||
@param targetColorType SkColorType of returned SkImage
|
||||
@param targetColorSpace SkColorSpace of returned SkImage
|
||||
@return created SkImage in target SkColorType and SkColorSpace
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeColorTypeAndColorSpace(GrDirectContext* direct,
|
||||
SkColorType targetColorType,
|
||||
sk_sp<SkColorSpace> targetCS) const = 0;
|
||||
|
||||
/** Experimental.
|
||||
Creates SkImage in target SkColorType and SkColorSpace.
|
||||
Returns nullptr if SkImage could not be created.
|
||||
|
||||
Returns original SkImage if it is in target SkColorType and SkColorSpace.
|
||||
|
||||
If this image is graphite-backed, the recorder parameter is required.
|
||||
|
||||
@param targetColorType SkColorType of returned SkImage
|
||||
@param targetColorSpace SkColorSpace of returned SkImage
|
||||
@param recorder The Recorder in which to create the new image
|
||||
@param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps)
|
||||
@return created SkImage in target SkColorType and SkColorSpace
|
||||
*/
|
||||
virtual sk_sp<SkImage> makeColorTypeAndColorSpace(skgpu::graphite::Recorder*,
|
||||
SkColorType targetColorType,
|
||||
sk_sp<SkColorSpace> targetColorSpace,
|
||||
RequiredProperties) const = 0;
|
||||
|
||||
/** Creates a new SkImage identical to this one, but with a different SkColorSpace.
|
||||
This does not convert the underlying pixel data, so the resulting image will draw
|
||||
differently.
|
||||
*/
|
||||
sk_sp<SkImage> reinterpretColorSpace(sk_sp<SkColorSpace> newColorSpace) const;
|
||||
|
||||
private:
|
||||
SkImage(const SkImageInfo& info, uint32_t uniqueID);
|
||||
|
||||
friend class SkBitmap;
|
||||
friend class SkImage_Base; // for private ctor
|
||||
friend class SkImage_Raster; // for withMipmaps
|
||||
friend class SkMipmapBuilder;
|
||||
|
||||
SkImageInfo fInfo;
|
||||
const uint32_t fUniqueID;
|
||||
|
||||
sk_sp<SkImage> withMipmaps(sk_sp<SkMipmap>) const;
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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 SkImageFilter_DEFINED
|
||||
#define SkImageFilter_DEFINED
|
||||
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class SkColorFilter;
|
||||
class SkMatrix;
|
||||
struct SkDeserialProcs;
|
||||
|
||||
/**
|
||||
* Base class for image filters. If one is installed in the paint, then all drawing occurs as
|
||||
* usual, but it is as if the drawing happened into an offscreen (before the xfermode is applied).
|
||||
* This offscreen bitmap will then be handed to the imagefilter, who in turn creates a new bitmap
|
||||
* which is what will finally be drawn to the device (using the original xfermode).
|
||||
*
|
||||
* The local space of image filters matches the local space of the drawn geometry. For instance if
|
||||
* there is rotation on the canvas, the blur will be computed along those rotated axes and not in
|
||||
* the device space. In order to achieve this result, the actual drawing of the geometry may happen
|
||||
* in an unrotated coordinate system so that the filtered image can be computed more easily, and
|
||||
* then it will be post transformed to match what would have been produced if the geometry were
|
||||
* drawn with the total canvas matrix to begin with.
|
||||
*/
|
||||
class SK_API SkImageFilter : public SkFlattenable {
|
||||
public:
|
||||
enum MapDirection {
|
||||
kForward_MapDirection,
|
||||
kReverse_MapDirection,
|
||||
};
|
||||
/**
|
||||
* Map a device-space rect recursively forward or backward through the filter DAG.
|
||||
* kForward_MapDirection is used to determine which pixels of the destination canvas a source
|
||||
* image rect would touch after filtering. kReverse_MapDirection is used to determine which rect
|
||||
* of the source image would be required to fill the given rect (typically, clip bounds). Used
|
||||
* for clipping and temp-buffer allocations, so the result need not be exact, but should never
|
||||
* be smaller than the real answer. The default implementation recursively unions all input
|
||||
* bounds, or returns the source rect if no inputs.
|
||||
*
|
||||
* In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward
|
||||
* mode it should always be null. If 'inputRect' is null in kReverse mode the resulting answer
|
||||
* may be incorrect.
|
||||
*/
|
||||
SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
|
||||
MapDirection, const SkIRect* inputRect = nullptr) const;
|
||||
|
||||
/**
|
||||
* Returns whether this image filter is a color filter and puts the color filter into the
|
||||
* "filterPtr" parameter if it can. Does nothing otherwise.
|
||||
* If this returns false, then the filterPtr is unchanged.
|
||||
* If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
|
||||
* (i.e. it may not be set to NULL).
|
||||
*/
|
||||
bool isColorFilterNode(SkColorFilter** filterPtr) const;
|
||||
|
||||
// DEPRECATED : use isColorFilterNode() instead
|
||||
bool asColorFilter(SkColorFilter** filterPtr) const {
|
||||
return this->isColorFilterNode(filterPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 same
|
||||
* way.
|
||||
*/
|
||||
bool asAColorFilter(SkColorFilter** filterPtr) const;
|
||||
|
||||
/**
|
||||
* Returns the number of inputs this filter will accept (some inputs can be NULL).
|
||||
*/
|
||||
int countInputs() const;
|
||||
|
||||
/**
|
||||
* Returns the input filter at a given index, or NULL if no input is connected. The indices
|
||||
* used are filter-specific.
|
||||
*/
|
||||
const SkImageFilter* getInput(int i) const;
|
||||
|
||||
// Default impl returns union of all input bounds.
|
||||
virtual SkRect computeFastBounds(const SkRect& bounds) const;
|
||||
|
||||
// Can this filter DAG compute the resulting bounds of an object-space rectangle?
|
||||
bool canComputeFastBounds() const;
|
||||
|
||||
/**
|
||||
* If this filter can be represented by another filter + a localMatrix, return that filter,
|
||||
* else return null.
|
||||
*/
|
||||
sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix& matrix) const;
|
||||
|
||||
static sk_sp<SkImageFilter> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr) {
|
||||
return sk_sp<SkImageFilter>(static_cast<SkImageFilter*>(
|
||||
SkFlattenable::Deserialize(kSkImageFilter_Type, data, size, procs).release()));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
sk_sp<SkImageFilter> refMe() const {
|
||||
return sk_ref_sp(const_cast<SkImageFilter*>(this));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class SkImageFilter_Base;
|
||||
|
||||
using INHERITED = SkFlattenable;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkImageGenerator_DEFINED
|
||||
#define SkImageGenerator_DEFINED
|
||||
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkPixmap.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkYUVAPixmaps.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#if defined(SK_GRAPHITE)
|
||||
#include "include/core/SkImage.h"
|
||||
#include "include/gpu/graphite/Recorder.h"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class GrRecordingContext;
|
||||
|
||||
class SK_API SkImageGenerator {
|
||||
public:
|
||||
/**
|
||||
* The PixelRef which takes ownership of this SkImageGenerator
|
||||
* will call the image generator's destructor.
|
||||
*/
|
||||
virtual ~SkImageGenerator() { }
|
||||
|
||||
uint32_t uniqueID() const { return fUniqueID; }
|
||||
|
||||
/**
|
||||
* Return a ref to the encoded (i.e. compressed) representation
|
||||
* of this data.
|
||||
*
|
||||
* If non-NULL is returned, the caller is responsible for calling
|
||||
* unref() on the data when it is finished.
|
||||
*/
|
||||
sk_sp<SkData> refEncodedData() {
|
||||
return this->onRefEncodedData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ImageInfo associated with this generator.
|
||||
*/
|
||||
const SkImageInfo& getInfo() const { return fInfo; }
|
||||
|
||||
/**
|
||||
* Can this generator be used to produce images that will be drawable to the specified context
|
||||
* (or to CPU, if context is nullptr)?
|
||||
*/
|
||||
bool isValid(GrRecordingContext* context) const {
|
||||
return this->onIsValid(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will this generator produce protected content
|
||||
*/
|
||||
bool isProtected() const {
|
||||
return this->onIsProtected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode into the given pixels, a block of memory of size at
|
||||
* least (info.fHeight - 1) * rowBytes + (info.fWidth *
|
||||
* bytesPerPixel)
|
||||
*
|
||||
* Repeated calls to this function should give the same results,
|
||||
* allowing the PixelRef to be immutable.
|
||||
*
|
||||
* @param info A description of the format
|
||||
* expected by the caller. This can simply be identical
|
||||
* to the info returned by getInfo().
|
||||
*
|
||||
* This contract also allows the caller to specify
|
||||
* different output-configs, which the implementation can
|
||||
* decide to support or not.
|
||||
*
|
||||
* A size that does not match getInfo() implies a request
|
||||
* to scale. If the generator cannot perform this scale,
|
||||
* it will return false.
|
||||
*
|
||||
* @return true on success.
|
||||
*/
|
||||
bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
|
||||
|
||||
bool getPixels(const SkPixmap& pm) {
|
||||
return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* If decoding to YUV is supported, this returns true. Otherwise, this
|
||||
* returns false and the caller will ignore output parameter yuvaPixmapInfo.
|
||||
*
|
||||
* @param supportedDataTypes Indicates the data type/planar config combinations that are
|
||||
* supported by the caller. If the generator supports decoding to
|
||||
* YUV(A), but not as a type in supportedDataTypes, this method
|
||||
* returns false.
|
||||
* @param yuvaPixmapInfo Output parameter that specifies the planar configuration, subsampling,
|
||||
* orientation, chroma siting, plane color types, and row bytes.
|
||||
*/
|
||||
bool queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
|
||||
SkYUVAPixmapInfo* yuvaPixmapInfo) const;
|
||||
|
||||
/**
|
||||
* Returns true on success and false on failure.
|
||||
* This always attempts to perform a full decode. To get the planar
|
||||
* configuration without decoding use queryYUVAInfo().
|
||||
*
|
||||
* @param yuvaPixmaps Contains preallocated pixmaps configured according to a successful call
|
||||
* to queryYUVAInfo().
|
||||
*/
|
||||
bool getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps);
|
||||
|
||||
virtual bool isTextureGenerator() const { return false; }
|
||||
|
||||
protected:
|
||||
static constexpr int kNeedNewImageUniqueID = 0;
|
||||
|
||||
SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);
|
||||
|
||||
virtual sk_sp<SkData> onRefEncodedData() { return nullptr; }
|
||||
struct Options {};
|
||||
virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
|
||||
virtual bool onIsValid(GrRecordingContext*) const { return true; }
|
||||
virtual bool onIsProtected() const { return false; }
|
||||
virtual bool onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes&,
|
||||
SkYUVAPixmapInfo*) const { return false; }
|
||||
virtual bool onGetYUVAPlanes(const SkYUVAPixmaps&) { return false; }
|
||||
|
||||
const SkImageInfo fInfo;
|
||||
|
||||
private:
|
||||
const uint32_t fUniqueID;
|
||||
|
||||
SkImageGenerator(SkImageGenerator&&) = delete;
|
||||
SkImageGenerator(const SkImageGenerator&) = delete;
|
||||
SkImageGenerator& operator=(SkImageGenerator&&) = delete;
|
||||
SkImageGenerator& operator=(const SkImageGenerator&) = delete;
|
||||
};
|
||||
|
||||
#endif // SkImageGenerator_DEFINED
|
@ -0,0 +1,628 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkImageInfo_DEFINED
|
||||
#define SkImageInfo_DEFINED
|
||||
|
||||
#include "include/core/SkAlphaType.h"
|
||||
#include "include/core/SkColorType.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkDebug.h"
|
||||
#include "include/private/base/SkMath.h"
|
||||
#include "include/private/base/SkTFitsIn.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
class SkColorSpace;
|
||||
|
||||
/** Returns the number of bytes required to store a pixel, including unused padding.
|
||||
Returns zero if ct is kUnknown_SkColorType or invalid.
|
||||
|
||||
@return bytes per pixel
|
||||
*/
|
||||
SK_API int SkColorTypeBytesPerPixel(SkColorType ct);
|
||||
|
||||
/** Returns true if SkColorType always decodes alpha to 1.0, making the pixel
|
||||
fully opaque. If true, SkColorType does not reserve bits to encode alpha.
|
||||
|
||||
@return true if alpha is always set to 1.0
|
||||
*/
|
||||
SK_API bool SkColorTypeIsAlwaysOpaque(SkColorType ct);
|
||||
|
||||
/** Returns true if canonical can be set to a valid SkAlphaType for colorType. If
|
||||
there is more than one valid canonical SkAlphaType, set to alphaType, if valid.
|
||||
If true is returned and canonical is not nullptr, store valid SkAlphaType.
|
||||
|
||||
Returns false only if alphaType is kUnknown_SkAlphaType, color type is not
|
||||
kUnknown_SkColorType, and SkColorType is not always opaque. If false is returned,
|
||||
canonical is ignored.
|
||||
|
||||
@param canonical storage for SkAlphaType
|
||||
@return true if valid SkAlphaType can be associated with colorType
|
||||
*/
|
||||
SK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
|
||||
SkAlphaType* canonical = nullptr);
|
||||
|
||||
/** \enum SkImageInfo::SkYUVColorSpace
|
||||
Describes color range of YUV pixels. The color mapping from YUV to RGB varies
|
||||
depending on the source. YUV pixels may be generated by JPEG images, standard
|
||||
video streams, or high definition video streams. Each has its own mapping from
|
||||
YUV to RGB.
|
||||
|
||||
JPEG YUV values encode the full range of 0 to 255 for all three components.
|
||||
Video YUV values often range from 16 to 235 for Y and from 16 to 240 for U and V (limited).
|
||||
Details of encoding and conversion to RGB are described in YCbCr color space.
|
||||
|
||||
The identity colorspace exists to provide a utility mapping from Y to R, U to G and V to B.
|
||||
It can be used to visualize the YUV planes or to explicitly post process the YUV channels.
|
||||
*/
|
||||
enum SkYUVColorSpace : int {
|
||||
kJPEG_Full_SkYUVColorSpace, //!< describes full range
|
||||
kRec601_Limited_SkYUVColorSpace, //!< describes SDTV range
|
||||
kRec709_Full_SkYUVColorSpace, //!< describes HDTV range
|
||||
kRec709_Limited_SkYUVColorSpace,
|
||||
kBT2020_8bit_Full_SkYUVColorSpace, //!< describes UHDTV range, non-constant-luminance
|
||||
kBT2020_8bit_Limited_SkYUVColorSpace,
|
||||
kBT2020_10bit_Full_SkYUVColorSpace,
|
||||
kBT2020_10bit_Limited_SkYUVColorSpace,
|
||||
kBT2020_12bit_Full_SkYUVColorSpace,
|
||||
kBT2020_12bit_Limited_SkYUVColorSpace,
|
||||
kFCC_Full_SkYUVColorSpace, //!< describes FCC range
|
||||
kFCC_Limited_SkYUVColorSpace,
|
||||
kSMPTE240_Full_SkYUVColorSpace, //!< describes SMPTE240M range
|
||||
kSMPTE240_Limited_SkYUVColorSpace,
|
||||
kYDZDX_Full_SkYUVColorSpace, //!< describes YDZDX range
|
||||
kYDZDX_Limited_SkYUVColorSpace,
|
||||
kGBR_Full_SkYUVColorSpace, //!< describes GBR range
|
||||
kGBR_Limited_SkYUVColorSpace,
|
||||
kYCgCo_8bit_Full_SkYUVColorSpace, //!< describes YCgCo matrix
|
||||
kYCgCo_8bit_Limited_SkYUVColorSpace,
|
||||
kYCgCo_10bit_Full_SkYUVColorSpace,
|
||||
kYCgCo_10bit_Limited_SkYUVColorSpace,
|
||||
kYCgCo_12bit_Full_SkYUVColorSpace,
|
||||
kYCgCo_12bit_Limited_SkYUVColorSpace,
|
||||
kIdentity_SkYUVColorSpace, //!< maps Y->R, U->G, V->B
|
||||
|
||||
kLastEnum_SkYUVColorSpace = kIdentity_SkYUVColorSpace, //!< last valid value
|
||||
|
||||
// Legacy (deprecated) names:
|
||||
kJPEG_SkYUVColorSpace = kJPEG_Full_SkYUVColorSpace,
|
||||
kRec601_SkYUVColorSpace = kRec601_Limited_SkYUVColorSpace,
|
||||
kRec709_SkYUVColorSpace = kRec709_Limited_SkYUVColorSpace,
|
||||
kBT2020_SkYUVColorSpace = kBT2020_8bit_Limited_SkYUVColorSpace,
|
||||
};
|
||||
|
||||
/** \struct SkColorInfo
|
||||
Describes pixel and encoding. SkImageInfo can be created from SkColorInfo by
|
||||
providing dimensions.
|
||||
|
||||
It encodes how pixel bits describe alpha, transparency; color components red, blue,
|
||||
and green; and SkColorSpace, the range and linearity of colors.
|
||||
*/
|
||||
class SK_API SkColorInfo {
|
||||
public:
|
||||
/** Creates an SkColorInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
|
||||
and no SkColorSpace.
|
||||
|
||||
@return empty SkImageInfo
|
||||
*/
|
||||
SkColorInfo();
|
||||
~SkColorInfo();
|
||||
|
||||
/** Creates SkColorInfo from SkColorType ct, SkAlphaType at, and optionally SkColorSpace cs.
|
||||
|
||||
If SkColorSpace cs is nullptr and SkColorInfo is part of drawing source: SkColorSpace
|
||||
defaults to sRGB, mapping into SkSurface SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
@return created SkColorInfo
|
||||
*/
|
||||
SkColorInfo(SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs);
|
||||
|
||||
SkColorInfo(const SkColorInfo&);
|
||||
SkColorInfo(SkColorInfo&&);
|
||||
|
||||
SkColorInfo& operator=(const SkColorInfo&);
|
||||
SkColorInfo& operator=(SkColorInfo&&);
|
||||
|
||||
SkColorSpace* colorSpace() const;
|
||||
sk_sp<SkColorSpace> refColorSpace() const;
|
||||
SkColorType colorType() const { return fColorType; }
|
||||
SkAlphaType alphaType() const { return fAlphaType; }
|
||||
|
||||
bool isOpaque() const {
|
||||
return SkAlphaTypeIsOpaque(fAlphaType)
|
||||
|| SkColorTypeIsAlwaysOpaque(fColorType);
|
||||
}
|
||||
|
||||
bool gammaCloseToSRGB() const;
|
||||
|
||||
/** Does other represent the same color type, alpha type, and color space? */
|
||||
bool operator==(const SkColorInfo& other) const;
|
||||
|
||||
/** Does other represent a different color type, alpha type, or color space? */
|
||||
bool operator!=(const SkColorInfo& other) const;
|
||||
|
||||
/** Creates SkColorInfo with same SkColorType, SkColorSpace, with SkAlphaType set
|
||||
to newAlphaType.
|
||||
|
||||
Created SkColorInfo contains newAlphaType even if it is incompatible with
|
||||
SkColorType, in which case SkAlphaType in SkColorInfo is ignored.
|
||||
*/
|
||||
SkColorInfo makeAlphaType(SkAlphaType newAlphaType) const;
|
||||
|
||||
/** Creates new SkColorInfo with same SkAlphaType, SkColorSpace, with SkColorType
|
||||
set to newColorType.
|
||||
*/
|
||||
SkColorInfo makeColorType(SkColorType newColorType) const;
|
||||
|
||||
/** Creates SkColorInfo with same SkAlphaType, SkColorType, with SkColorSpace
|
||||
set to cs. cs may be nullptr.
|
||||
*/
|
||||
SkColorInfo makeColorSpace(sk_sp<SkColorSpace> cs) const;
|
||||
|
||||
/** Returns number of bytes per pixel required by SkColorType.
|
||||
Returns zero if colorType() is kUnknown_SkColorType.
|
||||
|
||||
@return bytes in pixel
|
||||
|
||||
example: https://fiddle.skia.org/c/@ImageInfo_bytesPerPixel
|
||||
*/
|
||||
int bytesPerPixel() const;
|
||||
|
||||
/** Returns bit shift converting row bytes to row pixels.
|
||||
Returns zero for kUnknown_SkColorType.
|
||||
|
||||
@return one of: 0, 1, 2, 3, 4; left shift to convert pixels to bytes
|
||||
|
||||
example: https://fiddle.skia.org/c/@ImageInfo_shiftPerPixel
|
||||
*/
|
||||
int shiftPerPixel() const;
|
||||
|
||||
private:
|
||||
sk_sp<SkColorSpace> fColorSpace;
|
||||
SkColorType fColorType = kUnknown_SkColorType;
|
||||
SkAlphaType fAlphaType = kUnknown_SkAlphaType;
|
||||
};
|
||||
|
||||
/** \struct SkImageInfo
|
||||
Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface
|
||||
can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and
|
||||
SkPixmap, but not from SkImage and SkSurface. For example, SkImage and SkSurface
|
||||
implementations may defer pixel depth, so may not completely specify SkImageInfo.
|
||||
|
||||
SkImageInfo contains dimensions, the pixel integral width and height. It encodes
|
||||
how pixel bits describe alpha, transparency; color components red, blue,
|
||||
and green; and SkColorSpace, the range and linearity of colors.
|
||||
*/
|
||||
struct SK_API SkImageInfo {
|
||||
public:
|
||||
|
||||
/** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
|
||||
a width and height of zero, and no SkColorSpace.
|
||||
|
||||
@return empty SkImageInfo
|
||||
*/
|
||||
SkImageInfo() = default;
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, SkColorType ct,
|
||||
SkAlphaType at, and optionally SkColorSpace cs.
|
||||
|
||||
If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
|
||||
defaults to sRGB, mapping into SkSurface SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@param cs range of colors; may be nullptr
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at);
|
||||
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
|
||||
sk_sp<SkColorSpace> cs);
|
||||
static SkImageInfo Make(SkISize dimensions, SkColorType ct, SkAlphaType at);
|
||||
static SkImageInfo Make(SkISize dimensions, SkColorType ct, SkAlphaType at,
|
||||
sk_sp<SkColorSpace> cs);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions and SkColorInfo colorInfo,
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param dimensions pixel column and row count; must be zeros or greater
|
||||
@param SkColorInfo the pixel encoding consisting of SkColorType, SkAlphaType, and
|
||||
SkColorSpace (which may be nullptr)
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo Make(SkISize dimensions, const SkColorInfo& colorInfo) {
|
||||
return SkImageInfo(dimensions, colorInfo);
|
||||
}
|
||||
static SkImageInfo Make(SkISize dimensions, SkColorInfo&& colorInfo) {
|
||||
return SkImageInfo(dimensions, std::move(colorInfo));
|
||||
}
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
|
||||
SkAlphaType at, and optionally SkColorSpace cs. kN32_SkColorType will equal either
|
||||
kBGRA_8888_SkColorType or kRGBA_8888_SkColorType, whichever is optimal.
|
||||
|
||||
If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
|
||||
defaults to sRGB, mapping into SkSurface SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@param cs range of colors; may be nullptr
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeN32(int width, int height, SkAlphaType at);
|
||||
static SkImageInfo MakeN32(int width, int height, SkAlphaType at, sk_sp<SkColorSpace> cs);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
|
||||
SkAlphaType at, with sRGB SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
|
||||
example: https://fiddle.skia.org/c/@ImageInfo_MakeS32
|
||||
*/
|
||||
static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
|
||||
kPremul_SkAlphaType, with optional SkColorSpace.
|
||||
|
||||
If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
|
||||
defaults to sRGB, mapping into SkSurface SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@param cs range of colors; may be nullptr
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeN32Premul(int width, int height);
|
||||
static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
|
||||
kPremul_SkAlphaType, with SkColorSpace set to nullptr.
|
||||
|
||||
If SkImageInfo is part of drawing source: SkColorSpace defaults to sRGB, mapping
|
||||
into SkSurface SkColorSpace.
|
||||
|
||||
Parameters are not validated to see if their values are legal, or that the
|
||||
combination is supported.
|
||||
|
||||
@param dimensions width and height, each must be zero or greater
|
||||
@param cs range of colors; may be nullptr
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeN32Premul(SkISize dimensions);
|
||||
static SkImageInfo MakeN32Premul(SkISize dimensions, sk_sp<SkColorSpace> cs);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kAlpha_8_SkColorType,
|
||||
kPremul_SkAlphaType, with SkColorSpace set to nullptr.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeA8(int width, int height);
|
||||
/** Creates SkImageInfo from integral dimensions, kAlpha_8_SkColorType,
|
||||
kPremul_SkAlphaType, with SkColorSpace set to nullptr.
|
||||
|
||||
@param dimensions pixel row and column count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeA8(SkISize dimensions);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height, kUnknown_SkColorType,
|
||||
kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
|
||||
|
||||
Returned SkImageInfo as part of source does not draw, and as part of destination
|
||||
can not be drawn to.
|
||||
|
||||
@param width pixel column count; must be zero or greater
|
||||
@param height pixel row count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeUnknown(int width, int height);
|
||||
|
||||
/** Creates SkImageInfo from integral dimensions width and height set to zero,
|
||||
kUnknown_SkColorType, kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
|
||||
|
||||
Returned SkImageInfo as part of source does not draw, and as part of destination
|
||||
can not be drawn to.
|
||||
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
static SkImageInfo MakeUnknown() {
|
||||
return MakeUnknown(0, 0);
|
||||
}
|
||||
|
||||
/** Returns pixel count in each row.
|
||||
|
||||
@return pixel width
|
||||
*/
|
||||
int width() const { return fDimensions.width(); }
|
||||
|
||||
/** Returns pixel row count.
|
||||
|
||||
@return pixel height
|
||||
*/
|
||||
int height() const { return fDimensions.height(); }
|
||||
|
||||
SkColorType colorType() const { return fColorInfo.colorType(); }
|
||||
|
||||
SkAlphaType alphaType() const { return fColorInfo.alphaType(); }
|
||||
|
||||
/** Returns SkColorSpace, the range of colors. The reference count of
|
||||
SkColorSpace is unchanged. The returned SkColorSpace is immutable.
|
||||
|
||||
@return SkColorSpace, or nullptr
|
||||
*/
|
||||
SkColorSpace* colorSpace() const;
|
||||
|
||||
/** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer
|
||||
tracks the number of objects sharing this SkColorSpace reference so the memory
|
||||
is released when the owners destruct.
|
||||
|
||||
The returned SkColorSpace is immutable.
|
||||
|
||||
@return SkColorSpace wrapped in a smart pointer
|
||||
*/
|
||||
sk_sp<SkColorSpace> refColorSpace() const;
|
||||
|
||||
/** Returns if SkImageInfo describes an empty area of pixels by checking if either
|
||||
width or height is zero or smaller.
|
||||
|
||||
@return true if either dimension is zero or smaller
|
||||
*/
|
||||
bool isEmpty() const { return fDimensions.isEmpty(); }
|
||||
|
||||
/** Returns the dimensionless SkColorInfo that represents the same color type,
|
||||
alpha type, and color space as this SkImageInfo.
|
||||
*/
|
||||
const SkColorInfo& colorInfo() const { return fColorInfo; }
|
||||
|
||||
/** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
|
||||
alpha value is implicitly or explicitly 1.0. If true, and all pixels are
|
||||
not opaque, Skia may draw incorrectly.
|
||||
|
||||
Does not check if SkColorType allows alpha, or if any pixel value has
|
||||
transparency.
|
||||
|
||||
@return true if SkAlphaType is kOpaque_SkAlphaType
|
||||
*/
|
||||
bool isOpaque() const { return fColorInfo.isOpaque(); }
|
||||
|
||||
/** Returns SkISize { width(), height() }.
|
||||
|
||||
@return integral size of width() and height()
|
||||
*/
|
||||
SkISize dimensions() const { return fDimensions; }
|
||||
|
||||
/** Returns SkIRect { 0, 0, width(), height() }.
|
||||
|
||||
@return integral rectangle from origin to width() and height()
|
||||
*/
|
||||
SkIRect bounds() const { return SkIRect::MakeSize(fDimensions); }
|
||||
|
||||
/** Returns true if associated SkColorSpace is not nullptr, and SkColorSpace gamma
|
||||
is approximately the same as sRGB.
|
||||
This includes the
|
||||
|
||||
@return true if SkColorSpace gamma is approximately the same as sRGB
|
||||
*/
|
||||
bool gammaCloseToSRGB() const { return fColorInfo.gammaCloseToSRGB(); }
|
||||
|
||||
/** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,
|
||||
with dimensions set to width and height.
|
||||
|
||||
@param newWidth pixel column count; must be zero or greater
|
||||
@param newHeight pixel row count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
SkImageInfo makeWH(int newWidth, int newHeight) const {
|
||||
return Make({newWidth, newHeight}, fColorInfo);
|
||||
}
|
||||
|
||||
/** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,
|
||||
with dimensions set to newDimensions.
|
||||
|
||||
@param newSize pixel column and row count; must be zero or greater
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
SkImageInfo makeDimensions(SkISize newSize) const {
|
||||
return Make(newSize, fColorInfo);
|
||||
}
|
||||
|
||||
/** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height,
|
||||
with SkAlphaType set to newAlphaType.
|
||||
|
||||
Created SkImageInfo contains newAlphaType even if it is incompatible with
|
||||
SkColorType, in which case SkAlphaType in SkImageInfo is ignored.
|
||||
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
|
||||
return Make(fDimensions, fColorInfo.makeAlphaType(newAlphaType));
|
||||
}
|
||||
|
||||
/** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height,
|
||||
with SkColorType set to newColorType.
|
||||
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
SkImageInfo makeColorType(SkColorType newColorType) const {
|
||||
return Make(fDimensions, fColorInfo.makeColorType(newColorType));
|
||||
}
|
||||
|
||||
/** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height,
|
||||
with SkColorSpace set to cs.
|
||||
|
||||
@param cs range of colors; may be nullptr
|
||||
@return created SkImageInfo
|
||||
*/
|
||||
SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const;
|
||||
|
||||
/** Returns number of bytes per pixel required by SkColorType.
|
||||
Returns zero if colorType( is kUnknown_SkColorType.
|
||||
|
||||
@return bytes in pixel
|
||||
*/
|
||||
int bytesPerPixel() const { return fColorInfo.bytesPerPixel(); }
|
||||
|
||||
/** Returns bit shift converting row bytes to row pixels.
|
||||
Returns zero for kUnknown_SkColorType.
|
||||
|
||||
@return one of: 0, 1, 2, 3; left shift to convert pixels to bytes
|
||||
*/
|
||||
int shiftPerPixel() const { return fColorInfo.shiftPerPixel(); }
|
||||
|
||||
/** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
|
||||
specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
|
||||
in 31 bits.
|
||||
|
||||
@return width() times bytesPerPixel() as unsigned 64-bit integer
|
||||
*/
|
||||
uint64_t minRowBytes64() const {
|
||||
return (uint64_t)sk_64_mul(this->width(), this->bytesPerPixel());
|
||||
}
|
||||
|
||||
/** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
|
||||
specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
|
||||
in 31 bits.
|
||||
|
||||
@return width() times bytesPerPixel() as size_t
|
||||
*/
|
||||
size_t minRowBytes() const {
|
||||
uint64_t minRowBytes = this->minRowBytes64();
|
||||
if (!SkTFitsIn<int32_t>(minRowBytes)) {
|
||||
return 0;
|
||||
}
|
||||
return (size_t)minRowBytes;
|
||||
}
|
||||
|
||||
/** Returns byte offset of pixel from pixel base address.
|
||||
|
||||
Asserts in debug build if x or y is outside of bounds. Does not assert if
|
||||
rowBytes is smaller than minRowBytes(), even though result may be incorrect.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@param rowBytes size of pixel row or larger
|
||||
@return offset within pixel array
|
||||
|
||||
example: https://fiddle.skia.org/c/@ImageInfo_computeOffset
|
||||
*/
|
||||
size_t computeOffset(int x, int y, size_t rowBytes) const;
|
||||
|
||||
/** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
|
||||
SkAlphaType, and SkColorSpace are equivalent.
|
||||
|
||||
@param other SkImageInfo to compare
|
||||
@return true if SkImageInfo equals other
|
||||
*/
|
||||
bool operator==(const SkImageInfo& other) const {
|
||||
return fDimensions == other.fDimensions && fColorInfo == other.fColorInfo;
|
||||
}
|
||||
|
||||
/** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
|
||||
SkAlphaType, and SkColorSpace are not equivalent.
|
||||
|
||||
@param other SkImageInfo to compare
|
||||
@return true if SkImageInfo is not equal to other
|
||||
*/
|
||||
bool operator!=(const SkImageInfo& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/** Returns storage required by pixel array, given SkImageInfo dimensions, SkColorType,
|
||||
and rowBytes. rowBytes is assumed to be at least as large as minRowBytes().
|
||||
|
||||
Returns zero if height is zero.
|
||||
Returns SIZE_MAX if answer exceeds the range of size_t.
|
||||
|
||||
@param rowBytes size of pixel row or larger
|
||||
@return memory required by pixel buffer
|
||||
*/
|
||||
size_t computeByteSize(size_t rowBytes) const;
|
||||
|
||||
/** Returns storage required by pixel array, given SkImageInfo dimensions, and
|
||||
SkColorType. Uses minRowBytes() to compute bytes for pixel row.
|
||||
|
||||
Returns zero if height is zero.
|
||||
Returns SIZE_MAX if answer exceeds the range of size_t.
|
||||
|
||||
@return least memory required by pixel buffer
|
||||
*/
|
||||
size_t computeMinByteSize() const {
|
||||
return this->computeByteSize(this->minRowBytes());
|
||||
}
|
||||
|
||||
/** Returns true if byteSize equals SIZE_MAX. computeByteSize() and
|
||||
computeMinByteSize() return SIZE_MAX if size_t can not hold buffer size.
|
||||
|
||||
@param byteSize result of computeByteSize() or computeMinByteSize()
|
||||
@return true if computeByteSize() or computeMinByteSize() result exceeds size_t
|
||||
*/
|
||||
static bool ByteSizeOverflowed(size_t byteSize) {
|
||||
return SIZE_MAX == byteSize;
|
||||
}
|
||||
|
||||
/** Returns true if rowBytes is valid for this SkImageInfo.
|
||||
|
||||
@param rowBytes size of pixel row including padding
|
||||
@return true if rowBytes is large enough to contain pixel row and is properly
|
||||
aligned
|
||||
*/
|
||||
bool validRowBytes(size_t rowBytes) const {
|
||||
if (rowBytes < this->minRowBytes64()) {
|
||||
return false;
|
||||
}
|
||||
int shift = this->shiftPerPixel();
|
||||
size_t alignedRowBytes = rowBytes >> shift << shift;
|
||||
return alignedRowBytes == rowBytes;
|
||||
}
|
||||
|
||||
/** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
|
||||
a width and height of zero, and no SkColorSpace.
|
||||
*/
|
||||
void reset() { *this = {}; }
|
||||
|
||||
/** Asserts if internal values are illegal or inconsistent. Only available if
|
||||
SK_DEBUG is defined at compile time.
|
||||
*/
|
||||
SkDEBUGCODE(void validate() const;)
|
||||
|
||||
private:
|
||||
SkColorInfo fColorInfo;
|
||||
SkISize fDimensions = {0, 0};
|
||||
|
||||
SkImageInfo(SkISize dimensions, const SkColorInfo& colorInfo)
|
||||
: fColorInfo(colorInfo), fDimensions(dimensions) {}
|
||||
|
||||
SkImageInfo(SkISize dimensions, SkColorInfo&& colorInfo)
|
||||
: fColorInfo(std::move(colorInfo)), fDimensions(dimensions) {}
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkM44_DEFINED
|
||||
#define SkM44_DEFINED
|
||||
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
struct SkRect;
|
||||
|
||||
struct SK_API SkV2 {
|
||||
float x, y;
|
||||
|
||||
bool operator==(const SkV2 v) const { return x == v.x && y == v.y; }
|
||||
bool operator!=(const SkV2 v) const { return !(*this == v); }
|
||||
|
||||
static SkScalar Dot(SkV2 a, SkV2 b) { return a.x * b.x + a.y * b.y; }
|
||||
static SkScalar Cross(SkV2 a, SkV2 b) { return a.x * b.y - a.y * b.x; }
|
||||
static SkV2 Normalize(SkV2 v) { return v * (1.0f / v.length()); }
|
||||
|
||||
SkV2 operator-() const { return {-x, -y}; }
|
||||
SkV2 operator+(SkV2 v) const { return {x+v.x, y+v.y}; }
|
||||
SkV2 operator-(SkV2 v) const { return {x-v.x, y-v.y}; }
|
||||
|
||||
SkV2 operator*(SkV2 v) const { return {x*v.x, y*v.y}; }
|
||||
friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; }
|
||||
friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; }
|
||||
friend SkV2 operator/(SkV2 v, SkScalar s) { return {v.x/s, v.y/s}; }
|
||||
friend SkV2 operator/(SkScalar s, SkV2 v) { return {s/v.x, s/v.y}; }
|
||||
|
||||
void operator+=(SkV2 v) { *this = *this + v; }
|
||||
void operator-=(SkV2 v) { *this = *this - v; }
|
||||
void operator*=(SkV2 v) { *this = *this * v; }
|
||||
void operator*=(SkScalar s) { *this = *this * s; }
|
||||
void operator/=(SkScalar s) { *this = *this / s; }
|
||||
|
||||
SkScalar lengthSquared() const { return Dot(*this, *this); }
|
||||
SkScalar length() const { return SkScalarSqrt(this->lengthSquared()); }
|
||||
|
||||
SkScalar dot(SkV2 v) const { return Dot(*this, v); }
|
||||
SkScalar cross(SkV2 v) const { return Cross(*this, v); }
|
||||
SkV2 normalize() const { return Normalize(*this); }
|
||||
|
||||
const float* ptr() const { return &x; }
|
||||
float* ptr() { return &x; }
|
||||
};
|
||||
|
||||
struct SK_API SkV3 {
|
||||
float x, y, z;
|
||||
|
||||
bool operator==(const SkV3& v) const {
|
||||
return x == v.x && y == v.y && z == v.z;
|
||||
}
|
||||
bool operator!=(const SkV3& v) const { return !(*this == v); }
|
||||
|
||||
static SkScalar Dot(const SkV3& a, const SkV3& b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
|
||||
static SkV3 Cross(const SkV3& a, const SkV3& b) {
|
||||
return { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x };
|
||||
}
|
||||
static SkV3 Normalize(const SkV3& v) { return v * (1.0f / v.length()); }
|
||||
|
||||
SkV3 operator-() const { return {-x, -y, -z}; }
|
||||
SkV3 operator+(const SkV3& v) const { return { x + v.x, y + v.y, z + v.z }; }
|
||||
SkV3 operator-(const SkV3& v) const { return { x - v.x, y - v.y, z - v.z }; }
|
||||
|
||||
SkV3 operator*(const SkV3& v) const {
|
||||
return { x*v.x, y*v.y, z*v.z };
|
||||
}
|
||||
friend SkV3 operator*(const SkV3& v, SkScalar s) {
|
||||
return { v.x*s, v.y*s, v.z*s };
|
||||
}
|
||||
friend SkV3 operator*(SkScalar s, const SkV3& v) { return v*s; }
|
||||
|
||||
void operator+=(SkV3 v) { *this = *this + v; }
|
||||
void operator-=(SkV3 v) { *this = *this - v; }
|
||||
void operator*=(SkV3 v) { *this = *this * v; }
|
||||
void operator*=(SkScalar s) { *this = *this * s; }
|
||||
|
||||
SkScalar lengthSquared() const { return Dot(*this, *this); }
|
||||
SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); }
|
||||
|
||||
SkScalar dot(const SkV3& v) const { return Dot(*this, v); }
|
||||
SkV3 cross(const SkV3& v) const { return Cross(*this, v); }
|
||||
SkV3 normalize() const { return Normalize(*this); }
|
||||
|
||||
const float* ptr() const { return &x; }
|
||||
float* ptr() { return &x; }
|
||||
};
|
||||
|
||||
struct SK_API SkV4 {
|
||||
float x, y, z, w;
|
||||
|
||||
bool operator==(const SkV4& v) const {
|
||||
return x == v.x && y == v.y && z == v.z && w == v.w;
|
||||
}
|
||||
bool operator!=(const SkV4& v) const { return !(*this == v); }
|
||||
|
||||
static SkScalar Dot(const SkV4& a, const SkV4& b) {
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
|
||||
}
|
||||
static SkV4 Normalize(const SkV4& v) { return v * (1.0f / v.length()); }
|
||||
|
||||
SkV4 operator-() const { return {-x, -y, -z, -w}; }
|
||||
SkV4 operator+(const SkV4& v) const { return { x + v.x, y + v.y, z + v.z, w + v.w }; }
|
||||
SkV4 operator-(const SkV4& v) const { return { x - v.x, y - v.y, z - v.z, w - v.w }; }
|
||||
|
||||
SkV4 operator*(const SkV4& v) const {
|
||||
return { x*v.x, y*v.y, z*v.z, w*v.w };
|
||||
}
|
||||
friend SkV4 operator*(const SkV4& v, SkScalar s) {
|
||||
return { v.x*s, v.y*s, v.z*s, v.w*s };
|
||||
}
|
||||
friend SkV4 operator*(SkScalar s, const SkV4& v) { return v*s; }
|
||||
|
||||
SkScalar lengthSquared() const { return Dot(*this, *this); }
|
||||
SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); }
|
||||
|
||||
SkScalar dot(const SkV4& v) const { return Dot(*this, v); }
|
||||
SkV4 normalize() const { return Normalize(*this); }
|
||||
|
||||
const float* ptr() const { return &x; }
|
||||
float* ptr() { return &x; }
|
||||
|
||||
float operator[](int i) const {
|
||||
SkASSERT(i >= 0 && i < 4);
|
||||
return this->ptr()[i];
|
||||
}
|
||||
float& operator[](int i) {
|
||||
SkASSERT(i >= 0 && i < 4);
|
||||
return this->ptr()[i];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 4x4 matrix used by SkCanvas and other parts of Skia.
|
||||
*
|
||||
* Skia assumes a right-handed coordinate system:
|
||||
* +X goes to the right
|
||||
* +Y goes down
|
||||
* +Z goes into the screen (away from the viewer)
|
||||
*/
|
||||
class SK_API SkM44 {
|
||||
public:
|
||||
SkM44(const SkM44& src) = default;
|
||||
SkM44& operator=(const SkM44& src) = default;
|
||||
|
||||
constexpr SkM44()
|
||||
: fMat{1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1}
|
||||
{}
|
||||
|
||||
SkM44(const SkM44& a, const SkM44& b) {
|
||||
this->setConcat(a, b);
|
||||
}
|
||||
|
||||
enum Uninitialized_Constructor {
|
||||
kUninitialized_Constructor
|
||||
};
|
||||
SkM44(Uninitialized_Constructor) {}
|
||||
|
||||
enum NaN_Constructor {
|
||||
kNaN_Constructor
|
||||
};
|
||||
constexpr SkM44(NaN_Constructor)
|
||||
: fMat{SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
|
||||
SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
|
||||
SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN,
|
||||
SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN}
|
||||
{}
|
||||
|
||||
/**
|
||||
* The constructor parameters are in row-major order.
|
||||
*/
|
||||
constexpr SkM44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
|
||||
SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
|
||||
SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
|
||||
SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15)
|
||||
// fMat is column-major order in memory.
|
||||
: fMat{m0, m1, m2, m3,
|
||||
m4, m5, m6, m7,
|
||||
m8, m9, m10, m11,
|
||||
m12, m13, m14, m15}
|
||||
{}
|
||||
|
||||
static SkM44 Rows(const SkV4& r0, const SkV4& r1, const SkV4& r2, const SkV4& r3) {
|
||||
SkM44 m(kUninitialized_Constructor);
|
||||
m.setRow(0, r0);
|
||||
m.setRow(1, r1);
|
||||
m.setRow(2, r2);
|
||||
m.setRow(3, r3);
|
||||
return m;
|
||||
}
|
||||
static SkM44 Cols(const SkV4& c0, const SkV4& c1, const SkV4& c2, const SkV4& c3) {
|
||||
SkM44 m(kUninitialized_Constructor);
|
||||
m.setCol(0, c0);
|
||||
m.setCol(1, c1);
|
||||
m.setCol(2, c2);
|
||||
m.setCol(3, c3);
|
||||
return m;
|
||||
}
|
||||
|
||||
static SkM44 RowMajor(const SkScalar r[16]) {
|
||||
return SkM44(r[ 0], r[ 1], r[ 2], r[ 3],
|
||||
r[ 4], r[ 5], r[ 6], r[ 7],
|
||||
r[ 8], r[ 9], r[10], r[11],
|
||||
r[12], r[13], r[14], r[15]);
|
||||
}
|
||||
static SkM44 ColMajor(const SkScalar c[16]) {
|
||||
return SkM44(c[0], c[4], c[ 8], c[12],
|
||||
c[1], c[5], c[ 9], c[13],
|
||||
c[2], c[6], c[10], c[14],
|
||||
c[3], c[7], c[11], c[15]);
|
||||
}
|
||||
|
||||
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) {
|
||||
return SkM44(1, 0, 0, x,
|
||||
0, 1, 0, y,
|
||||
0, 0, 1, z,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) {
|
||||
return SkM44(x, 0, 0, 0,
|
||||
0, y, 0, 0,
|
||||
0, 0, z, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
static SkM44 Rotate(SkV3 axis, SkScalar radians) {
|
||||
SkM44 m(kUninitialized_Constructor);
|
||||
m.setRotate(axis, radians);
|
||||
return m;
|
||||
}
|
||||
|
||||
// Scales and translates 'src' to fill 'dst' exactly.
|
||||
static SkM44 RectToRect(const SkRect& src, const SkRect& dst);
|
||||
|
||||
static SkM44 LookAt(const SkV3& eye, const SkV3& center, const SkV3& up);
|
||||
static SkM44 Perspective(float near, float far, float angle);
|
||||
|
||||
bool operator==(const SkM44& other) const;
|
||||
bool operator!=(const SkM44& other) const {
|
||||
return !(other == *this);
|
||||
}
|
||||
|
||||
void getColMajor(SkScalar v[]) const {
|
||||
memcpy(v, fMat, sizeof(fMat));
|
||||
}
|
||||
void getRowMajor(SkScalar v[]) const;
|
||||
|
||||
SkScalar rc(int r, int c) const {
|
||||
SkASSERT(r >= 0 && r <= 3);
|
||||
SkASSERT(c >= 0 && c <= 3);
|
||||
return fMat[c*4 + r];
|
||||
}
|
||||
void setRC(int r, int c, SkScalar value) {
|
||||
SkASSERT(r >= 0 && r <= 3);
|
||||
SkASSERT(c >= 0 && c <= 3);
|
||||
fMat[c*4 + r] = value;
|
||||
}
|
||||
|
||||
SkV4 row(int i) const {
|
||||
SkASSERT(i >= 0 && i <= 3);
|
||||
return {fMat[i + 0], fMat[i + 4], fMat[i + 8], fMat[i + 12]};
|
||||
}
|
||||
SkV4 col(int i) const {
|
||||
SkASSERT(i >= 0 && i <= 3);
|
||||
return {fMat[i*4 + 0], fMat[i*4 + 1], fMat[i*4 + 2], fMat[i*4 + 3]};
|
||||
}
|
||||
|
||||
void setRow(int i, const SkV4& v) {
|
||||
SkASSERT(i >= 0 && i <= 3);
|
||||
fMat[i + 0] = v.x;
|
||||
fMat[i + 4] = v.y;
|
||||
fMat[i + 8] = v.z;
|
||||
fMat[i + 12] = v.w;
|
||||
}
|
||||
void setCol(int i, const SkV4& v) {
|
||||
SkASSERT(i >= 0 && i <= 3);
|
||||
memcpy(&fMat[i*4], v.ptr(), sizeof(v));
|
||||
}
|
||||
|
||||
SkM44& setIdentity() {
|
||||
*this = { 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1 };
|
||||
return *this;
|
||||
}
|
||||
|
||||
SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) {
|
||||
*this = { 1, 0, 0, x,
|
||||
0, 1, 0, y,
|
||||
0, 0, 1, z,
|
||||
0, 0, 0, 1 };
|
||||
return *this;
|
||||
}
|
||||
|
||||
SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) {
|
||||
*this = { x, 0, 0, 0,
|
||||
0, y, 0, 0,
|
||||
0, 0, z, 0,
|
||||
0, 0, 0, 1 };
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this matrix to rotate about the specified unit-length axis vector,
|
||||
* by an angle specified by its sin() and cos().
|
||||
*
|
||||
* This does not attempt to verify that axis.length() == 1 or that the sin,cos values
|
||||
* are correct.
|
||||
*/
|
||||
SkM44& setRotateUnitSinCos(SkV3 axis, SkScalar sinAngle, SkScalar cosAngle);
|
||||
|
||||
/**
|
||||
* Set this matrix to rotate about the specified unit-length axis vector,
|
||||
* by an angle specified in radians.
|
||||
*
|
||||
* This does not attempt to verify that axis.length() == 1.
|
||||
*/
|
||||
SkM44& setRotateUnit(SkV3 axis, SkScalar radians) {
|
||||
return this->setRotateUnitSinCos(axis, SkScalarSin(radians), SkScalarCos(radians));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this matrix to rotate about the specified axis vector,
|
||||
* by an angle specified in radians.
|
||||
*
|
||||
* Note: axis is not assumed to be unit-length, so it will be normalized internally.
|
||||
* If axis is already unit-length, call setRotateAboutUnitRadians() instead.
|
||||
*/
|
||||
SkM44& setRotate(SkV3 axis, SkScalar radians);
|
||||
|
||||
SkM44& setConcat(const SkM44& a, const SkM44& b);
|
||||
|
||||
friend SkM44 operator*(const SkM44& a, const SkM44& b) {
|
||||
return SkM44(a, b);
|
||||
}
|
||||
|
||||
SkM44& preConcat(const SkM44& m) {
|
||||
return this->setConcat(*this, m);
|
||||
}
|
||||
|
||||
SkM44& postConcat(const SkM44& m) {
|
||||
return this->setConcat(m, *this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 0, 1].
|
||||
* For most uses, a bottom row of [0, 0, 0, X] behaves like a non-perspective matrix, though
|
||||
* it will be categorized as perspective. Calling normalizePerspective() will change the
|
||||
* matrix such that, if its bottom row was [0, 0, 0, X], it will be changed to [0, 0, 0, 1]
|
||||
* by scaling the rest of the matrix by 1/X.
|
||||
*
|
||||
* | A B C D | | A/X B/X C/X D/X |
|
||||
* | E F G H | -> | E/X F/X G/X H/X | for X != 0
|
||||
* | I J K L | | I/X J/X K/X L/X |
|
||||
* | 0 0 0 X | | 0 0 0 1 |
|
||||
*/
|
||||
void normalizePerspective();
|
||||
|
||||
/** Returns true if all elements of the matrix are finite. Returns false if any
|
||||
element is infinity, or NaN.
|
||||
|
||||
@return true if matrix has only finite elements
|
||||
*/
|
||||
bool isFinite() const { return SkIsFinite(fMat, 16); }
|
||||
|
||||
/** If this is invertible, return that in inverse and return true. If it is
|
||||
* not invertible, return false and leave the inverse parameter unchanged.
|
||||
*/
|
||||
[[nodiscard]] bool invert(SkM44* inverse) const;
|
||||
|
||||
[[nodiscard]] SkM44 transpose() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
////////////
|
||||
|
||||
SkV4 map(float x, float y, float z, float w) const;
|
||||
SkV4 operator*(const SkV4& v) const {
|
||||
return this->map(v.x, v.y, v.z, v.w);
|
||||
}
|
||||
SkV3 operator*(SkV3 v) const {
|
||||
auto v4 = this->map(v.x, v.y, v.z, 0);
|
||||
return {v4.x, v4.y, v4.z};
|
||||
}
|
||||
////////////////////// Converting to/from SkMatrix
|
||||
|
||||
/* When converting from SkM44 to SkMatrix, the third row and
|
||||
* column is dropped. When converting from SkMatrix to SkM44
|
||||
* the third row and column remain as identity:
|
||||
* [ a b c ] [ a b 0 c ]
|
||||
* [ d e f ] -> [ d e 0 f ]
|
||||
* [ g h i ] [ 0 0 1 0 ]
|
||||
* [ g h 0 i ]
|
||||
*/
|
||||
SkMatrix asM33() const {
|
||||
return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12],
|
||||
fMat[1], fMat[5], fMat[13],
|
||||
fMat[3], fMat[7], fMat[15]);
|
||||
}
|
||||
|
||||
explicit SkM44(const SkMatrix& src)
|
||||
: SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX], 0, src[SkMatrix::kMTransX],
|
||||
src[SkMatrix::kMSkewY], src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY],
|
||||
0, 0, 1, 0,
|
||||
src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2])
|
||||
{}
|
||||
|
||||
SkM44& preTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
|
||||
SkM44& postTranslate(SkScalar x, SkScalar y, SkScalar z = 0);
|
||||
|
||||
SkM44& preScale(SkScalar x, SkScalar y);
|
||||
SkM44& preScale(SkScalar x, SkScalar y, SkScalar z);
|
||||
SkM44& preConcat(const SkMatrix&);
|
||||
|
||||
private:
|
||||
/* Stored in column-major.
|
||||
* Indices
|
||||
* 0 4 8 12 1 0 0 trans_x
|
||||
* 1 5 9 13 e.g. 0 1 0 trans_y
|
||||
* 2 6 10 14 0 0 1 trans_z
|
||||
* 3 7 11 15 0 0 0 1
|
||||
*/
|
||||
SkScalar fMat[16];
|
||||
|
||||
friend class SkMatrixPriv;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2008 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 SkMallocPixelRef_DEFINED
|
||||
#define SkMallocPixelRef_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class SkData;
|
||||
class SkPixelRef;
|
||||
struct SkImageInfo;
|
||||
|
||||
/** We explicitly use the same allocator for our pixels that SkMask does,
|
||||
so that we can freely assign memory allocated by one class to the other.
|
||||
*/
|
||||
namespace SkMallocPixelRef {
|
||||
/**
|
||||
* Return a new SkMallocPixelRef, automatically allocating storage for the
|
||||
* pixels. If rowBytes are 0, an optimal value will be chosen automatically.
|
||||
* If rowBytes is > 0, then it will be respected, or NULL will be returned
|
||||
* if rowBytes is invalid for the specified info.
|
||||
*
|
||||
* All pixel bytes are zeroed.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
SK_API sk_sp<SkPixelRef> MakeAllocate(const SkImageInfo&, size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Return a new SkMallocPixelRef that will use the provided SkData and
|
||||
* rowBytes as pixel storage. The SkData will be ref()ed and on
|
||||
* destruction of the PixelRef, the SkData will be unref()ed.
|
||||
*
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
SK_API sk_sp<SkPixelRef> MakeWithData(const SkImageInfo&, size_t rowBytes, sk_sp<SkData> data);
|
||||
} // namespace SkMallocPixelRef
|
||||
#endif
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 SkMaskFilter_DEFINED
|
||||
#define SkMaskFilter_DEFINED
|
||||
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
enum SkBlurStyle : int;
|
||||
struct SkDeserialProcs;
|
||||
struct SkRect;
|
||||
|
||||
/** \class SkMaskFilter
|
||||
|
||||
SkMaskFilter is the base class for object that perform transformations on
|
||||
the mask before drawing it. An example subclass is Blur.
|
||||
*/
|
||||
class SK_API SkMaskFilter : public SkFlattenable {
|
||||
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 respectCTM if true the blur's sigma is modified by the CTM.
|
||||
* @return The new blur maskfilter
|
||||
*/
|
||||
static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma,
|
||||
bool respectCTM = true);
|
||||
|
||||
/**
|
||||
* Returns the approximate bounds that would result from filtering the src rect.
|
||||
* The actual result may be different, but it should be contained within the
|
||||
* returned bounds.
|
||||
*/
|
||||
SkRect approximateFilteredBounds(const SkRect& src) const;
|
||||
|
||||
static sk_sp<SkMaskFilter> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
private:
|
||||
static void RegisterFlattenables();
|
||||
friend class SkFlattenable;
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,429 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkMesh_DEFINED
|
||||
#define SkMesh_DEFINED
|
||||
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/core/SkString.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkTArray.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
class GrDirectContext;
|
||||
class SkColorSpace;
|
||||
enum SkAlphaType : int;
|
||||
|
||||
namespace SkSL { struct Program; }
|
||||
|
||||
/**
|
||||
* A specification for custom meshes. Specifies the vertex buffer attributes and stride, the
|
||||
* vertex program that produces a user-defined set of varyings, and a fragment program that ingests
|
||||
* the interpolated varyings and produces local coordinates for shading and optionally a color.
|
||||
*
|
||||
* The varyings must include a float2 named "position". If the passed varyings does not
|
||||
* contain such a varying then one is implicitly added to the final specification and the SkSL
|
||||
* Varyings struct described below. It is an error to have a varying named "position" that has a
|
||||
* type other than float2.
|
||||
*
|
||||
* The provided attributes and varyings are used to create Attributes and Varyings structs in SkSL
|
||||
* that are used by the shaders. Each attribute from the Attribute span becomes a member of the
|
||||
* SkSL Attributes struct and likewise for the varyings.
|
||||
*
|
||||
* The signature of the vertex program must be:
|
||||
* Varyings main(const Attributes).
|
||||
*
|
||||
* The signature of the fragment program must be either:
|
||||
* float2 main(const Varyings)
|
||||
* or
|
||||
* float2 main(const Varyings, out (half4|float4) color)
|
||||
*
|
||||
* where the return value is the local coordinates that will be used to access SkShader. If the
|
||||
* color variant is used, the returned color will be blended with SkPaint's SkShader (or SkPaint
|
||||
* color in absence of a SkShader) using the SkBlender passed to SkCanvas drawMesh(). To use
|
||||
* interpolated local space positions as the shader coordinates, equivalent to how SkPaths are
|
||||
* shaded, return the position field from the Varying struct as the coordinates.
|
||||
*
|
||||
* The vertex and fragment programs may both contain uniforms. Uniforms with the same name are
|
||||
* assumed to be shared between stages. It is an error to specify uniforms in the vertex and
|
||||
* fragment program with the same name but different types, dimensionality, or layouts.
|
||||
*/
|
||||
class SK_API SkMeshSpecification : public SkNVRefCnt<SkMeshSpecification> {
|
||||
public:
|
||||
/** These values are enforced when creating a specification. */
|
||||
static constexpr size_t kMaxStride = 1024;
|
||||
static constexpr size_t kMaxAttributes = 8;
|
||||
static constexpr size_t kStrideAlignment = 4;
|
||||
static constexpr size_t kOffsetAlignment = 4;
|
||||
static constexpr size_t kMaxVaryings = 6;
|
||||
|
||||
struct Attribute {
|
||||
enum class Type : uint32_t { // CPU representation Shader Type
|
||||
kFloat, // float float
|
||||
kFloat2, // two floats float2
|
||||
kFloat3, // three floats float3
|
||||
kFloat4, // four floats float4
|
||||
kUByte4_unorm, // four bytes half4
|
||||
|
||||
kLast = kUByte4_unorm
|
||||
};
|
||||
Type type;
|
||||
size_t offset;
|
||||
SkString name;
|
||||
};
|
||||
|
||||
struct Varying {
|
||||
enum class Type : uint32_t {
|
||||
kFloat, // "float"
|
||||
kFloat2, // "float2"
|
||||
kFloat3, // "float3"
|
||||
kFloat4, // "float4"
|
||||
kHalf, // "half"
|
||||
kHalf2, // "half2"
|
||||
kHalf3, // "half3"
|
||||
kHalf4, // "half4"
|
||||
|
||||
kLast = kHalf4
|
||||
};
|
||||
Type type;
|
||||
SkString name;
|
||||
};
|
||||
|
||||
using Uniform = SkRuntimeEffect::Uniform;
|
||||
using Child = SkRuntimeEffect::Child;
|
||||
|
||||
~SkMeshSpecification();
|
||||
|
||||
struct Result {
|
||||
sk_sp<SkMeshSpecification> specification;
|
||||
SkString error;
|
||||
};
|
||||
|
||||
/**
|
||||
* If successful the return is a specification and an empty error string. Otherwise, it is a
|
||||
* null specification a non-empty error string.
|
||||
*
|
||||
* @param attributes The vertex attributes that will be consumed by 'vs'. Attributes need
|
||||
* not be tightly packed but attribute offsets must be aligned to
|
||||
* kOffsetAlignment and offset + size may not be greater than
|
||||
* 'vertexStride'. At least one attribute is required.
|
||||
* @param vertexStride The offset between successive attribute values. This must be aligned to
|
||||
* kStrideAlignment.
|
||||
* @param varyings The varyings that will be written by 'vs' and read by 'fs'. This may
|
||||
* be empty.
|
||||
* @param vs The vertex shader code that computes a vertex position and the varyings
|
||||
* from the attributes.
|
||||
* @param fs The fragment code that computes a local coordinate and optionally a
|
||||
* color from the varyings. The local coordinate is used to sample
|
||||
* SkShader.
|
||||
* @param cs The colorspace of the color produced by 'fs'. Ignored if 'fs's main()
|
||||
* function does not have a color out param.
|
||||
* @param at The alpha type of the color produced by 'fs'. Ignored if 'fs's main()
|
||||
* function does not have a color out param. Cannot be kUnknown.
|
||||
*/
|
||||
static Result Make(SkSpan<const Attribute> attributes,
|
||||
size_t vertexStride,
|
||||
SkSpan<const Varying> varyings,
|
||||
const SkString& vs,
|
||||
const SkString& fs);
|
||||
static Result Make(SkSpan<const Attribute> attributes,
|
||||
size_t vertexStride,
|
||||
SkSpan<const Varying> varyings,
|
||||
const SkString& vs,
|
||||
const SkString& fs,
|
||||
sk_sp<SkColorSpace> cs);
|
||||
static Result Make(SkSpan<const Attribute> attributes,
|
||||
size_t vertexStride,
|
||||
SkSpan<const Varying> varyings,
|
||||
const SkString& vs,
|
||||
const SkString& fs,
|
||||
sk_sp<SkColorSpace> cs,
|
||||
SkAlphaType at);
|
||||
|
||||
SkSpan<const Attribute> attributes() const { return SkSpan(fAttributes); }
|
||||
|
||||
/**
|
||||
* Combined size of all 'uniform' variables. When creating a SkMesh with this specification
|
||||
* provide an SkData of this size, containing values for all of those variables. Use uniforms()
|
||||
* to get the offset of each uniform within the SkData.
|
||||
*/
|
||||
size_t uniformSize() const;
|
||||
|
||||
/**
|
||||
* Provides info about individual uniforms including the offset into an SkData where each
|
||||
* uniform value should be placed.
|
||||
*/
|
||||
SkSpan<const Uniform> uniforms() const { return SkSpan(fUniforms); }
|
||||
|
||||
/** Provides basic info about individual children: names, indices and runtime effect type. */
|
||||
SkSpan<const Child> children() const { return SkSpan(fChildren); }
|
||||
|
||||
/** Returns a pointer to the named child's description, or nullptr if not found. */
|
||||
const Child* findChild(std::string_view name) const;
|
||||
|
||||
/** Returns a pointer to the named uniform variable's description, or nullptr if not found. */
|
||||
const Uniform* findUniform(std::string_view name) const;
|
||||
|
||||
/** Returns a pointer to the named attribute, or nullptr if not found. */
|
||||
const Attribute* findAttribute(std::string_view name) const;
|
||||
|
||||
/** Returns a pointer to the named varying, or nullptr if not found. */
|
||||
const Varying* findVarying(std::string_view name) const;
|
||||
|
||||
size_t stride() const { return fStride; }
|
||||
|
||||
SkColorSpace* colorSpace() const { return fColorSpace.get(); }
|
||||
|
||||
private:
|
||||
friend struct SkMeshSpecificationPriv;
|
||||
|
||||
enum class ColorType {
|
||||
kNone,
|
||||
kHalf4,
|
||||
kFloat4,
|
||||
};
|
||||
|
||||
static Result MakeFromSourceWithStructs(SkSpan<const Attribute> attributes,
|
||||
size_t stride,
|
||||
SkSpan<const Varying> varyings,
|
||||
const SkString& vs,
|
||||
const SkString& fs,
|
||||
sk_sp<SkColorSpace> cs,
|
||||
SkAlphaType at);
|
||||
|
||||
SkMeshSpecification(SkSpan<const Attribute>,
|
||||
size_t,
|
||||
SkSpan<const Varying>,
|
||||
int passthroughLocalCoordsVaryingIndex,
|
||||
uint32_t deadVaryingMask,
|
||||
std::vector<Uniform> uniforms,
|
||||
std::vector<Child> children,
|
||||
std::unique_ptr<const SkSL::Program>,
|
||||
std::unique_ptr<const SkSL::Program>,
|
||||
ColorType,
|
||||
sk_sp<SkColorSpace>,
|
||||
SkAlphaType);
|
||||
|
||||
SkMeshSpecification(const SkMeshSpecification&) = delete;
|
||||
SkMeshSpecification(SkMeshSpecification&&) = delete;
|
||||
|
||||
SkMeshSpecification& operator=(const SkMeshSpecification&) = delete;
|
||||
SkMeshSpecification& operator=(SkMeshSpecification&&) = delete;
|
||||
|
||||
const std::vector<Attribute> fAttributes;
|
||||
const std::vector<Varying> fVaryings;
|
||||
const std::vector<Uniform> fUniforms;
|
||||
const std::vector<Child> fChildren;
|
||||
const std::unique_ptr<const SkSL::Program> fVS;
|
||||
const std::unique_ptr<const SkSL::Program> fFS;
|
||||
const size_t fStride;
|
||||
uint32_t fHash;
|
||||
const int fPassthroughLocalCoordsVaryingIndex;
|
||||
const uint32_t fDeadVaryingMask;
|
||||
const ColorType fColorType;
|
||||
const sk_sp<SkColorSpace> fColorSpace;
|
||||
const SkAlphaType fAlphaType;
|
||||
};
|
||||
|
||||
/**
|
||||
* A vertex buffer, a topology, optionally an index buffer, and a compatible SkMeshSpecification.
|
||||
*
|
||||
* The data in the vertex buffer is expected to contain the attributes described by the spec
|
||||
* for vertexCount vertices, beginning at vertexOffset. vertexOffset must be aligned to the
|
||||
* SkMeshSpecification's vertex stride. The size of the buffer must be at least vertexOffset +
|
||||
* spec->stride()*vertexCount (even if vertex attributes contains pad at the end of the stride). If
|
||||
* the specified bounds do not contain all the points output by the spec's vertex program when
|
||||
* applied to the vertices in the custom mesh, then the result is undefined.
|
||||
*
|
||||
* MakeIndexed may be used to create an indexed mesh. indexCount indices are read from the index
|
||||
* buffer at the specified offset, which must be aligned to 2. The indices are always unsigned
|
||||
* 16-bit integers. The index count must be at least 3.
|
||||
*
|
||||
* If Make() is used, the implicit index sequence is 0, 1, 2, 3, ... and vertexCount must be at
|
||||
* least 3.
|
||||
*
|
||||
* Both Make() and MakeIndexed() take a SkData with the uniform values. See
|
||||
* SkMeshSpecification::uniformSize() and SkMeshSpecification::uniforms() for sizing and packing
|
||||
* uniforms into the SkData.
|
||||
*/
|
||||
class SK_API SkMesh {
|
||||
public:
|
||||
class IndexBuffer : public SkRefCnt {
|
||||
public:
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* Modifies the data in the IndexBuffer by copying size bytes from data into the buffer
|
||||
* at offset. Fails if offset + size > this->size() or if either offset or size is not
|
||||
* aligned to 4 bytes. The GrDirectContext* must match that used to create the buffer. We
|
||||
* take it as a parameter to emphasize that the context must be used to update the data and
|
||||
* thus the context must be valid for the current thread.
|
||||
*/
|
||||
bool update(GrDirectContext*, const void* data, size_t offset, size_t size);
|
||||
|
||||
private:
|
||||
virtual bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) = 0;
|
||||
};
|
||||
|
||||
class VertexBuffer : public SkRefCnt {
|
||||
public:
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* Modifies the data in the IndexBuffer by copying size bytes from data into the buffer
|
||||
* at offset. Fails if offset + size > this->size() or if either offset or size is not
|
||||
* aligned to 4 bytes. The GrDirectContext* must match that used to create the buffer. We
|
||||
* take it as a parameter to emphasize that the context must be used to update the data and
|
||||
* thus the context must be valid for the current thread.
|
||||
*/
|
||||
bool update(GrDirectContext*, const void* data, size_t offset, size_t size);
|
||||
|
||||
private:
|
||||
virtual bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) = 0;
|
||||
};
|
||||
|
||||
SkMesh();
|
||||
~SkMesh();
|
||||
|
||||
SkMesh(const SkMesh&);
|
||||
SkMesh(SkMesh&&);
|
||||
|
||||
SkMesh& operator=(const SkMesh&);
|
||||
SkMesh& operator=(SkMesh&&);
|
||||
|
||||
enum class Mode { kTriangles, kTriangleStrip };
|
||||
|
||||
struct Result;
|
||||
|
||||
using ChildPtr = SkRuntimeEffect::ChildPtr;
|
||||
|
||||
/**
|
||||
* Creates a non-indexed SkMesh. The returned SkMesh can be tested for validity using
|
||||
* SkMesh::isValid(). An invalid mesh simply fails to draws if passed to SkCanvas::drawMesh().
|
||||
* If the mesh is invalid the returned string give contain the reason for the failure (e.g. the
|
||||
* vertex buffer was null or uniform data too small).
|
||||
*/
|
||||
static Result Make(sk_sp<SkMeshSpecification>,
|
||||
Mode,
|
||||
sk_sp<VertexBuffer>,
|
||||
size_t vertexCount,
|
||||
size_t vertexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
SkSpan<ChildPtr> children,
|
||||
const SkRect& bounds);
|
||||
|
||||
/**
|
||||
* Creates an indexed SkMesh. The returned SkMesh can be tested for validity using
|
||||
* SkMesh::isValid(). A invalid mesh simply fails to draw if passed to SkCanvas::drawMesh().
|
||||
* If the mesh is invalid the returned string give contain the reason for the failure (e.g. the
|
||||
* index buffer was null or uniform data too small).
|
||||
*/
|
||||
static Result MakeIndexed(sk_sp<SkMeshSpecification>,
|
||||
Mode,
|
||||
sk_sp<VertexBuffer>,
|
||||
size_t vertexCount,
|
||||
size_t vertexOffset,
|
||||
sk_sp<IndexBuffer>,
|
||||
size_t indexCount,
|
||||
size_t indexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
SkSpan<ChildPtr> children,
|
||||
const SkRect& bounds);
|
||||
|
||||
sk_sp<SkMeshSpecification> refSpec() const { return fSpec; }
|
||||
SkMeshSpecification* spec() const { return fSpec.get(); }
|
||||
|
||||
Mode mode() const { return fMode; }
|
||||
|
||||
sk_sp<VertexBuffer> refVertexBuffer() const { return fVB; }
|
||||
VertexBuffer* vertexBuffer() const { return fVB.get(); }
|
||||
|
||||
size_t vertexOffset() const { return fVOffset; }
|
||||
size_t vertexCount() const { return fVCount; }
|
||||
|
||||
sk_sp<IndexBuffer> refIndexBuffer() const { return fIB; }
|
||||
IndexBuffer* indexBuffer() const { return fIB.get(); }
|
||||
|
||||
size_t indexOffset() const { return fIOffset; }
|
||||
size_t indexCount() const { return fICount; }
|
||||
|
||||
sk_sp<const SkData> refUniforms() const { return fUniforms; }
|
||||
const SkData* uniforms() const { return fUniforms.get(); }
|
||||
|
||||
SkSpan<const ChildPtr> children() const { return SkSpan(fChildren); }
|
||||
|
||||
SkRect bounds() const { return fBounds; }
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
private:
|
||||
std::tuple<bool, SkString> validate() const;
|
||||
|
||||
sk_sp<SkMeshSpecification> fSpec;
|
||||
|
||||
sk_sp<VertexBuffer> fVB;
|
||||
sk_sp<IndexBuffer> fIB;
|
||||
|
||||
sk_sp<const SkData> fUniforms;
|
||||
skia_private::STArray<2, ChildPtr> fChildren;
|
||||
|
||||
size_t fVOffset = 0; // Must be a multiple of spec->stride()
|
||||
size_t fVCount = 0;
|
||||
|
||||
size_t fIOffset = 0; // Must be a multiple of sizeof(uint16_t)
|
||||
size_t fICount = 0;
|
||||
|
||||
Mode fMode = Mode::kTriangles;
|
||||
|
||||
SkRect fBounds = SkRect::MakeEmpty();
|
||||
};
|
||||
|
||||
struct SkMesh::Result { SkMesh mesh; SkString error; };
|
||||
|
||||
namespace SkMeshes {
|
||||
/**
|
||||
* Makes a CPU-backed index buffer to be used with SkMeshes.
|
||||
*
|
||||
* @param data The data used to populate the buffer, or nullptr to create a zero-
|
||||
* initialized buffer.
|
||||
* @param size Both the size of the data in 'data' and the size of the resulting
|
||||
* buffer, in bytes.
|
||||
*/
|
||||
SK_API sk_sp<SkMesh::IndexBuffer> MakeIndexBuffer(const void* data, size_t size);
|
||||
|
||||
/**
|
||||
* Makes a copy of an index buffer. The copy will be CPU-backed.
|
||||
*/
|
||||
SK_API sk_sp<SkMesh::IndexBuffer> CopyIndexBuffer(const sk_sp<SkMesh::IndexBuffer>&);
|
||||
|
||||
/**
|
||||
* Makes a CPU-backed vertex buffer to be used with SkMeshes.
|
||||
*
|
||||
* @param data The data used to populate the buffer, or nullptr to create a zero-
|
||||
* initialized buffer.
|
||||
* @param size Both the size of the data in 'data' and the size of the resulting
|
||||
* buffer, in bytes.
|
||||
*/
|
||||
SK_API sk_sp<SkMesh::VertexBuffer> MakeVertexBuffer(const void*, size_t size);
|
||||
|
||||
/**
|
||||
* Makes a copy of a vertex buffer. The copy will be CPU-backed.
|
||||
*/
|
||||
SK_API sk_sp<SkMesh::VertexBuffer> CopyVertexBuffer(const sk_sp<SkMesh::VertexBuffer>&);
|
||||
} // namespace SkMeshes
|
||||
|
||||
#endif
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* 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 SK_MILESTONE
|
||||
#define SK_MILESTONE 127
|
||||
#endif
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2022 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkOpenTypeSVGDecoder_DEFINED
|
||||
#define SkOpenTypeSVGDecoder_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class SkCanvas;
|
||||
|
||||
class SkOpenTypeSVGDecoder {
|
||||
public:
|
||||
/** Each instance probably owns an SVG DOM.
|
||||
* The instance may be cached so needs to report how much memory it retains.
|
||||
*/
|
||||
virtual size_t approximateSize() = 0;
|
||||
virtual bool render(SkCanvas&, int upem, SkGlyphID glyphId,
|
||||
SkColor foregroundColor, SkSpan<SkColor> palette) = 0;
|
||||
virtual ~SkOpenTypeSVGDecoder() = default;
|
||||
};
|
||||
|
||||
#endif // SkOpenTypeSVGDecoder_DEFINED
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 SkOverdrawCanvas_DEFINED
|
||||
#define SkOverdrawCanvas_DEFINED
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkCanvasVirtualEnforcer.h"
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkSamplingOptions.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/utils/SkNWayCanvas.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class SkData;
|
||||
class SkDrawable;
|
||||
class SkImage;
|
||||
class SkMatrix;
|
||||
class SkPath;
|
||||
class SkPicture;
|
||||
class SkRRect;
|
||||
class SkRegion;
|
||||
class SkTextBlob;
|
||||
class SkVertices;
|
||||
enum class SkBlendMode;
|
||||
namespace sktext { class GlyphRunList; }
|
||||
struct SkDrawShadowRec;
|
||||
struct SkPoint;
|
||||
struct SkRSXform;
|
||||
struct SkRect;
|
||||
|
||||
/**
|
||||
* Captures all drawing commands. Rather than draw the actual content, this device
|
||||
* increments the alpha channel of each pixel every time it would have been touched
|
||||
* by a draw call. This is useful for detecting overdraw.
|
||||
*/
|
||||
class SK_API SkOverdrawCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {
|
||||
public:
|
||||
/* Does not take ownership of canvas */
|
||||
SkOverdrawCanvas(SkCanvas*);
|
||||
|
||||
void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
|
||||
void onDrawGlyphRunList(
|
||||
const sktext::GlyphRunList& glyphRunList, const SkPaint& paint) override;
|
||||
void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
|
||||
const SkPaint&) override;
|
||||
void onDrawPaint(const SkPaint&) override;
|
||||
void onDrawBehind(const SkPaint& paint) override;
|
||||
void onDrawRect(const SkRect&, const SkPaint&) override;
|
||||
void onDrawRegion(const SkRegion&, const SkPaint&) override;
|
||||
void onDrawOval(const SkRect&, const SkPaint&) override;
|
||||
void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
|
||||
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
|
||||
void onDrawRRect(const SkRRect&, const SkPaint&) override;
|
||||
void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override;
|
||||
void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
|
||||
void onDrawPath(const SkPath&, const SkPaint&) override;
|
||||
|
||||
void onDrawImage2(const SkImage*, SkScalar, SkScalar, const SkSamplingOptions&,
|
||||
const SkPaint*) override;
|
||||
void onDrawImageRect2(const SkImage*, const SkRect&, const SkRect&, const SkSamplingOptions&,
|
||||
const SkPaint*, SrcRectConstraint) override;
|
||||
void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect&, SkFilterMode,
|
||||
const SkPaint*) override;
|
||||
void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
|
||||
SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
|
||||
|
||||
void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
|
||||
void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
|
||||
|
||||
void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override;
|
||||
void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
|
||||
|
||||
void onDrawEdgeAAQuad(const SkRect&, const SkPoint[4], SkCanvas::QuadAAFlags, const SkColor4f&,
|
||||
SkBlendMode) override;
|
||||
void onDrawEdgeAAImageSet2(const ImageSetEntry[], int count, const SkPoint[], const SkMatrix[],
|
||||
const SkSamplingOptions&,const SkPaint*, SrcRectConstraint) override;
|
||||
|
||||
private:
|
||||
inline SkPaint overdrawPaint(const SkPaint& paint);
|
||||
|
||||
SkPaint fPaint;
|
||||
|
||||
using INHERITED = SkCanvasVirtualEnforcer<SkNWayCanvas>;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,695 @@
|
||||
/*
|
||||
* 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 SkPaint_DEFINED
|
||||
#define SkPaint_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkCPUTypes.h"
|
||||
#include "include/private/base/SkFloatingPoint.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
#include "include/private/base/SkTypeTraits.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
class SkBlender;
|
||||
class SkColorFilter;
|
||||
class SkColorSpace;
|
||||
class SkImageFilter;
|
||||
class SkMaskFilter;
|
||||
class SkPathEffect;
|
||||
class SkShader;
|
||||
enum class SkBlendMode;
|
||||
struct SkRect;
|
||||
|
||||
/** \class SkPaint
|
||||
SkPaint controls options applied when drawing. SkPaint collects all
|
||||
options outside of the SkCanvas clip and SkCanvas matrix.
|
||||
|
||||
Various options apply to strokes and fills, and images.
|
||||
|
||||
SkPaint collects effects and filters that describe single-pass and multiple-pass
|
||||
algorithms that alter the drawing geometry, color, and transparency. For instance,
|
||||
SkPaint does not directly implement dashing or blur, but contains the objects that do so.
|
||||
*/
|
||||
class SK_API SkPaint {
|
||||
public:
|
||||
|
||||
/** Constructs SkPaint with default values.
|
||||
|
||||
@return default initialized SkPaint
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_empty_constructor
|
||||
*/
|
||||
SkPaint();
|
||||
|
||||
/** Constructs SkPaint with default values and the given color.
|
||||
|
||||
Sets alpha and RGB used when stroking and filling. The color is four floating
|
||||
point values, unpremultiplied. The color values are interpreted as being in
|
||||
the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
|
||||
sRGB color space.
|
||||
|
||||
@param color unpremultiplied RGBA
|
||||
@param colorSpace SkColorSpace describing the encoding of color
|
||||
@return SkPaint with the given color
|
||||
*/
|
||||
explicit SkPaint(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
|
||||
|
||||
/** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
|
||||
SkMaskFilter, SkColorFilter, and SkImageFilter are shared
|
||||
between the original paint and the copy. Objects containing SkRefCnt increment
|
||||
their references by one.
|
||||
|
||||
The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
|
||||
and SkImageFilter cannot be modified after they are created.
|
||||
This prevents objects with SkRefCnt from being modified once SkPaint refers to them.
|
||||
|
||||
@param paint original to copy
|
||||
@return shallow copy of paint
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_copy_const_SkPaint
|
||||
*/
|
||||
SkPaint(const SkPaint& paint);
|
||||
|
||||
/** Implements a move constructor to avoid increasing the reference counts
|
||||
of objects referenced by the paint.
|
||||
|
||||
After the call, paint is undefined, and can be safely destructed.
|
||||
|
||||
@param paint original to move
|
||||
@return content of paint
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_move_SkPaint
|
||||
*/
|
||||
SkPaint(SkPaint&& paint);
|
||||
|
||||
/** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader,
|
||||
SkMaskFilter, SkColorFilter, and SkImageFilter. If the
|
||||
objects containing SkRefCnt go to zero, they are deleted.
|
||||
*/
|
||||
~SkPaint();
|
||||
|
||||
/** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
|
||||
SkMaskFilter, SkColorFilter, and SkImageFilter are shared
|
||||
between the original paint and the copy. Objects containing SkRefCnt in the
|
||||
prior destination are decreased by one, and the referenced objects are deleted if the
|
||||
resulting count is zero. Objects containing SkRefCnt in the parameter paint
|
||||
are increased by one. paint is unmodified.
|
||||
|
||||
@param paint original to copy
|
||||
@return content of paint
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_copy_operator
|
||||
*/
|
||||
SkPaint& operator=(const SkPaint& paint);
|
||||
|
||||
/** Moves the paint to avoid increasing the reference counts
|
||||
of objects referenced by the paint parameter. Objects containing SkRefCnt in the
|
||||
prior destination are decreased by one; those objects are deleted if the resulting count
|
||||
is zero.
|
||||
|
||||
After the call, paint is undefined, and can be safely destructed.
|
||||
|
||||
@param paint original to move
|
||||
@return content of paint
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_move_operator
|
||||
*/
|
||||
SkPaint& operator=(SkPaint&& paint);
|
||||
|
||||
/** Compares a and b, and returns true if a and b are equivalent. May return false
|
||||
if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
|
||||
or SkImageFilter have identical contents but different pointers.
|
||||
|
||||
@param a SkPaint to compare
|
||||
@param b SkPaint to compare
|
||||
@return true if SkPaint pair are equivalent
|
||||
*/
|
||||
SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
|
||||
|
||||
/** Compares a and b, and returns true if a and b are not equivalent. May return true
|
||||
if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
|
||||
or SkImageFilter have identical contents but different pointers.
|
||||
|
||||
@param a SkPaint to compare
|
||||
@param b SkPaint to compare
|
||||
@return true if SkPaint pair are not equivalent
|
||||
*/
|
||||
friend bool operator!=(const SkPaint& a, const SkPaint& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
/** Sets all SkPaint contents to their initial values. This is equivalent to replacing
|
||||
SkPaint with the result of SkPaint().
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_reset
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
|
||||
@return antialiasing state
|
||||
*/
|
||||
bool isAntiAlias() const {
|
||||
return SkToBool(fBitfields.fAntiAlias);
|
||||
}
|
||||
|
||||
/** Requests, but does not require, that edge pixels draw opaque or with
|
||||
partial transparency.
|
||||
@param aa setting for antialiasing
|
||||
*/
|
||||
void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); }
|
||||
|
||||
/** Returns true if color error may be distributed to smooth color transition.
|
||||
@return dithering state
|
||||
*/
|
||||
bool isDither() const {
|
||||
return SkToBool(fBitfields.fDither);
|
||||
}
|
||||
|
||||
/** Requests, but does not require, to distribute color error.
|
||||
@param dither setting for ditering
|
||||
*/
|
||||
void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); }
|
||||
|
||||
/** \enum SkPaint::Style
|
||||
Set Style to fill, stroke, or both fill and stroke geometry.
|
||||
The stroke and fill
|
||||
share all paint attributes; for instance, they are drawn with the same color.
|
||||
|
||||
Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
|
||||
a fill draw.
|
||||
*/
|
||||
enum Style : uint8_t {
|
||||
kFill_Style, //!< set to fill geometry
|
||||
kStroke_Style, //!< set to stroke geometry
|
||||
kStrokeAndFill_Style, //!< sets to stroke and fill geometry
|
||||
};
|
||||
|
||||
/** May be used to verify that SkPaint::Style is a legal value.
|
||||
*/
|
||||
static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
|
||||
|
||||
/** Returns whether the geometry is filled, stroked, or filled and stroked.
|
||||
*/
|
||||
Style getStyle() const { return (Style)fBitfields.fStyle; }
|
||||
|
||||
/** Sets whether the geometry is filled, stroked, or filled and stroked.
|
||||
Has no effect if style is not a legal SkPaint::Style value.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setStyle
|
||||
example: https://fiddle.skia.org/c/@Stroke_Width
|
||||
*/
|
||||
void setStyle(Style style);
|
||||
|
||||
/**
|
||||
* Set paint's style to kStroke if true, or kFill if false.
|
||||
*/
|
||||
void setStroke(bool);
|
||||
|
||||
/** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
|
||||
Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
|
||||
a color component.
|
||||
|
||||
@return unpremultiplied ARGB
|
||||
*/
|
||||
SkColor getColor() const { return fColor4f.toSkColor(); }
|
||||
|
||||
/** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are
|
||||
extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
|
||||
|
||||
@return unpremultiplied RGBA
|
||||
*/
|
||||
SkColor4f getColor4f() const { return fColor4f; }
|
||||
|
||||
/** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
|
||||
unpremultiplied, packing 8-bit components for alpha, red, blue, and green.
|
||||
|
||||
@param color unpremultiplied ARGB
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setColor
|
||||
*/
|
||||
void setColor(SkColor color);
|
||||
|
||||
/** Sets alpha and RGB used when stroking and filling. The color is four floating
|
||||
point values, unpremultiplied. The color values are interpreted as being in
|
||||
the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
|
||||
sRGB color space.
|
||||
|
||||
@param color unpremultiplied RGBA
|
||||
@param colorSpace SkColorSpace describing the encoding of color
|
||||
*/
|
||||
void setColor(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
|
||||
|
||||
void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace = nullptr) {
|
||||
this->setColor(color, colorSpace);
|
||||
}
|
||||
|
||||
/** Retrieves alpha from the color used when stroking and filling.
|
||||
|
||||
@return alpha ranging from zero, fully transparent, to one, fully opaque
|
||||
*/
|
||||
float getAlphaf() const { return fColor4f.fA; }
|
||||
|
||||
// Helper that scales the alpha by 255.
|
||||
uint8_t getAlpha() const {
|
||||
return static_cast<uint8_t>(sk_float_round2int(this->getAlphaf() * 255));
|
||||
}
|
||||
|
||||
/** Replaces alpha, leaving RGB
|
||||
unchanged. An out of range value triggers an assert in the debug
|
||||
build. a is a value from 0.0 to 1.0.
|
||||
a set to zero makes color fully transparent; a set to 1.0 makes color
|
||||
fully opaque.
|
||||
|
||||
@param a alpha component of color
|
||||
*/
|
||||
void setAlphaf(float a);
|
||||
|
||||
// Helper that accepts an int between 0 and 255, and divides it by 255.0
|
||||
void setAlpha(U8CPU a) {
|
||||
this->setAlphaf(a * (1.0f / 255));
|
||||
}
|
||||
|
||||
/** Sets color used when drawing solid fills. The color components range from 0 to 255.
|
||||
The color is unpremultiplied; alpha sets the transparency independent of RGB.
|
||||
|
||||
@param a amount of alpha, from fully transparent (0) to fully opaque (255)
|
||||
@param r amount of red, from no red (0) to full red (255)
|
||||
@param g amount of green, from no green (0) to full green (255)
|
||||
@param b amount of blue, from no blue (0) to full blue (255)
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setARGB
|
||||
*/
|
||||
void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
|
||||
|
||||
/** Returns the thickness of the pen used by SkPaint to
|
||||
outline the shape.
|
||||
|
||||
@return zero for hairline, greater than zero for pen thickness
|
||||
*/
|
||||
SkScalar getStrokeWidth() const { return fWidth; }
|
||||
|
||||
/** Sets the thickness of the pen used by the paint to outline the shape.
|
||||
A stroke-width of zero is treated as "hairline" width. Hairlines are always exactly one
|
||||
pixel wide in device space (their thickness does not change as the canvas is scaled).
|
||||
Negative stroke-widths are invalid; setting a negative width will have no effect.
|
||||
|
||||
@param width zero thickness for hairline; greater than zero for pen thickness
|
||||
|
||||
example: https://fiddle.skia.org/c/@Miter_Limit
|
||||
example: https://fiddle.skia.org/c/@Paint_setStrokeWidth
|
||||
*/
|
||||
void setStrokeWidth(SkScalar width);
|
||||
|
||||
/** Returns the limit at which a sharp corner is drawn beveled.
|
||||
|
||||
@return zero and greater miter limit
|
||||
*/
|
||||
SkScalar getStrokeMiter() const { return fMiterLimit; }
|
||||
|
||||
/** Sets the limit at which a sharp corner is drawn beveled.
|
||||
Valid values are zero and greater.
|
||||
Has no effect if miter is less than zero.
|
||||
|
||||
@param miter zero and greater miter limit
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setStrokeMiter
|
||||
*/
|
||||
void setStrokeMiter(SkScalar miter);
|
||||
|
||||
/** \enum SkPaint::Cap
|
||||
Cap draws at the beginning and end of an open path contour.
|
||||
*/
|
||||
enum Cap {
|
||||
kButt_Cap, //!< no stroke extension
|
||||
kRound_Cap, //!< adds circle
|
||||
kSquare_Cap, //!< adds square
|
||||
kLast_Cap = kSquare_Cap, //!< largest Cap value
|
||||
kDefault_Cap = kButt_Cap, //!< equivalent to kButt_Cap
|
||||
};
|
||||
|
||||
/** May be used to verify that SkPaint::Cap is a legal value.
|
||||
*/
|
||||
static constexpr int kCapCount = kLast_Cap + 1;
|
||||
|
||||
/** \enum SkPaint::Join
|
||||
Join specifies how corners are drawn when a shape is stroked. Join
|
||||
affects the four corners of a stroked rectangle, and the connected segments in a
|
||||
stroked path.
|
||||
|
||||
Choose miter join to draw sharp corners. Choose round join to draw a circle with a
|
||||
radius equal to the stroke width on top of the corner. Choose bevel join to minimally
|
||||
connect the thick strokes.
|
||||
|
||||
The fill path constructed to describe the stroked path respects the join setting but may
|
||||
not contain the actual join. For instance, a fill path constructed with round joins does
|
||||
not necessarily include circles at each connected segment.
|
||||
*/
|
||||
enum Join : uint8_t {
|
||||
kMiter_Join, //!< extends to miter limit
|
||||
kRound_Join, //!< adds circle
|
||||
kBevel_Join, //!< connects outside edges
|
||||
kLast_Join = kBevel_Join, //!< equivalent to the largest value for Join
|
||||
kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
|
||||
};
|
||||
|
||||
/** May be used to verify that SkPaint::Join is a legal value.
|
||||
*/
|
||||
static constexpr int kJoinCount = kLast_Join + 1;
|
||||
|
||||
/** Returns the geometry drawn at the beginning and end of strokes.
|
||||
*/
|
||||
Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
|
||||
|
||||
/** Sets the geometry drawn at the beginning and end of strokes.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setStrokeCap_a
|
||||
example: https://fiddle.skia.org/c/@Paint_setStrokeCap_b
|
||||
*/
|
||||
void setStrokeCap(Cap cap);
|
||||
|
||||
/** Returns the geometry drawn at the corners of strokes.
|
||||
*/
|
||||
Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
|
||||
|
||||
/** Sets the geometry drawn at the corners of strokes.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setStrokeJoin
|
||||
*/
|
||||
void setStrokeJoin(Join join);
|
||||
|
||||
/** Returns optional colors used when filling a path, such as a gradient.
|
||||
|
||||
Does not alter SkShader SkRefCnt.
|
||||
|
||||
@return SkShader if previously set, nullptr otherwise
|
||||
*/
|
||||
SkShader* getShader() const { return fShader.get(); }
|
||||
|
||||
/** Returns optional colors used when filling a path, such as a gradient.
|
||||
|
||||
Increases SkShader SkRefCnt by one.
|
||||
|
||||
@return SkShader if previously set, nullptr otherwise
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_refShader
|
||||
*/
|
||||
sk_sp<SkShader> refShader() const;
|
||||
|
||||
/** Sets optional colors used when filling a path, such as a gradient.
|
||||
|
||||
Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.
|
||||
Increments shader SkRefCnt by one.
|
||||
|
||||
@param shader how geometry is filled with color; if nullptr, color is used instead
|
||||
|
||||
example: https://fiddle.skia.org/c/@Color_Filter_Methods
|
||||
example: https://fiddle.skia.org/c/@Paint_setShader
|
||||
*/
|
||||
void setShader(sk_sp<SkShader> shader);
|
||||
|
||||
/** Returns SkColorFilter if set, or nullptr.
|
||||
Does not alter SkColorFilter SkRefCnt.
|
||||
|
||||
@return SkColorFilter if previously set, nullptr otherwise
|
||||
*/
|
||||
SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
|
||||
|
||||
/** Returns SkColorFilter if set, or nullptr.
|
||||
Increases SkColorFilter SkRefCnt by one.
|
||||
|
||||
@return SkColorFilter if set, or nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_refColorFilter
|
||||
*/
|
||||
sk_sp<SkColorFilter> refColorFilter() const;
|
||||
|
||||
/** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous
|
||||
SkColorFilter. Pass nullptr to clear SkColorFilter.
|
||||
|
||||
Increments filter SkRefCnt by one.
|
||||
|
||||
@param colorFilter SkColorFilter to apply to subsequent draw
|
||||
|
||||
example: https://fiddle.skia.org/c/@Blend_Mode_Methods
|
||||
example: https://fiddle.skia.org/c/@Paint_setColorFilter
|
||||
*/
|
||||
void setColorFilter(sk_sp<SkColorFilter> colorFilter);
|
||||
|
||||
/** If the current blender can be represented as a SkBlendMode enum, this returns that
|
||||
* enum in the optional's value(). If it cannot, then the returned optional does not
|
||||
* contain a value.
|
||||
*/
|
||||
std::optional<SkBlendMode> asBlendMode() const;
|
||||
|
||||
/**
|
||||
* Queries the blender, and if it can be represented as a SkBlendMode, return that mode,
|
||||
* else return the defaultMode provided.
|
||||
*/
|
||||
SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const;
|
||||
|
||||
/** Returns true iff the current blender claims to be equivalent to SkBlendMode::kSrcOver.
|
||||
*
|
||||
* Also returns true of the current blender is nullptr.
|
||||
*/
|
||||
bool isSrcOver() const;
|
||||
|
||||
/** Helper method for calling setBlender().
|
||||
*
|
||||
* This sets a blender that implements the specified blendmode enum.
|
||||
*/
|
||||
void setBlendMode(SkBlendMode mode);
|
||||
|
||||
/** Returns the user-supplied blend function, if one has been set.
|
||||
* Does not alter SkBlender's SkRefCnt.
|
||||
*
|
||||
* A nullptr blender signifies the default SrcOver behavior.
|
||||
*
|
||||
* @return the SkBlender assigned to this paint, otherwise nullptr
|
||||
*/
|
||||
SkBlender* getBlender() const { return fBlender.get(); }
|
||||
|
||||
/** Returns the user-supplied blend function, if one has been set.
|
||||
* Increments the SkBlender's SkRefCnt by one.
|
||||
*
|
||||
* A nullptr blender signifies the default SrcOver behavior.
|
||||
*
|
||||
* @return the SkBlender assigned to this paint, otherwise nullptr
|
||||
*/
|
||||
sk_sp<SkBlender> refBlender() const;
|
||||
|
||||
/** Sets the current blender, increasing its refcnt, and if a blender is already
|
||||
* present, decreasing that object's refcnt.
|
||||
*
|
||||
* A nullptr blender signifies the default SrcOver behavior.
|
||||
*
|
||||
* For convenience, you can call setBlendMode() if the blend effect can be expressed
|
||||
* as one of those values.
|
||||
*/
|
||||
void setBlender(sk_sp<SkBlender> blender);
|
||||
|
||||
/** Returns SkPathEffect if set, or nullptr.
|
||||
Does not alter SkPathEffect SkRefCnt.
|
||||
|
||||
@return SkPathEffect if previously set, nullptr otherwise
|
||||
*/
|
||||
SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
|
||||
|
||||
/** Returns SkPathEffect if set, or nullptr.
|
||||
Increases SkPathEffect SkRefCnt by one.
|
||||
|
||||
@return SkPathEffect if previously set, nullptr otherwise
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_refPathEffect
|
||||
*/
|
||||
sk_sp<SkPathEffect> refPathEffect() const;
|
||||
|
||||
/** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous
|
||||
SkPathEffect. Pass nullptr to leave the path geometry unaltered.
|
||||
|
||||
Increments pathEffect SkRefCnt by one.
|
||||
|
||||
@param pathEffect replace SkPath with a modification when drawn
|
||||
|
||||
example: https://fiddle.skia.org/c/@Mask_Filter_Methods
|
||||
example: https://fiddle.skia.org/c/@Paint_setPathEffect
|
||||
*/
|
||||
void setPathEffect(sk_sp<SkPathEffect> pathEffect);
|
||||
|
||||
/** Returns SkMaskFilter if set, or nullptr.
|
||||
Does not alter SkMaskFilter SkRefCnt.
|
||||
|
||||
@return SkMaskFilter if previously set, nullptr otherwise
|
||||
*/
|
||||
SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
|
||||
|
||||
/** Returns SkMaskFilter if set, or nullptr.
|
||||
|
||||
Increases SkMaskFilter SkRefCnt by one.
|
||||
|
||||
@return SkMaskFilter if previously set, nullptr otherwise
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_refMaskFilter
|
||||
*/
|
||||
sk_sp<SkMaskFilter> refMaskFilter() const;
|
||||
|
||||
/** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous
|
||||
SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on
|
||||
mask alpha unaltered.
|
||||
|
||||
Increments maskFilter SkRefCnt by one.
|
||||
|
||||
@param maskFilter modifies clipping mask generated from drawn geometry
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setMaskFilter
|
||||
example: https://fiddle.skia.org/c/@Typeface_Methods
|
||||
*/
|
||||
void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
|
||||
|
||||
/** Returns SkImageFilter if set, or nullptr.
|
||||
Does not alter SkImageFilter SkRefCnt.
|
||||
|
||||
@return SkImageFilter if previously set, nullptr otherwise
|
||||
*/
|
||||
SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
|
||||
|
||||
/** Returns SkImageFilter if set, or nullptr.
|
||||
Increases SkImageFilter SkRefCnt by one.
|
||||
|
||||
@return SkImageFilter if previously set, nullptr otherwise
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_refImageFilter
|
||||
*/
|
||||
sk_sp<SkImageFilter> refImageFilter() const;
|
||||
|
||||
/** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous
|
||||
SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect
|
||||
on drawing.
|
||||
|
||||
Increments imageFilter SkRefCnt by one.
|
||||
|
||||
@param imageFilter how SkImage is sampled when transformed
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_setImageFilter
|
||||
*/
|
||||
void setImageFilter(sk_sp<SkImageFilter> imageFilter);
|
||||
|
||||
/** Returns true if SkPaint prevents all drawing;
|
||||
otherwise, the SkPaint may or may not allow drawing.
|
||||
|
||||
Returns true if, for example, SkBlendMode combined with alpha computes a
|
||||
new alpha of zero.
|
||||
|
||||
@return true if SkPaint prevents all drawing
|
||||
|
||||
example: https://fiddle.skia.org/c/@Paint_nothingToDraw
|
||||
*/
|
||||
bool nothingToDraw() const;
|
||||
|
||||
/** (to be made private)
|
||||
Returns true if SkPaint does not include elements requiring extensive computation
|
||||
to compute device bounds of drawn geometry. For instance, SkPaint with SkPathEffect
|
||||
always returns false.
|
||||
|
||||
@return true if SkPaint allows for fast computation of bounds
|
||||
*/
|
||||
bool canComputeFastBounds() const;
|
||||
|
||||
/** (to be made private)
|
||||
Only call this if canComputeFastBounds() returned true. This takes a
|
||||
raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
|
||||
effects in the paint (e.g. stroking). If needed, it uses the storage
|
||||
parameter. It returns the adjusted bounds that can then be used
|
||||
for SkCanvas::quickReject tests.
|
||||
|
||||
The returned SkRect will either be orig or storage, thus the caller
|
||||
should not rely on storage being set to the result, but should always
|
||||
use the returned value. It is legal for orig and storage to be the same
|
||||
SkRect.
|
||||
For example:
|
||||
if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
|
||||
SkRect storage;
|
||||
if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
|
||||
return; // do not draw the path
|
||||
}
|
||||
}
|
||||
// draw the path
|
||||
|
||||
@param orig geometry modified by SkPaint when drawn
|
||||
@param storage computed bounds of geometry; may not be nullptr
|
||||
@return fast computed bounds
|
||||
*/
|
||||
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const;
|
||||
|
||||
/** (to be made private)
|
||||
|
||||
@param orig geometry modified by SkPaint when drawn
|
||||
@param storage computed bounds of geometry
|
||||
@return fast computed bounds
|
||||
*/
|
||||
const SkRect& computeFastStrokeBounds(const SkRect& orig,
|
||||
SkRect* storage) const {
|
||||
return this->doComputeFastBounds(orig, storage, kStroke_Style);
|
||||
}
|
||||
|
||||
/** (to be made private)
|
||||
Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to
|
||||
account for additional width required by stroking orig, without
|
||||
altering SkPaint::Style set to fill.
|
||||
|
||||
@param orig geometry modified by SkPaint when drawn
|
||||
@param storage computed bounds of geometry
|
||||
@param style overrides SkPaint::Style
|
||||
@return fast computed bounds
|
||||
*/
|
||||
const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
|
||||
Style style) const;
|
||||
|
||||
using sk_is_trivially_relocatable = std::true_type;
|
||||
|
||||
private:
|
||||
sk_sp<SkPathEffect> fPathEffect;
|
||||
sk_sp<SkShader> fShader;
|
||||
sk_sp<SkMaskFilter> fMaskFilter;
|
||||
sk_sp<SkColorFilter> fColorFilter;
|
||||
sk_sp<SkImageFilter> fImageFilter;
|
||||
sk_sp<SkBlender> fBlender;
|
||||
|
||||
SkColor4f fColor4f;
|
||||
SkScalar fWidth;
|
||||
SkScalar fMiterLimit;
|
||||
union {
|
||||
struct {
|
||||
unsigned fAntiAlias : 1;
|
||||
unsigned fDither : 1;
|
||||
unsigned fCapType : 2;
|
||||
unsigned fJoinType : 2;
|
||||
unsigned fStyle : 2;
|
||||
unsigned fPadding : 24; // 24 == 32 -1-1-2-2-2
|
||||
} fBitfields;
|
||||
uint32_t fBitfieldsUInt;
|
||||
};
|
||||
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fPathEffect)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fShader)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fMaskFilter)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fColorFilter)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fImageFilter)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fBlender)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fColor4f)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fBitfields)>::value);
|
||||
|
||||
friend class SkPaintPriv;
|
||||
};
|
||||
|
||||
#endif
|
1943
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/core/SkPath.h
Normal file
1943
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/core/SkPath.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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 SkPathBuilder_DEFINED
|
||||
#define SkPathBuilder_DEFINED
|
||||
|
||||
#include "include/core/SkPath.h"
|
||||
#include "include/core/SkPathTypes.h"
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/SkPathRef.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
class SkRRect;
|
||||
|
||||
class SK_API SkPathBuilder {
|
||||
public:
|
||||
SkPathBuilder();
|
||||
SkPathBuilder(SkPathFillType);
|
||||
SkPathBuilder(const SkPath&);
|
||||
SkPathBuilder(const SkPathBuilder&) = default;
|
||||
~SkPathBuilder();
|
||||
|
||||
SkPathBuilder& operator=(const SkPath&);
|
||||
SkPathBuilder& operator=(const SkPathBuilder&) = default;
|
||||
|
||||
SkPathFillType fillType() const { return fFillType; }
|
||||
SkRect computeBounds() const;
|
||||
|
||||
SkPath snapshot() const; // the builder is unchanged after returning this path
|
||||
SkPath detach(); // the builder is reset to empty after returning this path
|
||||
|
||||
SkPathBuilder& setFillType(SkPathFillType ft) { fFillType = ft; return *this; }
|
||||
SkPathBuilder& setIsVolatile(bool isVolatile) { fIsVolatile = isVolatile; return *this; }
|
||||
|
||||
SkPathBuilder& reset();
|
||||
|
||||
SkPathBuilder& moveTo(SkPoint pt);
|
||||
SkPathBuilder& moveTo(SkScalar x, SkScalar y) { return this->moveTo(SkPoint::Make(x, y)); }
|
||||
|
||||
SkPathBuilder& lineTo(SkPoint pt);
|
||||
SkPathBuilder& lineTo(SkScalar x, SkScalar y) { return this->lineTo(SkPoint::Make(x, y)); }
|
||||
|
||||
SkPathBuilder& quadTo(SkPoint pt1, SkPoint pt2);
|
||||
SkPathBuilder& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
||||
return this->quadTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2));
|
||||
}
|
||||
SkPathBuilder& quadTo(const SkPoint pts[2]) { return this->quadTo(pts[0], pts[1]); }
|
||||
|
||||
SkPathBuilder& conicTo(SkPoint pt1, SkPoint pt2, SkScalar w);
|
||||
SkPathBuilder& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
|
||||
return this->conicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), w);
|
||||
}
|
||||
SkPathBuilder& conicTo(const SkPoint pts[2], SkScalar w) {
|
||||
return this->conicTo(pts[0], pts[1], w);
|
||||
}
|
||||
|
||||
SkPathBuilder& cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
|
||||
SkPathBuilder& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
|
||||
return this->cubicTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), SkPoint::Make(x3, y3));
|
||||
}
|
||||
SkPathBuilder& cubicTo(const SkPoint pts[3]) {
|
||||
return this->cubicTo(pts[0], pts[1], pts[2]);
|
||||
}
|
||||
|
||||
SkPathBuilder& close();
|
||||
|
||||
// Append a series of lineTo(...)
|
||||
SkPathBuilder& polylineTo(const SkPoint pts[], int count);
|
||||
SkPathBuilder& polylineTo(const std::initializer_list<SkPoint>& list) {
|
||||
return this->polylineTo(list.begin(), SkToInt(list.size()));
|
||||
}
|
||||
|
||||
// Relative versions of segments, relative to the previous position.
|
||||
|
||||
SkPathBuilder& rLineTo(SkPoint pt);
|
||||
SkPathBuilder& rLineTo(SkScalar x, SkScalar y) { return this->rLineTo({x, y}); }
|
||||
SkPathBuilder& rQuadTo(SkPoint pt1, SkPoint pt2);
|
||||
SkPathBuilder& rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
||||
return this->rQuadTo({x1, y1}, {x2, y2});
|
||||
}
|
||||
SkPathBuilder& rConicTo(SkPoint p1, SkPoint p2, SkScalar w);
|
||||
SkPathBuilder& rConicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w) {
|
||||
return this->rConicTo({x1, y1}, {x2, y2}, w);
|
||||
}
|
||||
SkPathBuilder& rCubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3);
|
||||
SkPathBuilder& rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3) {
|
||||
return this->rCubicTo({x1, y1}, {x2, y2}, {x3, y3});
|
||||
}
|
||||
|
||||
// Arcs
|
||||
|
||||
/** Appends arc to the builder. Arc added is part of ellipse
|
||||
bounded by oval, from startAngle through sweepAngle. Both startAngle and
|
||||
sweepAngle are measured in degrees, where zero degrees is aligned with the
|
||||
positive x-axis, and positive sweeps extends arc clockwise.
|
||||
|
||||
arcTo() adds line connecting the builder's last point to initial arc point if forceMoveTo
|
||||
is false and the builder is not empty. Otherwise, added contour begins with first point
|
||||
of arc. Angles greater than -360 and less than 360 are treated modulo 360.
|
||||
|
||||
@param oval bounds of ellipse containing arc
|
||||
@param startAngleDeg starting angle of arc in degrees
|
||||
@param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
|
||||
@param forceMoveTo true to start a new contour with arc
|
||||
@return reference to the builder
|
||||
*/
|
||||
SkPathBuilder& arcTo(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg,
|
||||
bool forceMoveTo);
|
||||
|
||||
/** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
|
||||
weighted to describe part of circle. Arc is contained by tangent from
|
||||
last SkPath point to p1, and tangent from p1 to p2. Arc
|
||||
is part of circle sized to radius, positioned so it touches both tangent lines.
|
||||
|
||||
If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
|
||||
The length of vector from p1 to p2 does not affect arc.
|
||||
|
||||
Arc sweep is always less than 180 degrees. If radius is zero, or if
|
||||
tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
|
||||
|
||||
arcTo() appends at most one line and one conic.
|
||||
arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
|
||||
|
||||
@param p1 SkPoint common to pair of tangents
|
||||
@param p2 end of second tangent
|
||||
@param radius distance from arc to circle center
|
||||
@return reference to SkPath
|
||||
*/
|
||||
SkPathBuilder& arcTo(SkPoint p1, SkPoint p2, SkScalar radius);
|
||||
|
||||
enum ArcSize {
|
||||
kSmall_ArcSize, //!< smaller of arc pair
|
||||
kLarge_ArcSize, //!< larger of arc pair
|
||||
};
|
||||
|
||||
/** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
|
||||
part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
|
||||
from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
|
||||
clockwise or counterclockwise,
|
||||
and smaller or larger.
|
||||
|
||||
Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
|
||||
radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
|
||||
fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
|
||||
an arc.
|
||||
|
||||
arcTo() appends up to four conic curves.
|
||||
arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
|
||||
opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
|
||||
kCW_Direction cast to int is zero.
|
||||
|
||||
@param r radii on axes before x-axis rotation
|
||||
@param xAxisRotate x-axis rotation in degrees; positive values are clockwise
|
||||
@param largeArc chooses smaller or larger arc
|
||||
@param sweep chooses clockwise or counterclockwise arc
|
||||
@param xy end of arc
|
||||
@return reference to SkPath
|
||||
*/
|
||||
SkPathBuilder& arcTo(SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep,
|
||||
SkPoint xy);
|
||||
|
||||
/** Appends arc to the builder, as the start of new contour. Arc added is part of ellipse
|
||||
bounded by oval, from startAngle through sweepAngle. Both startAngle and
|
||||
sweepAngle are measured in degrees, where zero degrees is aligned with the
|
||||
positive x-axis, and positive sweeps extends arc clockwise.
|
||||
|
||||
If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
|
||||
zero, append oval instead of arc. Otherwise, sweepAngle values are treated
|
||||
modulo 360, and arc may or may not draw depending on numeric rounding.
|
||||
|
||||
@param oval bounds of ellipse containing arc
|
||||
@param startAngleDeg starting angle of arc in degrees
|
||||
@param sweepAngleDeg sweep, in degrees. Positive is clockwise; treated modulo 360
|
||||
@return reference to this builder
|
||||
*/
|
||||
SkPathBuilder& addArc(const SkRect& oval, SkScalar startAngleDeg, SkScalar sweepAngleDeg);
|
||||
|
||||
// Add a new contour
|
||||
|
||||
SkPathBuilder& addRect(const SkRect&, SkPathDirection, unsigned startIndex);
|
||||
SkPathBuilder& addOval(const SkRect&, SkPathDirection, unsigned startIndex);
|
||||
SkPathBuilder& addRRect(const SkRRect&, SkPathDirection, unsigned startIndex);
|
||||
|
||||
SkPathBuilder& addRect(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
|
||||
return this->addRect(rect, dir, 0);
|
||||
}
|
||||
SkPathBuilder& addOval(const SkRect& rect, SkPathDirection dir = SkPathDirection::kCW) {
|
||||
// legacy start index: 1
|
||||
return this->addOval(rect, dir, 1);
|
||||
}
|
||||
SkPathBuilder& addRRect(const SkRRect& rrect, SkPathDirection dir = SkPathDirection::kCW) {
|
||||
// legacy start indices: 6 (CW) and 7 (CCW)
|
||||
return this->addRRect(rrect, dir, dir == SkPathDirection::kCW ? 6 : 7);
|
||||
}
|
||||
|
||||
SkPathBuilder& addCircle(SkScalar center_x, SkScalar center_y, SkScalar radius,
|
||||
SkPathDirection dir = SkPathDirection::kCW);
|
||||
|
||||
SkPathBuilder& addPolygon(const SkPoint pts[], int count, bool isClosed);
|
||||
SkPathBuilder& addPolygon(const std::initializer_list<SkPoint>& list, bool isClosed) {
|
||||
return this->addPolygon(list.begin(), SkToInt(list.size()), isClosed);
|
||||
}
|
||||
|
||||
SkPathBuilder& addPath(const SkPath&);
|
||||
|
||||
// Performance hint, to reserve extra storage for subsequent calls to lineTo, quadTo, etc.
|
||||
|
||||
void incReserve(int extraPtCount, int extraVerbCount);
|
||||
void incReserve(int extraPtCount) {
|
||||
this->incReserve(extraPtCount, extraPtCount);
|
||||
}
|
||||
|
||||
SkPathBuilder& offset(SkScalar dx, SkScalar dy);
|
||||
|
||||
SkPathBuilder& toggleInverseFillType() {
|
||||
fFillType = (SkPathFillType)((unsigned)fFillType ^ 2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
SkPathRef::PointsArray fPts;
|
||||
SkPathRef::VerbsArray fVerbs;
|
||||
SkPathRef::ConicWeightsArray fConicWeights;
|
||||
|
||||
SkPathFillType fFillType;
|
||||
bool fIsVolatile;
|
||||
|
||||
unsigned fSegmentMask;
|
||||
SkPoint fLastMovePoint;
|
||||
int fLastMoveIndex; // only needed until SkPath is immutable
|
||||
bool fNeedsMoveVerb;
|
||||
|
||||
enum IsA {
|
||||
kIsA_JustMoves, // we only have 0 or more moves
|
||||
kIsA_MoreThanMoves, // we have verbs other than just move
|
||||
kIsA_Oval, // we are 0 or more moves followed by an oval
|
||||
kIsA_RRect, // we are 0 or more moves followed by a rrect
|
||||
};
|
||||
IsA fIsA = kIsA_JustMoves;
|
||||
int fIsAStart = -1; // tracks direction iff fIsA is not unknown
|
||||
bool fIsACCW = false; // tracks direction iff fIsA is not unknown
|
||||
|
||||
int countVerbs() const { return fVerbs.size(); }
|
||||
|
||||
// called right before we add a (non-move) verb
|
||||
void ensureMove() {
|
||||
fIsA = kIsA_MoreThanMoves;
|
||||
if (fNeedsMoveVerb) {
|
||||
this->moveTo(fLastMovePoint);
|
||||
}
|
||||
}
|
||||
|
||||
SkPath make(sk_sp<SkPathRef>) const;
|
||||
|
||||
SkPathBuilder& privateReverseAddPath(const SkPath&);
|
||||
|
||||
friend class SkPathPriv;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 SkPathEffect_DEFINED
|
||||
#define SkPathEffect_DEFINED
|
||||
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
// TODO(kjlubick) update clients and remove this unnecessary #include
|
||||
#include "include/core/SkPath.h" // IWYU pragma: keep
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class SkMatrix;
|
||||
class SkStrokeRec;
|
||||
struct SkDeserialProcs;
|
||||
struct SkRect;
|
||||
|
||||
/** \class SkPathEffect
|
||||
|
||||
SkPathEffect is the base class for objects in the SkPaint that affect
|
||||
the geometry of a drawing primitive before it is transformed by the
|
||||
canvas' matrix and drawn.
|
||||
|
||||
Dashing is implemented as a subclass of SkPathEffect.
|
||||
*/
|
||||
class SK_API SkPathEffect : public SkFlattenable {
|
||||
public:
|
||||
/**
|
||||
* Returns a patheffect that apples each effect (first and second) to the original path,
|
||||
* and returns a path with the sum of these.
|
||||
*
|
||||
* result = first(path) + second(path)
|
||||
*
|
||||
*/
|
||||
static sk_sp<SkPathEffect> MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second);
|
||||
|
||||
/**
|
||||
* Returns a patheffect that applies the inner effect to the path, and then applies the
|
||||
* outer effect to the result of the inner's.
|
||||
*
|
||||
* result = outer(inner(path))
|
||||
*/
|
||||
static sk_sp<SkPathEffect> MakeCompose(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner);
|
||||
|
||||
static SkFlattenable::Type GetFlattenableType() {
|
||||
return kSkPathEffect_Type;
|
||||
}
|
||||
|
||||
// move to base?
|
||||
|
||||
enum DashType {
|
||||
kNone_DashType, //!< ignores the info parameter
|
||||
kDash_DashType, //!< fills in all of the info parameter
|
||||
};
|
||||
|
||||
struct DashInfo {
|
||||
DashInfo() : fIntervals(nullptr), 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
|
||||
int32_t fCount; //!< Number of intervals in the dash. Should be even number
|
||||
SkScalar fPhase; //!< Offset into the dashed interval pattern
|
||||
// mod the sum of all intervals
|
||||
};
|
||||
|
||||
DashType asADash(DashInfo* info) const;
|
||||
|
||||
/**
|
||||
* Given a src path (input) and a stroke-rec (input and output), apply
|
||||
* this effect to the src path, returning the new path in dst, and return
|
||||
* true. If this effect cannot be applied, return false and ignore dst
|
||||
* and stroke-rec.
|
||||
*
|
||||
* The stroke-rec specifies the initial request for stroking (if any).
|
||||
* The effect can treat this as input only, or it can choose to change
|
||||
* the rec as well. For example, the effect can decide to change the
|
||||
* stroke's width or join, or the effect can change the rec from stroke
|
||||
* to fill (or fill to stroke) in addition to returning a new (dst) path.
|
||||
*
|
||||
* If this method returns true, the caller will apply (as needed) the
|
||||
* resulting stroke-rec to dst and then draw.
|
||||
*/
|
||||
bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect* cullR) const;
|
||||
|
||||
/** Version of filterPath that can be called when the CTM is known. */
|
||||
bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect* cullR,
|
||||
const SkMatrix& ctm) const;
|
||||
|
||||
/** True if this path effect requires a valid CTM */
|
||||
bool needsCTM() const;
|
||||
|
||||
static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
private:
|
||||
SkPathEffect() = default;
|
||||
friend class SkPathEffectBase;
|
||||
|
||||
using INHERITED = SkFlattenable;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 SkPathMeasure_DEFINED
|
||||
#define SkPathMeasure_DEFINED
|
||||
|
||||
#include "include/core/SkContourMeasure.h"
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkDebug.h"
|
||||
|
||||
class SkMatrix;
|
||||
class SkPath;
|
||||
|
||||
class SK_API SkPathMeasure {
|
||||
public:
|
||||
SkPathMeasure();
|
||||
/** Initialize the pathmeasure with the specified path. The parts of the path that are needed
|
||||
* are copied, so the client is free to modify/delete the path after this call.
|
||||
*
|
||||
* resScale controls the precision of the measure. values > 1 increase the
|
||||
* precision (and possibly slow down the computation).
|
||||
*/
|
||||
SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
|
||||
~SkPathMeasure();
|
||||
|
||||
SkPathMeasure(SkPathMeasure&&) = default;
|
||||
SkPathMeasure& operator=(SkPathMeasure&&) = default;
|
||||
|
||||
/** Reset the pathmeasure with the specified path. The parts of the path that are needed
|
||||
* are copied, so the client is free to modify/delete the path after this call..
|
||||
*/
|
||||
void setPath(const SkPath*, bool forceClosed);
|
||||
|
||||
/** Return the total length of the current contour, or 0 if no path
|
||||
is associated (e.g. resetPath(null))
|
||||
*/
|
||||
SkScalar getLength();
|
||||
|
||||
/** Pins distance to 0 <= distance <= getLength(), and then computes
|
||||
the corresponding position and tangent.
|
||||
Returns false if there is no path, or a zero-length path was specified, in which case
|
||||
position and tangent are unchanged.
|
||||
*/
|
||||
[[nodiscard]] bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent);
|
||||
|
||||
enum MatrixFlags {
|
||||
kGetPosition_MatrixFlag = 0x01,
|
||||
kGetTangent_MatrixFlag = 0x02,
|
||||
kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
|
||||
};
|
||||
|
||||
/** Pins distance to 0 <= distance <= getLength(), and then computes
|
||||
the corresponding matrix (by calling getPosTan).
|
||||
Returns false if there is no path, or a zero-length path was specified, in which case
|
||||
matrix is unchanged.
|
||||
*/
|
||||
[[nodiscard]] bool getMatrix(SkScalar distance, SkMatrix* matrix,
|
||||
MatrixFlags flags = kGetPosAndTan_MatrixFlag);
|
||||
|
||||
/** Given a start and stop distance, return in dst the intervening segment(s).
|
||||
If the segment is zero-length, return false, else return true.
|
||||
startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
|
||||
then return false (and leave dst untouched).
|
||||
Begin the segment with a moveTo if startWithMoveTo is true
|
||||
*/
|
||||
bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
|
||||
|
||||
/** Return true if the current contour is closed()
|
||||
*/
|
||||
bool isClosed();
|
||||
|
||||
/** Move to the next contour in the path. Return true if one exists, or false if
|
||||
we're done with the path.
|
||||
*/
|
||||
bool nextContour();
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void dump();
|
||||
#endif
|
||||
|
||||
const SkContourMeasure* currentMeasure() const { return fContour.get(); }
|
||||
|
||||
private:
|
||||
SkContourMeasureIter fIter;
|
||||
sk_sp<SkContourMeasure> fContour;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkPathTypes_DEFINED
|
||||
#define SkPathTypes_DEFINED
|
||||
|
||||
enum class SkPathFillType {
|
||||
/** Specifies that "inside" is computed by a non-zero sum of signed edge crossings */
|
||||
kWinding,
|
||||
/** Specifies that "inside" is computed by an odd number of edge crossings */
|
||||
kEvenOdd,
|
||||
/** Same as Winding, but draws outside of the path, rather than inside */
|
||||
kInverseWinding,
|
||||
/** Same as EvenOdd, but draws outside of the path, rather than inside */
|
||||
kInverseEvenOdd
|
||||
};
|
||||
|
||||
static inline bool SkPathFillType_IsEvenOdd(SkPathFillType ft) {
|
||||
return (static_cast<int>(ft) & 1) != 0;
|
||||
}
|
||||
|
||||
static inline bool SkPathFillType_IsInverse(SkPathFillType ft) {
|
||||
return (static_cast<int>(ft) & 2) != 0;
|
||||
}
|
||||
|
||||
static inline SkPathFillType SkPathFillType_ConvertToNonInverse(SkPathFillType ft) {
|
||||
return static_cast<SkPathFillType>(static_cast<int>(ft) & 1);
|
||||
}
|
||||
|
||||
enum class SkPathDirection {
|
||||
/** clockwise direction for adding closed contours */
|
||||
kCW,
|
||||
/** counter-clockwise direction for adding closed contours */
|
||||
kCCW,
|
||||
};
|
||||
|
||||
enum SkPathSegmentMask {
|
||||
kLine_SkPathSegmentMask = 1 << 0,
|
||||
kQuad_SkPathSegmentMask = 1 << 1,
|
||||
kConic_SkPathSegmentMask = 1 << 2,
|
||||
kCubic_SkPathSegmentMask = 1 << 3,
|
||||
};
|
||||
|
||||
enum class SkPathVerb {
|
||||
kMove, //!< SkPath::RawIter returns 1 point
|
||||
kLine, //!< SkPath::RawIter returns 2 points
|
||||
kQuad, //!< SkPath::RawIter returns 3 points
|
||||
kConic, //!< SkPath::RawIter returns 3 points + 1 weight
|
||||
kCubic, //!< SkPath::RawIter returns 4 points
|
||||
kClose //!< SkPath::RawIter returns 0 points
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkPathUtils_DEFINED
|
||||
#define SkPathUtils_DEFINED
|
||||
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
class SkMatrix;
|
||||
class SkPaint;
|
||||
class SkPath;
|
||||
struct SkRect;
|
||||
|
||||
namespace skpathutils {
|
||||
|
||||
/** Returns the filled equivalent of the stroked path.
|
||||
|
||||
@param src SkPath read to create a filled version
|
||||
@param paint SkPaint, from which attributes such as stroke cap, width, miter, and join,
|
||||
as well as pathEffect will be used.
|
||||
@param dst resulting SkPath; may be the same as src, but may not be nullptr
|
||||
@param cullRect optional limit passed to SkPathEffect
|
||||
@param resScale if > 1, increase precision, else if (0 < resScale < 1) reduce precision
|
||||
to favor speed and size
|
||||
@return true if the dst path was updated, false if it was not (e.g. if the path
|
||||
represents hairline and cannot be filled).
|
||||
*/
|
||||
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst,
|
||||
const SkRect *cullRect, SkScalar resScale = 1);
|
||||
|
||||
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst,
|
||||
const SkRect *cullRect, const SkMatrix &ctm);
|
||||
|
||||
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2007 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 SkPicture_DEFINED
|
||||
#define SkPicture_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkShader.h" // IWYU pragma: keep
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class SkCanvas;
|
||||
class SkData;
|
||||
class SkMatrix;
|
||||
class SkStream;
|
||||
class SkWStream;
|
||||
enum class SkFilterMode;
|
||||
struct SkDeserialProcs;
|
||||
struct SkSerialProcs;
|
||||
|
||||
// TODO(kjlubick) Remove this after cleaning up clients
|
||||
#include "include/core/SkTileMode.h" // IWYU pragma: keep
|
||||
|
||||
/** \class SkPicture
|
||||
SkPicture records drawing commands made to SkCanvas. The command stream may be
|
||||
played in whole or in part at a later time.
|
||||
|
||||
SkPicture is an abstract class. SkPicture may be generated by SkPictureRecorder
|
||||
or SkDrawable, or from SkPicture previously saved to SkData or SkStream.
|
||||
|
||||
SkPicture may contain any SkCanvas drawing command, as well as one or more
|
||||
SkCanvas matrix or SkCanvas clip. SkPicture has a cull SkRect, which is used as
|
||||
a bounding box hint. To limit SkPicture bounds, use SkCanvas clip when
|
||||
recording or drawing SkPicture.
|
||||
*/
|
||||
class SK_API SkPicture : public SkRefCnt {
|
||||
public:
|
||||
~SkPicture() override;
|
||||
|
||||
/** Recreates SkPicture that was serialized into a stream. Returns constructed SkPicture
|
||||
if successful; otherwise, returns nullptr. Fails if data does not permit
|
||||
constructing valid SkPicture.
|
||||
|
||||
procs->fPictureProc permits supplying a custom function to decode SkPicture.
|
||||
If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
|
||||
may be used to provide user context to procs->fPictureProc; procs->fPictureProc
|
||||
is called with a pointer to data, data byte length, and user context.
|
||||
|
||||
@param stream container for serial data
|
||||
@param procs custom serial data decoders; may be nullptr
|
||||
@return SkPicture constructed from stream data
|
||||
*/
|
||||
static sk_sp<SkPicture> MakeFromStream(SkStream* stream,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
/** Recreates SkPicture that was serialized into data. Returns constructed SkPicture
|
||||
if successful; otherwise, returns nullptr. Fails if data does not permit
|
||||
constructing valid SkPicture.
|
||||
|
||||
procs->fPictureProc permits supplying a custom function to decode SkPicture.
|
||||
If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
|
||||
may be used to provide user context to procs->fPictureProc; procs->fPictureProc
|
||||
is called with a pointer to data, data byte length, and user context.
|
||||
|
||||
@param data container for serial data
|
||||
@param procs custom serial data decoders; may be nullptr
|
||||
@return SkPicture constructed from data
|
||||
*/
|
||||
static sk_sp<SkPicture> MakeFromData(const SkData* data,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
/**
|
||||
|
||||
@param data pointer to serial data
|
||||
@param size size of data
|
||||
@param procs custom serial data decoders; may be nullptr
|
||||
@return SkPicture constructed from data
|
||||
*/
|
||||
static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,
|
||||
const SkDeserialProcs* procs = nullptr);
|
||||
|
||||
/** \class SkPicture::AbortCallback
|
||||
AbortCallback is an abstract class. An implementation of AbortCallback may
|
||||
passed as a parameter to SkPicture::playback, to stop it before all drawing
|
||||
commands have been processed.
|
||||
|
||||
If AbortCallback::abort returns true, SkPicture::playback is interrupted.
|
||||
*/
|
||||
class SK_API AbortCallback {
|
||||
public:
|
||||
/** Has no effect.
|
||||
*/
|
||||
virtual ~AbortCallback() = default;
|
||||
|
||||
/** Stops SkPicture playback when some condition is met. A subclass of
|
||||
AbortCallback provides an override for abort() that can stop SkPicture::playback.
|
||||
|
||||
The part of SkPicture drawn when aborted is undefined. SkPicture instantiations are
|
||||
free to stop drawing at different points during playback.
|
||||
|
||||
If the abort happens inside one or more calls to SkCanvas::save(), stack
|
||||
of SkCanvas matrix and SkCanvas clip values is restored to its state before
|
||||
SkPicture::playback was called.
|
||||
|
||||
@return true to stop playback
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_AbortCallback_abort
|
||||
*/
|
||||
virtual bool abort() = 0;
|
||||
|
||||
protected:
|
||||
AbortCallback() = default;
|
||||
AbortCallback(const AbortCallback&) = delete;
|
||||
AbortCallback& operator=(const AbortCallback&) = delete;
|
||||
};
|
||||
|
||||
/** Replays the drawing commands on the specified canvas. In the case that the
|
||||
commands are recorded, each command in the SkPicture is sent separately to canvas.
|
||||
|
||||
To add a single command to draw SkPicture to recording canvas, call
|
||||
SkCanvas::drawPicture instead.
|
||||
|
||||
@param canvas receiver of drawing commands
|
||||
@param callback allows interruption of playback
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_playback
|
||||
*/
|
||||
virtual void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const = 0;
|
||||
|
||||
/** Returns cull SkRect for this picture, passed in when SkPicture was created.
|
||||
Returned SkRect does not specify clipping SkRect for SkPicture; cull is hint
|
||||
of SkPicture bounds.
|
||||
|
||||
SkPicture is free to discard recorded drawing commands that fall outside
|
||||
cull.
|
||||
|
||||
@return bounds passed when SkPicture was created
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_cullRect
|
||||
*/
|
||||
virtual SkRect cullRect() const = 0;
|
||||
|
||||
/** Returns a non-zero value unique among SkPicture in Skia process.
|
||||
|
||||
@return identifier for SkPicture
|
||||
*/
|
||||
uint32_t uniqueID() const { return fUniqueID; }
|
||||
|
||||
/** Returns storage containing SkData describing SkPicture, using optional custom
|
||||
encoders.
|
||||
|
||||
procs->fPictureProc permits supplying a custom function to encode SkPicture.
|
||||
If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
|
||||
may be used to provide user context to procs->fPictureProc; procs->fPictureProc
|
||||
is called with a pointer to SkPicture and user context.
|
||||
|
||||
The default behavior for serializing SkImages is to encode a nullptr. Should
|
||||
clients want to, for example, encode these SkImages as PNGs so they can be
|
||||
deserialized, they must provide SkSerialProcs with the fImageProc set to do so.
|
||||
|
||||
@param procs custom serial data encoders; may be nullptr
|
||||
@return storage containing serialized SkPicture
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_serialize
|
||||
*/
|
||||
sk_sp<SkData> serialize(const SkSerialProcs* procs = nullptr) const;
|
||||
|
||||
/** Writes picture to stream, using optional custom encoders.
|
||||
|
||||
procs->fPictureProc permits supplying a custom function to encode SkPicture.
|
||||
If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
|
||||
may be used to provide user context to procs->fPictureProc; procs->fPictureProc
|
||||
is called with a pointer to SkPicture and user context.
|
||||
|
||||
The default behavior for serializing SkImages is to encode a nullptr. Should
|
||||
clients want to, for example, encode these SkImages as PNGs so they can be
|
||||
deserialized, they must provide SkSerialProcs with the fImageProc set to do so.
|
||||
|
||||
@param stream writable serial data stream
|
||||
@param procs custom serial data encoders; may be nullptr
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_serialize_2
|
||||
*/
|
||||
void serialize(SkWStream* stream, const SkSerialProcs* procs = nullptr) const;
|
||||
|
||||
/** Returns a placeholder SkPicture. Result does not draw, and contains only
|
||||
cull SkRect, a hint of its bounds. Result is immutable; it cannot be changed
|
||||
later. Result identifier is unique.
|
||||
|
||||
Returned placeholder can be intercepted during playback to insert other
|
||||
commands into SkCanvas draw stream.
|
||||
|
||||
@param cull placeholder dimensions
|
||||
@return placeholder with unique identifier
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_MakePlaceholder
|
||||
*/
|
||||
static sk_sp<SkPicture> MakePlaceholder(SkRect cull);
|
||||
|
||||
/** Returns the approximate number of operations in SkPicture. Returned value
|
||||
may be greater or less than the number of SkCanvas calls
|
||||
recorded: some calls may be recorded as more than one operation, other
|
||||
calls may be optimized away.
|
||||
|
||||
@param nested if true, include the op-counts of nested pictures as well, else
|
||||
just return count the ops in the top-level picture.
|
||||
@return approximate operation count
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_approximateOpCount
|
||||
*/
|
||||
virtual int approximateOpCount(bool nested = false) const = 0;
|
||||
|
||||
/** Returns the approximate byte size of SkPicture. Does not include large objects
|
||||
referenced by SkPicture.
|
||||
|
||||
@return approximate size
|
||||
|
||||
example: https://fiddle.skia.org/c/@Picture_approximateBytesUsed
|
||||
*/
|
||||
virtual size_t approximateBytesUsed() const = 0;
|
||||
|
||||
/** Return a new shader that will draw with this picture.
|
||||
*
|
||||
* @param tmx The tiling mode to use when sampling in the x-direction.
|
||||
* @param tmy The tiling mode to use when sampling in the y-direction.
|
||||
* @param mode How to filter the tiles
|
||||
* @param localMatrix Optional matrix used when sampling
|
||||
* @param tileRect The tile rectangle in picture coordinates: this represents the subset
|
||||
* (or superset) of the picture used when building a tile. It is not
|
||||
* affected by localMatrix and does not imply scaling (only translation
|
||||
* and cropping). If null, the tile rect is considered equal to the picture
|
||||
* bounds.
|
||||
* @return Returns a new shader object. Note: this function never returns null.
|
||||
*/
|
||||
sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode,
|
||||
const SkMatrix* localMatrix, const SkRect* tileRect) const;
|
||||
|
||||
sk_sp<SkShader> makeShader(SkTileMode tmx, SkTileMode tmy, SkFilterMode mode) const {
|
||||
return this->makeShader(tmx, tmy, mode, nullptr, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
// Allowed subclasses.
|
||||
SkPicture();
|
||||
friend class SkBigPicture;
|
||||
friend class SkEmptyPicture;
|
||||
friend class SkPicturePriv;
|
||||
|
||||
void serialize(SkWStream*, const SkSerialProcs*, class SkRefCntSet* typefaces,
|
||||
bool textBlobsOnly=false) const;
|
||||
static sk_sp<SkPicture> MakeFromStreamPriv(SkStream*, const SkDeserialProcs*,
|
||||
class SkTypefacePlayback*,
|
||||
int recursionLimit);
|
||||
friend class SkPictureData;
|
||||
|
||||
/** Return true if the SkStream/Buffer represents a serialized picture, and
|
||||
fills out SkPictInfo. After this function returns, the data source is not
|
||||
rewound so it will have to be manually reset before passing to
|
||||
MakeFromStream or MakeFromBuffer. Note, MakeFromStream and
|
||||
MakeFromBuffer perform this check internally so these entry points are
|
||||
intended for stand alone tools.
|
||||
If false is returned, SkPictInfo is unmodified.
|
||||
*/
|
||||
static bool StreamIsSKP(SkStream*, struct SkPictInfo*);
|
||||
static bool BufferIsSKP(class SkReadBuffer*, struct SkPictInfo*);
|
||||
friend bool SkPicture_StreamIsSKP(SkStream*, struct SkPictInfo*);
|
||||
|
||||
// Returns NULL if this is not an SkBigPicture.
|
||||
virtual const class SkBigPicture* asSkBigPicture() const { return nullptr; }
|
||||
|
||||
static bool IsValidPictInfo(const struct SkPictInfo& info);
|
||||
static sk_sp<SkPicture> Forwardport(const struct SkPictInfo&,
|
||||
const class SkPictureData*,
|
||||
class SkReadBuffer* buffer);
|
||||
|
||||
struct SkPictInfo createHeader() const;
|
||||
class SkPictureData* backport() const;
|
||||
|
||||
uint32_t fUniqueID;
|
||||
mutable std::atomic<bool> fAddedToCache{false};
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkPictureRecorder_DEFINED
|
||||
#define SkPictureRecorder_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
namespace android {
|
||||
class Picture;
|
||||
};
|
||||
#endif
|
||||
|
||||
class SkBBHFactory;
|
||||
class SkBBoxHierarchy;
|
||||
class SkCanvas;
|
||||
class SkDrawable;
|
||||
class SkPicture;
|
||||
class SkRecord;
|
||||
class SkRecorder;
|
||||
|
||||
class SK_API SkPictureRecorder {
|
||||
public:
|
||||
SkPictureRecorder();
|
||||
~SkPictureRecorder();
|
||||
|
||||
/** Returns the canvas that records the drawing commands.
|
||||
@param bounds the cull rect used when recording this picture. Any drawing the falls outside
|
||||
of this rect is undefined, and may be drawn or it may not.
|
||||
@param bbh optional acceleration structure
|
||||
@param recordFlags optional flags that control recording.
|
||||
@return the canvas.
|
||||
*/
|
||||
SkCanvas* beginRecording(const SkRect& bounds, sk_sp<SkBBoxHierarchy> bbh);
|
||||
|
||||
SkCanvas* beginRecording(const SkRect& bounds, SkBBHFactory* bbhFactory = nullptr);
|
||||
|
||||
SkCanvas* beginRecording(SkScalar width, SkScalar height,
|
||||
SkBBHFactory* bbhFactory = nullptr) {
|
||||
return this->beginRecording(SkRect::MakeWH(width, height), bbhFactory);
|
||||
}
|
||||
|
||||
/** Returns the recording canvas if one is active, or NULL if recording is
|
||||
not active. This does not alter the refcnt on the canvas (if present).
|
||||
*/
|
||||
SkCanvas* getRecordingCanvas();
|
||||
|
||||
/**
|
||||
* Signal that the caller is done recording. This invalidates the canvas returned by
|
||||
* beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
|
||||
* must call unref() when they are done using it.
|
||||
*
|
||||
* The returned picture is immutable. If during recording drawables were added to the canvas,
|
||||
* these will have been "drawn" into a recording canvas, so that this resulting picture will
|
||||
* reflect their current state, but will not contain a live reference to the drawables
|
||||
* themselves.
|
||||
*/
|
||||
sk_sp<SkPicture> finishRecordingAsPicture();
|
||||
|
||||
/**
|
||||
* Signal that the caller is done recording, and update the cull rect to use for bounding
|
||||
* box hierarchy (BBH) generation. The behavior is the same as calling
|
||||
* finishRecordingAsPicture(), except that this method updates the cull rect initially passed
|
||||
* into beginRecording.
|
||||
* @param cullRect the new culling rectangle to use as the overall bound for BBH generation
|
||||
* and subsequent culling operations.
|
||||
* @return the picture containing the recorded content.
|
||||
*/
|
||||
sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect);
|
||||
|
||||
/**
|
||||
* Signal that the caller is done recording. This invalidates the canvas returned by
|
||||
* beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
|
||||
* must call unref() when they are done using it.
|
||||
*
|
||||
* Unlike finishRecordingAsPicture(), which returns an immutable picture, the returned drawable
|
||||
* may contain live references to other drawables (if they were added to the recording canvas)
|
||||
* 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->makePictureSnapshot()).
|
||||
*/
|
||||
sk_sp<SkDrawable> finishRecordingAsDrawable();
|
||||
|
||||
private:
|
||||
void reset();
|
||||
|
||||
/** Replay the current (partially recorded) operation stream into
|
||||
canvas. This call doesn't close the current recording.
|
||||
*/
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
friend class android::Picture;
|
||||
#endif
|
||||
friend class SkPictureRecorderReplayTester; // for unit testing
|
||||
void partialReplay(SkCanvas* canvas) const;
|
||||
|
||||
bool fActivelyRecording;
|
||||
SkRect fCullRect;
|
||||
sk_sp<SkBBoxHierarchy> fBBH;
|
||||
std::unique_ptr<SkRecorder> fRecorder;
|
||||
sk_sp<SkRecord> fRecord;
|
||||
|
||||
SkPictureRecorder(SkPictureRecorder&&) = delete;
|
||||
SkPictureRecorder& operator=(SkPictureRecorder&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2008 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 SkPixelRef_DEFINED
|
||||
#define SkPixelRef_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/private/SkIDChangeListener.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class SkDiscardableMemory;
|
||||
|
||||
/** \class SkPixelRef
|
||||
|
||||
This class is the smart container for pixel memory, and is used with SkBitmap.
|
||||
This class can be shared/accessed between multiple threads.
|
||||
*/
|
||||
class SK_API SkPixelRef : public SkRefCnt {
|
||||
public:
|
||||
SkPixelRef(int width, int height, void* addr, size_t rowBytes);
|
||||
~SkPixelRef() override;
|
||||
|
||||
SkISize dimensions() const { return {fWidth, fHeight}; }
|
||||
int width() const { return fWidth; }
|
||||
int height() const { return fHeight; }
|
||||
void* pixels() const { return fPixels; }
|
||||
size_t rowBytes() const { return fRowBytes; }
|
||||
|
||||
/** Returns a non-zero, unique value corresponding to the pixels in this
|
||||
pixelref. Each time the pixels are changed (and notifyPixelsChanged is
|
||||
called), a different generation ID will be returned.
|
||||
*/
|
||||
uint32_t getGenerationID() const;
|
||||
|
||||
/**
|
||||
* Call this if you have changed the contents of the pixels. This will in-
|
||||
* turn cause a different generation ID value to be returned from
|
||||
* getGenerationID().
|
||||
*/
|
||||
void notifyPixelsChanged();
|
||||
|
||||
/** Returns true if this pixelref is marked as immutable, meaning that the
|
||||
contents of its pixels will not change for the lifetime of the pixelref.
|
||||
*/
|
||||
bool isImmutable() const { return fMutability != kMutable; }
|
||||
|
||||
/** Marks this pixelref is immutable, meaning that the contents of its
|
||||
pixels will not change for the lifetime of the pixelref. This state can
|
||||
be set on a pixelref, but it cannot be cleared once it is set.
|
||||
*/
|
||||
void setImmutable();
|
||||
|
||||
// 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
|
||||
// generation ID. If our generation ID changes and we decide not to call the listener, we'll
|
||||
// never call it: you must add a new listener for each generation ID change. We also won't call
|
||||
// the listener when we're certain no one knows what our generation ID is.
|
||||
//
|
||||
// This can be used to invalidate caches keyed by SkPixelRef generation ID.
|
||||
// Takes ownership of listener. Threadsafe.
|
||||
void addGenIDChangeListener(sk_sp<SkIDChangeListener> listener);
|
||||
|
||||
// Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
|
||||
// to know automatically those entries can be purged when this pixelref is changed or deleted.
|
||||
void notifyAddedToCache() {
|
||||
fAddedToCache.store(true);
|
||||
}
|
||||
|
||||
virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }
|
||||
|
||||
protected:
|
||||
void android_only_reset(int width, int height, size_t rowBytes);
|
||||
|
||||
private:
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
void* fPixels;
|
||||
size_t fRowBytes;
|
||||
|
||||
// Bottom bit indicates the Gen ID is unique.
|
||||
bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
|
||||
mutable std::atomic<uint32_t> fTaggedGenID;
|
||||
|
||||
SkIDChangeListener::List fGenIDChangeListeners;
|
||||
|
||||
// Set true by caches when they cache content that's derived from the current pixels.
|
||||
std::atomic<bool> fAddedToCache;
|
||||
|
||||
enum Mutability {
|
||||
kMutable, // PixelRefs begin mutable.
|
||||
kTemporarilyImmutable, // Considered immutable, but can revert to mutable.
|
||||
kImmutable, // Once set to this state, it never leaves.
|
||||
} fMutability : 8; // easily fits inside a byte
|
||||
|
||||
void needsNewGenID();
|
||||
void callGenIDChangeListeners();
|
||||
|
||||
void setTemporarilyImmutable();
|
||||
void restoreMutability();
|
||||
friend class SkSurface_Raster; // For temporary immutable methods above.
|
||||
|
||||
void setImmutableWithID(uint32_t genID);
|
||||
friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);
|
||||
|
||||
using INHERITED = SkRefCnt;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,731 @@
|
||||
/*
|
||||
* 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 SkPixmap_DEFINED
|
||||
#define SkPixmap_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkColorType.h"
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSamplingOptions.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkAssert.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class SkColorSpace;
|
||||
enum SkAlphaType : int;
|
||||
struct SkMask;
|
||||
|
||||
/** \class SkPixmap
|
||||
SkPixmap provides a utility to pair SkImageInfo with pixels and row bytes.
|
||||
SkPixmap is a low level class which provides convenience functions to access
|
||||
raster destinations. SkCanvas can not draw SkPixmap, nor does SkPixmap provide
|
||||
a direct drawing destination.
|
||||
|
||||
Use SkBitmap to draw pixels referenced by SkPixmap; use SkSurface to draw into
|
||||
pixels referenced by SkPixmap.
|
||||
|
||||
SkPixmap does not try to manage the lifetime of the pixel memory. Use SkPixelRef
|
||||
to manage pixel memory; SkPixelRef is safe across threads.
|
||||
*/
|
||||
class SK_API SkPixmap {
|
||||
public:
|
||||
|
||||
/** Creates an empty SkPixmap without pixels, with kUnknown_SkColorType, with
|
||||
kUnknown_SkAlphaType, and with a width and height of zero. Use
|
||||
reset() to associate pixels, SkColorType, SkAlphaType, width, and height
|
||||
after SkPixmap has been created.
|
||||
|
||||
@return empty SkPixmap
|
||||
*/
|
||||
SkPixmap()
|
||||
: fPixels(nullptr), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
|
||||
{}
|
||||
|
||||
/** Creates SkPixmap from info width, height, SkAlphaType, and SkColorType.
|
||||
addr points to pixels, or nullptr. rowBytes should be info.width() times
|
||||
info.bytesPerPixel(), or larger.
|
||||
|
||||
No parameter checking is performed; it is up to the caller to ensure that
|
||||
addr and rowBytes agree with info.
|
||||
|
||||
The memory lifetime of pixels is managed by the caller. When SkPixmap goes
|
||||
out of scope, addr is unaffected.
|
||||
|
||||
SkPixmap may be later modified by reset() to change its size, pixel type, or
|
||||
storage.
|
||||
|
||||
@param info width, height, SkAlphaType, SkColorType of SkImageInfo
|
||||
@param addr pointer to pixels allocated by caller; may be nullptr
|
||||
@param rowBytes size of one row of addr; width times pixel size, or larger
|
||||
@return initialized SkPixmap
|
||||
*/
|
||||
SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes)
|
||||
: fPixels(addr), fRowBytes(rowBytes), fInfo(info)
|
||||
{}
|
||||
|
||||
/** Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
|
||||
kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.
|
||||
|
||||
The prior pixels are unaffected; it is up to the caller to release pixels
|
||||
memory if desired.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_reset
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/** Sets width, height, SkAlphaType, and SkColorType from info.
|
||||
Sets pixel address from addr, which may be nullptr.
|
||||
Sets row bytes from rowBytes, which should be info.width() times
|
||||
info.bytesPerPixel(), or larger.
|
||||
|
||||
Does not check addr. Asserts if built with SK_DEBUG defined and if rowBytes is
|
||||
too small to hold one row of pixels.
|
||||
|
||||
The memory lifetime pixels are managed by the caller. When SkPixmap goes
|
||||
out of scope, addr is unaffected.
|
||||
|
||||
@param info width, height, SkAlphaType, SkColorType of SkImageInfo
|
||||
@param addr pointer to pixels allocated by caller; may be nullptr
|
||||
@param rowBytes size of one row of addr; width times pixel size, or larger
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_reset_2
|
||||
*/
|
||||
void reset(const SkImageInfo& info, const void* addr, size_t rowBytes);
|
||||
|
||||
/** Changes SkColorSpace in SkImageInfo; preserves width, height, SkAlphaType, and
|
||||
SkColorType in SkImage, and leaves pixel address and row bytes unchanged.
|
||||
SkColorSpace reference count is incremented.
|
||||
|
||||
@param colorSpace SkColorSpace moved to SkImageInfo
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_setColorSpace
|
||||
*/
|
||||
void setColorSpace(sk_sp<SkColorSpace> colorSpace);
|
||||
|
||||
/** Deprecated.
|
||||
*/
|
||||
[[nodiscard]] bool reset(const SkMask& mask);
|
||||
|
||||
/** Sets subset width, height, pixel address to intersection of SkPixmap with area,
|
||||
if intersection is not empty; and return true. Otherwise, leave subset unchanged
|
||||
and return false.
|
||||
|
||||
Failing to read the return value generates a compile time warning.
|
||||
|
||||
@param subset storage for width, height, pixel address of intersection
|
||||
@param area bounds to intersect with SkPixmap
|
||||
@return true if intersection of SkPixmap and area is not empty
|
||||
*/
|
||||
[[nodiscard]] bool extractSubset(SkPixmap* subset, const SkIRect& area) const;
|
||||
|
||||
/** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.
|
||||
|
||||
@return reference to SkImageInfo
|
||||
*/
|
||||
const SkImageInfo& info() const { return fInfo; }
|
||||
|
||||
/** Returns row bytes, the interval from one pixel row to the next. Row bytes
|
||||
is at least as large as: width() * info().bytesPerPixel().
|
||||
|
||||
Returns zero if colorType() is kUnknown_SkColorType.
|
||||
It is up to the SkBitmap creator to ensure that row bytes is a useful value.
|
||||
|
||||
@return byte length of pixel row
|
||||
*/
|
||||
size_t rowBytes() const { return fRowBytes; }
|
||||
|
||||
/** Returns pixel address, the base address corresponding to the pixel origin.
|
||||
|
||||
It is up to the SkPixmap creator to ensure that pixel address is a useful value.
|
||||
|
||||
@return pixel address
|
||||
*/
|
||||
const void* addr() const { return fPixels; }
|
||||
|
||||
/** Returns pixel count in each pixel row. Should be equal or less than:
|
||||
rowBytes() / info().bytesPerPixel().
|
||||
|
||||
@return pixel width in SkImageInfo
|
||||
*/
|
||||
int width() const { return fInfo.width(); }
|
||||
|
||||
/** Returns pixel row count.
|
||||
|
||||
@return pixel height in SkImageInfo
|
||||
*/
|
||||
int height() const { return fInfo.height(); }
|
||||
|
||||
/**
|
||||
* Return the dimensions of the pixmap (from its ImageInfo)
|
||||
*/
|
||||
SkISize dimensions() const { return fInfo.dimensions(); }
|
||||
|
||||
SkColorType colorType() const { return fInfo.colorType(); }
|
||||
|
||||
SkAlphaType alphaType() const { return fInfo.alphaType(); }
|
||||
|
||||
/** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
|
||||
reference count of SkColorSpace is unchanged. The returned SkColorSpace is
|
||||
immutable.
|
||||
|
||||
@return SkColorSpace in SkImageInfo, or nullptr
|
||||
*/
|
||||
SkColorSpace* colorSpace() const;
|
||||
|
||||
/** Returns smart pointer to SkColorSpace, the range of colors, associated with
|
||||
SkImageInfo. The smart pointer tracks the number of objects sharing this
|
||||
SkColorSpace reference so the memory is released when the owners destruct.
|
||||
|
||||
The returned SkColorSpace is immutable.
|
||||
|
||||
@return SkColorSpace in SkImageInfo wrapped in a smart pointer
|
||||
*/
|
||||
sk_sp<SkColorSpace> refColorSpace() const;
|
||||
|
||||
/** Returns true if SkAlphaType is kOpaque_SkAlphaType.
|
||||
Does not check if SkColorType allows alpha, or if any pixel value has
|
||||
transparency.
|
||||
|
||||
@return true if SkImageInfo has opaque SkAlphaType
|
||||
*/
|
||||
bool isOpaque() const { return fInfo.isOpaque(); }
|
||||
|
||||
/** Returns SkIRect { 0, 0, width(), height() }.
|
||||
|
||||
@return integral rectangle from origin to width() and height()
|
||||
*/
|
||||
SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
|
||||
|
||||
/** Returns number of pixels that fit on row. Should be greater than or equal to
|
||||
width().
|
||||
|
||||
@return maximum pixels per row
|
||||
*/
|
||||
int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }
|
||||
|
||||
/** Returns bit shift converting row bytes to row pixels.
|
||||
Returns zero for kUnknown_SkColorType.
|
||||
|
||||
@return one of: 0, 1, 2, 3; left shift to convert pixels to bytes
|
||||
*/
|
||||
int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
|
||||
|
||||
/** Returns minimum memory required for pixel storage.
|
||||
Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
|
||||
Returns SIZE_MAX if result does not fit in size_t.
|
||||
Returns zero if height() or width() is 0.
|
||||
Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.
|
||||
|
||||
@return size in bytes of image buffer
|
||||
*/
|
||||
size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }
|
||||
|
||||
/** Returns true if all pixels are opaque. SkColorType determines how pixels
|
||||
are encoded, and whether pixel describes alpha. Returns true for SkColorType
|
||||
without alpha in each pixel; for other SkColorType, returns true if all
|
||||
pixels have alpha values equivalent to 1.0 or greater.
|
||||
|
||||
For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
|
||||
returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
|
||||
kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
|
||||
For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
|
||||
For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
|
||||
greater.
|
||||
|
||||
Returns false for kUnknown_SkColorType.
|
||||
|
||||
@return true if all pixels have opaque values or SkColorType is opaque
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_computeIsOpaque
|
||||
*/
|
||||
bool computeIsOpaque() const;
|
||||
|
||||
/** Returns pixel at (x, y) as unpremultiplied color.
|
||||
Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined; and returns undefined values or may crash if
|
||||
SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
|
||||
pixel address is nullptr.
|
||||
|
||||
SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
|
||||
conversion to unpremultiplied color; original pixel data may have additional
|
||||
precision.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return pixel converted to unpremultiplied color
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_getColor
|
||||
*/
|
||||
SkColor getColor(int x, int y) const;
|
||||
|
||||
/** Returns pixel at (x, y) as unpremultiplied color as an SkColor4f.
|
||||
Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined; and returns undefined values or may crash if
|
||||
SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
|
||||
pixel address is nullptr.
|
||||
|
||||
SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
|
||||
conversion to unpremultiplied color; original pixel data may have additional
|
||||
precision, though this is less likely than for getColor(). Rounding errors may
|
||||
occur if the underlying type has lower precision.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return pixel converted to unpremultiplied float color
|
||||
*/
|
||||
SkColor4f getColor4f(int x, int y) const;
|
||||
|
||||
/** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
|
||||
This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
|
||||
(and more precise if the pixels store more than 8 bits per component).
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return alpha converted to normalized float
|
||||
*/
|
||||
float getAlphaf(int x, int y) const;
|
||||
|
||||
/** Returns readable pixel address at (x, y). Returns nullptr if SkPixelRef is nullptr.
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined. Returns nullptr if SkColorType is kUnknown_SkColorType.
|
||||
|
||||
Performs a lookup of pixel size; for better performance, call
|
||||
one of: addr8, addr16, addr32, addr64, or addrF16().
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable generic pointer to pixel
|
||||
*/
|
||||
const void* addr(int x, int y) const {
|
||||
return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
|
||||
}
|
||||
|
||||
/** Returns readable base pixel address. Result is addressable as unsigned 8-bit bytes.
|
||||
Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
|
||||
kGray_8_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
One byte corresponds to one pixel.
|
||||
|
||||
@return readable unsigned 8-bit pointer to pixels
|
||||
*/
|
||||
const uint8_t* addr8() const {
|
||||
SkASSERT(1 == fInfo.bytesPerPixel());
|
||||
return reinterpret_cast<const uint8_t*>(fPixels);
|
||||
}
|
||||
|
||||
/** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
|
||||
Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
|
||||
kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@return readable unsigned 16-bit pointer to pixels
|
||||
*/
|
||||
const uint16_t* addr16() const {
|
||||
SkASSERT(2 == fInfo.bytesPerPixel());
|
||||
return reinterpret_cast<const uint16_t*>(fPixels);
|
||||
}
|
||||
|
||||
/** Returns readable base pixel address. Result is addressable as unsigned 32-bit words.
|
||||
Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
|
||||
kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@return readable unsigned 32-bit pointer to pixels
|
||||
*/
|
||||
const uint32_t* addr32() const {
|
||||
SkASSERT(4 == fInfo.bytesPerPixel());
|
||||
return reinterpret_cast<const uint32_t*>(fPixels);
|
||||
}
|
||||
|
||||
/** Returns readable base pixel address. Result is addressable as unsigned 64-bit words.
|
||||
Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
|
||||
with SK_DEBUG defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@return readable unsigned 64-bit pointer to pixels
|
||||
*/
|
||||
const uint64_t* addr64() const {
|
||||
SkASSERT(8 == fInfo.bytesPerPixel());
|
||||
return reinterpret_cast<const uint64_t*>(fPixels);
|
||||
}
|
||||
|
||||
/** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
|
||||
Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
|
||||
with SK_DEBUG defined.
|
||||
|
||||
Each word represents one color component encoded as a half float.
|
||||
Four words correspond to one pixel.
|
||||
|
||||
@return readable unsigned 16-bit pointer to first component of pixels
|
||||
*/
|
||||
const uint16_t* addrF16() const {
|
||||
SkASSERT(8 == fInfo.bytesPerPixel());
|
||||
SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType() ||
|
||||
kRGBA_F16Norm_SkColorType == fInfo.colorType());
|
||||
return reinterpret_cast<const uint16_t*>(fPixels);
|
||||
}
|
||||
|
||||
/** Returns readable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined.
|
||||
|
||||
Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
|
||||
kGray_8_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable unsigned 8-bit pointer to pixel at (x, y)
|
||||
*/
|
||||
const uint8_t* addr8(int x, int y) const {
|
||||
SkASSERT((unsigned)x < (unsigned)fInfo.width());
|
||||
SkASSERT((unsigned)y < (unsigned)fInfo.height());
|
||||
return (const uint8_t*)((const char*)this->addr8() + (size_t)y * fRowBytes + (x << 0));
|
||||
}
|
||||
|
||||
/** Returns readable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined.
|
||||
|
||||
Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
|
||||
kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable unsigned 16-bit pointer to pixel at (x, y)
|
||||
*/
|
||||
const uint16_t* addr16(int x, int y) const {
|
||||
SkASSERT((unsigned)x < (unsigned)fInfo.width());
|
||||
SkASSERT((unsigned)y < (unsigned)fInfo.height());
|
||||
return (const uint16_t*)((const char*)this->addr16() + (size_t)y * fRowBytes + (x << 1));
|
||||
}
|
||||
|
||||
/** Returns readable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined.
|
||||
|
||||
Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
|
||||
kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable unsigned 32-bit pointer to pixel at (x, y)
|
||||
*/
|
||||
const uint32_t* addr32(int x, int y) const {
|
||||
SkASSERT((unsigned)x < (unsigned)fInfo.width());
|
||||
SkASSERT((unsigned)y < (unsigned)fInfo.height());
|
||||
return (const uint32_t*)((const char*)this->addr32() + (size_t)y * fRowBytes + (x << 2));
|
||||
}
|
||||
|
||||
/** Returns readable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined.
|
||||
|
||||
Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
|
||||
with SK_DEBUG defined.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable unsigned 64-bit pointer to pixel at (x, y)
|
||||
*/
|
||||
const uint64_t* addr64(int x, int y) const {
|
||||
SkASSERT((unsigned)x < (unsigned)fInfo.width());
|
||||
SkASSERT((unsigned)y < (unsigned)fInfo.height());
|
||||
return (const uint64_t*)((const char*)this->addr64() + (size_t)y * fRowBytes + (x << 3));
|
||||
}
|
||||
|
||||
/** Returns readable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined.
|
||||
|
||||
Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
|
||||
with SK_DEBUG defined.
|
||||
|
||||
Each unsigned 16-bit word represents one color component encoded as a half float.
|
||||
Four words correspond to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return readable unsigned 16-bit pointer to pixel component at (x, y)
|
||||
*/
|
||||
const uint16_t* addrF16(int x, int y) const {
|
||||
SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType() ||
|
||||
kRGBA_F16Norm_SkColorType == fInfo.colorType());
|
||||
return reinterpret_cast<const uint16_t*>(this->addr64(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable base pixel address.
|
||||
|
||||
@return writable generic base pointer to pixels
|
||||
*/
|
||||
void* writable_addr() const { return const_cast<void*>(fPixels); }
|
||||
|
||||
/** Returns writable pixel address at (x, y).
|
||||
|
||||
Input is not validated: out of bounds values of x or y trigger an assert() if
|
||||
built with SK_DEBUG defined. Returns zero if SkColorType is kUnknown_SkColorType.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable generic pointer to pixel
|
||||
*/
|
||||
void* writable_addr(int x, int y) const {
|
||||
return const_cast<void*>(this->addr(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable pixel address at (x, y). Result is addressable as unsigned
|
||||
8-bit bytes. Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType
|
||||
or kGray_8_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
One byte corresponds to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable unsigned 8-bit pointer to pixels
|
||||
*/
|
||||
uint8_t* writable_addr8(int x, int y) const {
|
||||
return const_cast<uint8_t*>(this->addr8(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable_addr pixel address at (x, y). Result is addressable as unsigned
|
||||
16-bit words. Will trigger an assert() if SkColorType is not kRGB_565_SkColorType
|
||||
or kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable unsigned 16-bit pointer to pixel
|
||||
*/
|
||||
uint16_t* writable_addr16(int x, int y) const {
|
||||
return const_cast<uint16_t*>(this->addr16(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable pixel address at (x, y). Result is addressable as unsigned
|
||||
32-bit words. Will trigger an assert() if SkColorType is not
|
||||
kRGBA_8888_SkColorType or kBGRA_8888_SkColorType, and is built with SK_DEBUG
|
||||
defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable unsigned 32-bit pointer to pixel
|
||||
*/
|
||||
uint32_t* writable_addr32(int x, int y) const {
|
||||
return const_cast<uint32_t*>(this->addr32(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable pixel address at (x, y). Result is addressable as unsigned
|
||||
64-bit words. Will trigger an assert() if SkColorType is not
|
||||
kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
|
||||
|
||||
One word corresponds to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable unsigned 64-bit pointer to pixel
|
||||
*/
|
||||
uint64_t* writable_addr64(int x, int y) const {
|
||||
return const_cast<uint64_t*>(this->addr64(x, y));
|
||||
}
|
||||
|
||||
/** Returns writable pixel address at (x, y). Result is addressable as unsigned
|
||||
16-bit words. Will trigger an assert() if SkColorType is not
|
||||
kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
|
||||
|
||||
Each word represents one color component encoded as a half float.
|
||||
Four words correspond to one pixel.
|
||||
|
||||
@param x column index, zero or greater, and less than width()
|
||||
@param y row index, zero or greater, and less than height()
|
||||
@return writable unsigned 16-bit pointer to first component of pixel
|
||||
*/
|
||||
uint16_t* writable_addrF16(int x, int y) const {
|
||||
return reinterpret_cast<uint16_t*>(writable_addr64(x, y));
|
||||
}
|
||||
|
||||
/** Copies a SkRect of pixels to dstPixels. Copy starts at (0, 0), and does not
|
||||
exceed SkPixmap (width(), height()).
|
||||
|
||||
dstInfo specifies width, height, SkColorType, SkAlphaType, and
|
||||
SkColorSpace of destination. dstRowBytes specifics the gap from one destination
|
||||
row to the next. Returns true if pixels are copied. Returns false if
|
||||
dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
|
||||
If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
|
||||
If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
|
||||
match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
Returns false if SkPixmap width() or height() is zero or negative.
|
||||
|
||||
@param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
|
||||
@param dstPixels destination pixel storage
|
||||
@param dstRowBytes destination row length
|
||||
@return true if pixels are copied to dstPixels
|
||||
*/
|
||||
bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
|
||||
return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
|
||||
}
|
||||
|
||||
/** Copies a SkRect of pixels to dstPixels. Copy starts at (srcX, srcY), and does not
|
||||
exceed SkPixmap (width(), height()).
|
||||
|
||||
dstInfo specifies width, height, SkColorType, SkAlphaType, and
|
||||
SkColorSpace of destination. dstRowBytes specifics the gap from one destination
|
||||
row to the next. Returns true if pixels are copied. Returns false if
|
||||
dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
|
||||
If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
|
||||
If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
|
||||
match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
srcX and srcY may be negative to copy only top or left of source. Returns
|
||||
false if SkPixmap width() or height() is zero or negative. Returns false if:
|
||||
abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
|
||||
|
||||
@param dstInfo destination width, height, SkColorType, SkAlphaType, SkColorSpace
|
||||
@param dstPixels destination pixel storage
|
||||
@param dstRowBytes destination row length
|
||||
@param srcX column index whose absolute value is less than width()
|
||||
@param srcY row index whose absolute value is less than height()
|
||||
@return true if pixels are copied to dstPixels
|
||||
*/
|
||||
bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,
|
||||
int srcY) const;
|
||||
|
||||
/** Copies a SkRect of pixels to dst. Copy starts at (srcX, srcY), and does not
|
||||
exceed SkPixmap (width(), height()). dst specifies width, height, SkColorType,
|
||||
SkAlphaType, and SkColorSpace of destination. Returns true if pixels are copied.
|
||||
Returns false if dst address equals nullptr, or dst.rowBytes() is less than
|
||||
dst SkImageInfo::minRowBytes.
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.info().colorType must match.
|
||||
If SkPixmap colorType() is kGray_8_SkColorType, dst.info().colorSpace must match.
|
||||
If SkPixmap alphaType() is kOpaque_SkAlphaType, dst.info().alphaType must
|
||||
match. If SkPixmap colorSpace() is nullptr, dst.info().colorSpace must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
srcX and srcY may be negative to copy only top or left of source. Returns
|
||||
false SkPixmap width() or height() is zero or negative. Returns false if:
|
||||
abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
|
||||
|
||||
@param dst SkImageInfo and pixel address to write to
|
||||
@param srcX column index whose absolute value is less than width()
|
||||
@param srcY row index whose absolute value is less than height()
|
||||
@return true if pixels are copied to dst
|
||||
*/
|
||||
bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
|
||||
return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
|
||||
}
|
||||
|
||||
/** Copies pixels inside bounds() to dst. dst specifies width, height, SkColorType,
|
||||
SkAlphaType, and SkColorSpace of destination. Returns true if pixels are copied.
|
||||
Returns false if dst address equals nullptr, or dst.rowBytes() is less than
|
||||
dst SkImageInfo::minRowBytes.
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
|
||||
If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
|
||||
If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
|
||||
match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
Returns false if SkPixmap width() or height() is zero or negative.
|
||||
|
||||
@param dst SkImageInfo and pixel address to write to
|
||||
@return true if pixels are copied to dst
|
||||
*/
|
||||
bool readPixels(const SkPixmap& dst) const {
|
||||
return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
|
||||
}
|
||||
|
||||
/** Copies SkBitmap to dst, scaling pixels to fit dst.width() and dst.height(), and
|
||||
converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
|
||||
pixels are copied. Returns false if dst address is nullptr, or dst.rowBytes() is
|
||||
less than dst SkImageInfo::minRowBytes.
|
||||
|
||||
Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
|
||||
kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
|
||||
If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
|
||||
If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
|
||||
match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
|
||||
false if pixel conversion is not possible.
|
||||
|
||||
Returns false if SkBitmap width() or height() is zero or negative.
|
||||
|
||||
@param dst SkImageInfo and pixel address to write to
|
||||
@return true if pixels are scaled to fit dst
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_scalePixels
|
||||
*/
|
||||
bool scalePixels(const SkPixmap& dst, const SkSamplingOptions&) const;
|
||||
|
||||
/** Writes color to pixels bounded by subset; returns true on success.
|
||||
Returns false if colorType() is kUnknown_SkColorType, or if subset does
|
||||
not intersect bounds().
|
||||
|
||||
@param color sRGB unpremultiplied color to write
|
||||
@param subset bounding integer SkRect of written pixels
|
||||
@return true if pixels are changed
|
||||
|
||||
example: https://fiddle.skia.org/c/@Pixmap_erase
|
||||
*/
|
||||
bool erase(SkColor color, const SkIRect& subset) const;
|
||||
|
||||
/** Writes color to pixels inside bounds(); returns true on success.
|
||||
Returns false if colorType() is kUnknown_SkColorType, or if bounds()
|
||||
is empty.
|
||||
|
||||
@param color sRGB unpremultiplied color to write
|
||||
@return true if pixels are changed
|
||||
*/
|
||||
bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
|
||||
|
||||
/** Writes color to pixels bounded by subset; returns true on success.
|
||||
if subset is nullptr, writes colors pixels inside bounds(). Returns false if
|
||||
colorType() is kUnknown_SkColorType, if subset is not nullptr and does
|
||||
not intersect bounds(), or if subset is nullptr and bounds() is empty.
|
||||
|
||||
@param color unpremultiplied color to write
|
||||
@param subset bounding integer SkRect of pixels to write; may be nullptr
|
||||
@return true if pixels are changed
|
||||
*/
|
||||
bool erase(const SkColor4f& color, const SkIRect* subset = nullptr) const;
|
||||
|
||||
private:
|
||||
const void* fPixels;
|
||||
size_t fRowBytes;
|
||||
SkImageInfo fInfo;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// SkPoint is part of the public API, but is also required by code in base. The following include
|
||||
// forwarding allows SkPoint to participate in the API and for use by code in base.
|
||||
|
||||
#include "include/private/base/SkPoint_impl.h" // IWYU pragma: export
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 SkPoint3_DEFINED
|
||||
#define SkPoint3_DEFINED
|
||||
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkFloatingPoint.h"
|
||||
|
||||
struct SK_API SkPoint3 {
|
||||
SkScalar fX, fY, fZ;
|
||||
|
||||
static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z) {
|
||||
SkPoint3 pt;
|
||||
pt.set(x, y, z);
|
||||
return pt;
|
||||
}
|
||||
|
||||
SkScalar x() const { return fX; }
|
||||
SkScalar y() const { return fY; }
|
||||
SkScalar z() const { return fZ; }
|
||||
|
||||
void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; }
|
||||
|
||||
friend bool operator==(const SkPoint3& a, const SkPoint3& b) {
|
||||
return a.fX == b.fX && a.fY == b.fY && a.fZ == b.fZ;
|
||||
}
|
||||
|
||||
friend bool operator!=(const SkPoint3& a, const SkPoint3& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
/** Returns the Euclidian distance from (0,0,0) to (x,y,z)
|
||||
*/
|
||||
static SkScalar Length(SkScalar x, SkScalar y, SkScalar z);
|
||||
|
||||
/** Return the Euclidian distance from (0,0,0) to the point
|
||||
*/
|
||||
SkScalar length() const { return SkPoint3::Length(fX, fY, fZ); }
|
||||
|
||||
/** Set the point (vector) to be unit-length in the same direction as it
|
||||
already points. If the point has a degenerate length (i.e., nearly 0)
|
||||
then set it to (0,0,0) and return false; otherwise return true.
|
||||
*/
|
||||
bool normalize();
|
||||
|
||||
/** Return a new point whose X, Y and Z coordinates are scaled.
|
||||
*/
|
||||
SkPoint3 makeScale(SkScalar scale) const {
|
||||
SkPoint3 p;
|
||||
p.set(scale * fX, scale * fY, scale * fZ);
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Scale the point's coordinates by scale.
|
||||
*/
|
||||
void scale(SkScalar value) {
|
||||
fX *= value;
|
||||
fY *= value;
|
||||
fZ *= value;
|
||||
}
|
||||
|
||||
/** Return a new point whose X, Y and Z coordinates are the negative of the
|
||||
original point's
|
||||
*/
|
||||
SkPoint3 operator-() const {
|
||||
SkPoint3 neg;
|
||||
neg.fX = -fX;
|
||||
neg.fY = -fY;
|
||||
neg.fZ = -fZ;
|
||||
return neg;
|
||||
}
|
||||
|
||||
/** Returns a new point whose coordinates are the difference between
|
||||
a and b (i.e., a - b)
|
||||
*/
|
||||
friend SkPoint3 operator-(const SkPoint3& a, const SkPoint3& b) {
|
||||
return { a.fX - b.fX, a.fY - b.fY, a.fZ - b.fZ };
|
||||
}
|
||||
|
||||
/** Returns a new point whose coordinates are the sum of a and b (a + b)
|
||||
*/
|
||||
friend SkPoint3 operator+(const SkPoint3& a, const SkPoint3& b) {
|
||||
return { a.fX + b.fX, a.fY + b.fY, a.fZ + b.fZ };
|
||||
}
|
||||
|
||||
/** Add v's coordinates to the point's
|
||||
*/
|
||||
void operator+=(const SkPoint3& v) {
|
||||
fX += v.fX;
|
||||
fY += v.fY;
|
||||
fZ += v.fZ;
|
||||
}
|
||||
|
||||
/** Subtract v's coordinates from the point's
|
||||
*/
|
||||
void operator-=(const SkPoint3& v) {
|
||||
fX -= v.fX;
|
||||
fY -= v.fY;
|
||||
fZ -= v.fZ;
|
||||
}
|
||||
|
||||
friend SkPoint3 operator*(SkScalar t, SkPoint3 p) {
|
||||
return { t * p.fX, t * p.fY, t * p.fZ };
|
||||
}
|
||||
|
||||
/** Returns true if fX, fY, and fZ are measurable values.
|
||||
|
||||
@return true for values other than infinities and NaN
|
||||
*/
|
||||
bool isFinite() const {
|
||||
return SkIsFinite(fX, fY, fZ);
|
||||
}
|
||||
|
||||
/** Returns the dot product of a and b, treating them as 3D vectors
|
||||
*/
|
||||
static SkScalar DotProduct(const SkPoint3& a, const SkPoint3& b) {
|
||||
return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
|
||||
}
|
||||
|
||||
SkScalar dot(const SkPoint3& vec) const {
|
||||
return DotProduct(*this, vec);
|
||||
}
|
||||
|
||||
/** Returns the cross product of a and b, treating them as 3D vectors
|
||||
*/
|
||||
static SkPoint3 CrossProduct(const SkPoint3& a, const SkPoint3& b) {
|
||||
SkPoint3 result;
|
||||
result.fX = a.fY*b.fZ - a.fZ*b.fY;
|
||||
result.fY = a.fZ*b.fX - a.fX*b.fZ;
|
||||
result.fZ = a.fX*b.fY - a.fY*b.fX;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SkPoint3 cross(const SkPoint3& vec) const {
|
||||
return CrossProduct(*this, vec);
|
||||
}
|
||||
};
|
||||
|
||||
typedef SkPoint3 SkVector3;
|
||||
typedef SkPoint3 SkColor3f;
|
||||
|
||||
#endif
|
@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright 2012 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkRRect_DEFINED
|
||||
#define SkRRect_DEFINED
|
||||
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
class SkMatrix;
|
||||
class SkString;
|
||||
|
||||
/** \class SkRRect
|
||||
SkRRect describes a rounded rectangle with a bounds and a pair of radii for each corner.
|
||||
The bounds and radii can be set so that SkRRect describes: a rectangle with sharp corners;
|
||||
a circle; an oval; or a rectangle with one or more rounded corners.
|
||||
|
||||
SkRRect allows implementing CSS properties that describe rounded corners.
|
||||
SkRRect may have up to eight different radii, one for each axis on each of its four
|
||||
corners.
|
||||
|
||||
SkRRect may modify the provided parameters when initializing bounds and radii.
|
||||
If either axis radii is zero or less: radii are stored as zero; corner is square.
|
||||
If corner curves overlap, radii are proportionally reduced to fit within bounds.
|
||||
*/
|
||||
class SK_API SkRRect {
|
||||
public:
|
||||
|
||||
/** Initializes bounds at (0, 0), the origin, with zero width and height.
|
||||
Initializes corner radii to (0, 0), and sets type of kEmpty_Type.
|
||||
|
||||
@return empty SkRRect
|
||||
*/
|
||||
SkRRect() = default;
|
||||
|
||||
/** Initializes to copy of rrect bounds and corner radii.
|
||||
|
||||
@param rrect bounds and corner to copy
|
||||
@return copy of rrect
|
||||
*/
|
||||
SkRRect(const SkRRect& rrect) = default;
|
||||
|
||||
/** Copies rrect bounds and corner radii.
|
||||
|
||||
@param rrect bounds and corner to copy
|
||||
@return copy of rrect
|
||||
*/
|
||||
SkRRect& operator=(const SkRRect& rrect) = default;
|
||||
|
||||
/** \enum SkRRect::Type
|
||||
Type describes possible specializations of SkRRect. Each Type is
|
||||
exclusive; a SkRRect may only have one type.
|
||||
|
||||
Type members become progressively less restrictive; larger values of
|
||||
Type have more degrees of freedom than smaller values.
|
||||
*/
|
||||
enum Type {
|
||||
kEmpty_Type, //!< zero width or height
|
||||
kRect_Type, //!< non-zero width and height, and zeroed radii
|
||||
kOval_Type, //!< non-zero width and height filled with radii
|
||||
kSimple_Type, //!< non-zero width and height with equal radii
|
||||
kNinePatch_Type, //!< non-zero width and height with axis-aligned radii
|
||||
kComplex_Type, //!< non-zero width and height with arbitrary radii
|
||||
kLastType = kComplex_Type, //!< largest Type value
|
||||
};
|
||||
|
||||
Type getType() const {
|
||||
SkASSERT(this->isValid());
|
||||
return static_cast<Type>(fType);
|
||||
}
|
||||
|
||||
Type type() const { return this->getType(); }
|
||||
|
||||
inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
|
||||
inline bool isRect() const { return kRect_Type == this->getType(); }
|
||||
inline bool isOval() const { return kOval_Type == this->getType(); }
|
||||
inline bool isSimple() const { return kSimple_Type == this->getType(); }
|
||||
inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
|
||||
inline bool isComplex() const { return kComplex_Type == this->getType(); }
|
||||
|
||||
/** Returns span on the x-axis. This does not check if result fits in 32-bit float;
|
||||
result may be infinity.
|
||||
|
||||
@return rect().fRight minus rect().fLeft
|
||||
*/
|
||||
SkScalar width() const { return fRect.width(); }
|
||||
|
||||
/** Returns span on the y-axis. This does not check if result fits in 32-bit float;
|
||||
result may be infinity.
|
||||
|
||||
@return rect().fBottom minus rect().fTop
|
||||
*/
|
||||
SkScalar height() const { return fRect.height(); }
|
||||
|
||||
/** Returns top-left corner radii. If type() returns kEmpty_Type, kRect_Type,
|
||||
kOval_Type, or kSimple_Type, returns a value representative of all corner radii.
|
||||
If type() returns kNinePatch_Type or kComplex_Type, at least one of the
|
||||
remaining three corners has a different value.
|
||||
|
||||
@return corner radii for simple types
|
||||
*/
|
||||
SkVector getSimpleRadii() const {
|
||||
return fRadii[0];
|
||||
}
|
||||
|
||||
/** Sets bounds to zero width and height at (0, 0), the origin. Sets
|
||||
corner radii to zero and sets type to kEmpty_Type.
|
||||
*/
|
||||
void setEmpty() { *this = SkRRect(); }
|
||||
|
||||
/** Sets bounds to sorted rect, and sets corner radii to zero.
|
||||
If set bounds has width and height, and sets type to kRect_Type;
|
||||
otherwise, sets type to kEmpty_Type.
|
||||
|
||||
@param rect bounds to set
|
||||
*/
|
||||
void setRect(const SkRect& rect) {
|
||||
if (!this->initializeRect(rect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(fRadii, 0, sizeof(fRadii));
|
||||
fType = kRect_Type;
|
||||
|
||||
SkASSERT(this->isValid());
|
||||
}
|
||||
|
||||
/** Initializes bounds at (0, 0), the origin, with zero width and height.
|
||||
Initializes corner radii to (0, 0), and sets type of kEmpty_Type.
|
||||
|
||||
@return empty SkRRect
|
||||
*/
|
||||
static SkRRect MakeEmpty() { return SkRRect(); }
|
||||
|
||||
/** Initializes to copy of r bounds and zeroes corner radii.
|
||||
|
||||
@param r bounds to copy
|
||||
@return copy of r
|
||||
*/
|
||||
static SkRRect MakeRect(const SkRect& r) {
|
||||
SkRRect rr;
|
||||
rr.setRect(r);
|
||||
return rr;
|
||||
}
|
||||
|
||||
/** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
|
||||
to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
|
||||
Otherwise, sets to kOval_Type.
|
||||
|
||||
@param oval bounds of oval
|
||||
@return oval
|
||||
*/
|
||||
static SkRRect MakeOval(const SkRect& oval) {
|
||||
SkRRect rr;
|
||||
rr.setOval(oval);
|
||||
return rr;
|
||||
}
|
||||
|
||||
/** Sets to rounded rectangle with the same radii for all four corners.
|
||||
If rect is empty, sets to kEmpty_Type.
|
||||
Otherwise, if xRad and yRad are zero, sets to kRect_Type.
|
||||
Otherwise, if xRad is at least half rect.width() and yRad is at least half
|
||||
rect.height(), sets to kOval_Type.
|
||||
Otherwise, sets to kSimple_Type.
|
||||
|
||||
@param rect bounds of rounded rectangle
|
||||
@param xRad x-axis radius of corners
|
||||
@param yRad y-axis radius of corners
|
||||
@return rounded rectangle
|
||||
*/
|
||||
static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
|
||||
SkRRect rr;
|
||||
rr.setRectXY(rect, xRad, yRad);
|
||||
return rr;
|
||||
}
|
||||
|
||||
/** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
|
||||
to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
|
||||
Otherwise, sets to kOval_Type.
|
||||
|
||||
@param oval bounds of oval
|
||||
*/
|
||||
void setOval(const SkRect& oval);
|
||||
|
||||
/** Sets to rounded rectangle with the same radii for all four corners.
|
||||
If rect is empty, sets to kEmpty_Type.
|
||||
Otherwise, if xRad or yRad is zero, sets to kRect_Type.
|
||||
Otherwise, if xRad is at least half rect.width() and yRad is at least half
|
||||
rect.height(), sets to kOval_Type.
|
||||
Otherwise, sets to kSimple_Type.
|
||||
|
||||
@param rect bounds of rounded rectangle
|
||||
@param xRad x-axis radius of corners
|
||||
@param yRad y-axis radius of corners
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_setRectXY
|
||||
*/
|
||||
void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
|
||||
|
||||
/** Sets bounds to rect. Sets radii to (leftRad, topRad), (rightRad, topRad),
|
||||
(rightRad, bottomRad), (leftRad, bottomRad).
|
||||
|
||||
If rect is empty, sets to kEmpty_Type.
|
||||
Otherwise, if leftRad and rightRad are zero, sets to kRect_Type.
|
||||
Otherwise, if topRad and bottomRad are zero, sets to kRect_Type.
|
||||
Otherwise, if leftRad and rightRad are equal and at least half rect.width(), and
|
||||
topRad and bottomRad are equal at least half rect.height(), sets to kOval_Type.
|
||||
Otherwise, if leftRad and rightRad are equal, and topRad and bottomRad are equal,
|
||||
sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.
|
||||
|
||||
Nine patch refers to the nine parts defined by the radii: one center rectangle,
|
||||
four edge patches, and four corner patches.
|
||||
|
||||
@param rect bounds of rounded rectangle
|
||||
@param leftRad left-top and left-bottom x-axis radius
|
||||
@param topRad left-top and right-top y-axis radius
|
||||
@param rightRad right-top and right-bottom x-axis radius
|
||||
@param bottomRad left-bottom and right-bottom y-axis radius
|
||||
*/
|
||||
void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
|
||||
SkScalar rightRad, SkScalar bottomRad);
|
||||
|
||||
/** Sets bounds to rect. Sets radii array for individual control of all for corners.
|
||||
|
||||
If rect is empty, sets to kEmpty_Type.
|
||||
Otherwise, if one of each corner radii are zero, sets to kRect_Type.
|
||||
Otherwise, if all x-axis radii are equal and at least half rect.width(), and
|
||||
all y-axis radii are equal at least half rect.height(), sets to kOval_Type.
|
||||
Otherwise, if all x-axis radii are equal, and all y-axis radii are equal,
|
||||
sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.
|
||||
|
||||
@param rect bounds of rounded rectangle
|
||||
@param radii corner x-axis and y-axis radii
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_setRectRadii
|
||||
*/
|
||||
void setRectRadii(const SkRect& rect, const SkVector radii[4]);
|
||||
|
||||
/** \enum SkRRect::Corner
|
||||
The radii are stored: top-left, top-right, bottom-right, bottom-left.
|
||||
*/
|
||||
enum Corner {
|
||||
kUpperLeft_Corner, //!< index of top-left corner radii
|
||||
kUpperRight_Corner, //!< index of top-right corner radii
|
||||
kLowerRight_Corner, //!< index of bottom-right corner radii
|
||||
kLowerLeft_Corner, //!< index of bottom-left corner radii
|
||||
};
|
||||
|
||||
/** Returns bounds. Bounds may have zero width or zero height. Bounds right is
|
||||
greater than or equal to left; bounds bottom is greater than or equal to top.
|
||||
Result is identical to getBounds().
|
||||
|
||||
@return bounding box
|
||||
*/
|
||||
const SkRect& rect() const { return fRect; }
|
||||
|
||||
/** Returns scalar pair for radius of curve on x-axis and y-axis for one corner.
|
||||
Both radii may be zero. If not zero, both are positive and finite.
|
||||
|
||||
@return x-axis and y-axis radii for one corner
|
||||
*/
|
||||
SkVector radii(Corner corner) const { return fRadii[corner]; }
|
||||
|
||||
/** Returns bounds. Bounds may have zero width or zero height. Bounds right is
|
||||
greater than or equal to left; bounds bottom is greater than or equal to top.
|
||||
Result is identical to rect().
|
||||
|
||||
@return bounding box
|
||||
*/
|
||||
const SkRect& getBounds() const { return fRect; }
|
||||
|
||||
/** Returns true if bounds and radii in a are equal to bounds and radii in b.
|
||||
|
||||
a and b are not equal if either contain NaN. a and b are equal if members
|
||||
contain zeroes with different signs.
|
||||
|
||||
@param a SkRect bounds and radii to compare
|
||||
@param b SkRect bounds and radii to compare
|
||||
@return true if members are equal
|
||||
*/
|
||||
friend bool operator==(const SkRRect& a, const SkRRect& b) {
|
||||
return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
|
||||
}
|
||||
|
||||
/** Returns true if bounds and radii in a are not equal to bounds and radii in b.
|
||||
|
||||
a and b are not equal if either contain NaN. a and b are equal if members
|
||||
contain zeroes with different signs.
|
||||
|
||||
@param a SkRect bounds and radii to compare
|
||||
@param b SkRect bounds and radii to compare
|
||||
@return true if members are not equal
|
||||
*/
|
||||
friend bool operator!=(const SkRRect& a, const SkRRect& b) {
|
||||
return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
|
||||
}
|
||||
|
||||
/** Copies SkRRect to dst, then insets dst bounds by dx and dy, and adjusts dst
|
||||
radii by dx and dy. dx and dy may be positive, negative, or zero. dst may be
|
||||
SkRRect.
|
||||
|
||||
If either corner radius is zero, the corner has no curvature and is unchanged.
|
||||
Otherwise, if adjusted radius becomes negative, pins radius to zero.
|
||||
If dx exceeds half dst bounds width, dst bounds left and right are set to
|
||||
bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
|
||||
bottom are set to bounds y-axis center.
|
||||
|
||||
If dx or dy cause the bounds to become infinite, dst bounds is zeroed.
|
||||
|
||||
@param dx added to rect().fLeft, and subtracted from rect().fRight
|
||||
@param dy added to rect().fTop, and subtracted from rect().fBottom
|
||||
@param dst insets bounds and radii
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_inset
|
||||
*/
|
||||
void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
|
||||
|
||||
/** Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
|
||||
positive, negative, or zero.
|
||||
|
||||
If either corner radius is zero, the corner has no curvature and is unchanged.
|
||||
Otherwise, if adjusted radius becomes negative, pins radius to zero.
|
||||
If dx exceeds half bounds width, bounds left and right are set to
|
||||
bounds x-axis center. If dy exceeds half bounds height, bounds top and
|
||||
bottom are set to bounds y-axis center.
|
||||
|
||||
If dx or dy cause the bounds to become infinite, bounds is zeroed.
|
||||
|
||||
@param dx added to rect().fLeft, and subtracted from rect().fRight
|
||||
@param dy added to rect().fTop, and subtracted from rect().fBottom
|
||||
*/
|
||||
void inset(SkScalar dx, SkScalar dy) {
|
||||
this->inset(dx, dy, this);
|
||||
}
|
||||
|
||||
/** Outsets dst bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
|
||||
positive, negative, or zero.
|
||||
|
||||
If either corner radius is zero, the corner has no curvature and is unchanged.
|
||||
Otherwise, if adjusted radius becomes negative, pins radius to zero.
|
||||
If dx exceeds half dst bounds width, dst bounds left and right are set to
|
||||
bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
|
||||
bottom are set to bounds y-axis center.
|
||||
|
||||
If dx or dy cause the bounds to become infinite, dst bounds is zeroed.
|
||||
|
||||
@param dx subtracted from rect().fLeft, and added to rect().fRight
|
||||
@param dy subtracted from rect().fTop, and added to rect().fBottom
|
||||
@param dst outset bounds and radii
|
||||
*/
|
||||
void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
|
||||
this->inset(-dx, -dy, dst);
|
||||
}
|
||||
|
||||
/** Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
|
||||
positive, negative, or zero.
|
||||
|
||||
If either corner radius is zero, the corner has no curvature and is unchanged.
|
||||
Otherwise, if adjusted radius becomes negative, pins radius to zero.
|
||||
If dx exceeds half bounds width, bounds left and right are set to
|
||||
bounds x-axis center. If dy exceeds half bounds height, bounds top and
|
||||
bottom are set to bounds y-axis center.
|
||||
|
||||
If dx or dy cause the bounds to become infinite, bounds is zeroed.
|
||||
|
||||
@param dx subtracted from rect().fLeft, and added to rect().fRight
|
||||
@param dy subtracted from rect().fTop, and added to rect().fBottom
|
||||
*/
|
||||
void outset(SkScalar dx, SkScalar dy) {
|
||||
this->inset(-dx, -dy, this);
|
||||
}
|
||||
|
||||
/** Translates SkRRect by (dx, dy).
|
||||
|
||||
@param dx offset added to rect().fLeft and rect().fRight
|
||||
@param dy offset added to rect().fTop and rect().fBottom
|
||||
*/
|
||||
void offset(SkScalar dx, SkScalar dy) {
|
||||
fRect.offset(dx, dy);
|
||||
}
|
||||
|
||||
/** Returns SkRRect translated by (dx, dy).
|
||||
|
||||
@param dx offset added to rect().fLeft and rect().fRight
|
||||
@param dy offset added to rect().fTop and rect().fBottom
|
||||
@return SkRRect bounds offset by (dx, dy), with unchanged corner radii
|
||||
*/
|
||||
[[nodiscard]] SkRRect makeOffset(SkScalar dx, SkScalar dy) const {
|
||||
return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
|
||||
}
|
||||
|
||||
/** Returns true if rect is inside the bounds and corner radii, and if
|
||||
SkRRect and rect are not empty.
|
||||
|
||||
@param rect area tested for containment
|
||||
@return true if SkRRect contains rect
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_contains
|
||||
*/
|
||||
bool contains(const SkRect& rect) const;
|
||||
|
||||
/** Returns true if bounds and radii values are finite and describe a SkRRect
|
||||
SkRRect::Type that matches getType(). All SkRRect methods construct valid types,
|
||||
even if the input values are not valid. Invalid SkRRect data can only
|
||||
be generated by corrupting memory.
|
||||
|
||||
@return true if bounds and radii match type()
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_isValid
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
static constexpr size_t kSizeInMemory = 12 * sizeof(SkScalar);
|
||||
|
||||
/** Writes SkRRect to buffer. Writes kSizeInMemory bytes, and returns
|
||||
kSizeInMemory, the number of bytes written.
|
||||
|
||||
@param buffer storage for SkRRect
|
||||
@return bytes written, kSizeInMemory
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_writeToMemory
|
||||
*/
|
||||
size_t writeToMemory(void* buffer) const;
|
||||
|
||||
/** Reads SkRRect from buffer, reading kSizeInMemory bytes.
|
||||
Returns kSizeInMemory, bytes read if length is at least kSizeInMemory.
|
||||
Otherwise, returns zero.
|
||||
|
||||
@param buffer memory to read from
|
||||
@param length size of buffer
|
||||
@return bytes read, or 0 if length is less than kSizeInMemory
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_readFromMemory
|
||||
*/
|
||||
size_t readFromMemory(const void* buffer, size_t length);
|
||||
|
||||
/** Transforms by SkRRect by matrix, storing result in dst.
|
||||
Returns true if SkRRect transformed can be represented by another SkRRect.
|
||||
Returns false if matrix contains transformations that are not axis aligned.
|
||||
|
||||
Asserts in debug builds if SkRRect equals dst.
|
||||
|
||||
@param matrix SkMatrix specifying the transform
|
||||
@param dst SkRRect to store the result
|
||||
@return true if transformation succeeded.
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_transform
|
||||
*/
|
||||
bool transform(const SkMatrix& matrix, SkRRect* dst) const;
|
||||
|
||||
/** Writes text representation of SkRRect to standard output.
|
||||
Set asHex true to generate exact binary representations
|
||||
of floating point numbers.
|
||||
|
||||
@param asHex true if SkScalar values are written as hexadecimal
|
||||
|
||||
example: https://fiddle.skia.org/c/@RRect_dump
|
||||
*/
|
||||
void dump(bool asHex) const;
|
||||
SkString dumpToString(bool asHex) const;
|
||||
|
||||
/** Writes text representation of SkRRect to standard output. The representation
|
||||
may be directly compiled as C++ code. Floating point values are written
|
||||
with limited precision; it may not be possible to reconstruct original
|
||||
SkRRect from output.
|
||||
*/
|
||||
void dump() const { this->dump(false); }
|
||||
|
||||
/** Writes text representation of SkRRect to standard output. The representation
|
||||
may be directly compiled as C++ code. Floating point values are written
|
||||
in hexadecimal to preserve their exact bit pattern. The output reconstructs the
|
||||
original SkRRect.
|
||||
*/
|
||||
void dumpHex() const { this->dump(true); }
|
||||
|
||||
private:
|
||||
static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]);
|
||||
|
||||
SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)
|
||||
: fRect(rect)
|
||||
, fRadii{radii[0], radii[1], radii[2], radii[3]}
|
||||
, fType(type) {}
|
||||
|
||||
/**
|
||||
* Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully
|
||||
* initialized and false is returned. Otherwise, just fRect is initialized and true is returned.
|
||||
*/
|
||||
bool initializeRect(const SkRect&);
|
||||
|
||||
void computeType();
|
||||
bool checkCornerContainment(SkScalar x, SkScalar y) const;
|
||||
// Returns true if the radii had to be scaled to fit rect
|
||||
bool scaleRadii();
|
||||
|
||||
SkRect fRect = SkRect::MakeEmpty();
|
||||
// Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
|
||||
SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}};
|
||||
// use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)
|
||||
int32_t fType = kEmpty_Type;
|
||||
// TODO: add padding so we can use memcpy for flattening and not copy uninitialized data
|
||||
|
||||
// to access fRadii directly
|
||||
friend class SkPath;
|
||||
friend class SkRRectPriv;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 SkRSXform_DEFINED
|
||||
#define SkRSXform_DEFINED
|
||||
|
||||
#include "include/core/SkPoint.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkSize.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
/**
|
||||
* A compressed form of a rotation+scale matrix.
|
||||
*
|
||||
* [ fSCos -fSSin fTx ]
|
||||
* [ fSSin fSCos fTy ]
|
||||
* [ 0 0 1 ]
|
||||
*/
|
||||
struct SK_API SkRSXform {
|
||||
static SkRSXform Make(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {
|
||||
SkRSXform xform = { scos, ssin, tx, ty };
|
||||
return xform;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a new xform based on the scale, rotation (in radians), final tx,ty location
|
||||
* and anchor-point ax,ay within the src quad.
|
||||
*
|
||||
* Note: the anchor point is not normalized (e.g. 0...1) but is in pixels of the src image.
|
||||
*/
|
||||
static SkRSXform MakeFromRadians(SkScalar scale, SkScalar radians, SkScalar tx, SkScalar ty,
|
||||
SkScalar ax, SkScalar ay) {
|
||||
const SkScalar s = SkScalarSin(radians) * scale;
|
||||
const SkScalar c = SkScalarCos(radians) * scale;
|
||||
return Make(c, s, tx + -c * ax + s * ay, ty + -s * ax - c * ay);
|
||||
}
|
||||
|
||||
SkScalar fSCos;
|
||||
SkScalar fSSin;
|
||||
SkScalar fTx;
|
||||
SkScalar fTy;
|
||||
|
||||
bool rectStaysRect() const {
|
||||
return 0 == fSCos || 0 == fSSin;
|
||||
}
|
||||
|
||||
void setIdentity() {
|
||||
fSCos = 1;
|
||||
fSSin = fTx = fTy = 0;
|
||||
}
|
||||
|
||||
void set(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {
|
||||
fSCos = scos;
|
||||
fSSin = ssin;
|
||||
fTx = tx;
|
||||
fTy = ty;
|
||||
}
|
||||
|
||||
void toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const;
|
||||
void toQuad(const SkSize& size, SkPoint quad[4]) const {
|
||||
this->toQuad(size.width(), size.height(), quad);
|
||||
}
|
||||
void toTriStrip(SkScalar width, SkScalar height, SkPoint strip[4]) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 SkRasterHandleAllocator_DEFINED
|
||||
#define SkRasterHandleAllocator_DEFINED
|
||||
|
||||
#include "include/core/SkImageInfo.h"
|
||||
|
||||
class SkBitmap;
|
||||
class SkCanvas;
|
||||
class SkMatrix;
|
||||
class SkSurfaceProps;
|
||||
|
||||
/**
|
||||
* If a client wants to control the allocation of raster layers in a canvas, it should subclass
|
||||
* SkRasterHandleAllocator. This allocator performs two tasks:
|
||||
* 1. controls how the memory for the pixels is allocated
|
||||
* 2. associates a "handle" to a private object that can track the matrix/clip of the SkCanvas
|
||||
*
|
||||
* This example allocates a canvas, and defers to the allocator to create the base layer.
|
||||
*
|
||||
* std::unique_ptr<SkCanvas> canvas = SkRasterHandleAllocator::MakeCanvas(
|
||||
* SkImageInfo::Make(...),
|
||||
* std::make_unique<MySubclassRasterHandleAllocator>(...),
|
||||
* nullptr);
|
||||
*
|
||||
* If you have already allocated the base layer (and its handle, release-proc etc.) then you
|
||||
* can pass those in using the last parameter to MakeCanvas().
|
||||
*
|
||||
* Regardless of how the base layer is allocated, each time canvas->saveLayer() is called,
|
||||
* your allocator's allocHandle() will be called.
|
||||
*/
|
||||
class SK_API SkRasterHandleAllocator {
|
||||
public:
|
||||
virtual ~SkRasterHandleAllocator() = default;
|
||||
|
||||
// The value that is returned to clients of the canvas that has this allocator installed.
|
||||
typedef void* Handle;
|
||||
|
||||
struct Rec {
|
||||
// When the allocation goes out of scope, this proc is called to free everything associated
|
||||
// with it: the pixels, the "handle", etc. This is passed the pixel address and fReleaseCtx.
|
||||
void (*fReleaseProc)(void* pixels, void* ctx);
|
||||
void* fReleaseCtx; // context passed to fReleaseProc
|
||||
void* fPixels; // pixels for this allocation
|
||||
size_t fRowBytes; // rowbytes for these pixels
|
||||
Handle fHandle; // public handle returned by SkCanvas::accessTopRasterHandle()
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a requested info, allocate the corresponding pixels/rowbytes, and whatever handle
|
||||
* is desired to give clients access to those pixels. The rec also contains a proc and context
|
||||
* which will be called when this allocation goes out of scope.
|
||||
*
|
||||
* e.g.
|
||||
* when canvas->saveLayer() is called, the allocator will be called to allocate the pixels
|
||||
* for the layer. When canvas->restore() is called, the fReleaseProc will be called.
|
||||
*/
|
||||
virtual bool allocHandle(const SkImageInfo&, Rec*) = 0;
|
||||
|
||||
/**
|
||||
* Clients access the handle for a given layer by calling SkCanvas::accessTopRasterHandle().
|
||||
* To allow the handle to reflect the current matrix/clip in the canvs, updateHandle() is
|
||||
* is called. The subclass is responsible to update the handle as it sees fit.
|
||||
*/
|
||||
virtual void updateHandle(Handle, const SkMatrix&, const SkIRect&) = 0;
|
||||
|
||||
/**
|
||||
* This creates a canvas which will use the allocator to manage pixel allocations, including
|
||||
* all calls to saveLayer().
|
||||
*
|
||||
* If rec is non-null, then it will be used as the base-layer of pixels/handle.
|
||||
* If rec is null, then the allocator will be called for the base-layer as well.
|
||||
*/
|
||||
static std::unique_ptr<SkCanvas> MakeCanvas(std::unique_ptr<SkRasterHandleAllocator>,
|
||||
const SkImageInfo&, const Rec* rec = nullptr,
|
||||
const SkSurfaceProps* props = nullptr);
|
||||
|
||||
protected:
|
||||
SkRasterHandleAllocator() = default;
|
||||
SkRasterHandleAllocator(const SkRasterHandleAllocator&) = delete;
|
||||
SkRasterHandleAllocator& operator=(const SkRasterHandleAllocator&) = delete;
|
||||
|
||||
private:
|
||||
friend class SkBitmapDevice;
|
||||
|
||||
Handle allocBitmap(const SkImageInfo&, SkBitmap*);
|
||||
};
|
||||
|
||||
#endif
|
1374
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/core/SkRect.h
Normal file
1374
Tests/LottieMetalTest/skia/PublicHeaders/skia/include/core/SkRect.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,389 @@
|
||||
/*
|
||||
* 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 SkRefCnt_DEFINED
|
||||
#define SkRefCnt_DEFINED
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkDebug.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
/** \class SkRefCntBase
|
||||
|
||||
SkRefCntBase is the base class for objects that may be shared by multiple
|
||||
objects. When an existing owner wants to share a reference, it calls ref().
|
||||
When an owner wants to release its reference, it calls unref(). When the
|
||||
shared object's reference count goes to zero as the result of an unref()
|
||||
call, its (virtual) destructor is called. It is an error for the
|
||||
destructor to be called explicitly (or via the object going out of scope on
|
||||
the stack or calling delete) if getRefCnt() > 1.
|
||||
*/
|
||||
class SK_API SkRefCntBase {
|
||||
public:
|
||||
/** Default construct, initializing the reference count to 1.
|
||||
*/
|
||||
SkRefCntBase() : fRefCnt(1) {}
|
||||
|
||||
/** Destruct, asserting that the reference count is 1.
|
||||
*/
|
||||
virtual ~SkRefCntBase() {
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERTF(this->getRefCnt() == 1, "fRefCnt was %d", this->getRefCnt());
|
||||
// illegal value, to catch us if we reuse after delete
|
||||
fRefCnt.store(0, std::memory_order_relaxed);
|
||||
#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 == 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().
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Increment the reference count. Must be balanced by a call to unref().
|
||||
*/
|
||||
void ref() const {
|
||||
SkASSERT(this->getRefCnt() > 0);
|
||||
// No barrier required.
|
||||
(void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
/** Decrement the reference count. If the reference count is 1 before the
|
||||
decrement, then delete the object. Note that if this is the case, then
|
||||
the object needs to have been allocated via new, and not on the stack.
|
||||
*/
|
||||
void unref() const {
|
||||
SkASSERT(this->getRefCnt() > 0);
|
||||
// A release here acts in place of all releases we "should" have been doing in ref().
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
/** Return the reference count. Use only for debugging. */
|
||||
int32_t getRefCnt() const {
|
||||
return fRefCnt.load(std::memory_order_relaxed);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Called when the ref count goes to 0.
|
||||
*/
|
||||
virtual void internal_dispose() const {
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERT(0 == this->getRefCnt());
|
||||
fRefCnt.store(1, std::memory_order_relaxed);
|
||||
#endif
|
||||
delete this;
|
||||
}
|
||||
|
||||
// The following friends are those which override internal_dispose()
|
||||
// and conditionally call SkRefCnt::internal_dispose().
|
||||
friend class SkWeakRefCnt;
|
||||
|
||||
mutable std::atomic<int32_t> fRefCnt;
|
||||
|
||||
SkRefCntBase(SkRefCntBase&&) = delete;
|
||||
SkRefCntBase(const SkRefCntBase&) = delete;
|
||||
SkRefCntBase& operator=(SkRefCntBase&&) = delete;
|
||||
SkRefCntBase& operator=(const SkRefCntBase&) = delete;
|
||||
};
|
||||
|
||||
#ifdef SK_REF_CNT_MIXIN_INCLUDE
|
||||
// It is the responsibility of the following include to define the type SkRefCnt.
|
||||
// This SkRefCnt should normally derive from SkRefCntBase.
|
||||
#include SK_REF_CNT_MIXIN_INCLUDE
|
||||
#else
|
||||
class SK_API SkRefCnt : public SkRefCntBase {
|
||||
// "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
|
||||
#if defined(SK_BUILD_FOR_GOOGLE3)
|
||||
public:
|
||||
void deref() const { this->unref(); }
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Call obj->ref() and return obj. The obj must not be nullptr.
|
||||
*/
|
||||
template <typename T> static inline T* SkRef(T* obj) {
|
||||
SkASSERT(obj);
|
||||
obj->ref();
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
|
||||
*/
|
||||
template <typename T> static inline T* SkSafeRef(T* obj) {
|
||||
if (obj) {
|
||||
obj->ref();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Check if the argument is non-null, and if so, call obj->unref()
|
||||
*/
|
||||
template <typename T> static inline void SkSafeUnref(T* obj) {
|
||||
if (obj) {
|
||||
obj->unref();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
|
||||
// There's only benefit to using this if the deriving class does not otherwise need a vtable.
|
||||
template <typename Derived>
|
||||
class SkNVRefCnt {
|
||||
public:
|
||||
SkNVRefCnt() : fRefCnt(1) {}
|
||||
~SkNVRefCnt() {
|
||||
#ifdef SK_DEBUG
|
||||
int rc = fRefCnt.load(std::memory_order_relaxed);
|
||||
SkASSERTF(rc == 1, "NVRefCnt was %d", rc);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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 == fRefCnt.load(std::memory_order_acquire); }
|
||||
void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
|
||||
void unref() const {
|
||||
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(); }
|
||||
|
||||
// This must be used with caution. It is only valid to call this when 'threadIsolatedTestCnt'
|
||||
// refs are known to be isolated to the current thread. That is, it is known that there are at
|
||||
// least 'threadIsolatedTestCnt' refs for which no other thread may make a balancing unref()
|
||||
// call. Assuming the contract is followed, if this returns false then no other thread has
|
||||
// ownership of this. If it returns true then another thread *may* have ownership.
|
||||
bool refCntGreaterThan(int32_t threadIsolatedTestCnt) const {
|
||||
int cnt = fRefCnt.load(std::memory_order_acquire);
|
||||
// If this fails then the above contract has been violated.
|
||||
SkASSERT(cnt >= threadIsolatedTestCnt);
|
||||
return cnt > threadIsolatedTestCnt;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::atomic<int32_t> fRefCnt;
|
||||
|
||||
SkNVRefCnt(SkNVRefCnt&&) = delete;
|
||||
SkNVRefCnt(const SkNVRefCnt&) = delete;
|
||||
SkNVRefCnt& operator=(SkNVRefCnt&&) = delete;
|
||||
SkNVRefCnt& operator=(const SkNVRefCnt&) = delete;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Shared pointer class to wrap classes that support a ref()/unref() interface.
|
||||
*
|
||||
* This can be used for classes inheriting from SkRefCnt, but it also works for other
|
||||
* classes that match the interface, but have different internal choices: e.g. the hosted class
|
||||
* may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
|
||||
*
|
||||
* Declared with the trivial_abi attribute where supported so that sk_sp and types containing it
|
||||
* may be considered as trivially relocatable by the compiler so that destroying-move operations
|
||||
* i.e. move constructor followed by destructor can be optimized to memcpy.
|
||||
*/
|
||||
template <typename T> class SK_TRIVIAL_ABI sk_sp {
|
||||
public:
|
||||
using element_type = T;
|
||||
|
||||
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 = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
|
||||
sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
|
||||
|
||||
/**
|
||||
* Move the underlying object from the argument to the newly created sk_sp. Afterwards only
|
||||
* the new sk_sp will have a reference to the object, and the argument will point to null.
|
||||
* No call to ref() or unref() will be made.
|
||||
*/
|
||||
sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
|
||||
template <typename U,
|
||||
typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
|
||||
sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
|
||||
|
||||
/**
|
||||
* Adopt the bare pointer into the newly created sk_sp.
|
||||
* No call to ref() or unref() will be made.
|
||||
*/
|
||||
explicit sk_sp(T* obj) : fPtr(obj) {}
|
||||
|
||||
/**
|
||||
* Calls unref() on the underlying object pointer.
|
||||
*/
|
||||
~sk_sp() {
|
||||
SkSafeUnref(fPtr);
|
||||
SkDEBUGCODE(fPtr = nullptr);
|
||||
}
|
||||
|
||||
sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
|
||||
|
||||
/**
|
||||
* Shares the underlying object referenced by the argument by calling ref() on it. If this
|
||||
* sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
|
||||
* object.
|
||||
*/
|
||||
sk_sp<T>& operator=(const sk_sp<T>& that) {
|
||||
if (this != &that) {
|
||||
this->reset(SkSafeRef(that.get()));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename U,
|
||||
typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
|
||||
sk_sp<T>& operator=(const sk_sp<U>& that) {
|
||||
this->reset(SkSafeRef(that.get()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
|
||||
* a reference to another object, unref() will be called on that object. No call to ref()
|
||||
* will be made.
|
||||
*/
|
||||
sk_sp<T>& operator=(sk_sp<T>&& that) {
|
||||
this->reset(that.release());
|
||||
return *this;
|
||||
}
|
||||
template <typename U,
|
||||
typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
|
||||
sk_sp<T>& operator=(sk_sp<U>&& that) {
|
||||
this->reset(that.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
SkASSERT(this->get() != nullptr);
|
||||
return *this->get();
|
||||
}
|
||||
|
||||
explicit operator bool() const { return this->get() != nullptr; }
|
||||
|
||||
T* get() const { return fPtr; }
|
||||
T* operator->() const { return fPtr; }
|
||||
|
||||
/**
|
||||
* Adopt the new bare pointer, and call unref() on any previously held object (if not null).
|
||||
* No call to ref() will be made.
|
||||
*/
|
||||
void reset(T* ptr = nullptr) {
|
||||
// Calling fPtr->unref() may call this->~() or this->reset(T*).
|
||||
// http://wg21.cmeerw.net/lwg/issue998
|
||||
// http://wg21.cmeerw.net/lwg/issue2262
|
||||
T* oldPtr = fPtr;
|
||||
fPtr = ptr;
|
||||
SkSafeUnref(oldPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bare pointer, and set the internal object pointer to nullptr.
|
||||
* The caller must assume ownership of the object, and manage its reference count directly.
|
||||
* No call to unref() will be made.
|
||||
*/
|
||||
[[nodiscard]] T* release() {
|
||||
T* ptr = fPtr;
|
||||
fPtr = nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void swap(sk_sp<T>& that) /*noexcept*/ {
|
||||
using std::swap;
|
||||
swap(fPtr, that.fPtr);
|
||||
}
|
||||
|
||||
using sk_is_trivially_relocatable = std::true_type;
|
||||
|
||||
private:
|
||||
T* fPtr;
|
||||
};
|
||||
|
||||
template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {
|
||||
return a.get() == b.get();
|
||||
}
|
||||
template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
|
||||
return !a;
|
||||
}
|
||||
template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
|
||||
return !b;
|
||||
}
|
||||
|
||||
template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {
|
||||
return a.get() != b.get();
|
||||
}
|
||||
template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
|
||||
return static_cast<bool>(a);
|
||||
}
|
||||
template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
|
||||
return static_cast<bool>(b);
|
||||
}
|
||||
|
||||
template <typename C, typename CT, typename T>
|
||||
auto operator<<(std::basic_ostream<C, CT>& os, const sk_sp<T>& sp) -> decltype(os << sp.get()) {
|
||||
return os << sp.get();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
sk_sp<T> sk_make_sp(Args&&... args) {
|
||||
return sk_sp<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).
|
||||
*
|
||||
* This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,
|
||||
* effectively "adopting" it.
|
||||
*/
|
||||
template <typename T> sk_sp<T> sk_ref_sp(T* obj) {
|
||||
return sk_sp<T>(SkSafeRef(obj));
|
||||
}
|
||||
|
||||
template <typename T> sk_sp<T> sk_ref_sp(const T* obj) {
|
||||
return sk_sp<T>(const_cast<T*>(SkSafeRef(obj)));
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,684 @@
|
||||
/*
|
||||
* Copyright 2005 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 SkRegion_DEFINED
|
||||
#define SkRegion_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
#include "include/private/base/SkAssert.h"
|
||||
#include "include/private/base/SkDebug.h"
|
||||
#include "include/private/base/SkTypeTraits.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
class SkPath;
|
||||
|
||||
/** \class SkRegion
|
||||
SkRegion describes the set of pixels used to clip SkCanvas. SkRegion is compact,
|
||||
efficiently storing a single integer rectangle, or a run length encoded array
|
||||
of rectangles. SkRegion may reduce the current SkCanvas clip, or may be drawn as
|
||||
one or more integer rectangles. SkRegion iterator returns the scan lines or
|
||||
rectangles contained by it, optionally intersecting a bounding rectangle.
|
||||
*/
|
||||
class SK_API SkRegion {
|
||||
typedef int32_t RunType;
|
||||
public:
|
||||
|
||||
/** Constructs an empty SkRegion. SkRegion is set to empty bounds
|
||||
at (0, 0) with zero width and height.
|
||||
|
||||
@return empty SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_empty_constructor
|
||||
*/
|
||||
SkRegion();
|
||||
|
||||
/** Constructs a copy of an existing region.
|
||||
Copy constructor makes two regions identical by value. Internally, region and
|
||||
the returned result share pointer values. The underlying SkRect array is
|
||||
copied when modified.
|
||||
|
||||
Creating a SkRegion copy is very efficient and never allocates memory.
|
||||
SkRegion are always copied by value from the interface; the underlying shared
|
||||
pointers are not exposed.
|
||||
|
||||
@param region SkRegion to copy by value
|
||||
@return copy of SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_copy_const_SkRegion
|
||||
*/
|
||||
SkRegion(const SkRegion& region);
|
||||
|
||||
/** Constructs a rectangular SkRegion matching the bounds of rect.
|
||||
|
||||
@param rect bounds of constructed SkRegion
|
||||
@return rectangular SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_copy_const_SkIRect
|
||||
*/
|
||||
explicit SkRegion(const SkIRect& rect);
|
||||
|
||||
/** Releases ownership of any shared data and deletes data if SkRegion is sole owner.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_destructor
|
||||
*/
|
||||
~SkRegion();
|
||||
|
||||
/** Constructs a copy of an existing region.
|
||||
Makes two regions identical by value. Internally, region and
|
||||
the returned result share pointer values. The underlying SkRect array is
|
||||
copied when modified.
|
||||
|
||||
Creating a SkRegion copy is very efficient and never allocates memory.
|
||||
SkRegion are always copied by value from the interface; the underlying shared
|
||||
pointers are not exposed.
|
||||
|
||||
@param region SkRegion to copy by value
|
||||
@return SkRegion to copy by value
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_copy_operator
|
||||
*/
|
||||
SkRegion& operator=(const SkRegion& region);
|
||||
|
||||
/** Compares SkRegion and other; returns true if they enclose exactly
|
||||
the same area.
|
||||
|
||||
@param other SkRegion to compare
|
||||
@return true if SkRegion pair are equivalent
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_equal1_operator
|
||||
*/
|
||||
bool operator==(const SkRegion& other) const;
|
||||
|
||||
/** Compares SkRegion and other; returns true if they do not enclose the same area.
|
||||
|
||||
@param other SkRegion to compare
|
||||
@return true if SkRegion pair are not equivalent
|
||||
*/
|
||||
bool operator!=(const SkRegion& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/** Sets SkRegion to src, and returns true if src bounds is not empty.
|
||||
This makes SkRegion and src identical by value. Internally,
|
||||
SkRegion and src share pointer values. The underlying SkRect array is
|
||||
copied when modified.
|
||||
|
||||
Creating a SkRegion copy is very efficient and never allocates memory.
|
||||
SkRegion are always copied by value from the interface; the underlying shared
|
||||
pointers are not exposed.
|
||||
|
||||
@param src SkRegion to copy
|
||||
@return copy of src
|
||||
*/
|
||||
bool set(const SkRegion& src) {
|
||||
*this = src;
|
||||
return !this->isEmpty();
|
||||
}
|
||||
|
||||
/** Exchanges SkIRect array of SkRegion and other. swap() internally exchanges pointers,
|
||||
so it is lightweight and does not allocate memory.
|
||||
|
||||
swap() usage has largely been replaced by operator=(const SkRegion& region).
|
||||
SkPath do not copy their content on assignment until they are written to,
|
||||
making assignment as efficient as swap().
|
||||
|
||||
@param other operator=(const SkRegion& region) set
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_swap
|
||||
*/
|
||||
void swap(SkRegion& other);
|
||||
|
||||
/** Returns true if SkRegion is empty.
|
||||
Empty SkRegion has bounds width or height less than or equal to zero.
|
||||
SkRegion() constructs empty SkRegion; setEmpty()
|
||||
and setRect() with dimensionless data make SkRegion empty.
|
||||
|
||||
@return true if bounds has no width or height
|
||||
*/
|
||||
bool isEmpty() const { return fRunHead == emptyRunHeadPtr(); }
|
||||
|
||||
/** Returns true if SkRegion is one SkIRect with positive dimensions.
|
||||
|
||||
@return true if SkRegion contains one SkIRect
|
||||
*/
|
||||
bool isRect() const { return fRunHead == kRectRunHeadPtr; }
|
||||
|
||||
/** Returns true if SkRegion is described by more than one rectangle.
|
||||
|
||||
@return true if SkRegion contains more than one SkIRect
|
||||
*/
|
||||
bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
|
||||
|
||||
/** Returns minimum and maximum axes values of SkIRect array.
|
||||
Returns (0, 0, 0, 0) if SkRegion is empty.
|
||||
|
||||
@return combined bounds of all SkIRect elements
|
||||
*/
|
||||
const SkIRect& getBounds() const { return fBounds; }
|
||||
|
||||
/** Returns a value that increases with the number of
|
||||
elements in SkRegion. Returns zero if SkRegion is empty.
|
||||
Returns one if SkRegion equals SkIRect; otherwise, returns
|
||||
value greater than one indicating that SkRegion is complex.
|
||||
|
||||
Call to compare SkRegion for relative complexity.
|
||||
|
||||
@return relative complexity
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_computeRegionComplexity
|
||||
*/
|
||||
int computeRegionComplexity() const;
|
||||
|
||||
/** Appends outline of SkRegion to path.
|
||||
Returns true if SkRegion is not empty; otherwise, returns false, and leaves path
|
||||
unmodified.
|
||||
|
||||
@param path SkPath to append to
|
||||
@return true if path changed
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_getBoundaryPath
|
||||
*/
|
||||
bool getBoundaryPath(SkPath* path) const;
|
||||
|
||||
/** Constructs an empty SkRegion. SkRegion is set to empty bounds
|
||||
at (0, 0) with zero width and height. Always returns false.
|
||||
|
||||
@return false
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_setEmpty
|
||||
*/
|
||||
bool setEmpty();
|
||||
|
||||
/** Constructs a rectangular SkRegion matching the bounds of rect.
|
||||
If rect is empty, constructs empty and returns false.
|
||||
|
||||
@param rect bounds of constructed SkRegion
|
||||
@return true if rect is not empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_setRect
|
||||
*/
|
||||
bool setRect(const SkIRect& rect);
|
||||
|
||||
/** Constructs SkRegion as the union of SkIRect in rects array. If count is
|
||||
zero, constructs empty SkRegion. Returns false if constructed SkRegion is empty.
|
||||
|
||||
May be faster than repeated calls to op().
|
||||
|
||||
@param rects array of SkIRect
|
||||
@param count array size
|
||||
@return true if constructed SkRegion is not empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_setRects
|
||||
*/
|
||||
bool setRects(const SkIRect rects[], int count);
|
||||
|
||||
/** Constructs a copy of an existing region.
|
||||
Makes two regions identical by value. Internally, region and
|
||||
the returned result share pointer values. The underlying SkRect array is
|
||||
copied when modified.
|
||||
|
||||
Creating a SkRegion copy is very efficient and never allocates memory.
|
||||
SkRegion are always copied by value from the interface; the underlying shared
|
||||
pointers are not exposed.
|
||||
|
||||
@param region SkRegion to copy by value
|
||||
@return SkRegion to copy by value
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_setRegion
|
||||
*/
|
||||
bool setRegion(const SkRegion& region);
|
||||
|
||||
/** Constructs SkRegion to match outline of path within clip.
|
||||
Returns false if constructed SkRegion is empty.
|
||||
|
||||
Constructed SkRegion draws the same pixels as path through clip when
|
||||
anti-aliasing is disabled.
|
||||
|
||||
@param path SkPath providing outline
|
||||
@param clip SkRegion containing path
|
||||
@return true if constructed SkRegion is not empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_setPath
|
||||
*/
|
||||
bool setPath(const SkPath& path, const SkRegion& clip);
|
||||
|
||||
/** Returns true if SkRegion intersects rect.
|
||||
Returns false if either rect or SkRegion is empty, or do not intersect.
|
||||
|
||||
@param rect SkIRect to intersect
|
||||
@return true if rect and SkRegion have area in common
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_intersects
|
||||
*/
|
||||
bool intersects(const SkIRect& rect) const;
|
||||
|
||||
/** Returns true if SkRegion intersects other.
|
||||
Returns false if either other or SkRegion is empty, or do not intersect.
|
||||
|
||||
@param other SkRegion to intersect
|
||||
@return true if other and SkRegion have area in common
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_intersects_2
|
||||
*/
|
||||
bool intersects(const SkRegion& other) const;
|
||||
|
||||
/** Returns true if SkIPoint (x, y) is inside SkRegion.
|
||||
Returns false if SkRegion is empty.
|
||||
|
||||
@param x test SkIPoint x-coordinate
|
||||
@param y test SkIPoint y-coordinate
|
||||
@return true if (x, y) is inside SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_contains
|
||||
*/
|
||||
bool contains(int32_t x, int32_t y) const;
|
||||
|
||||
/** Returns true if other is completely inside SkRegion.
|
||||
Returns false if SkRegion or other is empty.
|
||||
|
||||
@param other SkIRect to contain
|
||||
@return true if other is inside SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_contains_2
|
||||
*/
|
||||
bool contains(const SkIRect& other) const;
|
||||
|
||||
/** Returns true if other is completely inside SkRegion.
|
||||
Returns false if SkRegion or other is empty.
|
||||
|
||||
@param other SkRegion to contain
|
||||
@return true if other is inside SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_contains_3
|
||||
*/
|
||||
bool contains(const SkRegion& other) const;
|
||||
|
||||
/** Returns true if SkRegion is a single rectangle and contains r.
|
||||
May return false even though SkRegion contains r.
|
||||
|
||||
@param r SkIRect to contain
|
||||
@return true quickly if r points are equal or inside
|
||||
*/
|
||||
bool quickContains(const SkIRect& r) const {
|
||||
SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
|
||||
|
||||
return r.fLeft < r.fRight && r.fTop < r.fBottom &&
|
||||
fRunHead == kRectRunHeadPtr && // this->isRect()
|
||||
/* fBounds.contains(left, top, right, bottom); */
|
||||
fBounds.fLeft <= r.fLeft && fBounds.fTop <= r.fTop &&
|
||||
fBounds.fRight >= r.fRight && fBounds.fBottom >= r.fBottom;
|
||||
}
|
||||
|
||||
/** Returns true if SkRegion does not intersect rect.
|
||||
Returns true if rect is empty or SkRegion is empty.
|
||||
May return false even though SkRegion does not intersect rect.
|
||||
|
||||
@param rect SkIRect to intersect
|
||||
@return true if rect does not intersect
|
||||
*/
|
||||
bool quickReject(const SkIRect& rect) const {
|
||||
return this->isEmpty() || rect.isEmpty() ||
|
||||
!SkIRect::Intersects(fBounds, rect);
|
||||
}
|
||||
|
||||
/** Returns true if SkRegion does not intersect rgn.
|
||||
Returns true if rgn is empty or SkRegion is empty.
|
||||
May return false even though SkRegion does not intersect rgn.
|
||||
|
||||
@param rgn SkRegion to intersect
|
||||
@return true if rgn does not intersect
|
||||
*/
|
||||
bool quickReject(const SkRegion& rgn) const {
|
||||
return this->isEmpty() || rgn.isEmpty() ||
|
||||
!SkIRect::Intersects(fBounds, rgn.fBounds);
|
||||
}
|
||||
|
||||
/** Offsets SkRegion by ivector (dx, dy). Has no effect if SkRegion is empty.
|
||||
|
||||
@param dx x-axis offset
|
||||
@param dy y-axis offset
|
||||
*/
|
||||
void translate(int dx, int dy) { this->translate(dx, dy, this); }
|
||||
|
||||
/** Offsets SkRegion by ivector (dx, dy), writing result to dst. SkRegion may be passed
|
||||
as dst parameter, translating SkRegion in place. Has no effect if dst is nullptr.
|
||||
If SkRegion is empty, sets dst to empty.
|
||||
|
||||
@param dx x-axis offset
|
||||
@param dy y-axis offset
|
||||
@param dst translated result
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_translate_2
|
||||
*/
|
||||
void translate(int dx, int dy, SkRegion* dst) const;
|
||||
|
||||
/** \enum SkRegion::Op
|
||||
The logical operations that can be performed when combining two SkRegion.
|
||||
*/
|
||||
enum Op {
|
||||
kDifference_Op, //!< target minus operand
|
||||
kIntersect_Op, //!< target intersected with operand
|
||||
kUnion_Op, //!< target unioned with operand
|
||||
kXOR_Op, //!< target exclusive or with operand
|
||||
kReverseDifference_Op, //!< operand minus target
|
||||
kReplace_Op, //!< replace target with operand
|
||||
kLastOp = kReplace_Op, //!< last operator
|
||||
};
|
||||
|
||||
static const int kOpCnt = kLastOp + 1;
|
||||
|
||||
/** Replaces SkRegion with the result of SkRegion op rect.
|
||||
Returns true if replaced SkRegion is not empty.
|
||||
|
||||
@param rect SkIRect operand
|
||||
@return false if result is empty
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/** Replaces SkRegion with the result of SkRegion op rgn.
|
||||
Returns true if replaced SkRegion is not empty.
|
||||
|
||||
@param rgn SkRegion operand
|
||||
@return false if result is empty
|
||||
*/
|
||||
bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
|
||||
|
||||
/** Replaces SkRegion with the result of rect op rgn.
|
||||
Returns true if replaced SkRegion is not empty.
|
||||
|
||||
@param rect SkIRect operand
|
||||
@param rgn SkRegion operand
|
||||
@return false if result is empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_op_4
|
||||
*/
|
||||
bool op(const SkIRect& rect, const SkRegion& rgn, Op op);
|
||||
|
||||
/** Replaces SkRegion with the result of rgn op rect.
|
||||
Returns true if replaced SkRegion is not empty.
|
||||
|
||||
@param rgn SkRegion operand
|
||||
@param rect SkIRect operand
|
||||
@return false if result is empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_op_5
|
||||
*/
|
||||
bool op(const SkRegion& rgn, const SkIRect& rect, Op op);
|
||||
|
||||
/** Replaces SkRegion with the result of rgna op rgnb.
|
||||
Returns true if replaced SkRegion is not empty.
|
||||
|
||||
@param rgna SkRegion operand
|
||||
@param rgnb SkRegion operand
|
||||
@return false if result is empty
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_op_6
|
||||
*/
|
||||
bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
/** Private. Android framework only.
|
||||
|
||||
@return string representation of SkRegion
|
||||
*/
|
||||
char* toString();
|
||||
#endif
|
||||
|
||||
/** \class SkRegion::Iterator
|
||||
Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
|
||||
up SkRegion.
|
||||
*/
|
||||
class SK_API Iterator {
|
||||
public:
|
||||
|
||||
/** Initializes SkRegion::Iterator with an empty SkRegion. done() on SkRegion::Iterator
|
||||
returns true.
|
||||
Call reset() to initialized SkRegion::Iterator at a later time.
|
||||
|
||||
@return empty SkRegion iterator
|
||||
*/
|
||||
Iterator() : fRgn(nullptr), fDone(true) {}
|
||||
|
||||
/** Sets SkRegion::Iterator to return elements of SkIRect array in region.
|
||||
|
||||
@param region SkRegion to iterate
|
||||
@return SkRegion iterator
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Iterator_copy_const_SkRegion
|
||||
*/
|
||||
Iterator(const SkRegion& region);
|
||||
|
||||
/** SkPoint SkRegion::Iterator to start of SkRegion.
|
||||
Returns true if SkRegion was set; otherwise, returns false.
|
||||
|
||||
@return true if SkRegion was set
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Iterator_rewind
|
||||
*/
|
||||
bool rewind();
|
||||
|
||||
/** Resets iterator, using the new SkRegion.
|
||||
|
||||
@param region SkRegion to iterate
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Iterator_reset
|
||||
*/
|
||||
void reset(const SkRegion& region);
|
||||
|
||||
/** Returns true if SkRegion::Iterator is pointing to final SkIRect in SkRegion.
|
||||
|
||||
@return true if data parsing is complete
|
||||
*/
|
||||
bool done() const { return fDone; }
|
||||
|
||||
/** Advances SkRegion::Iterator to next SkIRect in SkRegion if it is not done.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Iterator_next
|
||||
*/
|
||||
void next();
|
||||
|
||||
/** Returns SkIRect element in SkRegion. Does not return predictable results if SkRegion
|
||||
is empty.
|
||||
|
||||
@return part of SkRegion as SkIRect
|
||||
*/
|
||||
const SkIRect& rect() const { return fRect; }
|
||||
|
||||
/** Returns SkRegion if set; otherwise, returns nullptr.
|
||||
|
||||
@return iterated SkRegion
|
||||
*/
|
||||
const SkRegion* rgn() const { return fRgn; }
|
||||
|
||||
private:
|
||||
const SkRegion* fRgn;
|
||||
const SkRegion::RunType* fRuns;
|
||||
SkIRect fRect = {0, 0, 0, 0};
|
||||
bool fDone;
|
||||
};
|
||||
|
||||
/** \class SkRegion::Cliperator
|
||||
Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
|
||||
up SkRegion intersected with the specified clip rectangle.
|
||||
*/
|
||||
class SK_API Cliperator {
|
||||
public:
|
||||
|
||||
/** Sets SkRegion::Cliperator to return elements of SkIRect array in SkRegion within clip.
|
||||
|
||||
@param region SkRegion to iterate
|
||||
@param clip bounds of iteration
|
||||
@return SkRegion iterator
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Cliperator_const_SkRegion_const_SkIRect
|
||||
*/
|
||||
Cliperator(const SkRegion& region, const SkIRect& clip);
|
||||
|
||||
/** Returns true if SkRegion::Cliperator is pointing to final SkIRect in SkRegion.
|
||||
|
||||
@return true if data parsing is complete
|
||||
*/
|
||||
bool done() { return fDone; }
|
||||
|
||||
/** Advances iterator to next SkIRect in SkRegion contained by clip.
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Cliperator_next
|
||||
*/
|
||||
void next();
|
||||
|
||||
/** Returns SkIRect element in SkRegion, intersected with clip passed to
|
||||
SkRegion::Cliperator constructor. Does not return predictable results if SkRegion
|
||||
is empty.
|
||||
|
||||
@return part of SkRegion inside clip as SkIRect
|
||||
*/
|
||||
const SkIRect& rect() const { return fRect; }
|
||||
|
||||
private:
|
||||
Iterator fIter;
|
||||
SkIRect fClip;
|
||||
SkIRect fRect = {0, 0, 0, 0};
|
||||
bool fDone;
|
||||
};
|
||||
|
||||
/** \class SkRegion::Spanerator
|
||||
Returns the line segment ends within SkRegion that intersect a horizontal line.
|
||||
*/
|
||||
class Spanerator {
|
||||
public:
|
||||
|
||||
/** Sets SkRegion::Spanerator to return line segments in SkRegion on scan line.
|
||||
|
||||
@param region SkRegion to iterate
|
||||
@param y horizontal line to intersect
|
||||
@param left bounds of iteration
|
||||
@param right bounds of iteration
|
||||
@return SkRegion iterator
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Spanerator_const_SkRegion_int_int_int
|
||||
*/
|
||||
Spanerator(const SkRegion& region, int y, int left, int right);
|
||||
|
||||
/** Advances iterator to next span intersecting SkRegion within line segment provided
|
||||
in constructor. Returns true if interval was found.
|
||||
|
||||
@param left pointer to span start; may be nullptr
|
||||
@param right pointer to span end; may be nullptr
|
||||
@return true if interval was found
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_Spanerator_next
|
||||
*/
|
||||
bool next(int* left, int* right);
|
||||
|
||||
private:
|
||||
const SkRegion::RunType* fRuns;
|
||||
int fLeft, fRight;
|
||||
bool fDone;
|
||||
};
|
||||
|
||||
/** Writes SkRegion to buffer, and returns number of bytes written.
|
||||
If buffer is nullptr, returns number number of bytes that would be written.
|
||||
|
||||
@param buffer storage for binary data
|
||||
@return size of SkRegion
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_writeToMemory
|
||||
*/
|
||||
size_t writeToMemory(void* buffer) const;
|
||||
|
||||
/** Constructs SkRegion from buffer of size length. Returns bytes read.
|
||||
Returned value will be multiple of four or zero if length was too small.
|
||||
|
||||
@param buffer storage for binary data
|
||||
@param length size of buffer
|
||||
@return bytes read
|
||||
|
||||
example: https://fiddle.skia.org/c/@Region_readFromMemory
|
||||
*/
|
||||
size_t readFromMemory(const void* buffer, size_t length);
|
||||
|
||||
using sk_is_trivially_relocatable = std::true_type;
|
||||
|
||||
private:
|
||||
static constexpr int kOpCount = kReplace_Op + 1;
|
||||
|
||||
// T
|
||||
// [B N L R S]
|
||||
// S
|
||||
static constexpr int kRectRegionRuns = 7;
|
||||
|
||||
struct RunHead;
|
||||
|
||||
static RunHead* emptyRunHeadPtr() { return (SkRegion::RunHead*) -1; }
|
||||
static constexpr RunHead* kRectRunHeadPtr = nullptr;
|
||||
|
||||
// allocate space for count runs
|
||||
void allocateRuns(int count);
|
||||
void allocateRuns(int count, int ySpanCount, int intervalCount);
|
||||
void allocateRuns(const RunHead& src);
|
||||
|
||||
SkDEBUGCODE(void dump() const;)
|
||||
|
||||
SkIRect fBounds;
|
||||
RunHead* fRunHead;
|
||||
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fBounds)>::value);
|
||||
static_assert(::sk_is_trivially_relocatable<decltype(fRunHead)>::value);
|
||||
|
||||
void freeRuns();
|
||||
|
||||
/**
|
||||
* Return the runs from this region, consing up fake runs if the region
|
||||
* is empty or a rect. In those 2 cases, we use tmpStorage to hold the
|
||||
* run data.
|
||||
*/
|
||||
const RunType* getRuns(RunType tmpStorage[], int* intervals) const;
|
||||
|
||||
// This is called with runs[] that do not yet have their interval-count
|
||||
// field set on each scanline. That is computed as part of this call
|
||||
// (inside ComputeRunBounds).
|
||||
bool setRuns(RunType runs[], int count);
|
||||
|
||||
int count_runtype_values(int* itop, int* ibot) const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
static void BuildRectRuns(const SkIRect& bounds,
|
||||
RunType runs[kRectRegionRuns]);
|
||||
|
||||
// If the runs define a simple rect, return true and set bounds to that
|
||||
// rect. If not, return false and ignore bounds.
|
||||
static bool RunsAreARect(const SkRegion::RunType runs[], int count,
|
||||
SkIRect* bounds);
|
||||
|
||||
/**
|
||||
* If the last arg is null, just return if the result is non-empty,
|
||||
* else store the result in the last arg.
|
||||
*/
|
||||
static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);
|
||||
|
||||
friend struct RunHead;
|
||||
friend class Iterator;
|
||||
friend class Spanerator;
|
||||
friend class SkRegionPriv;
|
||||
friend class SkRgnBuilder;
|
||||
friend class SkFlatRegion;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkImageSampling_DEFINED
|
||||
#define SkImageSampling_DEFINED
|
||||
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
enum class SkFilterMode {
|
||||
kNearest, // single sample point (nearest neighbor)
|
||||
kLinear, // interporate between 2x2 sample points (bilinear interpolation)
|
||||
|
||||
kLast = kLinear,
|
||||
};
|
||||
static constexpr int kSkFilterModeCount = static_cast<int>(SkFilterMode::kLast) + 1;
|
||||
|
||||
enum class SkMipmapMode {
|
||||
kNone, // ignore mipmap levels, sample from the "base"
|
||||
kNearest, // sample from the nearest level
|
||||
kLinear, // interpolate between the two nearest levels
|
||||
|
||||
kLast = kLinear,
|
||||
};
|
||||
static constexpr int kSkMipmapModeCount = static_cast<int>(SkMipmapMode::kLast) + 1;
|
||||
|
||||
/*
|
||||
* Specify B and C (each between 0...1) to create a shader that applies the corresponding
|
||||
* cubic reconstruction filter to the image.
|
||||
*
|
||||
* Example values:
|
||||
* B = 1/3, C = 1/3 "Mitchell" filter
|
||||
* B = 0, C = 1/2 "Catmull-Rom" filter
|
||||
*
|
||||
* See "Reconstruction Filters in Computer Graphics"
|
||||
* Don P. Mitchell
|
||||
* Arun N. Netravali
|
||||
* 1988
|
||||
* https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf
|
||||
*
|
||||
* Desmos worksheet https://www.desmos.com/calculator/aghdpicrvr
|
||||
* Nice overview https://entropymine.com/imageworsener/bicubic/
|
||||
*/
|
||||
struct SkCubicResampler {
|
||||
float B, C;
|
||||
|
||||
// Historic default for kHigh_SkFilterQuality
|
||||
static constexpr SkCubicResampler Mitchell() { return {1/3.0f, 1/3.0f}; }
|
||||
static constexpr SkCubicResampler CatmullRom() { return {0.0f, 1/2.0f}; }
|
||||
};
|
||||
|
||||
struct SK_API SkSamplingOptions {
|
||||
const int maxAniso = 0;
|
||||
const bool useCubic = false;
|
||||
const SkCubicResampler cubic = {0, 0};
|
||||
const SkFilterMode filter = SkFilterMode::kNearest;
|
||||
const SkMipmapMode mipmap = SkMipmapMode::kNone;
|
||||
|
||||
constexpr SkSamplingOptions() = default;
|
||||
SkSamplingOptions(const SkSamplingOptions&) = default;
|
||||
SkSamplingOptions& operator=(const SkSamplingOptions& that) {
|
||||
this->~SkSamplingOptions(); // A pedantic no-op.
|
||||
new (this) SkSamplingOptions(that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr SkSamplingOptions(SkFilterMode fm, SkMipmapMode mm)
|
||||
: filter(fm)
|
||||
, mipmap(mm) {}
|
||||
|
||||
// These are intentionally implicit because the single parameter clearly conveys what the
|
||||
// implicitly created SkSamplingOptions will be.
|
||||
constexpr SkSamplingOptions(SkFilterMode fm)
|
||||
: filter(fm)
|
||||
, mipmap(SkMipmapMode::kNone) {}
|
||||
|
||||
constexpr SkSamplingOptions(const SkCubicResampler& c)
|
||||
: useCubic(true)
|
||||
, cubic(c) {}
|
||||
|
||||
static constexpr SkSamplingOptions Aniso(int maxAniso) {
|
||||
return SkSamplingOptions{std::max(maxAniso, 1)};
|
||||
}
|
||||
|
||||
bool operator==(const SkSamplingOptions& other) const {
|
||||
return maxAniso == other.maxAniso
|
||||
&& useCubic == other.useCubic
|
||||
&& cubic.B == other.cubic.B
|
||||
&& cubic.C == other.cubic.C
|
||||
&& filter == other.filter
|
||||
&& mipmap == other.mipmap;
|
||||
}
|
||||
bool operator!=(const SkSamplingOptions& other) const { return !(*this == other); }
|
||||
|
||||
bool isAniso() const { return maxAniso != 0; }
|
||||
|
||||
private:
|
||||
constexpr SkSamplingOptions(int maxAniso) : maxAniso(maxAniso) {}
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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 SkScalar_DEFINED
|
||||
#define SkScalar_DEFINED
|
||||
|
||||
#include "include/private/base/SkAssert.h"
|
||||
#include "include/private/base/SkFloatingPoint.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
typedef float SkScalar;
|
||||
|
||||
#define SK_Scalar1 1.0f
|
||||
#define SK_ScalarHalf 0.5f
|
||||
#define SK_ScalarSqrt2 SK_FloatSqrt2
|
||||
#define SK_ScalarPI SK_FloatPI
|
||||
#define SK_ScalarTanPIOver8 0.414213562f
|
||||
#define SK_ScalarRoot2Over2 0.707106781f
|
||||
#define SK_ScalarMax 3.402823466e+38f
|
||||
#define SK_ScalarMin (-SK_ScalarMax)
|
||||
#define SK_ScalarInfinity SK_FloatInfinity
|
||||
#define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity
|
||||
#define SK_ScalarNaN SK_FloatNaN
|
||||
|
||||
#define SkScalarFloorToScalar(x) std::floor(x)
|
||||
#define SkScalarCeilToScalar(x) std::ceil(x)
|
||||
#define SkScalarRoundToScalar(x) sk_float_round(x)
|
||||
#define SkScalarTruncToScalar(x) std::trunc(x)
|
||||
|
||||
#define SkScalarFloorToInt(x) sk_float_floor2int(x)
|
||||
#define SkScalarCeilToInt(x) sk_float_ceil2int(x)
|
||||
#define SkScalarRoundToInt(x) sk_float_round2int(x)
|
||||
|
||||
#define SkScalarAbs(x) std::fabs(x)
|
||||
#define SkScalarCopySign(x, y) std::copysign(x, y)
|
||||
#define SkScalarMod(x, y) std::fmod(x,y)
|
||||
#define SkScalarSqrt(x) std::sqrt(x)
|
||||
#define SkScalarPow(b, e) std::pow(b, e)
|
||||
|
||||
#define SkScalarSin(radians) ((float)std::sin(radians))
|
||||
#define SkScalarCos(radians) ((float)std::cos(radians))
|
||||
#define SkScalarTan(radians) ((float)std::tan(radians))
|
||||
#define SkScalarASin(val) ((float)std::asin(val))
|
||||
#define SkScalarACos(val) ((float)std::acos(val))
|
||||
#define SkScalarATan2(y, x) ((float)std::atan2(y,x))
|
||||
#define SkScalarExp(x) ((float)std::exp(x))
|
||||
#define SkScalarLog(x) ((float)std::log(x))
|
||||
#define SkScalarLog2(x) ((float)std::log2(x))
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define SkIntToScalar(x) static_cast<SkScalar>(x)
|
||||
#define SkIntToFloat(x) static_cast<float>(x)
|
||||
#define SkScalarTruncToInt(x) sk_float_saturate2int(x)
|
||||
|
||||
#define SkScalarToFloat(x) static_cast<float>(x)
|
||||
#define SkFloatToScalar(x) static_cast<SkScalar>(x)
|
||||
#define SkScalarToDouble(x) static_cast<double>(x)
|
||||
#define SkDoubleToScalar(x) sk_double_to_float(x)
|
||||
|
||||
/** Returns the fractional part of the scalar. */
|
||||
static inline SkScalar SkScalarFraction(SkScalar x) {
|
||||
return x - SkScalarTruncToScalar(x);
|
||||
}
|
||||
|
||||
static inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
|
||||
|
||||
#define SkScalarInvert(x) (SK_Scalar1 / (x))
|
||||
#define SkScalarAve(a, b) (((a) + (b)) * SK_ScalarHalf)
|
||||
#define SkScalarHalf(a) ((a) * SK_ScalarHalf)
|
||||
|
||||
#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
|
||||
#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))
|
||||
|
||||
static inline bool SkScalarIsInt(SkScalar x) {
|
||||
return x == SkScalarFloorToScalar(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns -1 || 0 || 1 depending on the sign of value:
|
||||
* -1 if x < 0
|
||||
* 0 if x == 0
|
||||
* 1 if x > 0
|
||||
*/
|
||||
static inline int SkScalarSignAsInt(SkScalar x) {
|
||||
return x < 0 ? -1 : (x > 0);
|
||||
}
|
||||
|
||||
// Scalar result version of above
|
||||
static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
|
||||
return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
|
||||
}
|
||||
|
||||
#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12))
|
||||
|
||||
static inline bool SkScalarNearlyZero(SkScalar x,
|
||||
SkScalar tolerance = SK_ScalarNearlyZero) {
|
||||
SkASSERT(tolerance >= 0);
|
||||
return SkScalarAbs(x) <= tolerance;
|
||||
}
|
||||
|
||||
static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
|
||||
SkScalar tolerance = SK_ScalarNearlyZero) {
|
||||
SkASSERT(tolerance >= 0);
|
||||
return SkScalarAbs(x-y) <= tolerance;
|
||||
}
|
||||
|
||||
#define SK_ScalarSinCosNearlyZero (SK_Scalar1 / (1 << 16))
|
||||
|
||||
static inline float SkScalarSinSnapToZero(SkScalar radians) {
|
||||
float v = SkScalarSin(radians);
|
||||
return SkScalarNearlyZero(v, SK_ScalarSinCosNearlyZero) ? 0.0f : v;
|
||||
}
|
||||
|
||||
static inline float SkScalarCosSnapToZero(SkScalar radians) {
|
||||
float v = SkScalarCos(radians);
|
||||
return SkScalarNearlyZero(v, SK_ScalarSinCosNearlyZero) ? 0.0f : v;
|
||||
}
|
||||
|
||||
/** Linearly interpolate between A and B, based on t.
|
||||
If t is 0, return A
|
||||
If t is 1, return B
|
||||
else interpolate.
|
||||
t must be [0..SK_Scalar1]
|
||||
*/
|
||||
static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
|
||||
SkASSERT(t >= 0 && t <= SK_Scalar1);
|
||||
return A + (B - A) * t;
|
||||
}
|
||||
|
||||
/** Interpolate along the function described by (keys[length], values[length])
|
||||
for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length]
|
||||
clamp to the min or max value. This function assumes the number of pairs
|
||||
(length) will be small and a linear search is used.
|
||||
|
||||
Repeated keys are allowed for discontinuous functions (so long as keys is
|
||||
monotonically increasing). If key is the value of a repeated scalar in
|
||||
keys the first one will be used.
|
||||
*/
|
||||
SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
|
||||
const SkScalar values[], int length);
|
||||
|
||||
/*
|
||||
* Helper to compare an array of scalars.
|
||||
*/
|
||||
static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
|
||||
SkASSERT(n >= 0);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (a[i] != b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkSerialProcs_DEFINED
|
||||
#define SkSerialProcs_DEFINED
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
|
||||
class SkData;
|
||||
class SkImage;
|
||||
class SkPicture;
|
||||
class SkTypeface;
|
||||
class SkReadBuffer;
|
||||
enum SkAlphaType : int;
|
||||
namespace sktext::gpu {
|
||||
class Slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* A serial-proc is asked to serialize the specified object (e.g. picture or image).
|
||||
* If a data object is returned, it will be used (even if it is zero-length).
|
||||
* If null is returned, then Skia will take its default action.
|
||||
*
|
||||
* The default action for pictures is to use Skia's internal format.
|
||||
* The default action for images is to encode either in its native format or PNG.
|
||||
* The default action for typefaces is to use Skia's internal format.
|
||||
*/
|
||||
|
||||
using SkSerialPictureProc = sk_sp<SkData> (*)(SkPicture*, void* ctx);
|
||||
using SkSerialImageProc = sk_sp<SkData> (*)(SkImage*, void* ctx);
|
||||
using SkSerialTypefaceProc = sk_sp<SkData> (*)(SkTypeface*, void* ctx);
|
||||
|
||||
/**
|
||||
* Called with the encoded form of a picture (previously written with a custom
|
||||
* SkSerialPictureProc proc). Return a picture object, or nullptr indicating failure.
|
||||
*/
|
||||
using SkDeserialPictureProc = sk_sp<SkPicture> (*)(const void* data, size_t length, void* ctx);
|
||||
|
||||
/**
|
||||
* Called with the encoded form of an image. The proc can return an image object, or if it
|
||||
* returns nullptr, then Skia will take its default action to try to create an image from the data.
|
||||
*
|
||||
* This will also be used to decode the internal mipmap layers that are saved on some images.
|
||||
*
|
||||
* An explicit SkAlphaType may have been encoded in the bytestream; if not, then the passed in
|
||||
* optional will be not present.
|
||||
*
|
||||
* Clients should set at least SkDeserialImageProc; SkDeserialImageFromDataProc may be called
|
||||
* if the internal implementation has a SkData copy already. Implementations of SkDeserialImageProc
|
||||
* must make a copy of any data they needed after the proc finishes, since the data will go away
|
||||
* after serialization ends.
|
||||
*/
|
||||
#if !defined(SK_LEGACY_DESERIAL_IMAGE_PROC)
|
||||
using SkDeserialImageProc = sk_sp<SkImage> (*)(const void* data, size_t length, void* ctx);
|
||||
#else
|
||||
using SkDeserialImageProc = sk_sp<SkImage> (*)(const void* data,
|
||||
size_t length,
|
||||
std::optional<SkAlphaType>,
|
||||
void* ctx);
|
||||
#endif
|
||||
using SkDeserialImageFromDataProc = sk_sp<SkImage> (*)(sk_sp<SkData>,
|
||||
std::optional<SkAlphaType>,
|
||||
void* ctx);
|
||||
|
||||
/**
|
||||
* Slugs are currently only deserializable with a GPU backend. Clients will not be able to
|
||||
* provide a custom mechanism here, but can enable Slug deserialization by calling
|
||||
* sktext::gpu::AddDeserialProcs to add Skia's implementation.
|
||||
*/
|
||||
using SkSlugProc = sk_sp<sktext::gpu::Slug> (*)(SkReadBuffer&, void* ctx);
|
||||
|
||||
/**
|
||||
* Called with the encoded form of a typeface (previously written with a custom
|
||||
* SkSerialTypefaceProc proc). Return a typeface object, or nullptr indicating failure.
|
||||
*/
|
||||
using SkDeserialTypefaceProc = sk_sp<SkTypeface> (*)(const void* data, size_t length, void* ctx);
|
||||
|
||||
struct SK_API SkSerialProcs {
|
||||
SkSerialPictureProc fPictureProc = nullptr;
|
||||
void* fPictureCtx = nullptr;
|
||||
|
||||
SkSerialImageProc fImageProc = nullptr;
|
||||
void* fImageCtx = nullptr;
|
||||
|
||||
SkSerialTypefaceProc fTypefaceProc = nullptr;
|
||||
void* fTypefaceCtx = nullptr;
|
||||
};
|
||||
|
||||
struct SK_API SkDeserialProcs {
|
||||
SkDeserialPictureProc fPictureProc = nullptr;
|
||||
void* fPictureCtx = nullptr;
|
||||
|
||||
SkDeserialImageProc fImageProc = nullptr;
|
||||
SkDeserialImageFromDataProc fImageDataProc = nullptr;
|
||||
void* fImageCtx = nullptr;
|
||||
|
||||
SkSlugProc fSlugProc = nullptr;
|
||||
void* fSlugCtx = nullptr;
|
||||
|
||||
SkDeserialTypefaceProc fTypefaceProc = nullptr;
|
||||
void* fTypefaceCtx = nullptr;
|
||||
|
||||
// This looks like a flag, but it could be considered a proc as well (one that takes no
|
||||
// parameters and returns a bool). Given that there are only two valid implementations of that
|
||||
// proc, we just insert the bool directly.
|
||||
bool fAllowSkSL = true;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 SkShader_DEFINED
|
||||
#define SkShader_DEFINED
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/core/SkFlattenable.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/private/base/SkAPI.h"
|
||||
|
||||
class SkBlender;
|
||||
class SkColorFilter;
|
||||
class SkColorSpace;
|
||||
class SkImage;
|
||||
class SkMatrix;
|
||||
enum class SkBlendMode;
|
||||
enum class SkTileMode;
|
||||
struct SkRect;
|
||||
struct SkSamplingOptions;
|
||||
|
||||
/** \class SkShader
|
||||
*
|
||||
* Shaders specify the source color(s) for what is being drawn. If a paint
|
||||
* has no shader, then the paint's color is used. If the paint has a
|
||||
* shader, then the shader's color(s) are use instead, but they are
|
||||
* modulated by the paint's alpha. This makes it easy to create a shader
|
||||
* once (e.g. bitmap tiling or gradient) and then change its transparency
|
||||
* w/o having to modify the original shader... only the paint's alpha needs
|
||||
* to be modified.
|
||||
*/
|
||||
class SK_API SkShader : public SkFlattenable {
|
||||
public:
|
||||
/**
|
||||
* Returns true if the shader is guaranteed to produce only opaque
|
||||
* colors, subject to the SkPaint using the shader to apply an opaque
|
||||
* alpha value. Subclasses should override this to allow some
|
||||
* optimizations.
|
||||
*/
|
||||
virtual bool isOpaque() const { return false; }
|
||||
|
||||
/**
|
||||
* 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, SkTileMode xy[2]) const;
|
||||
|
||||
bool isAImage() const {
|
||||
return this->isAImage(nullptr, (SkTileMode*)nullptr) != nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Methods to create combinations or variants of shaders
|
||||
|
||||
/**
|
||||
* Return a shader that will apply the specified localMatrix to this shader.
|
||||
* The specified matrix will be applied before any matrix associated with this shader.
|
||||
*/
|
||||
sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const;
|
||||
|
||||
/**
|
||||
* Create a new shader that produces the same colors as invoking this shader and then applying
|
||||
* the colorfilter.
|
||||
*/
|
||||
sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const;
|
||||
|
||||
/**
|
||||
* Return a shader that will compute this shader in a specific color space.
|
||||
* By default, all shaders operate in the destination (surface) color space.
|
||||
* The results of a shader are still always converted to the destination - this
|
||||
* API has no impact on simple shaders or images. Primarily, it impacts shaders
|
||||
* that perform mathematical operations, like Blend shaders, or runtime shaders.
|
||||
*/
|
||||
sk_sp<SkShader> makeWithWorkingColorSpace(sk_sp<SkColorSpace>) const;
|
||||
|
||||
private:
|
||||
SkShader() = default;
|
||||
friend class SkShaderBase;
|
||||
|
||||
using INHERITED = SkFlattenable;
|
||||
};
|
||||
|
||||
namespace SkShaders {
|
||||
SK_API sk_sp<SkShader> Empty();
|
||||
SK_API sk_sp<SkShader> Color(SkColor);
|
||||
SK_API sk_sp<SkShader> Color(const SkColor4f&, sk_sp<SkColorSpace>);
|
||||
SK_API sk_sp<SkShader> Blend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src);
|
||||
SK_API sk_sp<SkShader> Blend(sk_sp<SkBlender>, sk_sp<SkShader> dst, sk_sp<SkShader> src);
|
||||
SK_API sk_sp<SkShader> CoordClamp(sk_sp<SkShader>, const SkRect& subset);
|
||||
|
||||
/*
|
||||
* Create an SkShader that will sample the 'image'. This is equivalent to SkImage::makeShader.
|
||||
*/
|
||||
SK_API sk_sp<SkShader> Image(sk_sp<SkImage> image,
|
||||
SkTileMode tmx, SkTileMode tmy,
|
||||
const SkSamplingOptions& options,
|
||||
const SkMatrix* localMatrix = nullptr);
|
||||
/*
|
||||
* Create an SkShader that will sample 'image' with minimal processing. This is equivalent to
|
||||
* SkImage::makeRawShader.
|
||||
*/
|
||||
SK_API sk_sp<SkShader> RawImage(sk_sp<SkImage> image,
|
||||
SkTileMode tmx, SkTileMode tmy,
|
||||
const SkSamplingOptions& options,
|
||||
const SkMatrix* localMatrix = nullptr);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 SkSize_DEFINED
|
||||
#define SkSize_DEFINED
|
||||
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct SkISize {
|
||||
int32_t fWidth;
|
||||
int32_t fHeight;
|
||||
|
||||
static constexpr SkISize Make(int32_t w, int32_t h) { return {w, h}; }
|
||||
|
||||
static constexpr SkISize MakeEmpty() { return {0, 0}; }
|
||||
|
||||
void set(int32_t w, int32_t h) { *this = SkISize{w, h}; }
|
||||
|
||||
/** Returns true iff fWidth == 0 && fHeight == 0
|
||||
*/
|
||||
bool isZero() const { return 0 == fWidth && 0 == fHeight; }
|
||||
|
||||
/** Returns true if either width or height are <= 0 */
|
||||
bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
|
||||
|
||||
/** Set the width and height to 0 */
|
||||
void setEmpty() { fWidth = fHeight = 0; }
|
||||
|
||||
constexpr int32_t width() const { return fWidth; }
|
||||
constexpr int32_t height() const { return fHeight; }
|
||||
|
||||
constexpr int64_t area() const { return SkToS64(fWidth) * SkToS64(fHeight); }
|
||||
|
||||
bool equals(int32_t w, int32_t h) const { return fWidth == w && fHeight == h; }
|
||||
};
|
||||
|
||||
static inline bool operator==(const SkISize& a, const SkISize& b) {
|
||||
return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
|
||||
}
|
||||
|
||||
static inline bool operator!=(const SkISize& a, const SkISize& b) { return !(a == b); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SkSize {
|
||||
SkScalar fWidth;
|
||||
SkScalar fHeight;
|
||||
|
||||
static constexpr SkSize Make(SkScalar w, SkScalar h) { return {w, h}; }
|
||||
|
||||
static constexpr SkSize Make(const SkISize& src) {
|
||||
return {SkIntToScalar(src.width()), SkIntToScalar(src.height())};
|
||||
}
|
||||
|
||||
static constexpr SkSize MakeEmpty() { return {0, 0}; }
|
||||
|
||||
void set(SkScalar w, SkScalar h) { *this = SkSize{w, h}; }
|
||||
|
||||
/** Returns true iff fWidth == 0 && fHeight == 0
|
||||
*/
|
||||
bool isZero() const { return 0 == fWidth && 0 == fHeight; }
|
||||
|
||||
/** Returns true if either width or height are <= 0 */
|
||||
bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
|
||||
|
||||
/** Set the width and height to 0 */
|
||||
void setEmpty() { *this = SkSize{0, 0}; }
|
||||
|
||||
SkScalar width() const { return fWidth; }
|
||||
SkScalar height() const { return fHeight; }
|
||||
|
||||
bool equals(SkScalar w, SkScalar h) const { return fWidth == w && fHeight == h; }
|
||||
|
||||
SkISize toRound() const { return {SkScalarRoundToInt(fWidth), SkScalarRoundToInt(fHeight)}; }
|
||||
|
||||
SkISize toCeil() const { return {SkScalarCeilToInt(fWidth), SkScalarCeilToInt(fHeight)}; }
|
||||
|
||||
SkISize toFloor() const { return {SkScalarFloorToInt(fWidth), SkScalarFloorToInt(fHeight)}; }
|
||||
};
|
||||
|
||||
static inline bool operator==(const SkSize& a, const SkSize& b) {
|
||||
return a.fWidth == b.fWidth && a.fHeight == b.fHeight;
|
||||
}
|
||||
|
||||
static inline bool operator!=(const SkSize& a, const SkSize& b) { return !(a == b); }
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// We want SkSpan to be a public API, but it is also fundamental to many of our internal types.
|
||||
// Thus, we have a public file that clients can include. This file defers to the private copy
|
||||
// so we do not have a dependency cycle from our "base" files to our "core" files.
|
||||
|
||||
#include "include/private/base/SkSpan_impl.h" // IWYU pragma: export
|
||||
|
@ -0,0 +1,512 @@
|
||||
/*
|
||||
* 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 SkStream_DEFINED
|
||||
#define SkStream_DEFINED
|
||||
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/private/base/SkCPUTypes.h"
|
||||
#include "include/private/base/SkTo.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
class SkStreamAsset;
|
||||
|
||||
/**
|
||||
* SkStream -- abstraction for a source of bytes. Subclasses can be backed by
|
||||
* memory, or a file, or something else.
|
||||
*/
|
||||
class SK_API SkStream {
|
||||
public:
|
||||
virtual ~SkStream() {}
|
||||
SkStream() {}
|
||||
|
||||
/**
|
||||
* Attempts to open the specified file as a stream, returns nullptr on failure.
|
||||
*/
|
||||
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.
|
||||
* If buffer != NULL, copy size bytes into buffer, return how many were copied.
|
||||
* @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer
|
||||
* @param size the number of bytes to skip or copy
|
||||
* @return the number of bytes actually read.
|
||||
*/
|
||||
virtual size_t read(void* buffer, size_t size) = 0;
|
||||
|
||||
/** Skip size number of bytes.
|
||||
* @return the actual number bytes that could be skipped.
|
||||
*/
|
||||
size_t skip(size_t size) {
|
||||
return this->read(nullptr, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to peek at size bytes.
|
||||
* If this stream supports peeking, copy min(size, peekable bytes) into
|
||||
* buffer, and return the number of bytes copied.
|
||||
* If the stream does not support peeking, or cannot peek any bytes,
|
||||
* return 0 and leave buffer unchanged.
|
||||
* The stream is guaranteed to be in the same visible state after this
|
||||
* call, regardless of success or failure.
|
||||
* @param buffer Must not be NULL, and must be at least size bytes. Destination
|
||||
* to copy bytes.
|
||||
* @param size Number of bytes to copy.
|
||||
* @return The number of bytes peeked/copied.
|
||||
*/
|
||||
virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }
|
||||
|
||||
/** Returns true when all the bytes in the stream have been read.
|
||||
* As SkStream represents synchronous I/O, isAtEnd returns false when the
|
||||
* final stream length isn't known yet, even when all the bytes available
|
||||
* so far have been read.
|
||||
* This may return true early (when there are no more bytes to be read)
|
||||
* or late (after the first unsuccessful read).
|
||||
*/
|
||||
virtual bool isAtEnd() const = 0;
|
||||
|
||||
[[nodiscard]] bool readS8(int8_t*);
|
||||
[[nodiscard]] bool readS16(int16_t*);
|
||||
[[nodiscard]] bool readS32(int32_t*);
|
||||
|
||||
[[nodiscard]] bool readU8(uint8_t* i) { return this->readS8((int8_t*)i); }
|
||||
[[nodiscard]] bool readU16(uint16_t* i) { return this->readS16((int16_t*)i); }
|
||||
[[nodiscard]] bool readU32(uint32_t* i) { return this->readS32((int32_t*)i); }
|
||||
|
||||
[[nodiscard]] bool readBool(bool* b) {
|
||||
uint8_t i;
|
||||
if (!this->readU8(&i)) { return false; }
|
||||
*b = (i != 0);
|
||||
return true;
|
||||
}
|
||||
[[nodiscard]] bool readScalar(SkScalar*);
|
||||
[[nodiscard]] bool readPackedUInt(size_t*);
|
||||
|
||||
//SkStreamRewindable
|
||||
/** Rewinds to the beginning of the stream. Returns true if the stream is known
|
||||
* to be at the beginning after this call returns.
|
||||
*/
|
||||
virtual bool rewind() { return false; }
|
||||
|
||||
/** Duplicates this stream. If this cannot be done, returns NULL.
|
||||
* The returned stream will be positioned at the beginning of its data.
|
||||
*/
|
||||
std::unique_ptr<SkStream> duplicate() const {
|
||||
return std::unique_ptr<SkStream>(this->onDuplicate());
|
||||
}
|
||||
/** Duplicates this stream. If this cannot be done, returns NULL.
|
||||
* The returned stream will be positioned the same as this stream.
|
||||
*/
|
||||
std::unique_ptr<SkStream> fork() const {
|
||||
return std::unique_ptr<SkStream>(this->onFork());
|
||||
}
|
||||
|
||||
//SkStreamSeekable
|
||||
/** Returns true if this stream can report its current position. */
|
||||
virtual bool hasPosition() const { return false; }
|
||||
/** Returns the current position in the stream. If this cannot be done, returns 0. */
|
||||
virtual size_t getPosition() const { return 0; }
|
||||
|
||||
/** Seeks to an absolute position in the stream. If this cannot be done, returns false.
|
||||
* If an attempt is made to seek past the end of the stream, the position will be set
|
||||
* to the end of the stream.
|
||||
*/
|
||||
virtual bool seek(size_t /*position*/) { return false; }
|
||||
|
||||
/** Seeks to an relative offset in the stream. If this cannot be done, returns false.
|
||||
* If an attempt is made to move to a position outside the stream, the position will be set
|
||||
* to the closest point within the stream (beginning or end).
|
||||
*/
|
||||
virtual bool move(long /*offset*/) { return false; }
|
||||
|
||||
//SkStreamAsset
|
||||
/** Returns true if this stream can report its total length. */
|
||||
virtual bool hasLength() const { return false; }
|
||||
/** Returns the total length of the stream. If this cannot be done, returns 0. */
|
||||
virtual size_t getLength() const { return 0; }
|
||||
|
||||
//SkStreamMemory
|
||||
/** Returns the starting address for the data. If this cannot be done, returns NULL. */
|
||||
virtual const void* getMemoryBase() { return nullptr; }
|
||||
virtual sk_sp<SkData> getData() const { return nullptr; }
|
||||
|
||||
private:
|
||||
virtual SkStream* onDuplicate() const { return nullptr; }
|
||||
virtual SkStream* onFork() const { return nullptr; }
|
||||
|
||||
SkStream(SkStream&&) = delete;
|
||||
SkStream(const SkStream&) = delete;
|
||||
SkStream& operator=(SkStream&&) = delete;
|
||||
SkStream& operator=(const SkStream&) = delete;
|
||||
};
|
||||
|
||||
/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */
|
||||
class SK_API SkStreamRewindable : public SkStream {
|
||||
public:
|
||||
bool rewind() override = 0;
|
||||
std::unique_ptr<SkStreamRewindable> duplicate() const {
|
||||
return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());
|
||||
}
|
||||
private:
|
||||
SkStreamRewindable* onDuplicate() const override = 0;
|
||||
};
|
||||
|
||||
/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */
|
||||
class SK_API SkStreamSeekable : public SkStreamRewindable {
|
||||
public:
|
||||
std::unique_ptr<SkStreamSeekable> duplicate() const {
|
||||
return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());
|
||||
}
|
||||
|
||||
bool hasPosition() const override { return true; }
|
||||
size_t getPosition() const override = 0;
|
||||
bool seek(size_t position) override = 0;
|
||||
bool move(long offset) override = 0;
|
||||
|
||||
std::unique_ptr<SkStreamSeekable> fork() const {
|
||||
return std::unique_ptr<SkStreamSeekable>(this->onFork());
|
||||
}
|
||||
private:
|
||||
SkStreamSeekable* onDuplicate() const override = 0;
|
||||
SkStreamSeekable* onFork() const override = 0;
|
||||
};
|
||||
|
||||
/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */
|
||||
class SK_API SkStreamAsset : public SkStreamSeekable {
|
||||
public:
|
||||
bool hasLength() const override { return true; }
|
||||
size_t getLength() const override = 0;
|
||||
|
||||
std::unique_ptr<SkStreamAsset> duplicate() const {
|
||||
return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
|
||||
}
|
||||
std::unique_ptr<SkStreamAsset> fork() const {
|
||||
return std::unique_ptr<SkStreamAsset>(this->onFork());
|
||||
}
|
||||
private:
|
||||
SkStreamAsset* onDuplicate() const override = 0;
|
||||
SkStreamAsset* onFork() const override = 0;
|
||||
};
|
||||
|
||||
/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */
|
||||
class SK_API SkStreamMemory : public SkStreamAsset {
|
||||
public:
|
||||
const void* getMemoryBase() override = 0;
|
||||
|
||||
std::unique_ptr<SkStreamMemory> duplicate() const {
|
||||
return std::unique_ptr<SkStreamMemory>(this->onDuplicate());
|
||||
}
|
||||
std::unique_ptr<SkStreamMemory> fork() const {
|
||||
return std::unique_ptr<SkStreamMemory>(this->onFork());
|
||||
}
|
||||
private:
|
||||
SkStreamMemory* onDuplicate() const override = 0;
|
||||
SkStreamMemory* onFork() const override = 0;
|
||||
};
|
||||
|
||||
class SK_API SkWStream {
|
||||
public:
|
||||
virtual ~SkWStream();
|
||||
SkWStream() {}
|
||||
|
||||
/** Called to write bytes to a SkWStream. Returns true on success
|
||||
@param buffer the address of at least size bytes to be written to the stream
|
||||
@param size The number of bytes in buffer to write to the stream
|
||||
@return true on success
|
||||
*/
|
||||
virtual bool write(const void* buffer, size_t size) = 0;
|
||||
virtual void flush();
|
||||
|
||||
virtual size_t bytesWritten() const = 0;
|
||||
|
||||
// helpers
|
||||
|
||||
bool write8(U8CPU value) {
|
||||
uint8_t v = SkToU8(value);
|
||||
return this->write(&v, 1);
|
||||
}
|
||||
bool write16(U16CPU value) {
|
||||
uint16_t v = SkToU16(value);
|
||||
return this->write(&v, 2);
|
||||
}
|
||||
bool write32(uint32_t v) {
|
||||
return this->write(&v, 4);
|
||||
}
|
||||
|
||||
bool writeText(const char text[]) {
|
||||
SkASSERT(text);
|
||||
return this->write(text, std::strlen(text));
|
||||
}
|
||||
|
||||
bool newline() { return this->write("\n", std::strlen("\n")); }
|
||||
|
||||
bool writeDecAsText(int32_t);
|
||||
bool writeBigDecAsText(int64_t, int minDigits = 0);
|
||||
bool writeHexAsText(uint32_t, int minDigits = 0);
|
||||
bool writeScalarAsText(SkScalar);
|
||||
|
||||
bool writeBool(bool v) { return this->write8(v); }
|
||||
bool writeScalar(SkScalar);
|
||||
bool writePackedUInt(size_t);
|
||||
|
||||
bool writeStream(SkStream* input, size_t length);
|
||||
|
||||
/**
|
||||
* This returns the number of bytes in the stream required to store
|
||||
* 'value'.
|
||||
*/
|
||||
static int SizeOfPackedUInt(size_t value);
|
||||
|
||||
private:
|
||||
SkWStream(const SkWStream&) = delete;
|
||||
SkWStream& operator=(const SkWStream&) = delete;
|
||||
};
|
||||
|
||||
class SK_API SkNullWStream : public SkWStream {
|
||||
public:
|
||||
SkNullWStream() : fBytesWritten(0) {}
|
||||
|
||||
bool write(const void* , size_t n) override { fBytesWritten += n; return true; }
|
||||
void flush() override {}
|
||||
size_t bytesWritten() const override { return fBytesWritten; }
|
||||
|
||||
private:
|
||||
size_t fBytesWritten;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** A stream that wraps a C FILE* file stream. */
|
||||
class SK_API SkFILEStream : public SkStreamAsset {
|
||||
public:
|
||||
/** Initialize the stream by calling sk_fopen on the specified path.
|
||||
* This internal stream will be closed in the destructor.
|
||||
*/
|
||||
explicit SkFILEStream(const char path[] = nullptr);
|
||||
|
||||
/** Initialize the stream with an existing C FILE stream.
|
||||
* The current position of the C FILE stream will be considered the
|
||||
* beginning of the SkFILEStream and the current seek end of the FILE will be the end.
|
||||
* The C FILE stream will be closed in the destructor.
|
||||
*/
|
||||
explicit SkFILEStream(FILE* file);
|
||||
|
||||
/** Initialize the stream with an existing C FILE stream.
|
||||
* The current position of the C FILE stream will be considered the
|
||||
* beginning of the SkFILEStream and size bytes later will be the end.
|
||||
* The C FILE stream will be closed in the destructor.
|
||||
*/
|
||||
explicit SkFILEStream(FILE* file, size_t size);
|
||||
|
||||
~SkFILEStream() override;
|
||||
|
||||
static std::unique_ptr<SkFILEStream> Make(const char path[]) {
|
||||
std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));
|
||||
return stream->isValid() ? std::move(stream) : nullptr;
|
||||
}
|
||||
|
||||
/** Returns true if the current path could be opened. */
|
||||
bool isValid() const { return fFILE != nullptr; }
|
||||
|
||||
/** Close this SkFILEStream. */
|
||||
void close();
|
||||
|
||||
size_t read(void* buffer, size_t size) override;
|
||||
bool isAtEnd() const override;
|
||||
|
||||
bool rewind() override;
|
||||
std::unique_ptr<SkStreamAsset> duplicate() const {
|
||||
return std::unique_ptr<SkStreamAsset>(this->onDuplicate());
|
||||
}
|
||||
|
||||
size_t getPosition() const override;
|
||||
bool seek(size_t position) override;
|
||||
bool move(long offset) override;
|
||||
|
||||
std::unique_ptr<SkStreamAsset> fork() const {
|
||||
return std::unique_ptr<SkStreamAsset>(this->onFork());
|
||||
}
|
||||
|
||||
size_t getLength() const override;
|
||||
|
||||
private:
|
||||
explicit SkFILEStream(FILE*, size_t size, size_t start);
|
||||
explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start);
|
||||
explicit SkFILEStream(std::shared_ptr<FILE>, size_t end, size_t start, size_t current);
|
||||
|
||||
SkStreamAsset* onDuplicate() const override;
|
||||
SkStreamAsset* onFork() const override;
|
||||
|
||||
std::shared_ptr<FILE> fFILE;
|
||||
// My own council will I keep on sizes and offsets.
|
||||
// These are seek positions in the underling FILE, not offsets into the stream.
|
||||
size_t fEnd;
|
||||
size_t fStart;
|
||||
size_t fCurrent;
|
||||
|
||||
using INHERITED = SkStreamAsset;
|
||||
};
|
||||
|
||||
class SK_API SkMemoryStream : public SkStreamMemory {
|
||||
public:
|
||||
SkMemoryStream();
|
||||
|
||||
/** We allocate (and free) the memory. Write to it via getMemoryBase() */
|
||||
SkMemoryStream(size_t length);
|
||||
|
||||
/** If copyData is true, the stream makes a private copy of the data. */
|
||||
SkMemoryStream(const void* data, size_t length, bool copyData = false);
|
||||
|
||||
/** Creates the stream to read from the specified data */
|
||||
SkMemoryStream(sk_sp<SkData> data);
|
||||
|
||||
/** Returns a stream with a copy of the input data. */
|
||||
static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);
|
||||
|
||||
/** Returns a stream with a bare pointer reference to the input data. */
|
||||
static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);
|
||||
|
||||
/** Returns a stream with a shared reference to the input data. */
|
||||
static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);
|
||||
|
||||
/** Resets the stream to the specified data and length,
|
||||
just like the constructor.
|
||||
if copyData is true, the stream makes a private copy of the data
|
||||
*/
|
||||
virtual void setMemory(const void* data, size_t length,
|
||||
bool copyData = false);
|
||||
/** Replace any memory buffer with the specified buffer. The caller
|
||||
must have allocated data with sk_malloc or sk_realloc, since it
|
||||
will be freed with sk_free.
|
||||
*/
|
||||
void setMemoryOwned(const void* data, size_t length);
|
||||
|
||||
sk_sp<SkData> getData() const override { return fData; }
|
||||
void setData(sk_sp<SkData> data);
|
||||
|
||||
const void* getAtPos();
|
||||
|
||||
size_t read(void* buffer, size_t size) override;
|
||||
bool isAtEnd() const override;
|
||||
|
||||
size_t peek(void* buffer, size_t size) const override;
|
||||
|
||||
bool rewind() override;
|
||||
|
||||
std::unique_ptr<SkMemoryStream> duplicate() const {
|
||||
return std::unique_ptr<SkMemoryStream>(this->onDuplicate());
|
||||
}
|
||||
|
||||
size_t getPosition() const override;
|
||||
bool seek(size_t position) override;
|
||||
bool move(long offset) override;
|
||||
|
||||
std::unique_ptr<SkMemoryStream> fork() const {
|
||||
return std::unique_ptr<SkMemoryStream>(this->onFork());
|
||||
}
|
||||
|
||||
size_t getLength() const override;
|
||||
|
||||
const void* getMemoryBase() override;
|
||||
|
||||
private:
|
||||
SkMemoryStream* onDuplicate() const override;
|
||||
SkMemoryStream* onFork() const override;
|
||||
|
||||
sk_sp<SkData> fData;
|
||||
size_t fOffset;
|
||||
|
||||
using INHERITED = SkStreamMemory;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SK_API SkFILEWStream : public SkWStream {
|
||||
public:
|
||||
SkFILEWStream(const char path[]);
|
||||
~SkFILEWStream() override;
|
||||
|
||||
/** Returns true if the current path could be opened.
|
||||
*/
|
||||
bool isValid() const { return fFILE != nullptr; }
|
||||
|
||||
bool write(const void* buffer, size_t size) override;
|
||||
void flush() override;
|
||||
void fsync();
|
||||
size_t bytesWritten() const override;
|
||||
|
||||
private:
|
||||
FILE* fFILE;
|
||||
|
||||
using INHERITED = SkWStream;
|
||||
};
|
||||
|
||||
class SK_API SkDynamicMemoryWStream : public SkWStream {
|
||||
public:
|
||||
SkDynamicMemoryWStream() = default;
|
||||
SkDynamicMemoryWStream(SkDynamicMemoryWStream&&);
|
||||
SkDynamicMemoryWStream& operator=(SkDynamicMemoryWStream&&);
|
||||
~SkDynamicMemoryWStream() override;
|
||||
|
||||
bool write(const void* buffer, size_t size) override;
|
||||
size_t bytesWritten() const override;
|
||||
|
||||
bool read(void* buffer, size_t offset, size_t size);
|
||||
|
||||
/** More efficient version of read(dst, 0, bytesWritten()). */
|
||||
void copyTo(void* dst) const;
|
||||
bool writeToStream(SkWStream* dst) const;
|
||||
|
||||
/** Equivalent to copyTo() followed by reset(), but may save memory use. */
|
||||
void copyToAndReset(void* dst);
|
||||
|
||||
/** Equivalent to writeToStream() followed by reset(), but may save memory use. */
|
||||
bool writeToAndReset(SkWStream* dst);
|
||||
|
||||
/** Equivalent to writeToStream() followed by reset(), but may save memory use.
|
||||
When the dst is also a SkDynamicMemoryWStream, the implementation is constant time. */
|
||||
bool writeToAndReset(SkDynamicMemoryWStream* dst);
|
||||
|
||||
/** Prepend this stream to dst, resetting this. */
|
||||
void prependToAndReset(SkDynamicMemoryWStream* dst);
|
||||
|
||||
/** Return the contents as SkData, and then reset the stream. */
|
||||
sk_sp<SkData> detachAsData();
|
||||
|
||||
/** Reset, returning a reader stream with the current content. */
|
||||
std::unique_ptr<SkStreamAsset> detachAsStream();
|
||||
|
||||
/** Reset the stream to its original, empty, state. */
|
||||
void reset();
|
||||
void padToAlign4();
|
||||
private:
|
||||
struct Block;
|
||||
Block* fHead = nullptr;
|
||||
Block* fTail = nullptr;
|
||||
size_t fBytesWrittenBeforeTail = 0;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void validate() const;
|
||||
#else
|
||||
void validate() const {}
|
||||
#endif
|
||||
|
||||
// For access to the Block type.
|
||||
friend class SkBlockMemoryStream;
|
||||
friend class SkBlockMemoryRefCnt;
|
||||
|
||||
using INHERITED = SkWStream;
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user