2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
19 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <glib/gi18n.h>
30 #include "editor/exporthtml.hpp"
31 #include "cave/cavetypes.hpp"
32 #include "cave/caveset.hpp"
33 #include "gtk/gtkscreen.hpp"
34 #include "settings.hpp"
35 #include "misc/logger.hpp"
36 #include "cave/caverendered.hpp"
37 #include "cave/titleanimation.hpp"
38 #include "editor/editorcellrenderer.hpp"
39 #include "gtk/gtkpixbuffactory.hpp"
40 #include "gtk/gtkpixbuf.hpp"
43 * Save caveset as html gallery.
44 * @param htmlname filename
45 * @param window show progress bar in a small dialog, transient for this window, if not NULL
47 void gd_save_html(char *htmlname
, GtkWidget
*window
, CaveSet
&caveset
) {
48 char *pngbasename
; /* used as a base for img src= tags */
49 char *pngoutbasename
; /* used as a base name for png output files */
50 GtkWidget
*dialog
= NULL
, *progress
= NULL
;
55 dialog
= gtk_dialog_new();
56 gtk_window_set_transient_for(GTK_WINDOW(dialog
), GTK_WINDOW(window
));
57 progress
= gtk_progress_bar_new();
58 gtk_window_set_title(GTK_WINDOW(dialog
), _("Saving HTML Gallery"));
59 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog
)->vbox
), progress
);
60 gtk_widget_show_all(dialog
);
63 if (g_str_has_suffix(htmlname
, ".html")) {
64 /* has html extension */
65 pngoutbasename
= g_strdup(htmlname
);
66 *g_strrstr(pngoutbasename
, ".html") = 0;
68 /* has no html extension */
69 pngoutbasename
= g_strdup(htmlname
);
70 htmlname
= g_strdup_printf("%s.html", pngoutbasename
);
72 pngbasename
= g_path_get_basename(pngoutbasename
);
74 contents
+= "<HTML>\n";
75 contents
+= "<HEAD>\n";
76 contents
+= SPrintf("<TITLE>%ms</TITLE>\n") % caveset
.name
;
77 contents
+= "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n";
78 if (gd_html_stylesheet_filename
)
79 contents
+= SPrintf("<link rel=\"stylesheet\" href=\"%s\">\n") % gd_html_stylesheet_filename
;
80 if (gd_html_favicon_filename
)
81 contents
+= SPrintf("<link rel=\"shortcut icon\" href=\"%s\">\n") % gd_html_favicon_filename
;
82 contents
+= "</HEAD>\n\n";
84 contents
+= "<BODY>\n";
87 contents
+= SPrintf("<H1>%ms</H1>\n") % caveset
.name
;
88 /* if the game has its own title screen */
89 if (caveset
.title_screen
!= "") {
92 /* create the title image and save it */
93 std::vector
<Pixbuf
*> title_images
= get_title_animation_pixbuf(caveset
.title_screen
, caveset
.title_screen_scroll
, true, pf
);
94 if (!title_images
.empty()) {
95 GdkPixbuf
*title_image
= static_cast<GTKPixbuf
*>(title_images
[0])->get_gdk_pixbuf();
97 char *pngname
= g_strdup_printf("%s_%03d.png", pngoutbasename
, 0); /* it is the "zeroth" image */
98 gdk_pixbuf_save(title_image
, pngname
, "png", &error
, "compression", "9", NULL
);
100 gd_warning(error
->message
);
106 contents
+= SPrintf("<IMAGE SRC=\"%s_%03d.png\" WIDTH=\"%d\" HEIGHT=\"%d\">\n") % pngbasename
% 0 % gdk_pixbuf_get_width(title_image
) % gdk_pixbuf_get_height(title_image
);
107 contents
+= "<BR>\n";
109 delete title_images
[0];
112 contents
+= "<TABLE>\n";
113 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Caves") % caveset
.caves
.size();
114 if (caveset
.author
!= "")
115 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Author") % caveset
.author
;
116 if (caveset
.description
!= "")
117 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Description") % caveset
.description
;
118 if (caveset
.www
!= "")
119 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("WWW") % caveset
.www
;
120 if (caveset
.remark
!= "")
121 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Remark") % caveset
.remark
;
122 if (caveset
.story
!= "")
123 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Story") % caveset
.story
;
124 contents
+= "</TABLE>\n";
126 /* cave names, descriptions, hrefs */
127 contents
+= "<DL>\n";
128 for (unsigned n
= 0; n
< caveset
.caves
.size(); n
++) {
129 CaveStored
&cave
= caveset
.cave(n
);
131 contents
+= SPrintf("<DT><A HREF=\"#cave%03d\">%s</A></DT>\n") % (n
+ 1) % cave
.name
;
132 if (cave
.description
!= "")
133 contents
+= SPrintf(" <DD>%s</DD>\n") % cave
.description
;
135 contents
+= "</DL>\n\n";
138 GTKScreen
screen(pf
, NULL
);
139 EditorCellRenderer
cr(screen
, gd_theme
);
140 for (unsigned i
= 0; i
< caveset
.caves
.size(); i
++) {
142 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress
), (float) i
/ caveset
.caves
.size());
143 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress
), CPrintf("%d/%d") % i
% caveset
.caves
.size());
144 gdk_window_process_all_updates();
147 /* rendering cave for png: seed=0 */
148 CaveStored
&cave
= caveset
.cave(i
);
149 CaveRendered
rendered(cave
, 0, 0);
151 /* check cave to see if we have amoeba or magic wall. properties will be shown in html, if so. */
152 bool has_amoeba
= false, has_magic
= false;
153 for (int y
= 0; y
< cave
.h
; y
++)
154 for (int x
= 0; x
< cave
.w
; x
++) {
155 if (rendered
.map(x
, y
) == O_AMOEBA
)
157 if (rendered
.map(x
, y
) == O_MAGIC_WALL
)
163 contents
+= SPrintf("<A NAME=\"cave%03d\"></A>\n<H2>%ms</H2>\n") % (i
+ 1) % cave
.name
;
166 char *pngname
= g_strdup_printf("%s_%03d.png", pngoutbasename
, i
+ 1);
167 GdkPixbuf
*pixbuf
= gd_drawcave_to_pixbuf(&rendered
, cr
, 0, 0, true, false);
168 GError
*error
= NULL
;
169 gdk_pixbuf_save(pixbuf
, pngname
, "png", &error
, "compression", "9", NULL
);
171 gd_warning(error
->message
);
176 contents
+= SPrintf("<IMAGE SRC=\"%s_%03d.png\" WIDTH=\"%d\" HEIGHT=\"%d\">\n") % pngbasename
% (i
+ 1) % gdk_pixbuf_get_width(pixbuf
) % gdk_pixbuf_get_height(pixbuf
);
177 g_object_unref(pixbuf
);
179 contents
+= "<BR>\n";
180 contents
+= "<TABLE>\n";
181 if (cave
.author
!= "")
182 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Author") % cave
.author
;
183 if (cave
.description
!= "")
184 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Description") % cave
.description
;
185 if (cave
.remark
!= "")
186 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Remark") % cave
.remark
;
187 if (cave
.story
!= "")
188 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Story") % cave
.story
;
189 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Type") % (cave
.intermission
? _("Intermission") : _("Normal cave"));
190 contents
+= SPrintf("<TR><TH>%ms<TD>%ms\n") % _("Selectable as start") % (cave
.selectable
? _("Yes") : _("No"));
191 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Diamonds needed") % cave
.level_diamonds
[0];
192 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Diamond value") % cave
.diamond_value
;
193 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Extra diamond value") % cave
.extra_diamond_value
;
194 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Time (s)") % cave
.level_time
[0];
196 contents
+= SPrintf("<TR><TH>%ms<TD>%d, %d\n") % _("Amoeba threshold and time (s)") % cave
.level_amoeba_threshold
[0] % cave
.level_amoeba_time
[0];
198 contents
+= SPrintf("<TR><TH>%ms<TD>%d\n") % _("Magic wall milling time (s)") % cave
.level_magic_wall_time
[0];
199 contents
+= "</TABLE>\n";
204 contents
+= "</BODY>\n";
205 contents
+= "</HTML>\n";
206 g_free(pngoutbasename
);
209 if (!g_file_set_contents(htmlname
, contents
.c_str(), contents
.size(), &error
)) {
210 /* could not save properly */
211 gd_critical(error
->message
);
216 gtk_widget_destroy(dialog
);