alaCarte Maps
Renderer for OpenStreetMap tiles
renderer.cpp
Go to the documentation of this file.
1 
22 /*
23  * =====================================================================================
24  *
25  * Filename: renderer.cpp
26  *
27  * Description: Renders a tile in the given image format using cairo.
28  *
29  * =====================================================================================
30  */
31 #include "config.hpp"
32 #include <boost/unordered_map.hpp>
33 #include <boost/math/constants/constants.hpp>
34 #include <cairo-svg.h>
35 #include <time.h>
36 
37 #include "utils/transform.hpp"
38 
39 #include "general/geodata.hpp"
40 #include "general/geo_object.hpp"
41 #include "general/way.hpp"
42 #include "general/node.hpp"
43 
45 #include "server/style.hpp"
46 #include "server/tile.hpp"
49 
53 
54 #include "node_renderer.hpp"
55 #include "way_renderer.hpp"
56 #include "relation_renderer.hpp"
57 
58 boost::mutex Renderer::renderLock;
59 
60 
62 template<typename IdType>
64 {
65  CompareObjects(const boost::unordered_map<IdType, Style*> & styles)
66  : styles(styles)
67  {
68  }
69 
70  bool operator ()(IdType first, IdType second) {
71  const Style* fs = styles.at(first);
72  const Style* ss = styles.at(second);
73  return (fs->z_index < ss->z_index)
74  || (fs->z_index == ss->z_index
75  && first.getRaw() < second.getRaw());
76  }
77 
78  const boost::unordered_map<IdType, Style*> &styles;
79 };
80 
82 template <typename LabelType>
83 bool CompareLabels(const shared_ptr<LabelType>& first, const shared_ptr<LabelType>& second) {
84  return (first->style->font_size > second->style->font_size)
85  || (first->style->font_size == second->style->font_size
86  && first->box.minX < second->box.minX);
87 }
88 
89 
90 Renderer::Renderer(const shared_ptr<Geodata>& data)
91  : data(data), bounds(FloatRect(0.0, 0.0, TILE_SIZE*META_TILE_SIZE, TILE_SIZE*META_TILE_SIZE))
92 {
93  double borderX = bounds.getWidth() * TILE_OVERLAP;
94  double borderY = bounds.getHeight() * TILE_OVERLAP;
101  neighbours[6] = bounds.translate( bounds.getWidth(), 0.0);
102  neighbours[7] = bounds.translate(-bounds.getWidth(), 0.0);
103  neighbourRequests[0] = neighbours[0].grow(borderX, borderY);
104  neighbourRequests[1] = neighbours[1].grow(borderX, borderY);
105  neighbourRequests[2] = neighbours[2].grow(borderX, borderY);
106  neighbourRequests[3] = neighbours[3].grow(borderX, borderY);
107  neighbourRequests[4] = neighbours[4].grow(borderX, borderY);
108  neighbourRequests[5] = neighbours[5].grow(borderX, borderY);
109  neighbourRequests[6] = neighbours[6].grow(borderX, borderY);
110  neighbourRequests[7] = neighbours[7].grow(borderX, borderY);
111 }
112 
113 
115 void Renderer::printTileId(cairo_t* cr,
116  const shared_ptr<TileIdentifier>& id) const
117 {
118  cairo_save(cr);
119 
120  cairo_set_font_size(cr, 10);
121  cairo_move_to(cr, 5.0, TILE_SIZE - 10);
122 
123  std::ostringstream labelstrm;
124  labelstrm << "X: " << id->getX() << " Y: " << id->getY();
125  labelstrm << " Zoom: " << id->getZoom();
126  labelstrm << " Style: " << id->getStylesheetPath();
127  std::string label = labelstrm.str();
128  cairo_text_path(cr, label.c_str());
129 
130  cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
131  cairo_set_line_width(cr, 2.0);
132  cairo_stroke_preserve(cr);
133  cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
134  cairo_fill(cr);
135 
136  cairo_restore(cr);
137 }
138 
141  std::vector<NodeId>& nodes,
142  std::vector<WayId>& ways,
143  std::vector<RelId>& relations) const
144 {
145  const boost::unordered_map<NodeId, Style*> &nodeMap = map.getNodeMap();
146  const boost::unordered_map<WayId, Style*> &wayMap = map.getWayMap();
147  const boost::unordered_map<RelId, Style*> &relationMap = map.getRelationMap();
148 
149  ways.reserve(wayMap.size());
150  for (auto& pair : wayMap) {
151  ways.push_back(pair.first);
152  }
153 
154  nodes.reserve(nodeMap.size());
155  for (auto& pair : nodeMap) {
156  nodes.push_back(pair.first);
157  }
158 
159  relations.reserve(relationMap.size());
160  for (auto& pair : relationMap) {
161  relations.push_back(pair.first);
162  }
163 
164  std::sort(ways.begin(), ways.end(), CompareObjects<WayId>(wayMap));
165  std::sort(nodes.begin(), nodes.end(), CompareObjects<NodeId>(nodeMap));
166  std::sort(relations.begin(), relations.end(), CompareObjects<RelId>(relationMap));
167 }
168 
171  RenderAttributes& map,
172  const cairo_matrix_t* transform,
173  std::vector<NodeId>& nodes,
174  std::vector<WayId>& ways,
175  std::vector<RelId>& relations,
176  std::list<shared_ptr<Label>>& labels,
177  std::list<shared_ptr<Shield>>& shields,
178  AssetCache& cache) const
179 {
180  const boost::unordered_map<WayId, Style*> &wayStyles = map.getWayMap();
181  const boost::unordered_map<NodeId, Style*> &nodeStyles = map.getNodeMap();
182  const boost::unordered_map<RelId, Style*> &relationStyles = map.getRelationMap();
183 
184  /* find min and max z_index */
185  int minZ = 0;
186  int maxZ = 0;
187  if (ways.size() > 0) {
188  minZ = std::min(minZ, wayStyles.at(ways.front())->z_index);
189  maxZ = std::max(maxZ, wayStyles.at(ways.back())->z_index);
190  }
191  if (nodes.size() > 0) {
192  minZ = std::min(minZ, nodeStyles.at(nodes.front())->z_index);
193  maxZ = std::max(maxZ, nodeStyles.at(nodes.back())->z_index);
194  }
195  if (relations.size() > 0) {
196  minZ = std::min(minZ, relationStyles.at(relations.front())->z_index);
197  maxZ = std::max(maxZ, relationStyles.at(relations.back())->z_index);
198  }
199 
200  auto rid = relations.begin();
201  auto wid = ways.begin();
202  auto nid = nodes.begin();
203  int nextZ; // used to skip empty z-index
204  int layer = minZ / 100; // z-index = osm_layer * 100 + mapcss_z_index
205  for (int z = minZ; z <= maxZ; z = nextZ)
206  {
207  if (z/100 != layer) {
208  layer = z/100;
209  compositeLayers(layers);
210  }
211 
212  // if nextZ is not overwritten we have reached the end
213  nextZ = INT_MAX;
214 
215  for (; rid != relations.end(); rid++)
216  {
217  const Style* s = relationStyles.at(*rid);
218  if (s->z_index > z) {
219  nextZ = std::min(nextZ, s->z_index);
220  break;
221  }
222  RelationRenderer renderer(data, *rid, s, transform);
223 
224  renderer.fill(layers[RenderCanvas::LAYER_FILL].cr, cache);
225  }
226 
227  for (; wid != ways.end(); wid++)
228  {
229  const Style* s = wayStyles.at(*wid);
230  if (s->z_index > z) {
231  nextZ = std::min(nextZ, s->z_index);
232  break;
233  }
234  WayRenderer renderer(data, *wid, s, transform);
235 
236  renderer.fill(layers[RenderCanvas::LAYER_FILL].cr, cache);
237  renderer.casing(layers[RenderCanvas::LAYER_CASING].cr);
238  renderer.stroke(layers[RenderCanvas::LAYER_STROKE].cr, cache);
239  renderer.label(layers[RenderCanvas::LAYER_LABELS].cr, labels, cache);
240  renderer.shield(layers[RenderCanvas::LAYER_LABELS].cr, shields, cache);
241  }
242 
243  for (; nid != nodes.end(); nid++)
244  {
245  const Style* s = nodeStyles.at(*nid);
246  if (s->z_index > z) {
247  nextZ = std::min(nextZ, s->z_index);
248  break;
249  }
250  NodeRenderer renderer(data, *nid, s, transform);
251 
252  renderer.casing(layers[RenderCanvas::LAYER_CASING].cr);
253  renderer.stroke(layers[RenderCanvas::LAYER_STROKE].cr);
254  renderer.label(layers[RenderCanvas::LAYER_LABELS].cr, labels, cache);
255  renderer.shield(layers[RenderCanvas::LAYER_LABELS].cr, shields, cache);
256  renderer.icon(layers[RenderCanvas::LAYER_ICONS].cr, cache);
257  }
258  }
259 }
260 
262 void Renderer::renderShields(cairo_t* cr,
263  std::vector<shared_ptr<Shield> >& shields) const
264 {
265  cairo_save(cr);
266 
267  cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
268 
269  for (auto& shield : shields)
270  {
271  const Style* s = shield->style;
272 
273  double x0, y0, height, width;
274  double border = ceil(s->shield_frame_width/2.0 + s->shield_casing_width);
275  x0 = shield->shield.minX + border;
276  y0 = shield->shield.minY + border;
277  width = shield->shield.getWidth() - 2*border;
278  height = shield->shield.getHeight() - 2*border;
279  if ((int) s->shield_frame_width % 2 == 1) {
280  x0 -= 0.5;
281  y0 -= 0.5;
282  }
283  if (s->shield_shape == Style::ShieldShape::ROUNDED) {
284  cairo_arc(cr, x0 + height/2.0, y0 + height/2.0,
285  height/2.0, boost::math::constants::pi<double>()/2.0, 3.0*boost::math::constants::pi<double>()/2.0);
286  cairo_arc(cr, x0 + width - height/2.0, y0 + height/2.0,
287  height/2.0, 3.0*boost::math::constants::pi<double>()/2.0, boost::math::constants::pi<double>()/2.0);
288  cairo_close_path(cr);
289  } else
290  cairo_rectangle(cr, x0, y0, width, height);
291 
292  // shield casing
293  if (s->shield_casing_width > 0) {
294  cairo_set_source_rgba(cr, COLOR2RGBA(s->shield_casing_color));
295  cairo_set_line_width(cr, s->shield_frame_width + s->shield_casing_width * 2.0);
296  cairo_stroke_preserve(cr);
297  }
298 
299  // shield background
300  cairo_set_source_rgba(cr, COLOR2RGBA(s->shield_color));
301  cairo_fill_preserve(cr);
302 
303  // shield frame
304  cairo_set_source_rgba(cr, COLOR2RGBA(s->shield_frame_color));
305  cairo_set_line_width(cr, s->shield_frame_width);
306  cairo_stroke(cr);
307  }
308 
309  cairo_restore(cr);
310 }
311 
312 template <typename LabelType>
313 void Renderer::renderLabels(cairo_t* cr,
314  std::vector<shared_ptr<LabelType> >& labels,
315  AssetCache& cache) const
316 {
317  cairo_save(cr);
318 
319  cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
320 
321  for (auto it = labels.rbegin(); it != labels.rend(); it++)
322  {
323  const shared_ptr<LabelType>& label = *it;
324  const Style* s = label->style;
325 
326  cairo_set_font_size(cr, s->font_size);
327 
328  cairo_move_to(cr, label->origin.x, label->origin.y);
329 
330  cairo_select_font_face(cr,
331  s->font_family.c_str(),
332  s->font_style == Style::STYLE_ITALIC ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL,
333  s->font_weight == Style::WEIGHT_BOLD ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL
334  );
335 
336  cairo_text_path(cr, label->text.c_str());
337 
338  if (s->text_halo_radius > 0.0)
339  {
340  cairo_set_source_rgba(cr, COLOR2RGBA(s->text_halo_color));
341  cairo_set_line_width(cr, s->text_halo_radius*2.0);
342  cairo_stroke_preserve(cr);
343  }
344 
345  cairo_set_source_rgba(cr, COLOR2RGBA(s->text_color));
346  cairo_fill(cr);
347  }
348 
349  cairo_restore(cr);
350 }
351 
353 bool Renderer::isCutOff(const FloatRect& box, const FloatRect& owner)
354 {
355  bool tooLarge = false;
356  for (int i = 0; i < 8 && !tooLarge; i++)
357  tooLarge = box.intersects(neighbours[i]) && !neighbourRequests[i].intersects(owner);
358  return tooLarge;
359 }
360 
362 void Renderer::placeLabels(const std::list<shared_ptr<Label> >& labels,
363  std::vector<shared_ptr<Label> >& placed)
364 {
365  std::vector<shared_ptr<Label>> contained;
366  contained.reserve(labels.size());
367 
368  // first sort out all out-of-bounds labels
369  for (auto& l : labels) {
370  if (bounds.contains(l->box))
371  contained.push_back(l);
372  else if (bounds.getIntersection(l->box).getArea() > 0.0){
373  if (isCutOff(l->box, l->owner))
374  continue;
375 
376  double intersect_max = 0.0;
377  for (auto& other : placed)
378  intersect_max = std::max(intersect_max, other->box.getIntersection(l->box).getArea());
379 
380 
381  if (intersect_max < RENDERER_LABEL_OVERLAP * l->box.getArea())
382  placed.push_back(l);
383  }
384  }
385 
386  for (auto& l : contained) {
387  double width = l->box.getWidth();
388  double height = l->box.getHeight();
389  FloatPoint trans[5] = {
390  FloatPoint(0.0, 0.0), // original
391  FloatPoint(0.0, -height/2.0), // above
392  FloatPoint(width/2.0, 0.0), // to the right
393  FloatPoint(0.0, height/2.0), // below
394  FloatPoint(width/2.0, 0.0) // to the left
395  };
396  FloatRect possible[5];
397  for (int i = 0; i < 5; i++)
398  possible[i] = l->box.translate(trans[i].x, trans[i].y);
399 
400  // stores the size of the intersecting area
401  double intersect_max[5] = {0.0, 0.0, 0.0, 0.0, 0.0};
402  for (auto& other : placed) {
403  for (int i = 0; i < 5; i++) {
404  FloatRect intersection = possible[i].getIntersection(other->box);
405  intersect_max[i] = std::max(intersect_max[i], intersection.getArea());
406  }
407  }
408 
409  int min = 0;
410  for (int i = 1; i < 5; i++)
411  if (intersect_max[i] < intersect_max[min]
412  && bounds.contains(possible[i])) // don't push label outside of the bounding-box
413  min = i;
414 
415  // only place label if intersecting area is 1/10 the label
416  if (intersect_max[min] < RENDERER_LABEL_OVERLAP * l->box.getArea()) {
417  l->translate(trans[min].x, trans[min].y);
418  placed.push_back(l);
419  }
420  }
421 }
422 
424 void Renderer::placeShields(const std::list<shared_ptr<Shield> >& shields,
425  std::vector<shared_ptr<Shield> >& placed)
426 {
427  std::vector<shared_ptr<Shield>> contained;
428  contained.reserve(10);
429 
430  // first sort out all out-of-bounds labels
431  for (auto& shield : shields) {
432  if (!bounds.contains(shield->shield))
433  continue;
434 
435  // stores the size of the intersecting area
436  double intersect_max = 0.0;
437  for (auto& other : placed) {
438  FloatRect intersection = shield->box.getIntersection(other->box);
439  intersect_max = std::max(intersect_max, intersection.getArea());
440  }
441 
442  // only place label if intersecting area is 1/10 the label
443  if (intersect_max < RENDERER_SHIELD_OVERLAP * shield->box.getArea())
444  placed.push_back(shield);
445  }
446 }
447 
450 {
451  cairo_t* cr = layers[0].cr;
452 
453  cairo_save(cr);
454 
455  for (int i = 1; i < RenderCanvas::LAYER_NUM; i++) {
456  cairo_surface_flush(layers[i].surface);
457  cairo_set_source_surface(cr, layers[i].surface, 0.0, 0.0);
458  cairo_paint(cr);
459  layers[i].clear();
460  }
461 
462  cairo_restore(cr);
463 }
464 
465 void Renderer::paintBackground(CairoLayer& layer, const Style* canvasStyle) const
466 {
467  const string& bg = canvasStyle->fill_image.str();
468  if (bg.size() > 0)
469  {
470  cairo_surface_t* image = cairo_image_surface_create_from_png(bg.c_str());
471  cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
472  cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
473  cairo_set_source(layer.cr, pattern);
474  cairo_pattern_destroy(pattern);
475  cairo_surface_destroy(image);
476  cairo_paint(layer.cr);
477  }
478  else
479  {
480  cairo_set_source_rgba(layer.cr, COLOR2RGBA(canvasStyle->fill_color));
481  cairo_paint(layer.cr);
482  }
483 }
484 
486  const shared_ptr<RenderCanvas>& canvas,
487  const shared_ptr<Tile>& tile)
488 {
489  const shared_ptr<TileIdentifier>& id = tile->getIdentifier();
490 
491  canvas->clear();
492 
493 #if RENDER_LOCK
494  renderLock.lock();
495 #endif
496  CairoLayer& layer = canvas->getSliceLayer();
497  paintBackground(layer, map.getCanvasStyle());
498 
499 #if DEBUG_BUILD
500  printTileId(layer.cr, tile->getIdentifier());
501 #endif
502 
503 #if RENDER_LOCK
504  renderLock.unlock();
505 #endif
506 
507  tile->setImage(canvas->copySliceImage());
508 }
509 
511  const shared_ptr<RenderCanvas>& canvas,
512  double width, double height,
513  RenderAttributes& map,
514  AssetCache& cache)
515 {
516  // sort objects into acroding to z-index
517  std::vector<NodeId> nodes;
518  std::vector<WayId> ways;
519  std::vector<RelId> relations;
520  sortObjects(map, nodes, ways, relations);
521 
522  // transform Mercator to tile coordinates
523  cairo_matrix_t trans;
524  cairo_matrix_init_scale(&trans, width / (double) area.getWidth(),
525  height / (double) area.getHeight());
526  cairo_matrix_translate(&trans, -area.minX, -area.minY);
527 
528  CairoLayer* layers = canvas->getImageLayers();
529 
530  paintBackground(layers[0], map.getCanvasStyle());
531 
532  std::list<shared_ptr<Label> > labels;
533  std::list<shared_ptr<Shield> > shields;
534 
535  // render objects and collect label positions
536  renderObjects(layers, map, &trans, nodes, ways, relations, labels, shields, cache);
537 
538  // sort, place and render shields
539  std::vector<shared_ptr<Shield> > placedShields;
540  placedShields.reserve(10);
541  shields.sort(&CompareLabels<Shield>);
542  placeShields(shields, placedShields);
543  renderShields(layers[RenderCanvas::LAYER_LABELS].cr, placedShields);
544  renderLabels<Shield>(layers[RenderCanvas::LAYER_LABELS].cr, placedShields, cache);
545 
546  // sort, place and render labels
547  std::vector<shared_ptr<Label> > placedLabels;
548  placedLabels.reserve(labels.size());
549  labels.sort(&CompareLabels<Label>);
550  placeLabels(labels, placedLabels);
551  renderLabels<Label>(layers[RenderCanvas::LAYER_LABELS].cr, placedLabels, cache);
552 
553  compositeLayers(layers);
554 }
555 
556 
557 void Renderer::sliceTile(const shared_ptr<RenderCanvas>& canvas,
558  const shared_ptr<MetaIdentifier>& mid,
559  const shared_ptr<Tile>& tile) const
560 {
561  int tx0 = mid->getX();
562  int ty0 = mid->getY();
563 
564  CairoLayer* layers = canvas->getImageLayers();
565  CairoLayer& slice = canvas->getSliceLayer();
566 
567  cairo_surface_flush(layers[0].surface);
568 
569  const shared_ptr<TileIdentifier>& tid = tile->getIdentifier();
570  int dx = (tid->getX() - tx0) * TILE_SIZE;
571  int dy = (tid->getY() - ty0) * TILE_SIZE;
572 
573  cairo_set_source_surface(slice.cr, layers[0].surface, -dx, -dy);
574  cairo_paint(slice.cr);
575 
576 #if DEBUG_BUILD
577  printTileId(slice.cr, tile->getIdentifier());
578 #endif
579 
580  tile->setImage(canvas->copySliceImage());
581 }
582 
583 void Renderer::renderMetaTile(RenderAttributes& map, const shared_ptr<RenderCanvas>& canvas, const shared_ptr<MetaIdentifier>& id)
584 {
585  int width = id->getWidth() * TILE_SIZE;
586  int height = id->getHeight() * TILE_SIZE;
587  int zoom = id->getZoom();
588  TileIdentifier::Format format = id->getIdentifiers()[0]->getImageFormat();
589 
590  FixedRect area;
591  tileToMercator(id->getX(), id->getY(), zoom, area.minX, area.minY);
592  tileToMercator(id->getX() + id->getWidth(),
593  id->getY() + id->getHeight(),
594  zoom, area.maxX, area.maxY);
595 
596 #if RENDER_LOCK
597  renderLock.lock();
598 #endif
599 
600  AssetCache cache;
601 
602  canvas->clear();
603 
604  renderArea(area, canvas, width, height, map, cache);
605 
606 #if RENDER_LOCK
607  renderLock.unlock();
608 #endif
609 }
void paintBackground(CairoLayer &layer, const Style *canvasStyle) const
Definition: renderer.cpp:465
void placeLabels(const std::list< shared_ptr< Label > > &labels, std::vector< shared_ptr< Label > > &placed)
Place labels with greedy algorithm.
Definition: renderer.cpp:362
float text_halo_radius
Definition: style.hpp:99
void casing(cairo_t *cr)
#define TILE_SIZE
This file is part of alaCarte.
Definition: renderer.hpp:33
void icon(cairo_t *cr, AssetCache &cache)
void stroke(cairo_t *cr)
void fill(cairo_t *cr, AssetCache &cache)
T getHeight() const
Definition: rect.hpp:158
cairo_surface_t * surface
float shield_casing_width
Definition: style.hpp:119
void stroke(cairo_t *cr, AssetCache &cache)
FloatRect bounds
Definition: renderer.hpp:68
const boost::unordered_map< IdType, Style * > & styles
Definition: renderer.cpp:78
float shield_frame_width
Definition: style.hpp:117
TESTABLE const boost::unordered_map< WayId, Style * > & getWayMap() const
Color shield_frame_color
Definition: style.hpp:115
void fill(cairo_t *cr, AssetCache &cache)
A RenderAttributes object contains mappings from NodeIDs and WayIDs to Style objects which define how...
const string & str() const
Returns the internal string.
bool intersects(const basic_rect< T > &bounding) const
Definition: rect.hpp:143
void sortObjects(RenderAttributes &map, std::vector< NodeId > &nodes, std::vector< WayId > &ways, std::vector< RelId > &relations) const
Sort objetcs into painting order.
Definition: renderer.cpp:140
void label(cairo_t *cr, std::list< shared_ptr< Label > > &labels, AssetCache &cache)
int z_index
Definition: style.hpp:128
TESTABLE Style * getCanvasStyle()
MaybeCachedString fill_image
Definition: style.hpp:82
cairo_t * cr
#define COLOR2RGBA(_X)
T getArea() const
Definition: rect.hpp:112
ShieldShape shield_shape
Definition: style.hpp:122
Format
Enumeration which contains all supported image formats.
MaybeCachedString font_family
Definition: style.hpp:93
T getWidth() const
Definition: rect.hpp:154
bool contains(const basic_vector2< T > &p) const
Definition: rect.hpp:130
TESTABLE const boost::unordered_map< RelId, Style * > & getRelationMap() const
Color text_color
Definition: style.hpp:90
void tileToMercator(int tx, int ty, int zoom, coord_t &x, coord_t &y)
converts tile coordinates to north-west corner of the tile in the Mercator projection.
Definition: transform.cpp:52
T minY
Definition: rect.hpp:52
void casing(cairo_t *cr)
TESTABLE const boost::unordered_map< NodeId, Style * > & getNodeMap() const
Color shield_casing_color
Definition: style.hpp:118
TESTABLE void sliceTile(const shared_ptr< RenderCanvas > &canvas, const shared_ptr< MetaIdentifier > &id, const shared_ptr< Tile > &tile) const
Definition: renderer.cpp:557
std::string string
Definition: settings.hpp:110
void label(cairo_t *cr, std::list< shared_ptr< Label > > &labels, AssetCache &cache)
FontWeight font_weight
Definition: style.hpp:94
void shield(cairo_t *cr, std::list< shared_ptr< Shield > > &shields, AssetCache &cache)
A Style stores the MapCSS properties for a single Node or Way, or a Relation of type multipolygon...
Definition: style.hpp:35
void renderArea(const FixedRect &area, const shared_ptr< RenderCanvas > &canvas, double width, double height, RenderAttributes &map, AssetCache &cache)
Definition: renderer.cpp:510
basic_rect< T > grow(T dx, T dy) const
Definition: rect.hpp:91
#define RENDERER_LABEL_OVERLAP
bool CompareLabels(const shared_ptr< LabelType > &first, const shared_ptr< LabelType > &second)
Sort labels according to their area and minX (for determinism)
Definition: renderer.cpp:83
FloatRect neighbours[8]
Definition: renderer.hpp:69
bool operator()(IdType first, IdType second)
Definition: renderer.cpp:70
void renderShields(cairo_t *cr, std::vector< shared_ptr< Shield > > &shields) const
Only renders the shield background, the text is rendered in renderLabels.
Definition: renderer.cpp:262
#define META_TILE_SIZE
Definition: settings.hpp:131
basic_rect< T > translate(T dx, T dy) const
Definition: rect.hpp:86
void placeShields(const std::list< shared_ptr< Shield > > &shields, std::vector< shared_ptr< Shield > > &placed)
Place labels with greedy algorithm.
Definition: renderer.cpp:424
float font_size
Definition: style.hpp:92
const shared_ptr< Geodata > data
stores the actual data
Definition: renderer.hpp:67
basic_vector2< double > FloatPoint
Definition: point.hpp:145
Color fill_color
Definition: style.hpp:79
bool isCutOff(const FloatRect &box, const FloatRect &owner)
Checks if all neighbour tile know about the owner of the label.
Definition: renderer.cpp:353
void renderLabels(cairo_t *cr, std::vector< shared_ptr< LabelType > > &labels, AssetCache &cache) const
Definition: renderer.cpp:313
basic_rect< T > getIntersection(const basic_rect< T > &other) const
Definition: rect.hpp:120
void renderObjects(CairoLayer *layers, RenderAttributes &map, const cairo_matrix_t *transform, std::vector< NodeId > &nodes, std::vector< WayId > &ways, std::vector< RelId > &relations, std::list< shared_ptr< Label >> &labels, std::list< shared_ptr< Shield >> &shields, AssetCache &cache) const
Renders a OSM layer onto the given cairo surface.
Definition: renderer.cpp:170
void compositeLayers(CairoLayer *layers) const
Composited all layers into the first layer.
Definition: renderer.cpp:449
This file is part of alaCarte.
const char * c_str() const
Returns the internal c string.
T maxX
Definition: rect.hpp:53
static boost::mutex renderLock
lock calls to cairo for old versions that are not thread-safe.
Definition: renderer.hpp:91
FontStyle font_style
Definition: style.hpp:95
TESTABLE void renderEmptyTile(RenderAttributes &map, const shared_ptr< RenderCanvas > &canvas, const shared_ptr< Tile > &tile)
Definition: renderer.cpp:485
Color text_halo_color
Definition: style.hpp:98
FloatRect neighbourRequests[8]
Definition: renderer.hpp:70
Sort objects according to osm-layer and z_index (and id for determinism)
Definition: renderer.cpp:63
void printTileId(cairo_t *cr, const shared_ptr< TileIdentifier > &id) const
Debug function that prints identifier on the tile.
Definition: renderer.cpp:115
void shield(cairo_t *cr, std::list< shared_ptr< Shield > > &shields, AssetCache &cache)
CompareObjects(const boost::unordered_map< IdType, Style * > &styles)
Definition: renderer.cpp:65
TESTABLE void renderMetaTile(RenderAttributes &map, const shared_ptr< RenderCanvas > &canvas, const shared_ptr< MetaIdentifier > &id)
Definition: renderer.cpp:583
Renderer(const shared_ptr< Geodata > &data)
Definition: renderer.cpp:90
Color shield_color
Definition: style.hpp:112
#define TILE_OVERLAP
Definition: settings.hpp:130
T maxY
Definition: rect.hpp:54
T minX
Definition: rect.hpp:51