Bug 716802 - Implement new 2D API functions. r=gwright

This commit is contained in:
Matt Woodrow 2012-01-19 17:48:33 +13:00
Родитель 92e358da8e
Коммит f00139a76c
2 изменённых файлов: 139 добавлений и 61 удалений

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

@ -65,8 +65,9 @@ SkColor ColorToSkColor(const Color &color, Float aAlpha)
class GradientStopsSkia : public GradientStops
{
public:
GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops)
GradientStopsSkia(const std::vector<GradientStop>& aStops, uint32_t aNumStops, ExtendMode aExtendMode)
: mCount(aNumStops)
, mExtendMode(aExtendMode)
{
if (mCount == 0) {
return;
@ -103,6 +104,7 @@ public:
std::vector<SkColor> mColors;
std::vector<SkScalar> mPositions;
int mCount;
ExtendMode mExtendMode;
};
SkXfermode::Mode
@ -208,12 +210,89 @@ ExtendModeToTileMode(ExtendMode aMode)
return SkShader::kClamp_TileMode;
}
void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0)
{
switch (aPattern.GetType()) {
case PATTERN_COLOR: {
Color color = static_cast<const ColorPattern&>(aPattern).mColor;
aPaint.setColor(ColorToSkColor(color, aAlpha));
break;
}
case PATTERN_LINEAR_GRADIENT: {
const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
if (stops->mCount >= 2) {
SkPoint points[2];
points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
SkShader* shader = SkGradientShader::CreateLinear(points,
&stops->mColors.front(),
&stops->mPositions.front(),
stops->mCount,
mode);
SkMatrix mat;
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
shader->setLocalMatrix(mat);
SkSafeUnref(aPaint.setShader(shader));
} else {
aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
}
break;
}
case PATTERN_RADIAL_GRADIENT: {
const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
if (stops->mCount >= 2) {
SkPoint points[2];
points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0],
SkFloatToScalar(pat.mRadius1),
points[1],
SkFloatToScalar(pat.mRadius2),
&stops->mColors.front(),
&stops->mPositions.front(),
stops->mCount,
mode);
SkMatrix mat;
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
shader->setLocalMatrix(mat);
SkSafeUnref(aPaint.setShader(shader));
} else {
aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
}
break;
}
case PATTERN_SURFACE: {
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(pat.mSurface.get())->GetBitmap();
SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
SkMatrix mat;
GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
shader->setLocalMatrix(mat);
SkSafeUnref(aPaint.setShader(shader));
if (pat.mFilter == FILTER_POINT) {
aPaint.setFilterBitmap(false);
}
break;
}
}
}
struct AutoPaintSetup {
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern)
: mNeedsRestore(false), mAlpha(1.0)
{
Init(aCanvas, aOptions);
SetPattern(aPattern);
SetPaintPattern(mPaint, aPattern, mAlpha);
}
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions)
@ -261,60 +340,6 @@ struct AutoPaintSetup {
mPaint.setFilterBitmap(true);
}
void SetPattern(const Pattern& aPattern)
{
if (aPattern.GetType() == PATTERN_COLOR) {
Color color = static_cast<const ColorPattern&>(aPattern).mColor;
mPaint.setColor(ColorToSkColor(color, mAlpha));
} else if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) {
const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
if (stops->mCount >= 2) {
SkPoint points[2];
points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
SkShader* shader = SkGradientShader::CreateLinear(points,
&stops->mColors.front(),
&stops->mPositions.front(),
stops->mCount,
SkShader::kClamp_TileMode);
SkSafeUnref(mPaint.setShader(shader));
} else {
mPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
}
} else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
if (stops->mCount >= 2) {
SkPoint points[2];
points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0],
SkFloatToScalar(pat.mRadius1),
points[1],
SkFloatToScalar(pat.mRadius2),
&stops->mColors.front(),
&stops->mPositions.front(),
stops->mCount,
SkShader::kClamp_TileMode);
SkSafeUnref(mPaint.setShader(shader));
} else {
mPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
}
} else {
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(pat.mSurface.get())->GetBitmap();
SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
SkSafeUnref(mPaint.setShader(shader));
}
}
// TODO: Maybe add an operator overload to access this easier?
SkPaint mPaint;
bool mNeedsRestore;
@ -542,6 +567,36 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont,
mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint);
}
void
DrawTargetSkia::Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions)
{
MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
SkPaint maskPaint;
SetPaintPattern(maskPaint, aMask);
SkLayerRasterizer *raster = new SkLayerRasterizer();
raster->addLayer(maskPaint);
SkSafeUnref(paint.mPaint.setRasterizer(raster));
// Skia only uses the mask rasterizer when we are drawing a path/rect.
// Take our destination bounds and convert them into user space to use
// as the path to draw.
SkPath path;
path.addRect(SkRect::MakeWH(mSize.width, mSize.height));
Matrix temp = mTransform;
temp.Invert();
SkMatrix mat;
GfxMatrixToSkiaMatrix(temp, mat);
path.transform(mat);
mCanvas->drawPath(path, paint.mPaint);
}
TemporaryRef<SourceSurface>
DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
@ -624,6 +679,21 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
return true;
}
void
DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
{
mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride);
mBitmap.setPixels(aData);
SkAutoTUnref<SkDevice> device(new SkDevice(mBitmap));
SkAutoTUnref<SkCanvas> canvas(new SkCanvas(device.get()));
mSize = aSize;
mDevice = device.get();
mCanvas = canvas.get();
mFormat = aFormat;
}
void
DrawTargetSkia::SetTransform(const Matrix& aTransform)
{
@ -665,6 +735,15 @@ DrawTargetSkia::PushClip(const Path *aPath)
mCanvas->clipPath(skiaPath->GetPath());
}
void
DrawTargetSkia::PushClipRect(const Rect& aRect)
{
SkRect rect = RectToSkRect(aRect);
mCanvas->save(SkCanvas::kClip_SaveFlag);
mCanvas->clipRect(rect);
}
void
DrawTargetSkia::PopClip()
{
@ -681,7 +760,7 @@ DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, Ex
}
std::stable_sort(stops.begin(), stops.end());
return new GradientStopsSkia(stops, aNumStops);
return new GradientStopsSkia(stops, aNumStops, aExtendMode);
}
void

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

@ -101,10 +101,9 @@ public:
const DrawOptions &aOptions = DrawOptions());
virtual void Mask(const Pattern &aSource,
const Pattern &aMask,
const DrawOptions &aOptions = DrawOptions())
{ return; }
const DrawOptions &aOptions = DrawOptions());
virtual void PushClip(const Path *aPath);
virtual void PushClipRect(const Rect &aRect) { }
virtual void PushClipRect(const Rect& aRect);
virtual void PopClip();
virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
const IntSize &aSize,
@ -120,6 +119,7 @@ public:
virtual void SetTransform(const Matrix &aTransform);
bool Init(const IntSize &aSize, SurfaceFormat aFormat);
void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
operator std::string() const {
std::stringstream stream;
@ -138,7 +138,6 @@ private:
SkRefPtr<SkCanvas> mCanvas;
SkRefPtr<SkDevice> mDevice;
nsRefPtr<gfxImageSurface> mImageSurface;
SurfaceFormat mFormat;
vector<SourceSurfaceSkia*> mSnapshots;
};