+ # export to an image
+ def export_image (self, pngfile, htmlfile=None, puztitle="Crossword Puzzle",
+ solution=True):
+ # don't export if grid is not frozen
+ if self.frozen_grid is False:
+ raise FrozenGridException
+
+ # create cairo image surface and context
+ px = 30
+ surf = cairo.ImageSurface (cairo.FORMAT_RGB24, self.cols*px, self.rows*px)
+ ctx = cairo.Context (surf)
+
+ ctx.set_source_rgb (1, 1, 1)
+ ctx.rectangle (0, 0, self.cols*px, self.rows*px)
+ ctx.fill ()
+
+ # get the clues across and down
+ clues_across = self.get_clues_across ()
+ clues_down = self.get_clues_down ()
+
+
+ # traverse through the grid
+ for row in range (self.rows):
+ for col in range (self.cols):
+ # if grid is un-occupied
+ if (self.data[row][col].occupied_across is False and
+ self.data[row][col].occupied_down is False):
+ ctx.set_source_rgb (0, 0, 0)
+ ctx.rectangle (col*px, row*px, px, px)
+ ctx.fill ()
+ # grid is occupied
+ else:
+ ctx.set_source_rgb (1, 1, 1)
+ ctx.rectangle (col*px, row*px, px, px)
+ ctx.fill ()
+ ctx.set_source_rgb (0, 0, 0)
+ ctx.rectangle (col*px, row*px, px, px)
+ ctx.stroke ()
+ # if solution is not to be provided, number the grid
+ if solution is False:
+ if self.data[row][col].numbered <> 0:
+ ctx.select_font_face ("Serif")
+ ctx.set_font_size (10)
+ ctx.move_to (col*px+5, row*px+10)
+ ctx.show_text (str(self.data[row][col].numbered))
+ # display the words
+ else:
+ ctx.select_font_face ("Serif")
+ ctx.set_font_size (16)
+ ctx.move_to (col*px+10, row*px+20)
+ ctx.show_text (self.data[row][col].char)
+
+ surf.write_to_png (open (pngfile, "wb"))
+
+ # if solution is false, publish the clues and the image in a HTML file
+ if htmlfile and solution is False:
+ html_contents = ["<html>", "<head>", "<title>"]
+ html_contents.append (puztitle)
+ html_contents.append ("</title>")
+ html_contents.append ("</head>")
+ html_contents.append ("<body>")
+ html_contents.append ("<h1>" + puztitle + "</h1>")
+ html_contents.append ('<img src="' + pngfile + '" alt="puzzle" />')
+
+ html_contents.append ("<h2>Across clues</h2>")
+ html_contents.append ("<p>")
+ for word, clue in clues_across:
+ # clue should be: <num> - clue text (chars)
+ clue_str = str (self.data[word[1]][word[2]].numbered) + " - " \
+ + clue + " (" + str (word[3]) + ")"
+ html_contents.append (clue_str)
+ html_contents.append ("<br />")
+ html_contents.append ("</p>")
+
+ html_contents.append ("<h2>Down clues</h2>")
+ html_contents.append ("<p>")
+ for word, clue in clues_down:
+ clue_str = str (self.data[word[1]][word[2]].numbered) + " - " \
+ + clue + " (" + str (word[3]) + ")"
+ html_contents.append (clue_str)
+ html_contents.append ("<br />")
+ html_contents.append ("</p>")
+ html_contents.append ("</body>")
+ html_contents.append ("</html>")
+
+ html_str = "\r\n".join (html_contents)
+
+ fhtml = open (htmlfile, "wb")
+ fhtml.write (html_str)
+ fhtml.close ()
+