static cairo_pattern_t * transition_pattern (cairo_pattern_t *start, cairo_pattern_t *end, double progress) { double sx0, sy0, sx1, sy1, sr0, sr1, ex0, ey0, ex1, ey1, er0, er1; cairo_pattern_t *result; int i, n; progress = CLAMP (progress, 0.0, 1.0); if (end == NULL) return fade_pattern (start, 1.0 - progress); g_assert (cairo_pattern_get_type (start) == cairo_pattern_get_type (end)); switch (cairo_pattern_get_type (start)) { case CAIRO_PATTERN_TYPE_LINEAR: cairo_pattern_get_linear_points (start, &sx0, &sy0, &sx1, &sy1); cairo_pattern_get_linear_points (end, &ex0, &ey0, &ex1, &ey1); result = cairo_pattern_create_linear ((1 - progress) * sx0 + progress * ex0, (1 - progress) * sx1 + progress * ex1, (1 - progress) * sy0 + progress * ey0, (1 - progress) * sy1 + progress * ey1); break; case CAIRO_PATTERN_TYPE_RADIAL: cairo_pattern_get_radial_circles (start, &sx0, &sy0, &sr0, &sx1, &sy1, &sr1); cairo_pattern_get_radial_circles (end, &ex0, &ey0, &er0, &ex1, &ey1, &er1); result = cairo_pattern_create_radial ((1 - progress) * sx0 + progress * ex0, (1 - progress) * sy0 + progress * ey0, (1 - progress) * sr0 + progress * er0, (1 - progress) * sx1 + progress * ex1, (1 - progress) * sy1 + progress * ey1, (1 - progress) * sr1 + progress * er1); break; default: g_return_val_if_reached (NULL); } cairo_pattern_get_color_stop_count (start, &n); for (i = 0; i < n; i++) { double so, sr, sg, sb, sa, eo, er, eg, eb, ea; cairo_pattern_get_color_stop_rgba (start, i, &so, &sr, &sg, &sb, &sa); cairo_pattern_get_color_stop_rgba (end, i, &eo, &er, &eg, &eb, &ea); cairo_pattern_add_color_stop_rgba (result, (1 - progress) * so + progress * eo, (1 - progress) * sr + progress * er, (1 - progress) * sg + progress * eg, (1 - progress) * sb + progress * eb, (1 - progress) * sa + progress * ea); } return result; }
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 cairo_pattern_t * fade_pattern (cairo_pattern_t *pattern, double opacity) { double x0, y0, x1, y1, r0, r1; cairo_pattern_t *result; int i, n; switch (cairo_pattern_get_type (pattern)) { case CAIRO_PATTERN_TYPE_LINEAR: cairo_pattern_get_linear_points (pattern, &x0, &y0, &x1, &y1); result = cairo_pattern_create_linear (x0, y0, x1, y1); break; case CAIRO_PATTERN_TYPE_RADIAL: cairo_pattern_get_radial_circles (pattern, &x0, &y0, &r0, &x1, &y1, &r1); result = cairo_pattern_create_radial (x0, y0, r0, x1, y1, r1); break; default: g_return_val_if_reached (NULL); } cairo_pattern_get_color_stop_count (pattern, &n); for (i = 0; i < n; i++) { double o, r, g, b, a; cairo_pattern_get_color_stop_rgba (pattern, i, &o, &r, &g, &b, &a); cairo_pattern_add_color_stop_rgba (result, o, r, g, b, a * opacity); } return result; }
static cairo_int_status_t _prevent_overlapping_drawing (cairo_gl_context_t *ctx, cairo_gl_composite_t *setup, cairo_composite_rectangles_t *composite, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm) { cairo_rectangle_int_t stroke_extents; const cairo_pattern_t *pattern = composite->original_source_pattern; cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern); if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) return CAIRO_INT_STATUS_UNSUPPORTED; /* XXX: improve me - since we have lazy init, we cannot use sample area */ if (type == CAIRO_PATTERN_TYPE_SOLID && _cairo_pattern_is_opaque_solid (pattern)) return CAIRO_INT_STATUS_SUCCESS; if (glIsEnabled (GL_STENCIL_TEST) == FALSE) { /* In case we have pending operations we have to flush before adding the stencil buffer. */ _cairo_gl_composite_flush (ctx); /* Enable the stencil buffer, even if we are not using it for clipping, so we can use it below to prevent overlapping shapes. We initialize it all to one here which represents infinite clip. */ if (! ctx->states_cache.depth_mask) { glDepthMask (GL_TRUE); ctx->states_cache.depth_mask = TRUE; } glEnable (GL_STENCIL_TEST); /* If we don't have clip, then we will setup clip extents based on approximate stroke extent. */ if (! setup->clip) { _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &stroke_extents); _cairo_gl_scissor_to_extents (setup->dst, &stroke_extents); } glClearStencil (1); glClear (GL_STENCIL_BUFFER_BIT); glStencilFunc (GL_EQUAL, 1, 1); } /* This means that once we draw to a particular pixel nothing else can be drawn there until the stencil buffer is reset or the stencil test is disabled. */ glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO); /* we need to clean up clip cache */ _cairo_clip_destroy (ctx->clip); ctx->clip = NULL; return CAIRO_INT_STATUS_SUCCESS; }
static inline cairo_bool_t _cairo_composite_rectangles_check_lazy_init (cairo_composite_rectangles_t *extents, cairo_surface_t *surface, const cairo_pattern_t *pattern) { cairo_pattern_type_t type; if (! extents->is_bounded) return FALSE; type = cairo_pattern_get_type ((cairo_pattern_t *)pattern); if (type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; cairo_surface_t *pattern_surface = pattern_surface = surface_pattern->surface; /* XXX: both source and target are GL surface */ if (cairo_surface_get_type (pattern_surface) == CAIRO_SURFACE_TYPE_GL && pattern_surface->backend->type == CAIRO_SURFACE_TYPE_GL && cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_GL && surface->device == pattern_surface->device) return TRUE; } else if (type == CAIRO_PATTERN_TYPE_SOLID || type == CAIRO_PATTERN_TYPE_RADIAL || type == CAIRO_PATTERN_TYPE_LINEAR) return TRUE; return FALSE; }
static void pattern_value_print (const GValue *value, GString *string) { cairo_pattern_t *pattern; cairo_surface_t *surface; pattern = g_value_get_boxed (value); if (pattern == NULL) { g_string_append (string, "none"); return; } switch (cairo_pattern_get_type (pattern)) { case CAIRO_PATTERN_TYPE_SURFACE: if (cairo_pattern_get_surface (pattern, &surface) != CAIRO_STATUS_SUCCESS) { g_assert_not_reached (); } surface_print (surface, string); break; case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: g_string_append (string, "none /* FIXME: add support for printing gradients */"); break; case CAIRO_PATTERN_TYPE_SOLID: default: g_assert_not_reached (); break; } }
static void bg(GtkStyleContext* sc, wxColour& color, int state = GTK_STATE_FLAG_NORMAL) { GdkRGBA* rgba; cairo_pattern_t* pattern = NULL; gtk_style_context_set_state(sc, GtkStateFlags(state)); gtk_style_context_get(sc, GtkStateFlags(state), "background-color", &rgba, "background-image", &pattern, NULL); color = wxColour(*rgba); gdk_rgba_free(rgba); // "background-image" takes precedence over "background-color". // If there is an image, try to get a color out of it. if (pattern) { if (cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t* surf; cairo_pattern_get_surface(pattern, &surf); if (cairo_surface_get_type(surf) == CAIRO_SURFACE_TYPE_IMAGE) { const guchar* data = cairo_image_surface_get_data(surf); const int stride = cairo_image_surface_get_stride(surf); // choose a pixel in the middle vertically, // images often have a vertical gradient const int i = stride * (cairo_image_surface_get_height(surf) / 2); const unsigned* p = reinterpret_cast<const unsigned*>(data + i); const unsigned pixel = *p; guchar r, g, b, a = 0xff; switch (cairo_image_surface_get_format(surf)) { case CAIRO_FORMAT_ARGB32: a = guchar(pixel >> 24); // fallthrough case CAIRO_FORMAT_RGB24: r = guchar(pixel >> 16); g = guchar(pixel >> 8); b = guchar(pixel); break; default: a = 0; break; } if (a != 0) { if (a != 0xff) { // un-premultiply r = guchar((r * 0xff) / a); g = guchar((g * 0xff) / a); b = guchar((b * 0xff) / a); } color.Set(r, g, b, a); } } } cairo_pattern_destroy(pattern); }
static void releasePattern(cairo_pattern_t *pat) { if (!pat) return; if (cairo_pattern_get_type(pat) == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t *surface; cairo_pattern_get_surface(pat, &surface); cairo_surface_destroy(surface); } cairo_pattern_destroy(pat); }
/** * gjs_cairo_pattern_from_pattern: * @context: the context * @pattern: cairo_pattern to attach to the object * * Constructs a pattern wrapper given cairo pattern. * A reference to @pattern will be taken. * */ JSObject * gjs_cairo_pattern_from_pattern(JSContext *context, cairo_pattern_t *pattern) { g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(pattern != NULL, NULL); switch (cairo_pattern_get_type(pattern)) { case CAIRO_PATTERN_TYPE_SOLID: return gjs_cairo_solid_pattern_from_pattern(context, pattern); case CAIRO_PATTERN_TYPE_SURFACE: return gjs_cairo_surface_pattern_from_pattern(context, pattern); case CAIRO_PATTERN_TYPE_LINEAR: return gjs_cairo_linear_gradient_from_pattern(context, pattern); case CAIRO_PATTERN_TYPE_RADIAL: return gjs_cairo_radial_gradient_from_pattern(context, pattern); default: break; } gjs_throw(context, "failed to create pattern, unsupported pattern type %d", cairo_pattern_get_type(pattern)); return NULL; }
static gboolean gtk_css_image_gradient_draw_circle (GtkCssImageGradient *image, cairo_t *cr, double width, double height) { cairo_pattern_t *pattern = image->pattern; double x0, y0, x1, y1, r0, r1; GdkRGBA color0, color1; double offset0, offset1; int n_stops; if (cairo_pattern_get_type (pattern) != CAIRO_PATTERN_TYPE_RADIAL) return FALSE; if (cairo_pattern_get_extend (pattern) != CAIRO_EXTEND_PAD) return FALSE; cairo_pattern_get_radial_circles (pattern, &x0, &y0, &r0, &x1, &y1, &r1); if (x0 != x1 || y0 != y1 || r0 != 0.0) return FALSE; cairo_pattern_get_color_stop_count (pattern, &n_stops); if (n_stops != 2) return FALSE; cairo_pattern_get_color_stop_rgba (pattern, 0, &offset0, &color0.red, &color0.green, &color0.blue, &color0.alpha); cairo_pattern_get_color_stop_rgba (pattern, 1, &offset1, &color1.red, &color1.green, &color1.blue, &color1.alpha); if (offset0 != offset1) return FALSE; cairo_scale (cr, width, height); cairo_rectangle (cr, 0, 0, 1, 1); cairo_clip (cr); gdk_cairo_set_source_rgba (cr, &color1); cairo_paint (cr); gdk_cairo_set_source_rgba (cr, &color0); cairo_arc (cr, x1, y1, r1 * offset1, 0, 2 * G_PI); cairo_fill (cr); return TRUE; }
JSObject * gjs_cairo_surface_pattern_from_pattern(JSContext *context, cairo_pattern_t *pattern) { JSObject *object; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(pattern != NULL, NULL); g_return_val_if_fail(cairo_pattern_get_type(pattern) == CAIRO_PATTERN_TYPE_SURFACE, NULL); object = JS_NewObject(context, &gjs_cairo_surface_pattern_class, NULL, NULL); if (!object) { gjs_throw(context, "failed to create surface pattern"); return NULL; } gjs_cairo_pattern_construct(context, object, pattern); return object; }
/* PycairoPattern_FromPattern * Create a new * PycairoSolidPattern, * PycairoSurfacePattern, * PycairoLinearGradient, or * PycairoRadialGradient from a cairo_pattern_t. * pattern - a cairo_pattern_t to 'wrap' into a Python object. * It is unreferenced if the PycairoPattern creation fails, or if the * pattern has an error status. * base - the base object used to create the pattern, or NULL. * It is referenced to keep it alive while the cairo_pattern_t is being used. * For PycairoSurfacePattern base should be the PycairoSurface, for other # patterns it should be NULL. * Return value: New reference or NULL on failure */ PyObject * PycairoPattern_FromPattern (cairo_pattern_t *pattern, PyObject *base) { PyTypeObject *type = NULL; PyObject *o; assert (pattern != NULL); if (Pycairo_Check_Status (cairo_pattern_status (pattern))) { cairo_pattern_destroy (pattern); return NULL; } switch (cairo_pattern_get_type (pattern)) { case CAIRO_PATTERN_TYPE_SOLID: type = &PycairoSolidPattern_Type; break; case CAIRO_PATTERN_TYPE_SURFACE: type = &PycairoSurfacePattern_Type; break; case CAIRO_PATTERN_TYPE_LINEAR: type = &PycairoLinearGradient_Type; break; case CAIRO_PATTERN_TYPE_RADIAL: type = &PycairoRadialGradient_Type; break; default: type = &PycairoPattern_Type; break; } o = type->tp_alloc(type, 0); if (o == NULL) { cairo_pattern_destroy (pattern); } else { ((PycairoPattern *)o)->pattern = pattern; Py_XINCREF(base); ((PycairoPattern *)o)->base = base; } return o; }
/* PycairoPattern_FromPattern * Create a new * PycairoSolidPattern, * PycairoSurfacePattern, * PycairoLinearGradient, or * PycairoRadialGradient from a cairo_pattern_t. * pattern - a cairo_pattern_t to 'wrap' into a Python object. * it is unreferenced if the PycairoPattern creation fails, or if the * pattern has an error status. * Return value: New reference or NULL on failure */ PyObject * PycairoPattern_FromPattern (cairo_pattern_t *pattern) { PyTypeObject *type = NULL; PyObject *o; assert (pattern != NULL); if (Pycairo_Check_Status (cairo_pattern_status (pattern))) { cairo_pattern_destroy (pattern); return NULL; } switch (cairo_pattern_get_type (pattern)) { case CAIRO_PATTERN_TYPE_SOLID: type = &PycairoSolidPattern_Type; break; case CAIRO_PATTERN_TYPE_SURFACE: type = &PycairoSurfacePattern_Type; break; case CAIRO_PATTERN_TYPE_LINEAR: type = &PycairoLinearGradient_Type; break; case CAIRO_PATTERN_TYPE_RADIAL: type = &PycairoRadialGradient_Type; break; default: PyErr_SetString(CairoError, "Unsupported Pattern type"); return NULL; } o = type->tp_alloc(type, 0); if (o == NULL) cairo_pattern_destroy (pattern); else ((PycairoPattern *)o)->pattern = pattern; return o; }
static JSBool getType_func(JSContext *context, unsigned argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(context, vp); cairo_pattern_t *pattern; cairo_pattern_type_t type; if (argc > 1) { gjs_throw(context, "Pattern.getType() takes no arguments"); return JS_FALSE; } pattern = gjs_cairo_pattern_get_pattern(context, obj); type = cairo_pattern_get_type(pattern); if (!gjs_cairo_check_status(context, cairo_pattern_status(pattern), "pattern")) return JS_FALSE; JS_SET_RVAL(context, vp, INT_TO_JSVAL(type)); return JS_TRUE; }
static void _gl_pattern_fix_reference_count (const cairo_pattern_t *pattern) { cairo_pattern_type_t pattern_type = cairo_pattern_get_type ((cairo_pattern_t *)pattern); /* We need to increase reference count on surface and gradient if the original_source_pattern is a cairo_gl_source_t type. */ if (pattern_type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)pattern; cairo_surface_t *pattern_surface = surface_pattern->surface; if (cairo_surface_get_type (pattern_surface) == CAIRO_SURFACE_TYPE_GL && ! pattern_surface->device && ! _cairo_surface_is_subsurface (pattern_surface)) { cairo_gl_source_t *_source = (cairo_gl_source_t *)pattern_surface; switch (_source->operand.type) { case CAIRO_GL_OPERAND_TEXTURE: cairo_surface_reference (&(_source->operand.texture.owns_surface)->base); break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: _cairo_gl_gradient_reference (_source->operand.gradient.gradient); break; default: case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: case CAIRO_GL_OPERAND_COUNT: break; } } } }
static VALUE cr_pattern_get_klass (cairo_pattern_t *pattern) { VALUE klass; cairo_pattern_type_t type; type = cairo_pattern_get_type (pattern); switch (type) { case CAIRO_PATTERN_TYPE_SOLID: klass = rb_cCairo_SolidPattern; break; case CAIRO_PATTERN_TYPE_SURFACE: klass = rb_cCairo_SurfacePattern; break; case CAIRO_PATTERN_TYPE_LINEAR: klass = rb_cCairo_LinearPattern; break; case CAIRO_PATTERN_TYPE_RADIAL: klass = rb_cCairo_RadialPattern; break; #if CAIRO_CHECK_VERSION(1, 11, 4) case CAIRO_PATTERN_TYPE_MESH: klass = rb_cCairo_MeshPattern; break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: klass = rb_cCairo_RasterSourcePattern; break; #endif default: rb_raise (rb_eArgError, "unknown pattern type: %d", type); break; } return klass; }
JNIEXPORT jint JNICALL Java_org_jclutter_cairo_CairoPattern_getType(JNIEnv *env, jobject obj){ return (jint)cairo_pattern_get_type(); }
static void _gtk_pixel_cache_create_surface_if_needed (GtkPixelCache *cache, GdkWindow *window, cairo_rectangle_int_t *view_rect, cairo_rectangle_int_t *canvas_rect) { cairo_rectangle_int_t rect; int surface_w, surface_h; cairo_content_t content; cairo_pattern_t *bg; double red, green, blue, alpha; content = CAIRO_CONTENT_COLOR_ALPHA; bg = gdk_window_get_background_pattern (window); if (bg != NULL && cairo_pattern_get_type (bg) == CAIRO_PATTERN_TYPE_SOLID && cairo_pattern_get_rgba (bg, &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS && alpha == 1.0) content = CAIRO_CONTENT_COLOR; surface_w = view_rect->width; if (canvas_rect->width > surface_w) surface_w = MIN (surface_w + EXTRA_SIZE, canvas_rect->width); surface_h = view_rect->height; if (canvas_rect->height > surface_h) surface_h = MIN (surface_h + EXTRA_SIZE, canvas_rect->height); /* If current surface can't fit view_rect or is too large, kill it */ if (cache->surface != NULL && (cairo_surface_get_content (cache->surface) != content || cache->surface_w < view_rect->width || cache->surface_w > surface_w + ALLOW_LARGER_SIZE || cache->surface_h < view_rect->height || cache->surface_h > surface_h + ALLOW_LARGER_SIZE || cache->surface_scale != gdk_window_get_scale_factor (window))) { cairo_surface_destroy (cache->surface); cache->surface = NULL; if (cache->surface_dirty) cairo_region_destroy (cache->surface_dirty); cache->surface_dirty = NULL; } /* Don't allocate a surface if view >= canvas, as we won't be scrolling then anyway */ if (cache->surface == NULL && (view_rect->width < canvas_rect->width || view_rect->height < canvas_rect->height)) { cache->surface_x = -canvas_rect->x; cache->surface_y = -canvas_rect->y; cache->surface_w = surface_w; cache->surface_h = surface_h; cache->surface_scale = gdk_window_get_scale_factor (window); cache->surface = gdk_window_create_similar_surface (window, content, surface_w, surface_h); rect.x = 0; rect.y = 0; rect.width = surface_w; rect.height = surface_h; cache->surface_dirty = cairo_region_create_rectangle (&rect); } }
/* * Implements * org.freedesktop.cairo.Plumbing.createPattern(long pointer) */ JNIEXPORT jobject JNICALL Java_org_freedesktop_cairo_Plumbing_createPattern ( JNIEnv* env, jclass cls, jlong _pointer ) { cairo_pattern_t* pattern; jclass found; static jclass SolidPattern = NULL; static jclass SurfacePattern = NULL; static jclass LinearPattern = NULL; static jclass RadialPattern = NULL; jclass type; jmethodID constructor; jobject proxy; // convert pointer pattern = (cairo_pattern_t*) _pointer; // increment reference count cairo_pattern_reference(pattern); // now figure out Proxy class and create switch (cairo_pattern_get_type(pattern)) { case CAIRO_PATTERN_TYPE_SOLID: if (SolidPattern == NULL) { found = (*env)->FindClass(env, "org/freedesktop/cairo/SolidPattern"); SolidPattern = (*env)->NewGlobalRef(env, found); } type = SolidPattern; break; case CAIRO_PATTERN_TYPE_SURFACE: if (SurfacePattern == NULL) { found = (*env)->FindClass(env, "org/freedesktop/cairo/SurfacePattern"); SurfacePattern = (*env)->NewGlobalRef(env, found); } type = SurfacePattern; break; case CAIRO_PATTERN_TYPE_LINEAR: if (LinearPattern == NULL) { found = (*env)->FindClass(env, "org/freedesktop/cairo/LinearPattern"); LinearPattern = (*env)->NewGlobalRef(env, found); } type = LinearPattern; break; case CAIRO_PATTERN_TYPE_RADIAL: if (RadialPattern == NULL) { found = (*env)->FindClass(env, "org/freedesktop/cairo/RadialPattern"); RadialPattern = (*env)->NewGlobalRef(env, found); } type = RadialPattern; break; default: g_critical("Unimplemented pattern type"); return NULL; } if (type == NULL) { bindings_java_throw(env, "FindClass() failed"); return NULL; } constructor = (*env)->GetMethodID(env, type, "<init>", "(J)V"); if (constructor == NULL) { g_error("Constructor methodID not found"); return NULL; } proxy = (*env)->NewObject(env, type, constructor, _pointer); return proxy; }