1 /* Page interface */
2 
3 JNIEXPORT void JNICALL
FUN(Page_finalize)4 FUN(Page_finalize)(JNIEnv *env, jobject self)
5 {
6 	fz_context *ctx = get_context(env);
7 	fz_page *page = from_Page_safe(env, self);
8 	if (!ctx || !page) return;
9 	(*env)->SetLongField(env, self, fid_Page_pointer, 0);
10 	fz_drop_page(ctx, page);
11 }
12 
13 JNIEXPORT jobject JNICALL
FUN(Page_toPixmap)14 FUN(Page_toPixmap)(JNIEnv *env, jobject self, jobject jctm, jobject jcs, jboolean alpha, jboolean showExtra)
15 {
16 	fz_context *ctx = get_context(env);
17 	fz_page *page = from_Page(env, self);
18 	fz_colorspace *cs = from_ColorSpace(env, jcs);
19 	fz_matrix ctm = from_Matrix(env, jctm);
20 	fz_pixmap *pixmap = NULL;
21 
22 	if (!ctx || !page) return NULL;
23 
24 	fz_try(ctx)
25 	{
26 		if (showExtra)
27 			pixmap = fz_new_pixmap_from_page(ctx, page, ctm, cs, alpha);
28 		else
29 			pixmap = fz_new_pixmap_from_page_contents(ctx, page, ctm, cs, alpha);
30 	}
31 	fz_catch(ctx)
32 		jni_rethrow(env, ctx);
33 
34 	return to_Pixmap_safe_own(ctx, env, pixmap);
35 }
36 
37 JNIEXPORT jobject JNICALL
FUN(Page_getBounds)38 FUN(Page_getBounds)(JNIEnv *env, jobject self)
39 {
40 	fz_context *ctx = get_context(env);
41 	fz_page *page = from_Page(env, self);
42 	fz_rect rect;
43 
44 	if (!ctx || !page) return NULL;
45 
46 	fz_try(ctx)
47 		rect = fz_bound_page(ctx, page);
48 	fz_catch(ctx)
49 		jni_rethrow(env, ctx);
50 
51 	return to_Rect_safe(ctx, env, rect);
52 }
53 
54 JNIEXPORT void JNICALL
FUN(Page_run)55 FUN(Page_run)(JNIEnv *env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
56 {
57 	fz_context *ctx = get_context(env);
58 	fz_page *page = from_Page(env, self);
59 	fz_device *dev = from_Device(env, jdev);
60 	fz_matrix ctm = from_Matrix(env, jctm);
61 	fz_cookie *cookie = from_Cookie(env, jcookie);
62 	NativeDeviceInfo *info;
63 	int err;
64 
65 	if (!ctx || !page) return;
66 	if (!dev) jni_throw_arg_void(env, "device must not be null");
67 
68 	info = lockNativeDevice(env, jdev, &err);
69 	if (err)
70 		return;
71 	fz_try(ctx)
72 		fz_run_page(ctx, page, dev, ctm, cookie);
73 	fz_always(ctx)
74 		unlockNativeDevice(env, info);
75 	fz_catch(ctx)
76 		jni_rethrow_void(env, ctx);
77 }
78 
79 JNIEXPORT void JNICALL
FUN(Page_runPageContents)80 FUN(Page_runPageContents)(JNIEnv *env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
81 {
82 	fz_context *ctx = get_context(env);
83 	fz_page *page = from_Page(env, self);
84 	fz_device *dev = from_Device(env, jdev);
85 	fz_matrix ctm = from_Matrix(env, jctm);
86 	fz_cookie *cookie = from_Cookie(env, jcookie);
87 	NativeDeviceInfo *info;
88 	int err;
89 
90 	if (!ctx || !page) return;
91 	if (!dev) jni_throw_arg_void(env, "device must not be null");
92 
93 	info = lockNativeDevice(env, jdev, &err);
94 	if (err)
95 		return;
96 	fz_try(ctx)
97 		fz_run_page_contents(ctx, page, dev, ctm, cookie);
98 	fz_always(ctx)
99 		unlockNativeDevice(env, info);
100 	fz_catch(ctx)
101 		jni_rethrow_void(env, ctx);
102 }
103 
104 JNIEXPORT void JNICALL
FUN(Page_runPageAnnots)105 FUN(Page_runPageAnnots)(JNIEnv *env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
106 {
107 	fz_context *ctx = get_context(env);
108 	fz_page *page = from_Page(env, self);
109 	fz_device *dev = from_Device(env, jdev);
110 	fz_matrix ctm = from_Matrix(env, jctm);
111 	fz_cookie *cookie = from_Cookie(env, jcookie);
112 	NativeDeviceInfo *info;
113 	int err;
114 
115 	if (!ctx || !page) return;
116 	if (!dev) jni_throw_arg_void(env, "device must not be null");
117 
118 	info = lockNativeDevice(env, jdev, &err);
119 	if (err)
120 		return;
121 	fz_try(ctx)
122 		fz_run_page_annots(ctx, page, dev, ctm, cookie);
123 	fz_always(ctx)
124 		unlockNativeDevice(env, info);
125 	fz_catch(ctx)
126 		jni_rethrow_void(env, ctx);
127 }
128 
129 JNIEXPORT void JNICALL
FUN(Page_runPageWidgets)130 FUN(Page_runPageWidgets)(JNIEnv *env, jobject self, jobject jdev, jobject jctm, jobject jcookie)
131 {
132 	fz_context *ctx = get_context(env);
133 	fz_page *page = from_Page(env, self);
134 	fz_device *dev = from_Device(env, jdev);
135 	fz_matrix ctm = from_Matrix(env, jctm);
136 	fz_cookie *cookie = from_Cookie(env, jcookie);
137 	NativeDeviceInfo *info;
138 	int err;
139 
140 	if (!ctx || !page) return;
141 	if (!dev) jni_throw_arg_void(env, "device must not be null");
142 
143 	info = lockNativeDevice(env, jdev, &err);
144 	if (err)
145 		return;
146 	fz_try(ctx)
147 		fz_run_page_widgets(ctx, page, dev, ctm, cookie);
148 	fz_always(ctx)
149 		unlockNativeDevice(env, info);
150 	fz_catch(ctx)
151 		jni_rethrow_void(env, ctx);
152 }
153 
154 JNIEXPORT jobject JNICALL
FUN(Page_getLinks)155 FUN(Page_getLinks)(JNIEnv *env, jobject self)
156 {
157 	fz_context *ctx = get_context(env);
158 	fz_page *page = from_Page(env, self);
159 	fz_link *link = NULL;
160 	fz_link *links = NULL;
161 	jobject jlinks = NULL;
162 	int link_count;
163 	int i;
164 
165 	if (!ctx || !page) return NULL;
166 
167 	fz_var(links);
168 
169 	fz_try(ctx)
170 		links = fz_load_links(ctx, page);
171 	fz_catch(ctx)
172 	{
173 		fz_drop_link(ctx, links);
174 		jni_rethrow(env, ctx);
175 	}
176 
177 	/* count the links */
178 	link = links;
179 	for (link_count = 0; link; link_count++)
180 		link = link->next;
181 
182 	/* no links, return NULL instead of empty array */
183 	if (link_count == 0)
184 	{
185 		fz_drop_link(ctx, links);
186 		return NULL;
187 	}
188 
189 	/* now run through actually creating the link objects */
190 	jlinks = (*env)->NewObjectArray(env, link_count, cls_Link, NULL);
191 	if (!jlinks || (*env)->ExceptionCheck(env))
192 	{
193 		fz_drop_link(ctx, links);
194 		return NULL;
195 	}
196 
197 	link = links;
198 	for (i = 0; link && i < link_count; i++)
199 	{
200 		jobject jbounds = NULL;
201 		jobject jlink = NULL;
202 		jobject juri = NULL;
203 
204 		jbounds = to_Rect_safe(ctx, env, link->rect);
205 		if (!jbounds || (*env)->ExceptionCheck(env))
206 		{
207 			fz_drop_link(ctx, links);
208 			return NULL;
209 		}
210 
211 		juri = (*env)->NewStringUTF(env, link->uri);
212 		if (!juri || (*env)->ExceptionCheck(env))
213 		{
214 			fz_drop_link(ctx, links);
215 			return NULL;
216 		}
217 
218 		jlink = (*env)->NewObject(env, cls_Link, mid_Link_init, jbounds, juri);
219 		if (!jlink || (*env)->ExceptionCheck(env))
220 		{
221 			fz_drop_link(ctx, links);
222 			return NULL;
223 		}
224 		(*env)->DeleteLocalRef(env, juri);
225 		(*env)->DeleteLocalRef(env, jbounds);
226 
227 		(*env)->SetObjectArrayElement(env, jlinks, i, jlink);
228 		if ((*env)->ExceptionCheck(env))
229 		{
230 			fz_drop_link(ctx, links);
231 			return NULL;
232 		}
233 
234 		(*env)->DeleteLocalRef(env, jlink);
235 		link = link->next;
236 	}
237 
238 	fz_drop_link(ctx, links);
239 
240 	return jlinks;
241 }
242 
243 JNIEXPORT jobject JNICALL
FUN(Page_search)244 FUN(Page_search)(JNIEnv *env, jobject self, jstring jneedle)
245 {
246 	fz_context *ctx = get_context(env);
247 	fz_page *page = from_Page(env, self);
248 	fz_quad hits[256];
249 	const char *needle = NULL;
250 	int n = 0;
251 
252 	if (!ctx || !page) return NULL;
253 	if (!jneedle) jni_throw_arg(env, "needle must not be null");
254 
255 	needle = (*env)->GetStringUTFChars(env, jneedle, NULL);
256 	if (!needle) return 0;
257 
258 	fz_try(ctx)
259 		n = fz_search_page(ctx, page, needle, hits, nelem(hits));
260 	fz_always(ctx)
261 		(*env)->ReleaseStringUTFChars(env, jneedle, needle);
262 	fz_catch(ctx)
263 		jni_rethrow(env, ctx);
264 
265 	return to_QuadArray_safe(ctx, env, hits, n);
266 }
267 
268 JNIEXPORT jobject JNICALL
FUN(Page_toDisplayList)269 FUN(Page_toDisplayList)(JNIEnv *env, jobject self, jboolean showExtra)
270 {
271 	fz_context *ctx = get_context(env);
272 	fz_page *page = from_Page(env, self);
273 	fz_display_list *list = NULL;
274 
275 	if (!ctx || !page) return NULL;
276 
277 	fz_try(ctx)
278 		if (showExtra)
279 			list = fz_new_display_list_from_page(ctx, page);
280 		else
281 			list = fz_new_display_list_from_page_contents(ctx, page);
282 	fz_catch(ctx)
283 		jni_rethrow(env, ctx);
284 
285 	return to_DisplayList_safe_own(ctx, env, list);
286 }
287 
288 JNIEXPORT jobject JNICALL
FUN(Page_toStructuredText)289 FUN(Page_toStructuredText)(JNIEnv *env, jobject self, jstring joptions)
290 {
291 	fz_context *ctx = get_context(env);
292 	fz_page *page = from_Page(env, self);
293 	fz_stext_page *text = NULL;
294 	const char *options= NULL;
295 	fz_stext_options opts;
296 
297 	if (!ctx || !page) return NULL;
298 
299 	if (joptions)
300 	{
301 		options = (*env)->GetStringUTFChars(env, joptions, NULL);
302 		if (!options) return NULL;
303 	}
304 
305 	fz_try(ctx)
306 	{
307 		fz_parse_stext_options(ctx, &opts, options);
308 		text = fz_new_stext_page_from_page(ctx, page, &opts);
309 	}
310 	fz_always(ctx)
311 	{
312 		if (options)
313 			(*env)->ReleaseStringUTFChars(env, joptions, options);
314 	}
315 	fz_catch(ctx)
316 		jni_rethrow(env, ctx);
317 
318 	return to_StructuredText_safe_own(ctx, env, text);
319 }
320 
321 JNIEXPORT jbyteArray JNICALL
FUN(Page_textAsHtml)322 FUN(Page_textAsHtml)(JNIEnv *env, jobject self)
323 {
324 	fz_context *ctx = get_context(env);
325 	fz_page *page = from_Page(env, self);
326 	fz_stext_page *text = NULL;
327 	fz_device *dev = NULL;
328 	fz_matrix ctm;
329 	jbyteArray arr = NULL;
330 	fz_buffer *buf = NULL;
331 	fz_output *out = NULL;
332 	unsigned char *data;
333 	size_t len;
334 
335 	if (!ctx || !page) return NULL;
336 
337 	fz_var(text);
338 	fz_var(dev);
339 	fz_var(buf);
340 	fz_var(out);
341 
342 	fz_try(ctx)
343 	{
344 		ctm = fz_identity;
345 		text = fz_new_stext_page(ctx, fz_bound_page(ctx, page));
346 		dev = fz_new_stext_device(ctx, text, NULL);
347 		fz_run_page(ctx, page, dev, ctm, NULL);
348 		fz_close_device(ctx, dev);
349 
350 		buf = fz_new_buffer(ctx, 256);
351 		out = fz_new_output_with_buffer(ctx, buf);
352 		fz_print_stext_header_as_html(ctx, out);
353 		fz_print_stext_page_as_html(ctx, out, text, page->number);
354 		fz_print_stext_trailer_as_html(ctx, out);
355 		fz_close_output(ctx, out);
356 
357 		len = fz_buffer_storage(ctx, buf, &data);
358 		arr = (*env)->NewByteArray(env, (jsize)len);
359 		if ((*env)->ExceptionCheck(env))
360 			fz_throw_java(ctx, env);
361 		if (!arr)
362 			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot create byte array");
363 
364 		(*env)->SetByteArrayRegion(env, arr, 0, (jsize)len, (jbyte *)data);
365 		if ((*env)->ExceptionCheck(env))
366 			fz_throw_java(ctx, env);
367 	}
368 	fz_always(ctx)
369 	{
370 		fz_drop_output(ctx, out);
371 		fz_drop_buffer(ctx, buf);
372 		fz_drop_device(ctx, dev);
373 		fz_drop_stext_page(ctx, text);
374 	}
375 	fz_catch(ctx)
376 		jni_rethrow(env, ctx);
377 
378 	return arr;
379 }
380