1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * deepzoomimagetilesource.cpp
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007,2009 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
22 #include "deepzoomimagetilesource.h"
23 #include "multiscalesubimage.h"
25 #include "file-downloader.h"
34 DisplayRect (long minLevel
, long maxLevel
)
70 DeepZoomImageTileSource
*source
;
76 long image_width
, image_height
;
77 DisplayRect
*current_rect
;
80 //Collection attributes
82 SubImage
*current_subimage
;
96 image_width
= image_height
= tile_size
= overlap
= 0;
100 current_subimage
= NULL
;
105 void start_element (void *data
, const char *el
, const char **attr
);
106 void end_element (void *data
, const char *el
);
109 get_tile_layer (int level
, int x
, int y
, Uri
*uri
, void *userdata
)
111 return ((DeepZoomImageTileSource
*)userdata
)->GetTileLayer (level
, x
, y
, uri
);
115 DeepZoomImageTileSource::Init ()
117 SetObjectType (Type::DEEPZOOMIMAGETILESOURCE
);
122 get_tile_func
= get_tile_layer
;
123 display_rects
= NULL
;
124 parsed_callback
= NULL
;
125 failed_callback
= NULL
;
126 sourcechanged_callback
= NULL
;
127 isCollection
= false;
130 get_resource_aborter
= NULL
;
134 DeepZoomImageTileSource::DeepZoomImageTileSource ()
139 DeepZoomImageTileSource::DeepZoomImageTileSource (Uri
*uri
, bool nested
)
142 this->nested
= nested
;
147 DeepZoomImageTileSource::~DeepZoomImageTileSource ()
151 delete get_resource_aborter
;
155 DeepZoomImageTileSource::Abort ()
157 if (get_resource_aborter
)
158 get_resource_aborter
->Cancel ();
160 XML_ParserFree (parser
);
165 DeepZoomImageTileSource::GetTileLayer (int level
, int x
, int y
, Uri
*uri
)
167 //check if there tile is listed in DisplayRects
174 frexp ((double) MAX (GetImageWidth (), GetImageHeight ()), &layers
);
176 while ((cur
= (DisplayRect
*)g_list_nth_data (display_rects
, i
))) {
179 if (!(cur
->min_level
<= level
&& level
<= cur
->max_level
))
182 int vtilesize
= GetTileWidth () * (layers
+ 1 - level
);
183 Rect virtualtile
= Rect (x
* vtilesize
, y
* vtilesize
, vtilesize
, vtilesize
);
184 if (cur
->rect
.IntersectsWith (virtualtile
)) {
194 const Uri
*baseUri
= GetValue (DeepZoomImageTileSource::UriSourceProperty
)->AsUri ();
195 const char *filename
, *ext
;
201 if ((filename
= strrchr (baseUri
->path
, '/')))
204 filename
= baseUri
->path
;
206 if (!(ext
= strrchr (filename
, '.')))
209 image
= g_strdup_printf ("%.*s_files/%d/%d_%d.%s", (int) (ext
- filename
), filename
, level
, x
, y
, format
);
211 Uri::Copy (baseUri
, uri
);
212 uri
->Combine (image
);
219 resource_notify (NotifyType type
, gint64 args
, gpointer user_data
)
221 DeepZoomImageTileSource
*dzits
= (DeepZoomImageTileSource
*)user_data
;
222 if (type
== NotifyFailed
)
223 dzits
->DownloaderFailed ();
224 else if (type
== NotifyCompleted
)
225 dzits
->DownloaderComplete ();
229 dz_write (void *buffer
, gint32 offset
, gint32 n
, gpointer data
)
231 DeepZoomImageTileSource
*dzits
= (DeepZoomImageTileSource
*) data
;
232 dzits
->XmlWrite ((char *) buffer
, offset
, n
);
236 DeepZoomImageTileSource::XmlWrite (char* buffer
, gint32 offset
, gint32 n
)
240 LOG_MSI ("Start parsing DeepZoom\n");
241 parser
= XML_ParserCreate (NULL
);
242 XML_SetElementHandler (parser
, start_element
, end_element
);
243 DZParserinfo
*info
= new DZParserinfo ();
245 XML_SetUserData (parser
, info
);
248 if (!XML_Parse (parser
, buffer
, n
, 0)) {
249 printf ("Parser error at line %d:\n%s\n", (int)XML_GetCurrentLineNumber (parser
), XML_ErrorString(XML_GetErrorCode(parser
)));
256 DeepZoomImageTileSource::Download ()
258 LOG_MSI ("DZITS::Download ()\n");
262 Application
*current
= Application::GetCurrent ();
263 Uri
*uri
= GetUriSource ();
265 if (current
&& uri
) {
267 if (get_resource_aborter
)
268 delete get_resource_aborter
;
269 get_resource_aborter
= new Cancellable ();
270 current
->GetResource (GetResourceBase(), uri
, resource_notify
, dz_write
, MediaPolicy
, get_resource_aborter
, this);
275 DeepZoomImageTileSource::DownloaderComplete ()
277 //set isFinal for the parser to complete
278 if (!XML_Parse (parser
, NULL
, 0, 1)) {
279 printf ("Parser error at line %d:\n%s\n", (int)XML_GetCurrentLineNumber (parser
), XML_ErrorString(XML_GetErrorCode(parser
)));
285 DZParserinfo
*info
= (DZParserinfo
*)XML_GetUserData (parser
);
287 if (!info
->isCollection
) {
288 SetImageWidth (info
->image_width
);
289 SetImageHeight (info
->image_height
);
290 SetTileOverlap (info
->overlap
);
291 display_rects
= info
->display_rects
;
293 subimages
= info
->sub_images
;
294 isCollection
= info
->isCollection
;
295 maxLevel
= info
->max_level
;
298 SetTileWidth (info
->tile_size
);
299 SetTileHeight (info
->tile_size
);
300 format
= g_strdup (info
->format
);
304 LOG_MSI ("Done parsing...\n");
306 XML_ParserFree (parser
);
310 parsed_callback (cb_userdata
);
314 DeepZoomImageTileSource::DownloaderFailed ()
316 LOG_MSI ("DZITS::dl failed\n");
318 failed_callback (cb_userdata
);
322 DeepZoomImageTileSource::UriSourceChanged ()
330 if (sourcechanged_callback
)
331 sourcechanged_callback (cb_userdata
);
335 DeepZoomImageTileSource::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
337 if (args
->GetId () == DeepZoomImageTileSource::UriSourceProperty
) {
342 if (args
->GetProperty ()->GetOwnerType () != Type::DEEPZOOMIMAGETILESOURCE
) {
343 DependencyObject::OnPropertyChanged (args
, error
);
347 NotifyListenersOfPropertyChange (args
, error
);
352 start_element (void *data
, const char *el
, const char **attr
)
354 DZParserinfo
*info
= (DZParserinfo
*)data
;
356 if (info
->skip
>= 0) {
360 switch (info
->depth
) {
362 //Image or Collection
363 if (!g_ascii_strcasecmp ("Image", el
)) {
364 info
->isCollection
= false;
366 for (i
= 0; attr
[i
]; i
+=2)
367 if (!g_ascii_strcasecmp ("Format", attr
[i
]))
368 info
->format
= g_strdup (attr
[i
+1]);
369 else if (!g_ascii_strcasecmp ("TileSize", attr
[i
]))
370 info
->tile_size
= atoi (attr
[i
+1]);
371 else if (!g_ascii_strcasecmp ("Overlap", attr
[i
]))
372 info
->overlap
= atoi (attr
[i
+1]);
374 LOG_MSI ("\tunparsed attr %s: %s\n", attr
[i
], attr
[i
+1]);
375 } else if (!g_ascii_strcasecmp ("Collection", el
)) {
376 info
->isCollection
= true;
378 for (i
= 0; attr
[i
]; i
+=2)
379 if (!g_ascii_strcasecmp ("Format", attr
[i
]))
380 info
->format
= g_strdup (attr
[i
+1]);
381 else if (!g_ascii_strcasecmp ("TileSize", attr
[i
]))
382 info
->tile_size
= atoi (attr
[i
+1]);
383 else if (!g_ascii_strcasecmp ("MaxLevel", attr
[i
]))
384 info
->max_level
= atoi (attr
[i
+1]);
386 LOG_MSI ("\tunparsed attr %s: %s\n", attr
[i
], attr
[i
+1]);
388 printf ("Unexpected element %s\n", el
);
393 if (!info
->isCollection
) {
394 //Size or DisplayRects
395 if (!g_ascii_strcasecmp ("Size", el
)) {
397 for (i
= 0; attr
[i
]; i
+=2)
398 if (!g_ascii_strcasecmp ("Width", attr
[i
]))
399 info
->image_width
= atol (attr
[i
+1]);
400 else if (!g_ascii_strcasecmp ("Height", attr
[i
]))
401 info
->image_height
= atol (attr
[i
+1]);
403 LOG_MSI ("\tunparsed attr %s: %s\n", attr
[i
], attr
[i
+1]);
404 } else if (!g_ascii_strcasecmp ("DisplayRects", el
)) {
405 //no attributes, only contains DisplayRect element
407 printf ("Unexpected element %s\n", el
);
411 if (!g_ascii_strcasecmp ("Items", el
)) {
412 //no attributes, only contains <I> elements
414 printf ("Unexpected element %d %s\n", info
->depth
, el
);
420 if (!info
->isCollection
) {
422 if (!g_ascii_strcasecmp ("DisplayRect", el
)) {
423 long min_level
= 0, max_level
= 0;
425 for (i
= 0; attr
[i
]; i
+=2)
426 if (!g_ascii_strcasecmp ("MinLevel", attr
[i
]))
427 min_level
= atol (attr
[i
+1]);
428 else if (!g_ascii_strcasecmp ("MaxLevel", attr
[i
]))
429 max_level
= atol (attr
[i
+1]);
431 LOG_MSI ("\tunparsed arg %s: %s\n", attr
[i
], attr
[i
+1]);
432 info
->current_rect
= new DisplayRect (min_level
, max_level
);
434 printf ("Unexpected element %s\n", el
);
438 if (!g_ascii_strcasecmp ("I", el
)) {
439 info
->current_subimage
= new SubImage ();
441 for (i
= 0; attr
[i
]; i
+=2)
442 if (!g_ascii_strcasecmp ("N", attr
[i
]))
443 info
->current_subimage
->n
= atoi (attr
[i
+1]);
444 else if (!g_ascii_strcasecmp ("Id", attr
[i
]))
445 info
->current_subimage
->id
= atoi (attr
[i
+1]);
446 else if (!g_ascii_strcasecmp ("Source", attr
[i
])) {
447 info
->current_subimage
->source
= new Uri ();
448 info
->current_subimage
->source
->Parse (attr
[i
+1]);
450 LOG_MSI ("\tunparsed arg %s: %s\n", attr
[i
], attr
[i
+1]);
453 printf ("Unexpected element %d %s\n", info
->depth
, el
);
459 if (!info
->isCollection
) {
461 if (!g_ascii_strcasecmp ("Rect", el
)) {
462 if (!info
->current_rect
) {
467 for (i
= 0; attr
[i
]; i
+=2)
468 if (!g_ascii_strcasecmp ("X", attr
[i
]))
469 info
->current_rect
->rect
.x
= (double)atol (attr
[i
+1]);
470 else if (!g_ascii_strcasecmp ("Y", attr
[i
]))
471 info
->current_rect
->rect
.y
= (double)atol (attr
[i
+1]);
472 else if (!g_ascii_strcasecmp ("Width", attr
[i
]))
473 info
->current_rect
->rect
.width
= (double)atol (attr
[i
+1]);
474 else if (!g_ascii_strcasecmp ("Height", attr
[i
]))
475 info
->current_rect
->rect
.height
= (double)atol (attr
[i
+1]);
477 LOG_MSI ("\tunparsed attr %s: %s\n", attr
[i
], attr
[i
+1]);
478 info
->display_rects
= g_list_append (info
->display_rects
, info
->current_rect
);
479 info
->current_rect
= NULL
;
481 printf ("Unexpected element %s\n", el
);
485 if (!g_ascii_strcasecmp ("Size", el
)) {
486 if (!info
->current_subimage
) {
491 info
->current_subimage
->has_size
= true;
494 for (i
= 0; attr
[i
]; i
+=2)
495 if (!g_ascii_strcasecmp ("Width", attr
[i
]))
496 info
->current_subimage
->width
= atol (attr
[i
+1]);
497 else if (!g_ascii_strcasecmp ("Height", attr
[i
]))
498 info
->current_subimage
->height
= atol (attr
[i
+1]);
500 LOG_MSI ("\tunparsed attr %s.%s: %s\n", el
, attr
[i
], attr
[i
+1]);
501 } else if (!g_ascii_strcasecmp ("Viewport", el
)) {
502 if (!info
->current_subimage
) {
507 info
->current_subimage
->has_viewport
= true;
510 for (i
= 0; attr
[i
]; i
+=2)
511 if (!g_ascii_strcasecmp ("X", attr
[i
]))
512 info
->current_subimage
->vp_x
= g_ascii_strtod (attr
[i
+1], NULL
);
513 else if (!g_ascii_strcasecmp ("Y", attr
[i
]))
514 info
->current_subimage
->vp_y
= g_ascii_strtod (attr
[i
+1], NULL
);
515 else if (!g_ascii_strcasecmp ("Width", attr
[i
]))
516 info
->current_subimage
->vp_w
= g_ascii_strtod (attr
[i
+1], NULL
);
518 LOG_MSI ("\tunparsed attr %s: %s\n", attr
[i
], attr
[i
+1]);
520 printf ("Unexpected element %s\n", el
);
532 DeepZoomImageTileSource::EndElement (void *data
, const char *el
)
534 DZParserinfo
*info
= (DZParserinfo
*)data
;
537 if (info
->skip
< 0) {
538 switch (info
->depth
) {
540 if (info
->isCollection
)
541 if (!g_ascii_strcasecmp ("I", el
)) {
542 DeepZoomImageTileSource
*subsource
= new DeepZoomImageTileSource (info
->current_subimage
->source
, TRUE
);
543 MultiScaleSubImage
*subi
= new MultiScaleSubImage (info
->source
->GetUriSource (),
545 info
->current_subimage
->id
,
546 info
->current_subimage
->n
);
547 subsource
->SetImageWidth (info
->current_subimage
->width
);
548 subsource
->SetImageHeight (info
->current_subimage
->height
);
549 subsource
->format
= info
->format
;
550 if (info
->current_subimage
->has_viewport
) {
551 subi
->SetViewportOrigin (new Point (info
->current_subimage
->vp_x
, info
->current_subimage
->vp_y
));
552 subi
->SetViewportWidth (info
->current_subimage
->vp_w
);
555 if (info
->current_subimage
->has_size
) {
556 subi
->SetValue (MultiScaleSubImage::AspectRatioProperty
, Value ((double)info
->current_subimage
->width
/(double)info
->current_subimage
->height
));
558 info
->sub_images
= g_list_append (info
->sub_images
, subi
);
559 info
->current_subimage
= NULL
;
565 if (info
->skip
== info
->depth
)
570 end_element (void *data
, const char *el
)
572 DZParserinfo
*info
= (DZParserinfo
*)data
;
573 DeepZoomImageTileSource
*dzits
= (DeepZoomImageTileSource
*)info
->source
;
575 g_assert ("That's wrong...\n");
576 dzits
->EndElement (info
, el
);