README.md edited online with Bitbucket
[gdash.git] / src / editor / exporthtml.cpp
blob1d46390098e910003c62751a5fcd501bd125f122
1 /*
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.
24 #include "config.h"
26 #include <glib.h>
27 #include <gtk/gtk.h>
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"
42 /**
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;
51 std::string contents;
52 GError *error = NULL;
54 if (window) {
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;
67 } else {
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";
86 // CAVESET DATA
87 contents += SPrintf("<H1>%ms</H1>\n") % caveset.name;
88 /* if the game has its own title screen */
89 if (caveset.title_screen != "") {
90 GTKPixbufFactory pf;
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);
99 if (error) {
100 gd_warning(error->message);
101 g_error_free(error);
102 error = NULL;
104 g_free(pngname);
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";
137 GTKPixbufFactory pf;
138 GTKScreen screen(pf, NULL);
139 EditorCellRenderer cr(screen, gd_theme);
140 for (unsigned i = 0; i < caveset.caves.size(); i++) {
141 if (progress) {
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)
156 has_amoeba = true;
157 if (rendered.map(x, y) == O_MAGIC_WALL)
158 has_magic = true;
159 break;
162 /* cave header */
163 contents += SPrintf("<A NAME=\"cave%03d\"></A>\n<H2>%ms</H2>\n") % (i + 1) % cave.name;
165 /* save image */
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);
170 if (error) {
171 gd_warning(error->message);
172 g_error_free(error);
173 error = NULL;
175 g_free(pngname);
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];
195 if (has_amoeba)
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];
197 if (has_magic)
198 contents += SPrintf("<TR><TH>%ms<TD>%d\n") % _("Magic wall milling time (s)") % cave.level_magic_wall_time[0];
199 contents += "</TABLE>\n";
201 contents += "\n";
204 contents += "</BODY>\n";
205 contents += "</HTML>\n";
206 g_free(pngoutbasename);
207 g_free(pngbasename);
209 if (!g_file_set_contents(htmlname, contents.c_str(), contents.size(), &error)) {
210 /* could not save properly */
211 gd_critical(error->message);
212 g_error_free(error);
215 if (dialog)
216 gtk_widget_destroy(dialog);