cairo_pattern_t* SPSolidColor::pattern_new(cairo_t * /*ct*/, Geom::OptRect const & /*bbox*/, double opacity) { SPIColor *c = &(this->style->solid_color); cairo_pattern_t *cp = cairo_pattern_create_rgba ( c->value.color.v.c[0], c->value.color.v.c[1], c->value.color.v.c[2], SP_SCALE24_TO_FLOAT(this->style->solid_opacity.value) * opacity ); return cp; }
// TODO: memoize, maybe void VectorGraphics::apply_color(double r, double g, double b, double a) { if(solid_) { cairo_pattern_destroy(solid_); } solid_ = cairo_pattern_create_rgba(r, g, b, a); cairo_set_source(cr(), solid_); }
static int new_SolidPattern (lua_State *L) { double red; double green; double blue; double alpha; cairo_pattern_t* cp = NULL; lua_remove(L, 1); // remove cairo.SolidPattern //{"create_rgb", l_cairo_pattern_create_rgb}, //{"create_rgba", l_cairo_pattern_create_rgba}, red = luaL_checknumber(L, 1); green = luaL_checknumber(L, 2); blue = luaL_checknumber(L, 3); alpha = luaL_optnumber(L, 4, -1); if (alpha < 0) cp = cairo_pattern_create_rgb (red, green, blue); else cp = cairo_pattern_create_rgba (red, green, blue, alpha); return new_Pattern(L, LUACAIRO ".SolidPattern.mt", cp, CAIRO_PATTERN_TYPE_SOLID, 1); }
gboolean gxps_brush_solid_color_parse (const gchar *data, GXPSArchive *zip, gdouble alpha, cairo_pattern_t **pattern) { GXPSColor color; cairo_pattern_t *retval; if (!gxps_color_parse (data, zip, &color)) return FALSE; retval = cairo_pattern_create_rgba (color.red, color.green, color.blue, color.alpha * alpha); if (cairo_pattern_status (retval)) { cairo_pattern_destroy (retval); return FALSE; } if (pattern) *pattern = retval; return TRUE; }
void QCairoPaintEngine::updateBrush() { //qDebug()<<" QCairoPaintEnginePrivate::updateBrush() "<<cdirtyflags; //if (cdirtyflags&QPaintEngine::DirtyBrush==QPaintEngine::DirtyBrush) { //qDebug()<<"updateBrush "<<cbrush; cairo_pattern_t *pat=NULL; switch (cbrush.style()) { case Qt::NoBrush: break; default: case Qt::SolidPattern: pat = cairo_pattern_create_rgba(cbrush.color().redF(), cbrush.color().greenF(), cbrush.color().blueF(), cbrush.color().alphaF()); break; } if (brushpattern) { releasePattern(brushpattern); } brushpattern=pat; cairo_set_source(cr, brushpattern); //cairo_set_source_rgba(cr, cbrush.color().redF(), cbrush.color().greenF(), cbrush.color().blueF(), cbrush.color().alphaF()); //cairo_fill_preserve(cr); //cairo_set_source_rgba (cr, cpen.color().redF(), cpen.color().greenF(), cpen.color().blueF(), cpen.color().alphaF()); //cdirtyflags=cdirtyflags&(~QPaintEngine::DirtyBrush); //} }
static PyObject * solid_pattern_new (PyTypeObject *type, PyObject *args, PyObject *kwds) { double r, g, b, a = 1.0; if (!PyArg_ParseTuple (args, "ddd|d:SolidPattern.__new__", &r, &g, &b, &a)) return NULL; return PycairoPattern_FromPattern (cairo_pattern_create_rgba (r, g, b, a), NULL); }
static int l_pattern_create_color(lua_State * L) { double red = luaL_optnumber(L, 1, 1); double green = luaL_optnumber(L, 2, 1); double blue = luaL_optnumber(L, 3, 1); double alpha = luaL_optnumber(L, 4, 1); struct lpattern_t * pattern = lua_newuserdata(L, sizeof(struct lpattern_t)); pattern->pattern = cairo_pattern_create_rgba(red, green, blue, alpha); luaL_setmetatable(L, MT_PATTERN); return 1; }
int l_cairo_pattern_create_rgba(lua_State * L) { double red = luaL_checknumber(L, 1); double green = luaL_checknumber(L, 2); double blue = luaL_checknumber(L, 3); double alpha = luaL_checknumber(L, 3); cairo_pattern_t ** pattern = lua_newuserdata(L, sizeof(cairo_pattern_t *)); *pattern = cairo_pattern_create_rgba(red, green, blue, alpha); luaL_setmetatable(L, MT_NAME_CAIRO_PATTERN); return 1; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_pattern_t *blue; cairo_pattern_t *red; blue = cairo_pattern_create_rgba (0.0, 0.0, 1.0, 0.8); red = cairo_pattern_create_rgba (1.0, 0.0, 0.0, 0.2); cairo_test_paint_checkered (cr); fill_and_stroke (cr, rectangle, blue, red); cairo_translate (cr, SIZE + 2 * PAD, 0); fill_and_stroke (cr, circle, red, blue); cairo_pattern_destroy (blue); cairo_pattern_destroy (red); return CAIRO_TEST_SUCCESS; }
int main (void) { cairo_test_context_t ctx; cairo_surface_t *surface; cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial; cairo_test_status_t result = CAIRO_TEST_SUCCESS; cairo_test_init (&ctx, "pattern-get-type"); cairo_test_log (&ctx, "Creating patterns of all types\n"); solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2); solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); surface_pattern = cairo_pattern_create_for_surface (surface); linear = cairo_pattern_create_linear (0.0, 0.0, 10.0, 10.0); radial = cairo_pattern_create_radial (10.0, 10.0, 0.1, 10.0, 10.0, 1.0); cairo_test_log (&ctx, "Verifying return values of cairo_pattern_get_type\n"); if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID) result = CAIRO_TEST_FAILURE; if (cairo_pattern_get_type (solid_rgba) != CAIRO_PATTERN_TYPE_SOLID) result = CAIRO_TEST_FAILURE; if (cairo_pattern_get_type (surface_pattern) != CAIRO_PATTERN_TYPE_SURFACE) result = CAIRO_TEST_FAILURE; if (cairo_pattern_get_type (linear) != CAIRO_PATTERN_TYPE_LINEAR) result = CAIRO_TEST_FAILURE; if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL) result = CAIRO_TEST_FAILURE; cairo_test_log (&ctx, "Cleaning up\n"); cairo_pattern_destroy (solid_rgb); cairo_pattern_destroy (solid_rgba); cairo_pattern_destroy (surface_pattern); cairo_surface_destroy (surface); cairo_pattern_destroy (linear); cairo_pattern_destroy (radial); cairo_test_fini (&ctx); return result; }
static void na_tray_child_realize (GtkWidget *widget) { NaTrayChild *child = NA_TRAY_CHILD (widget); GdkVisual *visual = gtk_widget_get_visual (widget); GdkWindow *window; GTK_WIDGET_CLASS (na_tray_child_parent_class)->realize (widget); window = gtk_widget_get_window (widget); if (child->has_alpha) { /* We have real transparency with an ARGB visual and the Composite * extension. */ /* Set a transparent background */ cairo_pattern_t *transparent = cairo_pattern_create_rgba (0, 0, 0, 0); gdk_window_set_background_pattern (window, transparent); gdk_window_set_composited (window, TRUE); cairo_pattern_destroy (transparent); child->parent_relative_bg = FALSE; } else if (visual == gdk_window_get_visual (gdk_window_get_parent (window))) { /* Otherwise, if the visual matches the visual of the parent window, we * can use a parent-relative background and fake transparency. */ gdk_window_set_background_pattern (window, NULL); child->parent_relative_bg = TRUE; } else { /* Nothing to do; the icon will sit on top of an ugly gray box */ child->parent_relative_bg = FALSE; } gdk_window_set_composited (window, child->composited); gtk_widget_set_app_paintable (GTK_WIDGET (child), child->parent_relative_bg || child->has_alpha); /* Double-buffering will interfere with the parent-relative-background fake * transparency, since the double-buffer code doesn't know how to fill in the * background of the double-buffer correctly. */ gtk_widget_set_double_buffered (GTK_WIDGET (child), child->parent_relative_bg); }
virtual pattern_attached_t create_detached (double r, double g, double b, double a = -1) const { pattern_attached_t detached = 0; if ((a < 0)) { if (!(detached = cairo_pattern_create_rgb(r,g,b))) { LAMNA_LOG_ERROR("failed on cairo_pattern_create_rgb()"); } } else { if (!(a > 1)) { if (!(detached = cairo_pattern_create_rgba(r,g,b,a))) { LAMNA_LOG_ERROR("failed on cairo_pattern_create_rgba()"); } } } return detached; }
static int cairo_pattern_create_rgba_l( lua_State* L ) { double red = luaL_checknumber( L, 1 ); double green = luaL_checknumber( L, 2 ); double blue = luaL_checknumber( L, 3 ); double alpha = luaL_checknumber( L, 4 ); lua_cairo_pattern_t* lcp = (lua_cairo_pattern_t*)lua_newuserdata( L, sizeof( lua_cairo_pattern_t ) ); memset( lcp, 0, sizeof( lua_cairo_pattern_t ) ); luaL_getmetatable( L, "lua_cairo_pattern_t" ); lua_setmetatable( L, -2 ); lcp->pattern = cairo_pattern_create_rgba( red, green, blue, alpha ); return( 1 ); }
/*********************************************** * ge_cairo_color_pattern - * * Create A Solid Color Pattern ***********************************************/ CairoPattern* ge_cairo_color_pattern(CairoColor *base) { CairoPattern * result = g_new0(CairoPattern, 1); result->scale = GE_DIRECTION_NONE; result->translate = GE_DIRECTION_NONE; result->handle = cairo_pattern_create_rgba(base->r, base->g, base->b, base->a); result->operator = CAIRO_OPERATOR_SOURCE; return result; }
bool NRStyle::prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox) { if (!stroke_pattern) { switch (stroke.type) { case PAINT_SERVER: { stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct.raw(), paintbox, stroke.opacity); } break; case PAINT_COLOR: { SPColor const &c = stroke.color; stroke_pattern = cairo_pattern_create_rgba( c.v.c[0], c.v.c[1], c.v.c[2], stroke.opacity); } break; default: break; } } if (!stroke_pattern) return false; return true; }
bool NRStyle::prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox) { if (!text_decoration_stroke_pattern) { switch (text_decoration_stroke.type) { case PAINT_SERVER: { text_decoration_stroke_pattern = text_decoration_stroke.server->pattern_new(dc.raw(), paintbox, text_decoration_stroke.opacity); } break; case PAINT_COLOR: { SPColor const &c = text_decoration_stroke.color; text_decoration_stroke_pattern = cairo_pattern_create_rgba( c.v.c[0], c.v.c[1], c.v.c[2], text_decoration_stroke.opacity); } break; default: break; } } if (!text_decoration_stroke_pattern) return false; return true; }
bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox) { // update fill pattern if (!fill_pattern) { switch (fill.type) { case PAINT_SERVER: { fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity); } break; case PAINT_COLOR: { SPColor const &c = fill.color; fill_pattern = cairo_pattern_create_rgba( c.v.c[0], c.v.c[1], c.v.c[2], fill.opacity); } break; default: break; } } if (!fill_pattern) return false; return true; }
/*********************************************** * ge_cairo_color_pattern - * * Create A Solid Color Pattern ***********************************************/ CairoPattern* ge_cairo_color_pattern(CairoColor *base) { CairoPattern * result = g_new0(CairoPattern, 1); #if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2))) result->type = CAIRO_PATTERN_TYPE_SOLID; #endif result->scale = GE_DIRECTION_NONE; result->translate = GE_DIRECTION_NONE; result->handle = cairo_pattern_create_rgba(base->r, base->g, base->b, base->a); result->operator = CAIRO_OPERATOR_SOURCE; return result; }
static cairo_status_t _cairo_default_context_set_source_rgba (void *abstract_cr, double red, double green, double blue, double alpha) { cairo_default_context_t *cr = abstract_cr; cairo_pattern_t *pattern; cairo_status_t status; if (_current_source_matches_solid (cr->gstate->source, red, green, blue, alpha)) return CAIRO_STATUS_SUCCESS; /* push the current pattern to the freed lists */ _cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black); pattern = cairo_pattern_create_rgba (red, green, blue, alpha); if (unlikely (pattern->status)) return pattern->status; status = _cairo_default_context_set_source (cr, pattern); cairo_pattern_destroy (pattern); return status; }
static cairo_pattern_t *mkbrush(uiDrawBrush *b) { cairo_pattern_t *pat; size_t i; switch (b->Type) { case uiDrawBrushTypeSolid: pat = cairo_pattern_create_rgba(b->R, b->G, b->B, b->A); break; case uiDrawBrushTypeLinearGradient: pat = cairo_pattern_create_linear(b->X0, b->Y0, b->X1, b->Y1); break; case uiDrawBrushTypeRadialGradient: // make the start circle radius 0 to make it a point pat = cairo_pattern_create_radial( b->X0, b->Y0, 0, b->X1, b->Y1, b->OuterRadius); break; // case uiDrawBrushTypeImage: } if (cairo_pattern_status(pat) != CAIRO_STATUS_SUCCESS) implbug("error creating pattern in mkbrush(): %s", cairo_status_to_string(cairo_pattern_status(pat))); switch (b->Type) { case uiDrawBrushTypeLinearGradient: case uiDrawBrushTypeRadialGradient: for (i = 0; i < b->NumStops; i++) cairo_pattern_add_color_stop_rgba(pat, b->Stops[i].Pos, b->Stops[i].R, b->Stops[i].G, b->Stops[i].B, b->Stops[i].A); } return pat; }
void QCairoPaintEngine::updatePen() { //qDebug()<<"updatePen: "<<cpen; //if (cdirtyflags&QPaintEngine::DirtyPen==QPaintEngine::DirtyPen) { double penwidth=0.01; if (cpen.widthF()!=0) penwidth=cpen.widthF(); cairo_set_line_width (cr, penwidth); cairo_line_cap_t cap = CAIRO_LINE_CAP_ROUND; switch (cpen.capStyle()) { case Qt::FlatCap: cap = CAIRO_LINE_CAP_BUTT; break; case Qt::SquareCap: cap = CAIRO_LINE_CAP_SQUARE; break; case Qt::RoundCap: cap = CAIRO_LINE_CAP_ROUND; break; default: break; } cairo_set_line_cap(cr, cap); cairo_line_join_t join = CAIRO_LINE_JOIN_ROUND; switch (cpen.joinStyle()) { case Qt::MiterJoin: case Qt::SvgMiterJoin: join = CAIRO_LINE_JOIN_MITER; break; case Qt::BevelJoin: join = CAIRO_LINE_JOIN_BEVEL; break; case Qt::RoundJoin: join = CAIRO_LINE_JOIN_ROUND; break; default: break; } cairo_set_line_join(cr, join); cairo_set_miter_limit(cr, cpen.miterLimit() * 2.0); QVector<qreal> dashes = cpen.dashPattern(); for (int i = 0; i < dashes.size(); i++) dashes[i] *= penwidth; cairo_set_dash(cr, dashes.data(), dashes.size(), 0); //qDebug()<<"set pen"<<cpen; //cairo_set_source_rgba (cr, cpen.color().redF(), cpen.color().greenF(), cpen.color().blueF(), cpen.color().alphaF()); if (penpattern) { releasePattern(penpattern); } penpattern=cairo_pattern_create_rgba(cpen.color().redF(), cpen.color().greenF(), cpen.color().blueF(), cpen.color().alphaF()); cairo_set_source(cr, penpattern); //} }
value lime_cairo_pattern_create_rgba (double r, double g, double b, double a) { cairo_pattern_t* pattern = cairo_pattern_create_rgba (r, g, b, a); return CFFIPointer (pattern, gc_cairo_pattern); }
double lime_cairo_pattern_create_rgba (double r, double g, double b, double a) { return (intptr_t)cairo_pattern_create_rgba (r, g, b, a); }
static VALUE cr_solid_pattern_initialize (int argc, VALUE *argv, VALUE self) { VALUE red, green, blue, alpha; int n; cairo_pattern_t *pattern; n = rb_scan_args (argc, argv, "13", &red, &green, &blue, &alpha); if (n == 1) { VALUE color = red; color = cr_color_parse (color); if (rb_cairo__is_kind_of (color, rb_cCairo_Color_Base)) red = rb_funcall (rb_funcall (color, id_to_rgb, 0), id_to_a, 0); } if (n == 1 && rb_cairo__is_kind_of (red, rb_cArray) && (RARRAY_LEN (red) == 3 || RARRAY_LEN (red) == 4)) { VALUE ary = red; n = RARRAY_LEN (ary); red = rb_ary_entry (ary, 0); green = rb_ary_entry (ary, 1); blue = rb_ary_entry (ary, 2); alpha = rb_ary_entry (ary, 3); } if (n == 3) { pattern = cairo_pattern_create_rgb (NUM2DBL (red), NUM2DBL (green), NUM2DBL (blue)); } else if (n == 4) { pattern = cairo_pattern_create_rgba (NUM2DBL (red), NUM2DBL (green), NUM2DBL (blue), NUM2DBL (alpha)); } else { VALUE inspected; inspected = rb_funcall (argc == 1 ? red : rb_ary_new4 (argc, argv), id_inspect, 0); rb_raise (rb_eArgError, "invalid argument: %s (expect " "(color_name), " "(color_hex_triplet), " "(Cairo::Color::RGB), " "(Cairo::Color::CMYK), " "(Cairo::Color::HSV), " "(red, green, blue), " "([red, green, blue]), " "(red, green, blue, alpha) or " "([red, green, blue, alpha])" ")", RVAL2CSTR (inspected)); } cr_pattern_check_status (pattern); DATA_PTR (self) = pattern; return Qnil; }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); cairo_status_t status; cairo_pattern_t *pat; /* Test pattern_get_rgba */ { double r, g, b, a; pat = cairo_pattern_create_rgba (0.2, 0.3, 0.4, 0.5); status = cairo_pattern_get_rgba (pat, &r, &g, &b, &a); CHECK_SUCCESS; if (!CAIRO_TEST_DOUBLE_EQUALS(r,0.2) || !CAIRO_TEST_DOUBLE_EQUALS(g,0.3) || !CAIRO_TEST_DOUBLE_EQUALS(b,0.4) || !CAIRO_TEST_DOUBLE_EQUALS(a,0.5)) { cairo_test_log (ctx, "Error: cairo_pattern_get_rgba returned unexepcted results: %g, %g, %g, %g\n", r, g, b, a); return CAIRO_TEST_FAILURE; } cairo_pattern_destroy (pat); } /* Test pattern_get_surface */ { cairo_surface_t *surf; pat = cairo_pattern_create_for_surface (cairo_get_target (cr)); status = cairo_pattern_get_surface (pat, &surf); CHECK_SUCCESS; if (surf != cairo_get_target (cr)) { cairo_test_log (ctx, "Error: cairo_pattern_get_resurface returned wrong surface\n"); return CAIRO_TEST_FAILURE; } cairo_pattern_destroy (pat); } /* Test get_color_stops & linear_get_points */ { int i; double x0, y0, x1, y1; double expected_values[15] = { 0.0, 0.2, 0.4, 0.2, 1.0, 0.5, 0.4, 0.5, 0.2, 0.5, 1.0, 0.2, 0.4, 0.5, 0.2 }; double new_buf[15]; pat = cairo_pattern_create_linear (1.0, 2.0, 3.0, 4.0); for (i = 0; i < 3; i++) { cairo_pattern_add_color_stop_rgba (pat, expected_values[i*5+0], expected_values[i*5+1], expected_values[i*5+2], expected_values[i*5+3], expected_values[i*5+4]); } status = cairo_pattern_get_linear_points (pat, &x0, &y0, &x1, &y1); CHECK_SUCCESS; if (!CAIRO_TEST_DOUBLE_EQUALS(x0,1.0) || !CAIRO_TEST_DOUBLE_EQUALS(y0,2.0) || !CAIRO_TEST_DOUBLE_EQUALS(x1,3.0) || !CAIRO_TEST_DOUBLE_EQUALS(y1,4.0)) return CAIRO_TEST_FAILURE; status = cairo_pattern_get_color_stop_count (pat, &i); CHECK_SUCCESS; if (i != 3) return CAIRO_TEST_FAILURE; for (i = 0; i < 3; i++) { status = cairo_pattern_get_color_stop_rgba (pat, i, &new_buf[i*5+0], &new_buf[i*5+1], &new_buf[i*5+2], &new_buf[i*5+3], &new_buf[i*5+4]); CHECK_SUCCESS; } status = cairo_pattern_get_color_stop_rgba (pat, 5, NULL, NULL, NULL, NULL, NULL); if (status != CAIRO_STATUS_INVALID_INDEX) return CAIRO_TEST_FAILURE; if (!double_buf_equal (ctx, new_buf, expected_values, sizeof(expected_values)/sizeof(double)) != 0) return CAIRO_TEST_FAILURE; cairo_pattern_destroy (pat); } /* Test radial_get_circles */ { double a, b, c, d, e, f; pat = cairo_pattern_create_radial (1, 2, 3, 4, 5, 6); status = cairo_pattern_get_radial_circles (pat, &a, &b, &c, &d, &e, &f); CHECK_SUCCESS; if (!CAIRO_TEST_DOUBLE_EQUALS(a,1.0) || !CAIRO_TEST_DOUBLE_EQUALS(b,2.0) || !CAIRO_TEST_DOUBLE_EQUALS(c,3.0) || !CAIRO_TEST_DOUBLE_EQUALS(d,4.0) || !CAIRO_TEST_DOUBLE_EQUALS(e,5.0) || !CAIRO_TEST_DOUBLE_EQUALS(f,6.0)) return CAIRO_TEST_FAILURE; cairo_pattern_destroy (pat); } cairo_set_source_rgb (cr, 0, 1, 0); cairo_paint (cr); return CAIRO_TEST_SUCCESS; }
///////////////////////////////////////////////////////////////////////////// // PatternSolid PatternSolid::PatternSolid( const ColorA &color ) : Pattern( cairo_pattern_create_rgba( color.r, color.g, color.b, color.a ) ) { }
/** * _st_create_shadow_cairo_pattern: * @shadow_spec: the definition of the shadow * @src_pattern: surface pattern for which we create the shadow * (must be a surface pattern) * * This is a utility function for creating shadows used by * st-theme-node.c; it's in this file to share the gaussian * blur implementation. The usage of this function is quite different * depending on whether shadow_spec->inset is %TRUE or not. If * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern * which is the <i>inverse</i> of what they want shadowed, and must take * care of the spread and offset from the shadow spec themselves. If * shadow_spec->inset is %FALSE then the caller should pass in what they * want shadowed directly, and this function takes care of the spread and * the offset. */ cairo_pattern_t * _st_create_shadow_cairo_pattern (StShadow *shadow_spec, cairo_pattern_t *src_pattern) { static cairo_user_data_key_t shadow_pattern_user_data; cairo_t *cr; cairo_surface_t *src_surface; cairo_surface_t *surface_in; cairo_surface_t *surface_out; cairo_pattern_t *dst_pattern; guchar *pixels_in, *pixels_out; gint width_in, height_in, rowstride_in; gint width_out, height_out, rowstride_out; cairo_matrix_t shadow_matrix; int i, j; g_return_val_if_fail (shadow_spec != NULL, NULL); g_return_val_if_fail (src_pattern != NULL, NULL); if (cairo_pattern_get_surface (src_pattern, &src_surface) != CAIRO_STATUS_SUCCESS) /* The most likely reason we can't get the pattern is that sizing went hairwire * and the caller tried to create a surface too big for memory, leaving us with * a pattern in an error state; we return a transparent pattern for the shadow. */ return cairo_pattern_create_rgba(1.0, 1.0, 1.0, 0.0); width_in = cairo_image_surface_get_width (src_surface); height_in = cairo_image_surface_get_height (src_surface); /* We want the output to be a color agnostic alpha mask, * so we need to strip the color channels from the input */ if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8) { surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8, width_in, height_in); cr = cairo_create (surface_in); cairo_set_source_surface (cr, src_surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); } else { surface_in = cairo_surface_reference (src_surface); } pixels_in = cairo_image_surface_get_data (surface_in); rowstride_in = cairo_image_surface_get_stride (surface_in); pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in, shadow_spec->blur, &width_out, &height_out, &rowstride_out); cairo_surface_destroy (surface_in); /* Invert pixels for inset shadows */ if (shadow_spec->inset) { for (j = 0; j < height_out; j++) { guchar *p = pixels_out + rowstride_out * j; for (i = 0; i < width_out; i++, p++) *p = ~*p; } } surface_out = cairo_image_surface_create_for_data (pixels_out, CAIRO_FORMAT_A8, width_out, height_out, rowstride_out); cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data, pixels_out, (cairo_destroy_func_t) g_free); dst_pattern = cairo_pattern_create_for_surface (surface_out); cairo_surface_destroy (surface_out); cairo_pattern_get_matrix (src_pattern, &shadow_matrix); if (shadow_spec->inset) { /* For inset shadows, offsets and spread radius have already been * applied to the original pattern, so all left to do is shift the * blurred image left, so that it aligns centered under the * unblurred one */ cairo_matrix_translate (&shadow_matrix, (width_out - width_in) / 2.0, (height_out - height_in) / 2.0); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; } /* Read all the code from the cairo_pattern_set_matrix call * at the end of this function to here from bottom to top, * because each new affine transformation is applied in * front of all the previous ones */ /* 6. Invert the matrix back */ cairo_matrix_invert (&shadow_matrix); /* 5. Adjust based on specified offsets */ cairo_matrix_translate (&shadow_matrix, shadow_spec->xoffset, shadow_spec->yoffset); /* 4. Recenter the newly scaled image */ cairo_matrix_translate (&shadow_matrix, - shadow_spec->spread, - shadow_spec->spread); /* 3. Scale up the blurred image to fill the spread */ cairo_matrix_scale (&shadow_matrix, (width_in + 2.0 * shadow_spec->spread) / width_in, (height_in + 2.0 * shadow_spec->spread) / height_in); /* 2. Shift the blurred image left, so that it aligns centered * under the unblurred one */ cairo_matrix_translate (&shadow_matrix, - (width_out - width_in) / 2.0, - (height_out - height_in) / 2.0); /* 1. Invert the matrix so we can work with it in pattern space */ cairo_matrix_invert (&shadow_matrix); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; }