alaCarte Maps
Renderer for OpenStreetMap tiles
render_canvas.cpp
Go to the documentation of this file.
1 
22 /*
23  * =====================================================================================
24  *
25  * Filename: render_canvas.cpp
26  *
27  * Description: Canvas objects are wrappers for a set if CairoLayers.
28  *
29  * =====================================================================================
30  */
31 
32 #include "config.hpp"
33 
34 #include <cairo-svg.h>
35 #include <boost/pointer_cast.hpp>
36 
37 #include "server/tile.hpp"
38 
39 
42 
44 
46 {
47 private:
50 
51 public:
55  TILE_SIZE,
56  TILE_SIZE)
57  {
58  }
59 
60  PNGRenderCanvas(unsigned int layerWidth, unsigned int layerHeight,
61  unsigned int sliceWidth, unsigned int sliceHeight);
62  virtual ~PNGRenderCanvas() = default;
63  virtual void clear();
64  virtual CairoLayer* getImageLayers() { return layers; }
65  virtual CairoLayer& getSliceLayer() { return slice; }
67 };
68 
70 {
71 private:
75 
76 public:
80  TILE_SIZE,
81  TILE_SIZE)
82  {
83  }
84 
85  SVGRenderCanvas(unsigned int layerWidth, unsigned int layerHeight,
86  unsigned int sliceWidth, unsigned int sliceHeight);
87 
88  virtual void clear();
89  virtual CairoLayer* getImageLayers() { return layers; }
90  virtual CairoLayer& getSliceLayer() { return slice; }
92 };
93 
94 
99 : svgCanvas(boost::dynamic_pointer_cast<RenderCanvas>(boost::make_shared<SVGRenderCanvas>()))
100 , pngCanvas(boost::dynamic_pointer_cast<RenderCanvas>(boost::make_shared<PNGRenderCanvas>()))
101 {
102 }
103 
105 static cairo_status_t cairoWriter(void* closure, const unsigned char* data,
106  unsigned int length)
107 {
108  Tile::ImageType::element_type* b = (Tile::ImageType::element_type*) closure;
109  b->insert(b->end(), data, data+length);
110  return CAIRO_STATUS_SUCCESS;
111 }
112 
113 
114 /*
115  * PNG Canvas.
116  */
117 
118 PNGRenderCanvas::PNGRenderCanvas(unsigned int layerWidth,
119  unsigned int layerHeight,
120  unsigned int sliceWidth,
121  unsigned int sliceHeight)
122 {
123  for (int i = 0; i < LAYER_NUM; i++)
124  {
125  layers[i].surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, layerWidth, layerHeight);
126  layers[i].cr = cairo_create(layers[i].surface);
127  }
128 
129  slice.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, sliceWidth, sliceHeight);
130  slice.cr = cairo_create(slice.surface);
131 
132  cairo_font_options_t* fontOpts = cairo_font_options_create();
133  cairo_font_options_set_hint_style(fontOpts, CAIRO_HINT_STYLE_NONE);
134  cairo_font_options_set_hint_metrics(fontOpts, CAIRO_HINT_METRICS_OFF);
135  cairo_set_font_options(layers[LAYER_LABELS].cr, fontOpts);
136  cairo_select_font_face(layers[LAYER_LABELS].cr, DEFAULT_FONT,
137  CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
138 }
139 
141 {
142  for (int i = 0; i < LAYER_NUM; i++)
143  layers[i].clear();
144 
145  slice.clear();
146 }
147 
149 {
150  cairo_surface_flush(slice.surface);
151  Tile::ImageType buffer = boost::make_shared<Tile::ImageType::element_type>();
152  buffer->reserve(10*1024);
153  cairo_surface_write_to_png_stream(slice.surface, cairoWriter, (void*) buffer.get());
154  return buffer;
155 }
156 
157 /*
158  * SVG Canvas.
159  */
160 
161 SVGRenderCanvas::SVGRenderCanvas(unsigned int layerWidth,
162  unsigned int layerHeight,
163  unsigned int sliceWidth,
164  unsigned int sliceHeight)
165  : buffer(boost::make_shared<Tile::ImageType::element_type>())
166 {
167  for (int i = 0; i < LAYER_NUM; i++)
168  {
169  layers[i].surface = cairo_svg_surface_create_for_stream(NULL, NULL, layerWidth, layerHeight);
170  layers[i].cr = cairo_create(layers[i].surface);
171  }
172 
173  slice.surface = cairo_svg_surface_create_for_stream(cairoWriter,
174  (void*) buffer.get(), sliceWidth, sliceHeight);
175  slice.cr = cairo_create(slice.surface);
176 
177  /* Just select default font face. Font Hinting/Metric does not affect SVG */
178  cairo_select_font_face(layers[LAYER_LABELS].cr, DEFAULT_FONT,
179  CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
180 }
181 
183 {
184  for (int i = 0; i < LAYER_NUM; i++)
185  layers[i].clear();
186 
187  slice.clear();
188  buffer->clear();
189 }
190 
192 {
193  cairo_surface_flush(layers[0].surface);
194  /* do nothing because cairo_surface_flush(surface) will call cairoWriter */
195 
196  /* we need to make a copy since the buffer is owned by the canvas and will be cleared */
197  Tile::ImageType copiedBuffer = boost::make_shared<Tile::ImageType::element_type>(*buffer);
198  return copiedBuffer;
199 }
CairoLayer slice
#define TILE_SIZE
This file is part of alaCarte.
Definition: renderer.hpp:33
virtual CairoLayer * getImageLayers()
Layers to paint the MetaTile onto.
#define DEFAULT_FONT
Definition: settings.hpp:129
cairo_surface_t * surface
This file is part of alaCarte.
virtual void clear()
Clears every layer. Should always be called before use.
virtual Tile::ImageType copySliceImage()
Returns the rendered slice.
virtual void clear()
Clears every layer. Should always be called before use.
cairo_t * cr
Definition: tile.hpp:30
virtual CairoLayer & getSliceLayer()
Get layer that is the size of a final tile for slicing.
Tile::ImageType buffer
virtual CairoLayer & getSliceLayer()
Get layer that is the size of a final tile for slicing.
CairoLayer layers[LAYER_NUM]
static cairo_status_t cairoWriter(void *closure, const unsigned char *data, unsigned int length)
Write function to capture the final PNG image.
virtual ~PNGRenderCanvas()=default
#define META_TILE_SIZE
Definition: settings.hpp:131
shared_ptr< std::vector< uint8_t > > ImageType
Definition: tile.hpp:33
virtual Tile::ImageType copySliceImage()
Returns the rendered slice.
This file is part of alaCarte.
virtual CairoLayer * getImageLayers()
Layers to paint the MetaTile onto.
CairoLayer layers[LAYER_NUM]
CairoLayer slice