60 |
|
|
61 |
static jmethodID areaPreparedID; |
static jmethodID areaPreparedID; |
62 |
static jmethodID areaUpdatedID; |
static jmethodID areaUpdatedID; |
63 |
|
static jmethodID dataOutputWriteID; |
64 |
|
static jmethodID registerFormatID; |
65 |
|
|
66 |
static void |
static void |
67 |
area_prepared (GdkPixbufLoader *loader, |
area_prepared (GdkPixbufLoader *loader, |
195 |
NSA_SET_PB_PTR (env, obj, loader); |
NSA_SET_PB_PTR (env, obj, loader); |
196 |
} |
} |
197 |
|
|
198 |
|
static void |
199 |
|
query_formats (JNIEnv *env, jclass clazz) |
200 |
|
{ |
201 |
|
jobject jformat; |
202 |
|
GSList *formats, *f; |
203 |
|
GdkPixbufFormat *format; |
204 |
|
char **ch, *name; |
205 |
|
|
206 |
|
jclass formatClass; |
207 |
|
jmethodID addExtensionID; |
208 |
|
jmethodID addMimeTypeID; |
209 |
|
|
210 |
|
formatClass = (*env)->FindClass |
211 |
|
(env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec"); |
212 |
|
|
213 |
|
g_assert(formatClass != NULL); |
214 |
|
|
215 |
|
addExtensionID = (*env)->GetMethodID (env, formatClass, |
216 |
|
"addExtension", |
217 |
|
"(Ljava/lang/String;)V"); |
218 |
|
|
219 |
|
addMimeTypeID = (*env)->GetMethodID (env, formatClass, |
220 |
|
"addMimeType", |
221 |
|
"(Ljava/lang/String;)V"); |
222 |
|
|
223 |
|
formats = gdk_pixbuf_get_formats (); |
224 |
|
|
225 |
|
for (f = formats; f; f = f->next) |
226 |
|
{ |
227 |
|
format = (GdkPixbufFormat *) f->data; |
228 |
|
name = gdk_pixbuf_format_get_name(format); |
229 |
|
|
230 |
|
jformat = (*env)->CallStaticObjectMethod |
231 |
|
(env, clazz, registerFormatID, |
232 |
|
(*env)->NewStringUTF(env, name), |
233 |
|
(jboolean) gdk_pixbuf_format_is_writable(format)); |
234 |
|
|
235 |
|
g_assert(jformat != NULL); |
236 |
|
|
237 |
|
ch = gdk_pixbuf_format_get_extensions(format); |
238 |
|
while (*ch) |
239 |
|
{ |
240 |
|
(*env)->CallVoidMethod (env, jformat, addExtensionID, |
241 |
|
(*env)->NewStringUTF(env, *ch)); |
242 |
|
++ch; |
243 |
|
} |
244 |
|
|
245 |
|
ch = gdk_pixbuf_format_get_mime_types(format); |
246 |
|
while (*ch) |
247 |
|
{ |
248 |
|
(*env)->CallVoidMethod (env, jformat, addMimeTypeID, |
249 |
|
(*env)->NewStringUTF(env, *ch)); |
250 |
|
++ch; |
251 |
|
} |
252 |
|
} |
253 |
|
|
254 |
|
g_slist_free(formats); |
255 |
|
} |
256 |
|
|
257 |
|
|
258 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
259 |
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState |
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState |
260 |
(JNIEnv *env, jclass clazz) |
(JNIEnv *env, jclass clazz) |
261 |
{ |
{ |
262 |
|
jclass dataOutputClass; |
263 |
|
|
264 |
(*env)->GetJavaVM(env, &vm); |
(*env)->GetJavaVM(env, &vm); |
265 |
|
|
266 |
areaPreparedID = (*env)->GetMethodID (env, clazz, |
areaPreparedID = (*env)->GetMethodID (env, clazz, |
270 |
areaUpdatedID = (*env)->GetMethodID (env, clazz, |
areaUpdatedID = (*env)->GetMethodID (env, clazz, |
271 |
"areaUpdated", |
"areaUpdated", |
272 |
"(IIII[II)V"); |
"(IIII[II)V"); |
273 |
|
|
274 |
|
registerFormatID = (*env)->GetStaticMethodID |
275 |
|
(env, clazz, |
276 |
|
"registerFormat", |
277 |
|
"(Ljava/lang/String;Z)" |
278 |
|
"Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;"); |
279 |
|
|
280 |
|
|
281 |
|
dataOutputClass = (*env)->FindClass(env, "java/io/DataOutput"); |
282 |
|
dataOutputWriteID = (*env)->GetMethodID (env, dataOutputClass, |
283 |
|
"write", "([B)V"); |
284 |
|
|
285 |
|
query_formats (env, clazz); |
286 |
|
|
287 |
NSA_PB_INIT (env, clazz); |
NSA_PB_INIT (env, clazz); |
288 |
} |
} |
289 |
|
|
304 |
gdk_threads_leave (); |
gdk_threads_leave (); |
305 |
} |
} |
306 |
|
|
307 |
|
struct stream_save_request |
308 |
|
{ |
309 |
|
JNIEnv *env; |
310 |
|
jobject *stream; |
311 |
|
}; |
312 |
|
|
313 |
|
static gboolean |
314 |
|
save_to_stream(const gchar *buf, |
315 |
|
gsize count, |
316 |
|
GError **error __attribute__((unused)), |
317 |
|
gpointer data) |
318 |
|
{ |
319 |
|
struct stream_save_request *ssr = (struct stream_save_request *)data; |
320 |
|
|
321 |
|
jbyteArray jbuf; |
322 |
|
jbyte *cbuf; |
323 |
|
|
324 |
|
gdk_threads_leave (); |
325 |
|
jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count); |
326 |
|
cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL); |
327 |
|
memcpy (cbuf, buf, count); |
328 |
|
(*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0); |
329 |
|
(*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->stream), |
330 |
|
dataOutputWriteID, jbuf); |
331 |
|
gdk_threads_enter (); |
332 |
|
return TRUE; |
333 |
|
} |
334 |
|
|
335 |
|
|
336 |
|
JNIEXPORT void JNICALL |
337 |
|
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage |
338 |
|
(JNIEnv *env, jclass clazz __attribute__((unused)), |
339 |
|
jintArray jarr, jstring jenctype, jint width, jint height, |
340 |
|
jboolean hasAlpha, jobject stream) |
341 |
|
{ |
342 |
|
GdkPixbuf* pixbuf; |
343 |
|
jint *ints; |
344 |
|
guchar a, r, g, b, *pix, *p; |
345 |
|
GError *err = NULL; |
346 |
|
const char *enctype; |
347 |
|
int i; |
348 |
|
|
349 |
|
struct stream_save_request ssr; |
350 |
|
ssr.stream = &stream; |
351 |
|
ssr.env = env; |
352 |
|
|
353 |
|
ints = (*env)->GetIntArrayElements (env, jarr, NULL); |
354 |
|
pix = g_malloc(width * height * (hasAlpha ? 4 : 3)); |
355 |
|
|
356 |
|
enctype = (*env)->GetStringUTFChars (env, jenctype, NULL); |
357 |
|
g_assert(enctype != NULL); |
358 |
|
|
359 |
|
g_assert (pix != NULL); |
360 |
|
g_assert (ints != NULL); |
361 |
|
|
362 |
|
p = pix; |
363 |
|
for (i = 0; i < width*height; ++i) |
364 |
|
{ |
365 |
|
/* |
366 |
|
* Java encodes pixels as integers in a predictable arithmetic order: |
367 |
|
* 0xAARRGGBB. Since these are jints, JNI has already byte-swapped |
368 |
|
* them for us if necessary, so they're in "our" endianness, whatever |
369 |
|
* that is. It uses 4 bytes per pixel whether or not there's an alpha |
370 |
|
* channel. |
371 |
|
*/ |
372 |
|
|
373 |
|
a = 0xff & (ints[i] >> 24); |
374 |
|
r = 0xff & (ints[i] >> 16); |
375 |
|
g = 0xff & (ints[i] >> 8); |
376 |
|
b = 0xff & ints[i]; |
377 |
|
|
378 |
|
/* |
379 |
|
* GDK-pixbuf has a very different storage model: |
380 |
|
* |
381 |
|
* - A different alpha order (alpha after colors). |
382 |
|
* - A different packing model (no alpha -> 3-bytes-per-pixel). |
383 |
|
* - A different "RGB" order (host memory order, not endian-neutral). |
384 |
|
*/ |
385 |
|
|
386 |
|
*p++ = r; |
387 |
|
*p++ = g; |
388 |
|
*p++ = b; |
389 |
|
if (hasAlpha) |
390 |
|
*p++ = a; |
391 |
|
} |
392 |
|
|
393 |
|
gdk_threads_enter (); |
394 |
|
pixbuf = gdk_pixbuf_new_from_data (pix, |
395 |
|
GDK_COLORSPACE_RGB, |
396 |
|
(gboolean) hasAlpha, |
397 |
|
8, width, height, |
398 |
|
width * (hasAlpha ? 4 : 3), /* rowstride */ |
399 |
|
NULL, NULL); |
400 |
|
g_assert (pixbuf != NULL); |
401 |
|
|
402 |
|
g_assert(gdk_pixbuf_save_to_callback (pixbuf, |
403 |
|
&save_to_stream, |
404 |
|
&ssr, |
405 |
|
enctype, |
406 |
|
&err, NULL)); |
407 |
|
|
408 |
|
g_object_unref (pixbuf); |
409 |
|
|
410 |
|
gdk_threads_leave (); |
411 |
|
g_free(pix); |
412 |
|
|
413 |
|
(*env)->ReleaseStringUTFChars (env, jenctype, enctype); |
414 |
|
(*env)->ReleaseIntArrayElements (env, jarr, ints, 0); |
415 |
|
} |
416 |
|
|
417 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
418 |
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes |
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes |