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;
}
Esempio n. 2
0
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 ();
}