зеркало из https://github.com/mozilla/gecko-dev.git
Bug 715652 - Implement significantly more of the 2D API for the Cairo backend. r=jrmuizel
--HG-- extra : rebase_source : b23314691fef65db2518d3e738a66039e3c18909
This commit is contained in:
Родитель
64c03d88cb
Коммит
188a24ed30
|
@ -35,24 +35,54 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "DrawTargetCairo.h"
|
||||
|
||||
#include "SourceSurfaceCairo.h"
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#include "Blur.h"
|
||||
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
#include "cairo-quartz.h"
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
#ifdef CAIRO_HAS_XLIB_SURFACE
|
||||
#include "cairo-xlib.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
cairo_operator_t
|
||||
static cairo_operator_t
|
||||
GfxOpToCairoOp(CompositionOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case OP_OVER:
|
||||
return CAIRO_OPERATOR_OVER;
|
||||
case OP_SOURCE:
|
||||
return CAIRO_OPERATOR_SOURCE;
|
||||
case OP_ADD:
|
||||
return CAIRO_OPERATOR_ADD;
|
||||
case OP_ATOP:
|
||||
return CAIRO_OPERATOR_ATOP;
|
||||
case OP_OUT:
|
||||
return CAIRO_OPERATOR_OUT;
|
||||
case OP_IN:
|
||||
return CAIRO_OPERATOR_IN;
|
||||
case OP_SOURCE:
|
||||
return CAIRO_OPERATOR_SOURCE;
|
||||
case OP_DEST_IN:
|
||||
return CAIRO_OPERATOR_DEST_IN;
|
||||
case OP_DEST_OUT:
|
||||
return CAIRO_OPERATOR_DEST_OUT;
|
||||
case OP_DEST_OVER:
|
||||
return CAIRO_OPERATOR_DEST_OVER;
|
||||
case OP_DEST_ATOP:
|
||||
return CAIRO_OPERATOR_DEST_ATOP;
|
||||
case OP_XOR:
|
||||
return CAIRO_OPERATOR_XOR;
|
||||
case OP_COUNT:
|
||||
break;
|
||||
}
|
||||
|
@ -60,7 +90,7 @@ GfxOpToCairoOp(CompositionOp op)
|
|||
return CAIRO_OPERATOR_OVER;
|
||||
}
|
||||
|
||||
cairo_filter_t
|
||||
static cairo_filter_t
|
||||
GfxFilterToCairoFilter(Filter filter)
|
||||
{
|
||||
switch (filter)
|
||||
|
@ -74,7 +104,23 @@ GfxFilterToCairoFilter(Filter filter)
|
|||
return CAIRO_FILTER_BILINEAR;
|
||||
}
|
||||
|
||||
cairo_format_t
|
||||
static cairo_extend_t
|
||||
GfxExtendToCairoExtend(ExtendMode extend)
|
||||
{
|
||||
switch (extend)
|
||||
{
|
||||
case EXTEND_CLAMP:
|
||||
return CAIRO_EXTEND_PAD;
|
||||
case EXTEND_REPEAT:
|
||||
return CAIRO_EXTEND_REPEAT;
|
||||
case EXTEND_REFLECT:
|
||||
return CAIRO_EXTEND_REFLECT;
|
||||
}
|
||||
|
||||
return CAIRO_EXTEND_PAD;
|
||||
}
|
||||
|
||||
static cairo_format_t
|
||||
GfxFormatToCairoFormat(SurfaceFormat format)
|
||||
{
|
||||
switch (format)
|
||||
|
@ -90,12 +136,223 @@ GfxFormatToCairoFormat(SurfaceFormat format)
|
|||
return CAIRO_FORMAT_ARGB32;
|
||||
}
|
||||
|
||||
static cairo_content_t
|
||||
GfxFormatToCairoContent(SurfaceFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_B8G8R8A8:
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
case FORMAT_B8G8R8X8:
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
case FORMAT_A8:
|
||||
return CAIRO_CONTENT_ALPHA;
|
||||
}
|
||||
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
}
|
||||
|
||||
static cairo_line_join_t
|
||||
GfxLineJoinToCairoLineJoin(JoinStyle style)
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case JOIN_BEVEL:
|
||||
return CAIRO_LINE_JOIN_BEVEL;
|
||||
case JOIN_ROUND:
|
||||
return CAIRO_LINE_JOIN_ROUND;
|
||||
case JOIN_MITER:
|
||||
return CAIRO_LINE_JOIN_MITER;
|
||||
case JOIN_MITER_OR_BEVEL:
|
||||
return CAIRO_LINE_JOIN_MITER;
|
||||
}
|
||||
|
||||
return CAIRO_LINE_JOIN_MITER;
|
||||
}
|
||||
|
||||
static cairo_line_cap_t
|
||||
GfxLineCapToCairoLineCap(CapStyle style)
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case CAP_BUTT:
|
||||
return CAIRO_LINE_CAP_BUTT;
|
||||
case CAP_ROUND:
|
||||
return CAIRO_LINE_CAP_ROUND;
|
||||
case CAP_SQUARE:
|
||||
return CAIRO_LINE_CAP_SQUARE;
|
||||
}
|
||||
|
||||
return CAIRO_LINE_CAP_BUTT;
|
||||
}
|
||||
|
||||
static SurfaceFormat
|
||||
CairoContentToGfxFormat(cairo_content_t content)
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
return FORMAT_B8G8R8A8;
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
return FORMAT_B8G8R8X8;
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
return FORMAT_A8;
|
||||
}
|
||||
|
||||
return FORMAT_B8G8R8A8;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetCairoSurfaceSize(cairo_surface_t* surface, IntSize& size)
|
||||
{
|
||||
switch (cairo_surface_get_type(surface))
|
||||
{
|
||||
case CAIRO_SURFACE_TYPE_IMAGE:
|
||||
{
|
||||
size.width = cairo_image_surface_get_width(surface);
|
||||
size.height = cairo_image_surface_get_height(surface);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CAIRO_HAS_XLIB_SURFACE
|
||||
case CAIRO_SURFACE_TYPE_XLIB:
|
||||
{
|
||||
size.width = cairo_xlib_surface_get_width(surface);
|
||||
size.height = cairo_xlib_surface_get_height(surface);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CAIRO_HAS_QUARTZ_SURFACE
|
||||
case CAIRO_SURFACE_TYPE_QUARTZ:
|
||||
{
|
||||
CGContextRef cgc = cairo_quartz_surface_get_cg_context(surface);
|
||||
|
||||
// It's valid to call these CGBitmapContext functions on non-bitmap
|
||||
// contexts; they'll just return 0 in that case.
|
||||
size.width = CGBitmapContextGetWidth(cgc);
|
||||
size.height = CGBitmapContextGetWidth(cgc);
|
||||
return size.width != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GfxMatrixToCairoMatrix(const Matrix& mat, cairo_matrix_t& retval)
|
||||
{
|
||||
cairo_matrix_init(&retval, mat._11, mat._12, mat._21, mat._22, mat._31, mat._32);
|
||||
}
|
||||
|
||||
cairo_pattern_t*
|
||||
GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
|
||||
{
|
||||
cairo_pattern_t* pat = NULL;
|
||||
|
||||
switch (aPattern.GetType())
|
||||
{
|
||||
case PATTERN_COLOR:
|
||||
{
|
||||
Color color = static_cast<const ColorPattern&>(aPattern).mColor;
|
||||
pat = cairo_pattern_create_rgba(color.r, color.g, color.b, color.a * aAlpha);
|
||||
break;
|
||||
}
|
||||
|
||||
case PATTERN_SURFACE:
|
||||
{
|
||||
const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
|
||||
cairo_surface_t* surf = NULL;
|
||||
|
||||
if (pattern.mSurface->GetType() == SURFACE_CAIRO) {
|
||||
const SourceSurfaceCairo* sourcesurf = static_cast<const SourceSurfaceCairo*>(pattern.mSurface.get());
|
||||
surf = sourcesurf->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
} else if (pattern.mSurface->GetType() == SURFACE_CAIRO_IMAGE) {
|
||||
const DataSourceSurfaceCairo* sourcesurf =
|
||||
static_cast<const DataSourceSurfaceCairo*>(pattern.mSurface.get());
|
||||
surf = sourcesurf->GetSurface();
|
||||
cairo_surface_reference(surf);
|
||||
} else {
|
||||
RefPtr<DataSourceSurface> sourcesurf = pattern.mSurface->GetDataSurface();
|
||||
surf = cairo_image_surface_create_for_data(sourcesurf->GetData(),
|
||||
GfxFormatToCairoFormat(sourcesurf->GetFormat()),
|
||||
sourcesurf->GetSize().width,
|
||||
sourcesurf->GetSize().height,
|
||||
sourcesurf->Stride());
|
||||
}
|
||||
|
||||
pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
|
||||
cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(pattern.mExtendMode));
|
||||
|
||||
cairo_surface_destroy(surf);
|
||||
|
||||
break;
|
||||
}
|
||||
case PATTERN_LINEAR_GRADIENT:
|
||||
{
|
||||
const LinearGradientPattern& pattern = static_cast<const LinearGradientPattern&>(aPattern);
|
||||
RefPtr<GradientStops> stops = pattern.mStops;
|
||||
if (stops->GetBackendType() == BACKEND_CAIRO) {
|
||||
pat = cairo_pattern_create_linear(pattern.mBegin.x, pattern.mBegin.y,
|
||||
pattern.mEnd.x, pattern.mEnd.y);
|
||||
|
||||
const std::vector<GradientStop>& stops =
|
||||
static_cast<GradientStopsCairo*>(pattern.mStops.get())->GetStops();
|
||||
for (std::vector<GradientStop>::const_iterator i = stops.begin();
|
||||
i != stops.end();
|
||||
++i) {
|
||||
cairo_pattern_add_color_stop_rgba(pat, i->offset, i->color.r,
|
||||
i->color.g, i->color.b,
|
||||
i->color.a);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PATTERN_RADIAL_GRADIENT:
|
||||
{
|
||||
const RadialGradientPattern& pattern = static_cast<const RadialGradientPattern&>(aPattern);
|
||||
RefPtr<GradientStops> stops = pattern.mStops;
|
||||
if (stops->GetBackendType() == BACKEND_CAIRO) {
|
||||
pat = cairo_pattern_create_radial(pattern.mCenter1.x, pattern.mCenter1.y, pattern.mRadius1,
|
||||
pattern.mCenter2.x, pattern.mCenter2.y, pattern.mRadius2);
|
||||
|
||||
const std::vector<GradientStop>& stops =
|
||||
static_cast<GradientStopsCairo*>(pattern.mStops.get())->GetStops();
|
||||
for (std::vector<GradientStop>::const_iterator i = stops.begin();
|
||||
i != stops.end();
|
||||
++i) {
|
||||
cairo_pattern_add_color_stop_rgba(pat, i->offset, i->color.r,
|
||||
i->color.g, i->color.b,
|
||||
i->color.a);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pat;
|
||||
}
|
||||
|
||||
bool
|
||||
NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
|
||||
{
|
||||
// We pre-multiply colours' alpha by the global alpha, so we don't need to
|
||||
// use an intermediate surface for them.
|
||||
if (aPattern.GetType() == PATTERN_COLOR)
|
||||
return false;
|
||||
|
||||
if (aOptions.mAlpha == 1.0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DrawTargetCairo::DrawTargetCairo()
|
||||
: mContext(NULL)
|
||||
{
|
||||
|
@ -103,12 +360,30 @@ DrawTargetCairo::DrawTargetCairo()
|
|||
|
||||
DrawTargetCairo::~DrawTargetCairo()
|
||||
{
|
||||
MarkSnapshotsIndependent();
|
||||
cairo_destroy(mContext);
|
||||
}
|
||||
|
||||
IntSize
|
||||
DrawTargetCairo::GetSize()
|
||||
{
|
||||
return IntSize();
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::Snapshot()
|
||||
{
|
||||
cairo_surface_t* csurf = cairo_get_target(mContext);
|
||||
IntSize size;
|
||||
if (GetCairoSurfaceSize(csurf, size)) {
|
||||
cairo_content_t content = cairo_surface_get_content(csurf);
|
||||
RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(csurf, size,
|
||||
CairoContentToGfxFormat(content),
|
||||
this);
|
||||
AppendSnapshot(surf);
|
||||
return surf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -119,6 +394,16 @@ DrawTargetCairo::Flush()
|
|||
cairo_surface_flush(surf);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PrepareForDrawing(cairo_t* aContext)
|
||||
{
|
||||
MarkChanged();
|
||||
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(mTransform, mat);
|
||||
cairo_set_matrix(aContext, &mat);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
|
||||
const Rect &aDest,
|
||||
|
@ -126,12 +411,14 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
|
|||
const DrawSurfaceOptions &aSurfOptions,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
|
||||
float sx = aSource.Width() / aDest.Width();
|
||||
float sy = aSource.Height() / aDest.Height();
|
||||
|
||||
cairo_matrix_t src_mat;
|
||||
cairo_matrix_init_scale(&src_mat, sx, sy);
|
||||
cairo_matrix_translate(&src_mat, -aSource.X(), -aSource.Y());
|
||||
cairo_matrix_translate(&src_mat, aSource.X(), aSource.Y());
|
||||
|
||||
cairo_surface_t* surf = NULL;
|
||||
if (aSurface->GetType() == SURFACE_CAIRO) {
|
||||
|
@ -142,31 +429,304 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
|
|||
cairo_pattern_set_matrix(pat, &src_mat);
|
||||
cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
|
||||
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
cairo_rectangle(mContext, aDest.X(), aDest.Y(),
|
||||
aDest.Width(), aDest.Height());
|
||||
cairo_fill(mContext);
|
||||
|
||||
cairo_translate(mContext, aDest.X(), aDest.Y());
|
||||
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
cairo_clip(mContext);
|
||||
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
|
||||
|
||||
cairo_restore(mContext);
|
||||
|
||||
cairo_pattern_destroy(pat);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
||||
const Point &aDest,
|
||||
const Color &aColor,
|
||||
const Point &aOffset,
|
||||
Float aSigma,
|
||||
CompositionOp aOperator)
|
||||
{
|
||||
MarkChanged();
|
||||
|
||||
if (aSurface->GetType() != SURFACE_CAIRO) {
|
||||
return;
|
||||
}
|
||||
|
||||
SourceSurfaceCairo* sourcesurf = static_cast<SourceSurfaceCairo*>(aSurface);
|
||||
|
||||
Float width = aSurface->GetSize().width,
|
||||
height = aSurface->GetSize().height;
|
||||
Rect extents(0, 0, width, height);
|
||||
|
||||
AlphaBoxBlur blur(extents, IntSize(0, 0),
|
||||
AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)),
|
||||
NULL, NULL);
|
||||
if (!blur.GetData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IntSize blursize = blur.GetSize();
|
||||
|
||||
cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
|
||||
CAIRO_FORMAT_A8,
|
||||
blursize.width,
|
||||
blursize.height,
|
||||
blur.GetStride());
|
||||
|
||||
// Draw the source surface into the surface we're going to blur.
|
||||
cairo_surface_t* surf = sourcesurf->GetSurface();
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
|
||||
|
||||
cairo_t* ctx = cairo_create(blursurf);
|
||||
|
||||
cairo_set_source(ctx, pat);
|
||||
|
||||
IntRect blurrect = blur.GetRect();
|
||||
cairo_new_path(ctx);
|
||||
cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height);
|
||||
cairo_clip(ctx);
|
||||
cairo_paint(ctx);
|
||||
|
||||
cairo_destroy(ctx);
|
||||
|
||||
// Blur the result, then use that blurred result as a mask to draw the shadow
|
||||
// colour to the surface.
|
||||
blur.Blur();
|
||||
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
|
||||
|
||||
cairo_identity_matrix(mContext);
|
||||
cairo_translate(mContext, aDest.x, aDest.y);
|
||||
|
||||
cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
|
||||
|
||||
// Now that the shadow has been drawn, we can draw the surface on top.
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
|
||||
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, width, height);
|
||||
cairo_clip(mContext);
|
||||
|
||||
cairo_paint(mContext);
|
||||
|
||||
cairo_restore(mContext);
|
||||
|
||||
cairo_pattern_destroy(pat);
|
||||
}
|
||||
|
||||
void
|
||||
SetStrokeOptions(cairo_t* aCtx, const StrokeOptions& aStrokeOptions)
|
||||
{
|
||||
cairo_set_line_width(aCtx, aStrokeOptions.mLineWidth);
|
||||
|
||||
cairo_set_miter_limit(aCtx, aStrokeOptions.mMiterLimit);
|
||||
|
||||
if (aStrokeOptions.mDashPattern) {
|
||||
// Convert array of floats to array of doubles
|
||||
std::vector<double> dashes(aStrokeOptions.mDashLength);
|
||||
for (size_t i = 0; i < aStrokeOptions.mDashLength; ++i) {
|
||||
dashes[i] = aStrokeOptions.mDashPattern[i];
|
||||
}
|
||||
cairo_set_dash(aCtx, &dashes[0], aStrokeOptions.mDashLength,
|
||||
aStrokeOptions.mDashOffset);
|
||||
}
|
||||
|
||||
cairo_set_line_join(aCtx, GfxLineJoinToCairoLineJoin(aStrokeOptions.mLineJoin));
|
||||
|
||||
cairo_set_line_cap(aCtx, GfxLineCapToCairoLineCap(aStrokeOptions.mLineCap));
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::DrawPattern(const Rect& aRect,
|
||||
const Pattern& aPattern,
|
||||
const StrokeOptions& aStrokeOptions,
|
||||
const DrawOptions& aOptions,
|
||||
DrawPatternType aDrawType)
|
||||
{
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
|
||||
bool needIntermediate = NeedIntermediateSurface(aPattern, aOptions);
|
||||
if (needIntermediate) {
|
||||
cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
// Don't want operators to be applied twice
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_SOURCE);
|
||||
}
|
||||
|
||||
cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
|
||||
|
||||
if (pat) {
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
|
||||
|
||||
if (aDrawType == DRAW_STROKE) {
|
||||
SetStrokeOptions(mContext, aStrokeOptions);
|
||||
cairo_stroke(mContext);
|
||||
} else {
|
||||
// It's possible that we could simply always clip and paint here, but the
|
||||
// old canvas implementation didn't, so to maintain similar performance
|
||||
// characteristics we choose the same.
|
||||
if (needIntermediate || aOptions.mAlpha == 1.0) {
|
||||
cairo_fill(mContext);
|
||||
} else {
|
||||
cairo_clip(mContext);
|
||||
cairo_paint(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_pattern_destroy(pat);
|
||||
}
|
||||
|
||||
if (needIntermediate) {
|
||||
cairo_pop_group_to_source(mContext);
|
||||
|
||||
cairo_paint_with_alpha(mContext, aOptions.mAlpha);
|
||||
}
|
||||
|
||||
cairo_restore(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::FillRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
|
||||
DrawPattern(aRect, aPattern, StrokeOptions(), aOptions, DRAW_FILL);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::ClearRect(const Rect& aRect)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_rectangle(mContext, aRect.X(), aRect.Y(),
|
||||
aRect.Width(), aRect.Height());
|
||||
cairo_fill(mContext);
|
||||
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
cairo_restore(mContext);
|
||||
}
|
||||
|
||||
if (aPattern.GetType() == PATTERN_COLOR) {
|
||||
Color color = static_cast<const ColorPattern&>(aPattern).mColor;
|
||||
cairo_set_source_rgba(mContext, color.r, color.g,
|
||||
color.b, color.a);
|
||||
void
|
||||
DrawTargetCairo::StrokeRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions /* = StrokeOptions() */,
|
||||
const DrawOptions &aOptions /* = DrawOptions() */)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
|
||||
DrawPattern(aRect, aPattern, aStrokeOptions, aOptions, DRAW_STROKE);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::StrokeLine(const Point &aStart,
|
||||
const Point &aEnd,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions /* = StrokeOptions() */,
|
||||
const DrawOptions &aOptions /* = DrawOptions() */)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
|
||||
cairo_save(mContext);
|
||||
|
||||
cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
|
||||
if (pat) {
|
||||
SetStrokeOptions(mContext, aStrokeOptions);
|
||||
cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
|
||||
|
||||
cairo_set_source(mContext, pat);
|
||||
|
||||
cairo_new_path(mContext);
|
||||
cairo_move_to(mContext, aStart.x, aStart.y);
|
||||
cairo_line_to(mContext, aEnd.x, aEnd.y);
|
||||
|
||||
cairo_stroke(mContext);
|
||||
|
||||
cairo_pattern_destroy(pat);
|
||||
}
|
||||
|
||||
cairo_fill(mContext);
|
||||
cairo_restore(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::Stroke(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions /* = StrokeOptions() */,
|
||||
const DrawOptions &aOptions /* = DrawOptions() */)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::Fill(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions /* = DrawOptions() */)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::FillGlyphs(ScaledFont *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
PrepareForDrawing(mContext);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PushClip(const Path *aPath)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::PopClip()
|
||||
{
|
||||
}
|
||||
|
||||
TemporaryRef<PathBuilder>
|
||||
DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FILL_WINDING */) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TemporaryRef<GradientStops>
|
||||
DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
|
||||
{
|
||||
RefPtr<GradientStopsCairo> stops = new GradientStopsCairo(aStops, aNumStops);
|
||||
return stops;
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
|
@ -180,8 +740,7 @@ DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
|||
aSize.width,
|
||||
aSize.height,
|
||||
aStride);
|
||||
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo();
|
||||
source_surf->InitFromSurface(surf, aSize, aFormat);
|
||||
RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
|
||||
cairo_surface_destroy(surf);
|
||||
return source_surf;
|
||||
}
|
||||
|
@ -189,12 +748,38 @@ DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
|
|||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const
|
||||
{
|
||||
return NULL;
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
|
||||
{
|
||||
if (aSurface.mType == NATIVE_SURFACE_CAIRO_SURFACE) {
|
||||
IntSize size;
|
||||
cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
|
||||
if (GetCairoSurfaceSize(surf, size)) {
|
||||
RefPtr<SourceSurfaceCairo> sourcesurf =
|
||||
new SourceSurfaceCairo(surf, size, aSurface.mFormat);
|
||||
return sourcesurf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TemporaryRef<DrawTarget>
|
||||
DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
|
||||
{
|
||||
cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext),
|
||||
GfxFormatToCairoContent(aFormat),
|
||||
aSize.width, aSize.height);
|
||||
|
||||
if (!cairo_surface_status(similar)) {
|
||||
RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
|
||||
target->Init(similar);
|
||||
return target;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -206,14 +791,58 @@ DrawTargetCairo::Init(cairo_surface_t* aSurface)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::SetTransform(const Matrix& aTransform)
|
||||
void *
|
||||
DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
|
||||
{
|
||||
cairo_matrix_t mat;
|
||||
GfxMatrixToCairoMatrix(aTransform, mat);
|
||||
cairo_set_matrix(mContext, &mat);
|
||||
mTransform = aTransform;
|
||||
if (aType == NATIVE_SURFACE_CAIRO_SURFACE) {
|
||||
return cairo_get_target(mContext);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::MarkSnapshotsIndependent()
|
||||
{
|
||||
// Make a copy of the vector, since MarkIndependent implicitly modifies mSnapshots.
|
||||
std::vector<SourceSurfaceCairo*> snapshots = mSnapshots;
|
||||
for (std::vector<SourceSurfaceCairo*>::iterator iter = snapshots.begin();
|
||||
iter != snapshots.end();
|
||||
++iter) {
|
||||
(*iter)->MarkIndependent();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::AppendSnapshot(SourceSurfaceCairo* aSnapshot)
|
||||
{
|
||||
mSnapshots.push_back(aSnapshot);
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::RemoveSnapshot(SourceSurfaceCairo* aSnapshot)
|
||||
{
|
||||
std::vector<SourceSurfaceCairo*>::iterator iter = std::find(mSnapshots.begin(),
|
||||
mSnapshots.end(),
|
||||
aSnapshot);
|
||||
if (iter != mSnapshots.end()) {
|
||||
mSnapshots.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::MarkChanged()
|
||||
{
|
||||
if (!mSnapshots.empty()) {
|
||||
for (std::vector<SourceSurfaceCairo*>::iterator iter = mSnapshots.begin();
|
||||
iter != mSnapshots.end(); ++iter) {
|
||||
(*iter)->DrawTargetWillChange();
|
||||
}
|
||||
// All snapshots will now have copied data.
|
||||
mSnapshots.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,36 @@
|
|||
#include "2D.h"
|
||||
#include "cairo.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class SourceSurfaceCairo;
|
||||
|
||||
class GradientStopsCairo : public GradientStops
|
||||
{
|
||||
public:
|
||||
GradientStopsCairo(GradientStop* aStops, uint32_t aNumStops)
|
||||
{
|
||||
for (uint32_t i = 0; i < aNumStops; ++i) {
|
||||
mStops.push_back(aStops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GradientStopsCairo() {}
|
||||
|
||||
const std::vector<GradientStop>& GetStops() const
|
||||
{
|
||||
return mStops;
|
||||
}
|
||||
|
||||
virtual BackendType GetBackendType() const { return BACKEND_CAIRO; }
|
||||
|
||||
private:
|
||||
std::vector<GradientStop> mStops;
|
||||
};
|
||||
|
||||
class DrawTargetCairo : public DrawTarget
|
||||
{
|
||||
public:
|
||||
|
@ -51,7 +78,7 @@ public:
|
|||
|
||||
virtual BackendType GetType() const { return BACKEND_CAIRO; }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize() { return IntSize(); }
|
||||
virtual IntSize GetSize();
|
||||
|
||||
virtual void Flush();
|
||||
virtual void DrawSurface(SourceSurface *aSurface,
|
||||
|
@ -64,16 +91,13 @@ public:
|
|||
const Color &aColor,
|
||||
const Point &aOffset,
|
||||
Float aSigma,
|
||||
CompositionOp aOperator)
|
||||
{ }
|
||||
CompositionOp aOperator);
|
||||
|
||||
virtual void ClearRect(const Rect &aRect)
|
||||
{ }
|
||||
virtual void ClearRect(const Rect &aRect);
|
||||
|
||||
virtual void CopySurface(SourceSurface *aSurface,
|
||||
const IntRect &aSourceRect,
|
||||
const IntPoint &aDestination)
|
||||
{ }
|
||||
const IntPoint &aDestination);
|
||||
|
||||
virtual void FillRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
|
@ -81,41 +105,37 @@ public:
|
|||
virtual void StrokeRect(const Rect &aRect,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions = StrokeOptions(),
|
||||
const DrawOptions &aOptions = DrawOptions())
|
||||
{ return; }
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
virtual void StrokeLine(const Point &aStart,
|
||||
const Point &aEnd,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions = StrokeOptions(),
|
||||
const DrawOptions &aOptions = DrawOptions())
|
||||
{ return; }
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
virtual void Stroke(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
const StrokeOptions &aStrokeOptions = StrokeOptions(),
|
||||
const DrawOptions &aOptions = DrawOptions())
|
||||
{ return; }
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
virtual void Fill(const Path *aPath,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions = DrawOptions())
|
||||
{ return; }
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
virtual void FillGlyphs(ScaledFont *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Pattern &aPattern,
|
||||
const DrawOptions &aOptions)
|
||||
{ return; }
|
||||
const DrawOptions &aOptions);
|
||||
virtual void Mask(const Pattern &aSource,
|
||||
const Pattern &aMask,
|
||||
const DrawOptions &aOptions = DrawOptions())
|
||||
{ return; }
|
||||
{ }
|
||||
|
||||
virtual void PushClip(const Path *aPath) { }
|
||||
virtual void PushClipRect(const Rect &aRect) { }
|
||||
virtual void PopClip() { }
|
||||
virtual void PushClip(const Path *aPath);
|
||||
virtual void PushClipRect(const Rect &aRect)
|
||||
{ }
|
||||
virtual void PopClip();
|
||||
|
||||
virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const { return NULL; }
|
||||
virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
|
||||
|
||||
virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
|
||||
const IntSize &aSize,
|
||||
|
@ -125,22 +145,43 @@ public:
|
|||
virtual TemporaryRef<SourceSurface>
|
||||
CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const;
|
||||
virtual TemporaryRef<DrawTarget>
|
||||
CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
|
||||
{ return NULL; }
|
||||
CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
|
||||
|
||||
virtual TemporaryRef<GradientStops> CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode = EXTEND_CLAMP) const
|
||||
{ return NULL; }
|
||||
virtual TemporaryRef<GradientStops>
|
||||
CreateGradientStops(GradientStop *aStops,
|
||||
uint32_t aNumStops,
|
||||
ExtendMode aExtendMode = EXTEND_CLAMP) const;
|
||||
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType)
|
||||
{ return NULL; }
|
||||
|
||||
virtual void SetTransform(const Matrix& aTransform);
|
||||
virtual void *GetNativeSurface(NativeSurfaceType aType);
|
||||
|
||||
bool Init(cairo_surface_t* aSurface);
|
||||
|
||||
private:
|
||||
private: // methods
|
||||
void PrepareForDrawing(cairo_t* aContext);
|
||||
|
||||
enum DrawPatternType { DRAW_FILL, DRAW_STROKE };
|
||||
void DrawPattern(const Rect& aRect,
|
||||
const Pattern& aPattern,
|
||||
const StrokeOptions& aStrokeOptions,
|
||||
const DrawOptions& aOptions,
|
||||
DrawPatternType aDrawType);
|
||||
|
||||
// Copy-on-write support for snapshot surfaces.
|
||||
friend class SourceSurfaceCairo;
|
||||
void AppendSnapshot(SourceSurfaceCairo* aSnapshot);
|
||||
void RemoveSnapshot(SourceSurfaceCairo* aSnapshot);
|
||||
|
||||
// Call before you make any changes to the backing surface with which this
|
||||
// context is associated.
|
||||
void MarkChanged();
|
||||
|
||||
// Call if there is any reason to disassociate all snapshots from this draw
|
||||
// target; for example, because we're going to be destroyed.
|
||||
void MarkSnapshotsIndependent();
|
||||
|
||||
private: // data
|
||||
cairo_t* mContext;
|
||||
std::vector<SourceSurfaceCairo*> mSnapshots;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -36,18 +36,76 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "SourceSurfaceCairo.h"
|
||||
#include "DrawTargetCairo.h"
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
SourceSurfaceCairo::SourceSurfaceCairo()
|
||||
static cairo_format_t
|
||||
GfxFormatToCairoFormat(SurfaceFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_B8G8R8A8:
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
case FORMAT_B8G8R8X8:
|
||||
return CAIRO_FORMAT_RGB24;
|
||||
case FORMAT_A8:
|
||||
return CAIRO_FORMAT_A8;
|
||||
}
|
||||
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
}
|
||||
|
||||
static SurfaceFormat
|
||||
CairoFormatToSurfaceFormat(cairo_format_t format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
return FORMAT_B8G8R8A8;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
return FORMAT_B8G8R8X8;
|
||||
case CAIRO_FORMAT_A8:
|
||||
return FORMAT_A8;
|
||||
}
|
||||
|
||||
return FORMAT_B8G8R8A8;
|
||||
}
|
||||
|
||||
static cairo_content_t
|
||||
GfxFormatToCairoContent(SurfaceFormat format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case FORMAT_B8G8R8A8:
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
case FORMAT_B8G8R8X8:
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
case FORMAT_A8:
|
||||
return CAIRO_CONTENT_ALPHA;
|
||||
}
|
||||
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
}
|
||||
|
||||
SourceSurfaceCairo::SourceSurfaceCairo(cairo_surface_t* aSurface,
|
||||
const IntSize& aSize,
|
||||
const SurfaceFormat& aFormat,
|
||||
DrawTargetCairo* aDrawTarget /* = NULL */)
|
||||
: mSize(aSize)
|
||||
, mFormat(aFormat)
|
||||
, mSurface(aSurface)
|
||||
, mDrawTarget(aDrawTarget)
|
||||
{
|
||||
cairo_surface_reference(mSurface);
|
||||
}
|
||||
|
||||
SourceSurfaceCairo::~SourceSurfaceCairo()
|
||||
{
|
||||
MarkIndependent();
|
||||
cairo_surface_destroy(mSurface);
|
||||
}
|
||||
|
||||
|
@ -66,26 +124,108 @@ SourceSurfaceCairo::GetFormat() const
|
|||
TemporaryRef<DataSourceSurface>
|
||||
SourceSurfaceCairo::GetDataSurface()
|
||||
{
|
||||
return NULL;
|
||||
RefPtr<DataSourceSurfaceCairo> dataSurf;
|
||||
|
||||
if (cairo_surface_get_type(mSurface) == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
dataSurf = new DataSourceSurfaceCairo(mSurface);
|
||||
} else {
|
||||
cairo_surface_t* imageSurf = cairo_image_surface_create(GfxFormatToCairoFormat(mFormat),
|
||||
mSize.width, mSize.height);
|
||||
|
||||
// Fill the new image surface with the contents of our surface.
|
||||
cairo_t* ctx = cairo_create(imageSurf);
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(mSurface);
|
||||
cairo_set_source(ctx, pat);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
|
||||
dataSurf = new DataSourceSurfaceCairo(imageSurf);
|
||||
cairo_surface_destroy(imageSurf);
|
||||
}
|
||||
|
||||
return dataSurf;
|
||||
}
|
||||
|
||||
cairo_surface_t*
|
||||
SourceSurfaceCairo::GetSurface()
|
||||
SourceSurfaceCairo::GetSurface() const
|
||||
{
|
||||
return mSurface;
|
||||
}
|
||||
|
||||
bool
|
||||
SourceSurfaceCairo::InitFromSurface(cairo_surface_t* aSurface,
|
||||
const IntSize& aSize,
|
||||
const SurfaceFormat& aFormat)
|
||||
void
|
||||
SourceSurfaceCairo::DrawTargetWillChange()
|
||||
{
|
||||
mSurface = aSurface;
|
||||
cairo_surface_reference(mSurface);
|
||||
mSize = aSize;
|
||||
mFormat = aFormat;
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget = NULL;
|
||||
|
||||
return true;
|
||||
// We're about to lose our version of the surface, so make a copy of it.
|
||||
cairo_surface_t* surface = cairo_surface_create_similar(mSurface,
|
||||
GfxFormatToCairoContent(mFormat),
|
||||
mSize.width, mSize.height);
|
||||
cairo_t* ctx = cairo_create(surface);
|
||||
cairo_pattern_t* pat = cairo_pattern_create_for_surface(mSurface);
|
||||
cairo_set_source(ctx, pat);
|
||||
cairo_paint(ctx);
|
||||
cairo_destroy(ctx);
|
||||
|
||||
// Swap in this new surface.
|
||||
cairo_surface_destroy(mSurface);
|
||||
mSurface = surface;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceSurfaceCairo::MarkIndependent()
|
||||
{
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->RemoveSnapshot(this);
|
||||
mDrawTarget = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DataSourceSurfaceCairo::DataSourceSurfaceCairo(cairo_surface_t* imageSurf)
|
||||
: mImageSurface(imageSurf)
|
||||
{
|
||||
cairo_surface_reference(mImageSurface);
|
||||
}
|
||||
|
||||
DataSourceSurfaceCairo::~DataSourceSurfaceCairo()
|
||||
{
|
||||
cairo_surface_destroy(mImageSurface);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
DataSourceSurfaceCairo::GetData()
|
||||
{
|
||||
return cairo_image_surface_get_data(mImageSurface);
|
||||
}
|
||||
|
||||
int32_t
|
||||
DataSourceSurfaceCairo::Stride()
|
||||
{
|
||||
return cairo_image_surface_get_stride(mImageSurface);
|
||||
}
|
||||
|
||||
IntSize
|
||||
DataSourceSurfaceCairo::GetSize() const
|
||||
{
|
||||
IntSize size;
|
||||
size.width = cairo_image_surface_get_width(mImageSurface);
|
||||
size.height = cairo_image_surface_get_height(mImageSurface);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
DataSourceSurfaceCairo::GetFormat() const
|
||||
{
|
||||
return CairoFormatToSurfaceFormat(cairo_image_surface_get_format(mImageSurface));
|
||||
}
|
||||
|
||||
cairo_surface_t*
|
||||
DataSourceSurfaceCairo::GetSurface() const
|
||||
{
|
||||
return mImageSurface;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,27 +42,56 @@
|
|||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class DrawTargetCairo;
|
||||
|
||||
class SourceSurfaceCairo : public SourceSurface
|
||||
{
|
||||
public:
|
||||
SourceSurfaceCairo();
|
||||
~SourceSurfaceCairo();
|
||||
// Create a SourceSurfaceCairo. The surface will not be copied, but simply
|
||||
// referenced.
|
||||
// If aDrawTarget is non-NULL, it is assumed that this is a snapshot source
|
||||
// surface, and we'll call DrawTargetCairo::RemoveSnapshot(this) on it when
|
||||
// we're destroyed.
|
||||
SourceSurfaceCairo(cairo_surface_t* aSurface, const IntSize& aSize,
|
||||
const SurfaceFormat& aFormat,
|
||||
DrawTargetCairo* aDrawTarget = NULL);
|
||||
virtual ~SourceSurfaceCairo();
|
||||
|
||||
virtual SurfaceType GetType() const { return SURFACE_CAIRO; }
|
||||
virtual IntSize GetSize() const;
|
||||
virtual SurfaceFormat GetFormat() const;
|
||||
virtual TemporaryRef<DataSourceSurface> GetDataSurface();
|
||||
|
||||
cairo_surface_t* GetSurface();
|
||||
cairo_surface_t* GetSurface() const;
|
||||
|
||||
bool InitFromSurface(cairo_surface_t* aSurface,
|
||||
const IntSize& aSize,
|
||||
const SurfaceFormat& aFormat);
|
||||
private: // methods
|
||||
friend class DrawTargetCairo;
|
||||
void DrawTargetWillChange();
|
||||
void MarkIndependent();
|
||||
|
||||
private:
|
||||
private: // data
|
||||
IntSize mSize;
|
||||
SurfaceFormat mFormat;
|
||||
cairo_surface_t* mSurface;
|
||||
DrawTargetCairo* mDrawTarget;
|
||||
};
|
||||
|
||||
class DataSourceSurfaceCairo : public DataSourceSurface
|
||||
{
|
||||
public:
|
||||
DataSourceSurfaceCairo(cairo_surface_t* imageSurf);
|
||||
virtual ~DataSourceSurfaceCairo();
|
||||
virtual unsigned char *GetData();
|
||||
virtual int32_t Stride();
|
||||
|
||||
virtual SurfaceType GetType() const { return SURFACE_CAIRO_IMAGE; }
|
||||
virtual IntSize GetSize() const;
|
||||
virtual SurfaceFormat GetFormat() const;
|
||||
|
||||
cairo_surface_t* GetSurface() const;
|
||||
|
||||
private:
|
||||
cairo_surface_t* mImageSurface;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -84,7 +84,8 @@ enum FontType
|
|||
|
||||
enum NativeSurfaceType
|
||||
{
|
||||
NATIVE_SURFACE_D3D10_TEXTURE
|
||||
NATIVE_SURFACE_D3D10_TEXTURE,
|
||||
NATIVE_SURFACE_CAIRO_SURFACE
|
||||
};
|
||||
|
||||
enum NativeFontType
|
||||
|
|
Загрузка…
Ссылка в новой задаче