JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePixels (JNIEnv *env, jobject obj) { struct graphics2d *gr = NULL; jintArray java_pixels; jint* native_pixels; GdkPixbuf *buf = NULL; gint width, height; gint bits_per_sample = 8; gboolean has_alpha = TRUE; gint total_channels = 4; jint i; gdk_threads_enter(); if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return NULL; } gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("getImagePixels\n"); gdk_drawable_get_size (gr->drawable, &width, &height); buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, bits_per_sample, width, height); g_assert (buf != NULL); g_assert (gdk_pixbuf_get_bits_per_sample (buf) == bits_per_sample); g_assert (gdk_pixbuf_get_n_channels (buf) == total_channels); /* copy pixels from drawable to pixbuf */ gdk_pixbuf_get_from_drawable (buf, gr->drawable, NULL, 0, 0, 0, 0, width, height); native_pixels= gdk_pixbuf_get_pixels (buf); #ifndef WORDS_BIGENDIAN /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ for (i=0; i<width * height; i++) { native_pixels[i] = SWAPU32 ((unsigned)native_pixels[i]); } #endif java_pixels = (*env) -> NewIntArray (env, width * height); (*env)->SetIntArrayRegion(env, java_pixels, (jsize)0, (jsize) width*height, (jint*) native_pixels); gdk_threads_leave(); return java_pixels; }
int __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, __nl_catd catalog) { int fd = -1; struct stat64 st; int swapping; size_t cnt; size_t max_offset; size_t tab_size; const char *lastp; int result = -1; char *buf = NULL; if (strchr (cat_name, '/') != NULL || nlspath == NULL) fd = open_not_cancel_2 (cat_name, O_RDONLY); else { const char *run_nlspath = nlspath; #define ENOUGH(n) \ if (__glibc_unlikely (bufact + (n) >= bufmax)) \ { \ char *old_buf = buf; \ bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \ buf = realloc (buf, bufmax); \ if (__glibc_unlikely (buf == NULL)) \ { \ free (old_buf); \ return -1; \ } \ } /* The RUN_NLSPATH variable contains a colon separated list of descriptions where we expect to find catalogs. We have to recognize certain % substitutions and stop when we found the first existing file. */ size_t bufact; size_t bufmax = 0; size_t len; fd = -1; while (*run_nlspath != '\0') { bufact = 0; if (*run_nlspath == ':') { /* Leading colon or adjacent colons - treat same as %N. */ len = strlen (cat_name); ENOUGH (len); memcpy (&buf[bufact], cat_name, len); bufact += len; } else while (*run_nlspath != ':' && *run_nlspath != '\0') if (*run_nlspath == '%') { const char *tmp; ++run_nlspath; /* We have seen the `%'. */ switch (*run_nlspath++) { case 'N': /* Use the catalog name. */ len = strlen (cat_name); ENOUGH (len); memcpy (&buf[bufact], cat_name, len); bufact += len; break; case 'L': /* Use the current locale category value. */ len = strlen (env_var); ENOUGH (len); memcpy (&buf[bufact], env_var, len); bufact += len; break; case 'l': /* Use language element of locale category value. */ tmp = env_var; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); break; case 't': /* Use territory element of locale category value. */ tmp = env_var; do ++tmp; while (*tmp != '\0' && *tmp != '_' && *tmp != '.'); if (*tmp == '_') { ++tmp; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0' && *tmp != '.'); } break; case 'c': /* Use code set element of locale category value. */ tmp = env_var; do ++tmp; while (*tmp != '\0' && *tmp != '.'); if (*tmp == '.') { ++tmp; do { ENOUGH (1); buf[bufact++] = *tmp++; } while (*tmp != '\0'); } break; case '%': ENOUGH (1); buf[bufact++] = '%'; break; default: /* Unknown variable: ignore this path element. */ bufact = 0; while (*run_nlspath != '\0' && *run_nlspath != ':') ++run_nlspath; break; } } else { ENOUGH (1); buf[bufact++] = *run_nlspath++; } ENOUGH (1); buf[bufact] = '\0'; if (bufact != 0) { fd = open_not_cancel_2 (buf, O_RDONLY); if (fd >= 0) break; } ++run_nlspath; } } /* Avoid dealing with directories and block devices */ if (__builtin_expect (fd, 0) < 0) { free (buf); return -1; } if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0) goto close_unlock_return; if (__builtin_expect (!S_ISREG (st.st_mode), 0) || (size_t) st.st_size < sizeof (struct catalog_obj)) { /* `errno' is not set correctly but the file is not usable. Use an reasonable error value. */ __set_errno (EINVAL); goto close_unlock_return; } catalog->file_size = st.st_size; #ifdef _POSIX_MAPPED_FILES # ifndef MAP_COPY /* Linux seems to lack read-only copy-on-write. */ # define MAP_COPY MAP_PRIVATE # endif # ifndef MAP_FILE /* Some systems do not have this flag; it is superfluous. */ # define MAP_FILE 0 # endif catalog->file_ptr = (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ, MAP_FILE|MAP_COPY, fd, 0); if (__builtin_expect (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED, 1)) /* Tell the world we managed to mmap the file. */ catalog->status = mmapped; else #endif /* _POSIX_MAPPED_FILES */ { /* mmap failed perhaps because the system call is not implemented. Try to load the file. */ size_t todo; catalog->file_ptr = malloc (st.st_size); if (catalog->file_ptr == NULL) goto close_unlock_return; todo = st.st_size; /* Save read, handle partial reads. */ do { size_t now = read_not_cancel (fd, (((char *) catalog->file_ptr) + (st.st_size - todo)), todo); if (now == 0 || now == (size_t) -1) { #ifdef EINTR if (now == (size_t) -1 && errno == EINTR) continue; #endif free ((void *) catalog->file_ptr); goto close_unlock_return; } todo -= now; } while (todo > 0); catalog->status = malloced; } /* Determine whether the file is a catalog file and if yes whether it is written using the correct byte order. Else we have to swap the values. */ if (__glibc_likely (catalog->file_ptr->magic == CATGETS_MAGIC)) swapping = 0; else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC)) swapping = 1; else { invalid_file: /* Invalid file. Free the resources and mark catalog as not usable. */ #ifdef _POSIX_MAPPED_FILES if (catalog->status == mmapped) __munmap ((void *) catalog->file_ptr, catalog->file_size); else #endif /* _POSIX_MAPPED_FILES */ free (catalog->file_ptr); goto close_unlock_return; } #define SWAP(x) (swapping ? SWAPU32 (x) : (x)) /* Get dimensions of the used hashing table. */ catalog->plane_size = SWAP (catalog->file_ptr->plane_size); catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth); /* The file contains two versions of the pointer tables. Pick the right one for the local byte order. */ #if __BYTE_ORDER == __LITTLE_ENDIAN catalog->name_ptr = &catalog->file_ptr->name_ptr[0]; #elif __BYTE_ORDER == __BIG_ENDIAN catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3]; #else # error Cannot handle __BYTE_ORDER byte order #endif /* The rest of the file contains all the strings. They are addressed relative to the position of the first string. */ catalog->strings = (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3 * 2]; /* Determine the largest string offset mentioned in the table. */ max_offset = 0; tab_size = 3 * catalog->plane_size * catalog->plane_depth; for (cnt = 2; cnt < tab_size; cnt += 3) if (catalog->name_ptr[cnt] > max_offset) max_offset = catalog->name_ptr[cnt]; /* Now we can check whether the file is large enough to contain the tables it says it contains. */ if ((size_t) st.st_size <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset)) /* The last string is not contained in the file. */ goto invalid_file; lastp = catalog->strings + max_offset; max_offset = (st.st_size - sizeof (struct catalog_obj) + 2 * tab_size + max_offset); while (*lastp != '\0') { if (--max_offset == 0) goto invalid_file; ++lastp; } /* We succeeded. */ result = 0; /* Release the lock again. */ close_unlock_return: close_not_cancel_no_status (fd); free (buf); return result; }
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkImagePainter_drawPixels (JNIEnv *env, jobject obj __attribute__((unused)), jobject gc_obj, jint bg_red, jint bg_green, jint bg_blue, jint x, jint y, jint width, jint height, jintArray jpixels, jint offset, jint scansize, jdoubleArray jaffine) { struct graphics *g; jint *pixels, *elems; guchar *packed; int i; jsize num_pixels; guchar *j_rgba, *c_rgb; g = (struct graphics *) NSA_GET_PTR (env, gc_obj); if (!jpixels) return; elems = (*env)->GetIntArrayElements (env, jpixels, NULL); num_pixels = (*env)->GetArrayLength (env, jpixels); /* get a copy of the pixel data so we can modify it */ pixels = malloc (sizeof (jint) * num_pixels); memcpy (pixels, elems, sizeof (jint) * num_pixels); (*env)->ReleaseIntArrayElements (env, jpixels, elems, 0); #ifndef WORDS_BIGENDIAN /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ for (i = 0; i < num_pixels; i++) pixels[i] = SWAPU32 ((unsigned)pixels[i]); #endif packed = (guchar *) malloc (sizeof (guchar) * 3 * num_pixels); j_rgba = (guchar *) pixels; c_rgb = packed; /* copy over pixels in DirectColorModel format to 24 bit RGB image data, and process the alpha channel */ for (i = 0; i < num_pixels; i++) { jint ialpha = *j_rgba++; switch (ialpha) { case 0: /* full transparency */ *c_rgb++ = bg_red; *c_rgb++ = bg_green; *c_rgb++ = bg_blue; j_rgba += 3; break; case 255: /* opaque */ *c_rgb++ = *j_rgba++; *c_rgb++ = *j_rgba++; *c_rgb++ = *j_rgba++; break; default: /* compositing required */ { jfloat alpha = ialpha / 255.0; jfloat comp_alpha = 1.0 - alpha; *c_rgb++ = *j_rgba++ * alpha + bg_red * comp_alpha; *c_rgb++ = *j_rgba++ * alpha + bg_green * comp_alpha; *c_rgb++ = *j_rgba++ * alpha + bg_blue * comp_alpha; } break; } } if (jaffine) { jdouble *affine; ArtAlphaGamma *alphagamma = NULL; art_u8 *dst; int new_width, new_height; affine = (*env)->GetDoubleArrayElements (env, jaffine, NULL); new_width = abs (width * affine[0]); new_height = abs (height * affine[3]); dst = (art_u8 *) malloc (sizeof (art_u8) * 3 * (new_width * new_height)); art_rgb_affine (dst, 0, 0, new_width, new_height, new_width * 3, (art_u8 *) packed + offset * 3, width, height, scansize * 3, affine, ART_FILTER_NEAREST, alphagamma); (*env)->ReleaseDoubleArrayElements (env, jaffine, affine, JNI_ABORT); free (packed); packed = (guchar *) dst; width = scansize = new_width; height = new_height; offset = 0; } gdk_threads_enter (); if (!g || !GDK_IS_DRAWABLE (g->drawable)) { gdk_threads_leave (); return; } gdk_draw_rgb_image (g->drawable, g->gc, x + g->x_offset, y + g->y_offset, width, height, GDK_RGB_DITHER_NORMAL, packed + offset * 3, scansize * 3); gdk_threads_leave (); free (pixels); free (packed); }
static void area_updated_cb (GdkPixbufLoader *loader, gint x, gint y, gint width, gint height, jobject *decoder) { JNIEnv *env; union env_union e; jint stride_bytes, stride_pixels, n_channels, n_pixels; jintArray jpixels; jint *java_pixels; guchar *gdk_pixels; GdkPixbuf *pixbuf_no_alpha = NULL; GdkPixbuf *pixbuf = NULL; #ifndef WORDS_BIGENDIAN int i; #endif pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf_no_alpha == NULL) return; pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0); g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); stride_bytes = gdk_pixbuf_get_rowstride (pixbuf); n_channels = gdk_pixbuf_get_n_channels (pixbuf); stride_pixels = stride_bytes / n_channels; n_pixels = height * stride_pixels; gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); e.jni_env = &env; (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1); jpixels = (*env)->NewIntArray (env, n_pixels); java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL); memcpy (java_pixels, gdk_pixels + (y * stride_bytes), (height * stride_bytes)); #ifndef WORDS_BIGENDIAN /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ for (i = 0; i < n_pixels; ++i) { java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]); } #endif g_object_unref (pixbuf); (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0); (*env)->CallVoidMethod (env, *decoder, areaUpdatedID, (jint) x, (jint) y, (jint) width, (jint) height, jpixels, stride_pixels); (*env)->DeleteLocalRef(env, jpixels); }
static void area_updated (GdkPixbufLoader *loader, gint x, gint y, gint width, gint height, struct loader_vector *lv) { ArtPixBuf *pixbuf; jintArray jpixels; jint *pixels, scansize, num_pixels; /* pixbuf = gdk_pixbuf_loader_get_pixbuf (loader)->art_pixbuf; g_return_if_fail (pixbuf->format == ART_PIX_RGB); g_return_if_fail (pixbuf->bits_per_sample == 8); g_return_if_fail (pixbuf->n_channels == 3 + (pixbuf->has_alpha != 0)); scansize = pixbuf->rowstride / pixbuf->n_channels; num_pixels = height * scansize; jpixels = (*gdk_env)->NewIntArray (gdk_env, num_pixels); pixels = (*gdk_env)->GetIntArrayElements (gdk_env, jpixels, NULL); if (pixbuf->has_alpha) { memcpy (pixels, pixbuf->pixels + (y * pixbuf->rowstride + (x << 2)), height * pixbuf->rowstride); } else // add in alpha data { int i; art_u8 *src, *dest; src = pixbuf->pixels + (y * pixbuf->rowstride + x * 3); dest = (art_u8 *) pixels; for (i = 0; i < num_pixels; i++) { *dest++ = *src++; //red *dest++ = *src++; // green *dest++ = *src++; // blue *dest++ = 0xff; // alpha } } */ gdk_threads_leave (); #ifndef WORDS_BIGENDIAN { int i; for (i = 0; i < num_pixels; i++) pixels[i] = SWAPU32 ((unsigned)pixels[i]); } #endif (*gdk_env)->ReleaseIntArrayElements (gdk_env, jpixels, pixels, 0); (*gdk_env)->CallVoidMethod (gdk_env, *(lv->loader), areaUpdatedID, *(lv->vector), (jint) x, (jint) y, (jint) width, (jint) height, jpixels, scansize); gdk_threads_enter (); }