maposmatic-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Maposmatic-dev] [PATCH] multi-page: finalize and refactor code for fro


From: Thomas Petazzoni
Subject: [Maposmatic-dev] [PATCH] multi-page: finalize and refactor code for front page generation
Date: Fri, 30 Mar 2012 23:41:38 +0200

Signed-off-by: Thomas Petazzoni <address@hidden>
---
 ocitysmap2/layoutlib/multi_page_renderer.py |  177 +++++++++++++++++++++------
 1 files changed, 137 insertions(+), 40 deletions(-)

diff --git a/ocitysmap2/layoutlib/multi_page_renderer.py 
b/ocitysmap2/layoutlib/multi_page_renderer.py
index 7baac31..e214860 100644
--- a/ocitysmap2/layoutlib/multi_page_renderer.py
+++ b/ocitysmap2/layoutlib/multi_page_renderer.py
@@ -33,6 +33,7 @@ import coords
 import locale
 import pangocairo
 import pango
+import datetime
 
 from itertools import groupby
 
@@ -230,6 +231,9 @@ class MultiPageRenderer(Renderer):
         # Merge all indexes
         self.index_categories = self._merge_page_indexes(indexes)
 
+        # Prepare the small map for the front page
+        self._front_page_map = self._prepare_front_page_map(dpi)
+
     def _merge_page_indexes(self, indexes):
         # First, we split street categories and "other" categories,
         # because we sort them and we don't want to have the "other"
@@ -312,32 +316,40 @@ class MultiPageRenderer(Renderer):
         c1 = self._proj.inverse(mapnik.Coord(envelope.maxx, envelope.maxy))
         return coords.BoundingBox(c0.y, c0.x, c1.y, c1.x)
 
-    def _render_front_page(self, ctx, cairo_surface, dpi):
-
-        ctx.save()
-
-        # Draw a nice grey rectangle covering the whole page
-        ctx.set_source_rgb(.85,.85,.85)
-        ctx.rectangle(Renderer.PRINT_SAFE_MARGIN_PT,
-                      Renderer.PRINT_SAFE_MARGIN_PT,
-                      self._usable_area_width_pt,
-                      self._usable_area_height_pt)
-        ctx.fill()
+    def _prepare_front_page_map(self, dpi):
+        front_page_map_w = \
+            self._usable_area_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT
+        front_page_map_h = \
+            (self._usable_area_height_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT) 
/ 2
 
-        ctx.save()
+        # Create the nice small map
+        front_page_map = \
+            MapCanvas(self.rc.stylesheet,
+                      self.rc.bounding_box,
+                      front_page_map_w,
+                      front_page_map_h,
+                      dpi,
+                      extend_bbox_to_ratio=True)
 
-        # Translate into the working area, taking another
-        # PRINT_SAFE_MARGIN_PT inside the grey area.
-        ctx.translate(2 * Renderer.PRINT_SAFE_MARGIN_PT,
-                      2 * Renderer.PRINT_SAFE_MARGIN_PT)
-        w = self._usable_area_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT
-        h = self._usable_area_height_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT
+        # Add the shape that greys out everything that is outside of
+        # the administrative boundary.
+        exterior = 
shapely.wkt.loads(front_page_map.get_actual_bounding_box().as_wkt())
+        interior = shapely.wkt.loads(self.rc.polygon_wkt)
+        shade_wkt = exterior.difference(interior).wkt
+        shade = maplib.shapes.PolyShapeFile(self.rc.bounding_box,
+                os.path.join(self.tmpdir, 'shape_overview_cover.shp'),
+                             'shade-overview-cover')
+        shade.add_shade_from_wkt(shade_wkt)
+        front_page_map.add_shape_file(shade)
+        front_page_map.render()
+        return front_page_map
 
+    def _render_front_page_header(self, ctx, w, h):
         # Draw a light blue block which will contain the name of the
         # city being rendered.
         blue_w = w
         blue_h = 0.3 * h
-        ctx.set_source_rgb(0.807, 0.898, 0.964)
+        ctx.set_source_rgb(.80,.80,.80)
         ctx.rectangle(0, 0, blue_w, blue_h)
         ctx.fill()
 
@@ -361,31 +373,116 @@ class MultiPageRenderer(Renderer):
         pc.show_layout(layout)
         ctx.restore()
 
-        # Create the nice small map
-        map_canvas = MapCanvas(self.rc.stylesheet,
-                               self.rc.bounding_box,
-                               w, 0.5 * h, dpi,
-                               extend_bbox_to_ratio=True)
-
-        # We will render it slightly below the title
+    def _render_front_page_map(self, ctx, dpi, w, h):
+        # We will render the map slightly below the title
+        ctx.save()
         ctx.translate(0, 0.3 * h + Renderer.PRINT_SAFE_MARGIN_PT)
 
-        # Add the shape that greys out everything that is outside of
-        # the administrative boundary.
-        exterior = 
shapely.wkt.loads(map_canvas.get_actual_bounding_box().as_wkt())
-        interior = shapely.wkt.loads(self.rc.polygon_wkt)
-        shade_wkt = exterior.difference(interior).wkt
-        shade = maplib.shapes.PolyShapeFile(self.rc.bounding_box,
-                os.path.join(self.tmpdir, 'shape_overview_cover.shp'),
-                             'shade-overview-cover')
-        shade.add_shade_from_wkt(shade_wkt)
-        map_canvas.add_shape_file(shade)
-
         # Render the map !
-        map_canvas.render()
-        mapnik.render(map_canvas.get_rendered_map(), ctx)
+        mapnik.render(self._front_page_map.get_rendered_map(), ctx)
+        ctx.restore()
+
+    def _render_front_page_footer(self, ctx, w, h, osm_date):
+        ctx.save()
+
+        # Draw the footer
+        ctx.translate(0, 0.8 * h + 2 * Renderer.PRINT_SAFE_MARGIN_PT)
+
+        # Display a nice grey rectangle as the background of the
+        # footer
+        footer_w = w
+        footer_h = 0.2 * h - 2 * Renderer.PRINT_SAFE_MARGIN_PT
+        ctx.set_source_rgb(.80,.80,.80)
+        ctx.rectangle(0, 0, footer_w, footer_h)
+        ctx.fill()
+
+        # Draw the OpenStreetMap logo to the right of the footer
+        logo_height = footer_h / 2
+        grp, logo_width = self._get_osm_logo(ctx, logo_height)
+        if grp:
+            ctx.save()
+            ctx.translate(w - logo_width - Renderer.PRINT_SAFE_MARGIN_PT,
+                          logo_height / 2)
+            ctx.set_source(grp)
+            ctx.paint_with_alpha(0.8)
+            ctx.restore()
+
+        # Prepare the text for the left of the footer
+        today = datetime.date.today()
+        notice = \
+            _(u'Copyright © %(year)d MapOSMatic/OCitySMap developers.\n'
+              u'http://www.maposmatic.org\n\n'
+              u'Map data © %(year)d OpenStreetMap.org '
+              u'and contributors (cc-by-sa).\n'
+              u'http://www.openstreetmap.org\n\n'
+              u'Map rendered on: %(date)s. OSM data updated on: %(osmdate)s.\n'
+              u'The map may be incomplete or inaccurate. '
+              u'You can contribute to improve this map.\n'
+              u'See http://wiki.openstreetmap.org')
+
+        # We need the correct locale to be set for strftime().
+        prev_locale = locale.getlocale(locale.LC_TIME)
+        locale.setlocale(locale.LC_TIME, self.rc.i18n.language_code())
+        try:
+            if osm_date is None:
+                osm_date_str = _(u'unknown')
+            else:
+                osm_date_str = osm_date.strftime("%d %B %Y %H:%M")
+
+            notice = notice % {'year': today.year,
+                               'date': today.strftime("%d %B %Y"),
+                               'osmdate': osm_date_str}
+        finally:
+            locale.setlocale(locale.LC_TIME, prev_locale)
+
+        # Render the text
+        pc = pangocairo.CairoContext(ctx)
+        layout = pc.create_layout()
+        layout.set_width(int(footer_w * 0.7) * pango.SCALE)
+        layout.set_alignment(pango.ALIGN_LEFT)
+        fd = pango.FontDescription("Georgia Bold")
+        fd.set_size(pango.SCALE)
+        layout.set_font_description(fd)
+        layout.set_text(notice)
+        self._adjust_font_size(layout, fd, footer_w * 0.7, footer_h * 0.8)
+
+        text_x, text_y, text_w, text_h = layout.get_extents()[1]
+        ctx.save()
+        ctx.set_source_rgb(0,0,0)
+        ctx.translate(Renderer.PRINT_SAFE_MARGIN_PT,
+                      (footer_h / 2) - (text_h / 2.0 / pango.SCALE))
+        # Hack to workaround what appears to be a Cairo bug: without
+        # drawing a rectangle here, the translation above is not taken
+        # into account for rendering the text.
+        ctx.rectangle(0, 0, 0, 0)
+        pc.show_layout(layout)
+        ctx.restore()
 
         ctx.restore()
+
+    def _render_front_page(self, ctx, cairo_surface, dpi, osm_date):
+        # Draw a nice grey rectangle covering the whole page
+        ctx.save()
+        ctx.set_source_rgb(.95,.95,.95)
+        ctx.rectangle(Renderer.PRINT_SAFE_MARGIN_PT,
+                      Renderer.PRINT_SAFE_MARGIN_PT,
+                      self._usable_area_width_pt,
+                      self._usable_area_height_pt)
+        ctx.fill()
+        ctx.restore()
+
+        # Translate into the working area, taking another
+        # PRINT_SAFE_MARGIN_PT inside the grey area.
+        ctx.save()
+        ctx.translate(2 * Renderer.PRINT_SAFE_MARGIN_PT,
+                      2 * Renderer.PRINT_SAFE_MARGIN_PT)
+        w = self._usable_area_width_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT
+        h = self._usable_area_height_pt - 2 * Renderer.PRINT_SAFE_MARGIN_PT
+
+        self._render_front_page_header(ctx, w, h)
+        self._render_front_page_map(ctx, dpi, w, h)
+        self._render_front_page_footer(ctx, w, h, osm_date)
+
         ctx.restore()
 
         cairo_surface.show_page()
@@ -393,7 +490,7 @@ class MultiPageRenderer(Renderer):
     def render(self, cairo_surface, dpi, osm_date):
         ctx = cairo.Context(cairo_surface)
 
-        self._render_front_page(ctx, cairo_surface, dpi)
+        self._render_front_page(ctx, cairo_surface, dpi, osm_date)
 
         for i, (canvas, grid) in enumerate(self.pages):
             ctx.save()
-- 
1.7.4.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]