libosmscout  1.1.1
LabelLayouter.h
Go to the documentation of this file.
1 #ifndef OSMSCOUT_MAP_LABELLAYOUTER_H
2 #define OSMSCOUT_MAP_LABELLAYOUTER_H
3 
4 /*
5  This source is part of the libosmscout-map library
6  Copyright (C) 2018 Lukas Karas
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 
23 #include <memory>
24 #include <set>
25 #include <array>
26 
28 
29 #include <osmscout/StyleConfig.h>
30 #include <osmscout/LabelPath.h>
31 #include <osmscout/system/Math.h>
32 
33 //#define DEBUG_LABEL_LAYOUTER
34 
35 #ifdef DEBUG_LABEL_LAYOUTER
36 #include <iostream>
37 #endif
38 
39 namespace osmscout {
40 
41  template <typename T>
42  struct Rectangle {
43  T x;
44  T y;
45  T width;
46  T height;
47 
48  // not initialised viewport
49  Rectangle() = default;
50 
51  Rectangle(T x, T y, T width, T height):
52  x(x), y(y), width(width), height(height)
53  {
54  }
55 
56  Rectangle<T>& Set(T nx, T ny, T nw, T nh)
57  {
58  x = nx;
59  y = ny;
60  width = nw;
61  height = nh;
62  return *this;
63  }
64 
73  bool Intersects(const Rectangle<T> &other)
74  {
75  return !(
76  (x + width) < other.x ||
77  x > (other.x + other.width) ||
78  (y + height) < other.y ||
79  y > (other.y + other.height)
80  );
81  }
82  };
83 
86 
88  {
89  public:
90  size_t priority{0};
91  std::string text;
92  double height;
96  };
97 
98  class LabelData
99  {
100  public:
101  enum Type
102  {
106  };
107  public:
108  Type type{Type::Text};
109  size_t priority{0};
110  size_t position{0};
111 
112  double alpha{1.0};
113  double fontSize{0};
114 
116  std::string text;
117 
119  double iconWidth{0};
120  double iconHeight{0};
121 
122  public:
123  LabelData() = default;
124  ~LabelData() = default;
125  };
126 
127 
128  template<class NativeGlyph>
129  class Glyph {
130  public:
131  NativeGlyph glyph;
132  osmscout::Vertex2D position;
133  double angle{0};
134 
135  osmscout::Vertex2D trPosition{0,0};
136  double trWidth{0};
137  double trHeight{0};
138  };
139 
143  template<class NativeGlyph, class NativeLabel>
144  class Label
145  {
146  public:
147  NativeLabel label;
148 
149  double width{-1};
150  double height{-1};
151 
152  double fontSize{1};
153  std::string text;
154 
155  Label() = default;
156 
157  template<typename... Args>
158  Label(Args&&... args):
159  label(std::forward<Args>(args)...)
160  {}
161 
168  std::vector<Glyph<NativeGlyph>> ToGlyphs() const;
169  };
170 
171  template<class NativeGlyph, class NativeLabel>
173  {
174  public:
175  struct Element
176  {
178  double x;
179  double y;
180  std::shared_ptr<Label<NativeGlyph, NativeLabel>>
182  };
183 
184  public:
185  size_t priority{std::numeric_limits<size_t>::max()};
186  // TODO: move priority from label to element
187  std::vector<Element> elements;
188  };
189 
190  template<class NativeGlyph>
192  {
193  public:
194 #ifdef DEBUG_LABEL_LAYOUTER
195  std::string text;
196 #endif
197  size_t priority;
198  std::vector<Glyph<NativeGlyph>> glyphs;
200  };
201 
202  class Mask
203  {
204  public:
205  explicit Mask(size_t rowSize) : d(rowSize)
206  {
207  };
208 
209  Mask(const Mask &m) = default;
210  ~Mask() = default;
211 
212  Mask(Mask &&m) = delete;
213  Mask &operator=(const Mask &m) = delete;
214  Mask &operator=(Mask &&m) = delete;
215 
216  OSMSCOUT_MAP_API void prepare(const IntRectangle &rect);
217 
218  int64_t size() const
219  {
220  return d.size();
221  };
222 
223  std::vector<uint64_t> d;
224 
225  int cellFrom{0};
226  int cellTo{0};
227  int rowFrom{0};
228  int rowTo{0};
229  };
230 
231  template <class NativeGlyph, class NativeLabel>
234  {
235  if (a.priority == b.priority) {
236  assert(!a.elements.empty());
237  assert(!b.elements.empty());
238  return a.elements[0].x < b.elements[0].x;
239  }
240  return a.priority < b.priority;
241  }
242 
243  template <class NativeGlyph>
245  const ContourLabel<NativeGlyph> &b)
246  {
247  if (a.priority == b.priority) {
248  assert(!a.glyphs.empty());
249  assert(!b.glyphs.empty());
250  return a.glyphs[0].trPosition.GetX() < b.glyphs[0].trPosition.GetX();
251  }
252  return a.priority < b.priority;
253  }
254 
276  template <class NativeGlyph, class NativeLabel, class TextLayouter>
278  {
279 
280  public:
283  using LabelPtr = std::shared_ptr<LabelType>;
285 
286  public:
287  explicit LabelLayouter(TextLayouter *textLayouter):
288  textLayouter(textLayouter)
289  {};
290 
292  {
293  visibleViewport = v;
294  SetLayoutOverlap(layoutOverlap);
295  }
296 
297  void SetLayoutOverlap(uint32_t overlap)
298  {
299  layoutOverlap = overlap;
300  layoutViewport.width = visibleViewport.width + (overlap * 2);
301  layoutViewport.height = visibleViewport.height + (overlap * 2);
302  layoutViewport.x = visibleViewport.x - overlap;
303  layoutViewport.y = visibleViewport.y - overlap;
304  }
305 
306  void Reset()
307  {
308  contourLabelInstances.clear();
309  labelInstances.clear();
310  }
311 
312  bool CheckLabelCollision(const std::vector<uint64_t> &canvas,
313  const Mask &mask,
314  int64_t viewportHeight) const
315  {
316  bool collision=false;
317  for (int r=std::max(0,mask.rowFrom); !collision && r<=std::min((int)viewportHeight-1, mask.rowTo); r++){
318  for (int c=std::max(0,mask.cellFrom); !collision && c<=std::min((int)mask.size()-1,mask.cellTo); c++){
319  collision |= (mask.d[c] & canvas[r*mask.size() + c]) != 0;
320  }
321  }
322  return collision;
323  }
324 
325  void MarkLabelPlace(std::vector<uint64_t> &canvas,
326  const Mask &mask,
327  int viewportHeight) const
328  {
329  for (int r=std::max(0,mask.rowFrom); r<=std::min((int)viewportHeight-1, mask.rowTo); r++){
330  for (int c=std::max(0,mask.cellFrom); c<=std::min((int)mask.size()-1, mask.cellTo); c++){
331  canvas[r*mask.size() + c] = mask.d[c] | canvas[r*mask.size() + c];
332  }
333  }
334  }
335 
336  // Something is an overlay, if its alpha is <0.8
337  bool IsOverlay(const LabelData &labelData) const
338  {
339  return labelData.alpha < 0.8;
340  }
341 
342  void Layout(const Projection& projection,
343  const MapParameter& parameter)
344  {
345  std::vector<ContourLabelType> allSortedContourLabels;
346  std::vector<LabelInstanceType> allSortedLabels;
347 
348  double iconPadding = projection.ConvertWidthToPixel(parameter.GetIconPadding());
349  double labelPadding = projection.ConvertWidthToPixel(parameter.GetLabelPadding());
350  double shieldLabelPadding = projection.ConvertWidthToPixel(parameter.GetPlateLabelPadding());
351  double contourLabelPadding = projection.ConvertWidthToPixel(parameter.GetContourLabelPadding());
352  double overlayLabelPadding = projection.ConvertWidthToPixel(parameter.GetOverlayLabelPadding());
353 
354  std::swap(allSortedLabels, labelInstances);
355  std::swap(allSortedContourLabels, contourLabelInstances);
356 
357  // sort labels by priority and position (to be deterministic)
358  std::stable_sort(allSortedLabels.begin(),
359  allSortedLabels.end(),
360  LabelInstanceSorter<NativeGlyph, NativeLabel>);
361  std::stable_sort(allSortedContourLabels.begin(),
362  allSortedContourLabels.end(),
363  ContourLabelSorter<NativeGlyph>);
364 
365  // compute collisions, hide some labels
366  int64_t rowSize = (layoutViewport.width / 64)+1;
367  std::vector<uint64_t> iconCanvas((size_t)(rowSize*layoutViewport.height));
368  std::vector<uint64_t> labelCanvas((size_t)(rowSize*layoutViewport.height));
369  std::vector<uint64_t> overlayCanvas((size_t)(rowSize*layoutViewport.height));
370 
371  auto labelIter = allSortedLabels.begin();
372  auto contourLabelIter = allSortedContourLabels.begin();
373  while (labelIter != allSortedLabels.end()
374  || contourLabelIter != allSortedContourLabels.end()) {
375 
376  auto currentLabel = labelIter;
377  auto currentContourLabel = contourLabelIter;
378  if (currentLabel != allSortedLabels.end()
379  && currentContourLabel != allSortedContourLabels.end()) {
380  if (currentLabel->priority != currentContourLabel->priority) {
381  if (currentLabel->priority < currentContourLabel->priority) {
382  currentContourLabel = allSortedContourLabels.end();
383  } else {
384  currentLabel = allSortedLabels.end();
385  }
386  }
387  }
388 
389  if (currentLabel != allSortedLabels.end()){
390  Mask m(rowSize);
391  std::vector<Mask> masks(currentLabel->elements.size(), m);
392  std::vector<std::vector<uint64_t> *> canvases(currentLabel->elements.size(), nullptr);
393 
394  std::vector<typename LabelInstance<NativeGlyph, NativeLabel>::Element> visibleElements;
395 
396  for (size_t eli=0; eli < currentLabel->elements.size(); eli++){
397  const typename LabelInstance<NativeGlyph, NativeLabel>::Element& element = currentLabel->elements[eli];
398  Mask& row=masks[eli];
399 
400  double padding;
401  if (element.labelData.type==LabelData::Icon || element.labelData.type==LabelData::Symbol) {
402  padding = iconPadding;
403  } else if (IsOverlay(element.labelData)) {
404  padding = overlayLabelPadding;
405  } else if (dynamic_cast<const ShieldStyle*>(element.labelData.style.get())!=nullptr){
406  padding = shieldLabelPadding;
407  } else {
408  padding = labelPadding;
409  }
410 
411  IntRectangle rectangle{ (int)std::floor(element.x - layoutViewport.x - padding),
412  (int)std::floor(element.y - layoutViewport.y - padding),
413  0, 0 };
414  std::vector<uint64_t> *canvas = &labelCanvas;
415  if (element.labelData.type==LabelData::Icon || element.labelData.type==LabelData::Symbol){
416  if (element.labelData.iconStyle->IsOverlay()) {
417  rectangle.width = 0;
418  rectangle.height = 0;
419  }
420  else {
421  rectangle.width = std::ceil(element.labelData.iconWidth + 2*padding);
422  rectangle.height = std::ceil(element.labelData.iconHeight + 2*padding);
423  }
424  canvas = &iconCanvas;
425 #ifdef DEBUG_LABEL_LAYOUTER
426  if (element.labelData.type==LabelData::Icon) {
427  std::cout << "Test icon " << element.labelData.iconStyle->GetIconName() <<
428  " prio " << currentLabel->priority;
429  }else{
430  std::cout << "Test symbol " << element.labelData.iconStyle->GetSymbol()->GetName() <<
431  " prio " << currentLabel->priority;
432  }
433 #endif
434  } else {
435 #ifdef DEBUG_LABEL_LAYOUTER
436  std::cout << "Test " << (IsOverlay(element.labelData) ? "overlay " : "") <<
437  "label prio " << currentLabel->priority << ": " <<
438  element.labelData.text;
439 #endif
440 
441  rectangle.width = std::ceil(element.label->width + 2*padding);
442  rectangle.height = std::ceil(element.label->height + 2*padding);
443 
444  if (IsOverlay(element.labelData)){
445  canvas = &overlayCanvas;
446  }
447  }
448  row.prepare(rectangle);
449  bool collision = CheckLabelCollision(*canvas, row, layoutViewport.height);
450  if (!collision) {
451  visibleElements.push_back(element);
452  canvases[eli]=canvas;
453  }
454 #ifdef DEBUG_LABEL_LAYOUTER
455  std::cout << " -> " << (collision ? "skipped" : "added") << std::endl;
456  // p->DrawRectangle(rectangle.x, rectangle.y,
457  // rectangle.width, rectangle.height,
458  // collision ? Color(0.8, 0, 0, 0.8): Color(0, 0.8, 0, 0.8));
459 #endif
460  }
461  LabelInstanceType instanceCopy;
462  instanceCopy.priority = currentLabel->priority;
463  instanceCopy.elements = visibleElements;
464  if (!instanceCopy.elements.empty()) {
465  labelInstances.push_back(instanceCopy);
466 
467  // mark all labels at once
468  for (size_t eli=0; eli < currentLabel->elements.size(); eli++) {
469  if (canvases[eli] != nullptr) {
470  MarkLabelPlace(*(canvases[eli]), masks[eli], layoutViewport.height);
471  }
472  }
473  }
474 
475  labelIter++;
476  }
477 
478  if (currentContourLabel != allSortedContourLabels.end()){
479  int glyphCnt=currentContourLabel->glyphs.size();
480 
481 #ifdef DEBUG_LABEL_LAYOUTER
482  std::cout << "Test contour label prio " << currentContourLabel->priority << ": " << currentContourLabel->text;
483 #endif
484 
485  Mask m(rowSize);
486  std::vector<Mask> masks(glyphCnt, m);
487  bool collision=false;
488  for (int gi=0; !collision && gi<glyphCnt; gi++) {
489 
490  auto glyph=currentContourLabel->glyphs[gi];
491  IntRectangle rect{
492  (int)(glyph.trPosition.GetX() - layoutViewport.x - contourLabelPadding),
493  (int)(glyph.trPosition.GetY() - layoutViewport.y - contourLabelPadding),
494  (int)(glyph.trWidth + 2*contourLabelPadding),
495  (int)(glyph.trHeight + 2*contourLabelPadding)
496  };
497  masks[gi].prepare(rect);
498  collision |= CheckLabelCollision(labelCanvas, masks[gi], layoutViewport.height);
499  }
500  if (!collision) {
501  for (int gi=0; gi<glyphCnt; gi++) {
502  MarkLabelPlace(labelCanvas, masks[gi], layoutViewport.height);
503  }
504  contourLabelInstances.push_back(*currentContourLabel);
505  }
506 #ifdef DEBUG_LABEL_LAYOUTER
507  std::cout << " -> " << (collision ? "skipped" : "added") << std::endl;
508 #endif
509  contourLabelIter++;
510  }
511  }
512  }
513 
543  template<class Painter>
544  void DrawLabels(const Projection& projection,
545  const MapParameter& parameter,
546  Painter *p)
547  {
548  // draw symbols and icons first, then standard labels and then overlays
549  std::vector<const typename LabelInstanceType::Element*> textElements;
550  std::vector<const typename LabelInstanceType::Element*> overlayElements;
551 
552  for (const LabelInstanceType &inst : Labels()){
553  for (const typename LabelInstanceType::Element &el : inst.elements) {
554  DoubleRectangle elementRectangle;
555  if (el.labelData.type==LabelData::Text) {
556  elementRectangle.Set(el.x, el.y, el.label->width, el.label->height);
557  }else{
558  elementRectangle.Set(el.x, el.y, el.labelData.iconWidth, el.labelData.iconHeight);
559  }
560 
561  if (!visibleViewport.Intersects(elementRectangle)){
562  continue;
563  }
564 
566  p->DrawSymbol(projection,
567  parameter,
568  *(el.labelData.iconStyle->GetSymbol()),
569  el.x + el.labelData.iconWidth/2,
570  el.y + el.labelData.iconHeight/2);
571 
572  } else if (el.labelData.type==LabelData::Icon){
573  p->DrawIcon(el.labelData.iconStyle.get(),
574  el.x + el.labelData.iconWidth/2,
575  el.y + el.labelData.iconHeight/2,
576  el.labelData.iconWidth,
577  el.labelData.iconHeight);
578 
579  } else {
580  // postpone text elements
581  if (IsOverlay(el.labelData)){
582  overlayElements.push_back(&el);
583  }else {
584  textElements.push_back(&el);
585  }
586  }
587  }
588  }
589 
590  // draw postponed text elements
591  for (const typename LabelInstanceType::Element *el : textElements) {
592  p->DrawLabel(projection, parameter,
593  DoubleRectangle(el->x, el->y, el->label->width, el->label->height),
594  el->labelData, el->label->label);
595  }
596 
597  for (const typename LabelInstanceType::Element *el : overlayElements) {
598  p->DrawLabel(projection, parameter,
599  DoubleRectangle(el->x, el->y, el->label->width, el->label->height),
600  el->labelData, el->label->label);
601  }
602 
603  for (const ContourLabelType &label:ContourLabels()){
604  p->DrawGlyphs(projection, parameter,
605  label.style, label.glyphs);
606  }
607  }
608 
609  void RegisterLabel(const Projection& projection,
610  const MapParameter& parameter,
611  const Vertex2D& point,
612  const std::vector<LabelData> &data,
613  double objectWidth = 10.0)
614  {
615  LabelInstanceType instance;
616 
617  double offset=-1;
618  for (const auto &d:data) {
620  element.labelData=d;
621  if (d.type==LabelData::Type::Icon || d.type==LabelData::Type::Symbol){
622  instance.priority = std::min(d.priority, instance.priority);
623  element.x = point.GetX() - d.iconWidth / 2;
624  if (offset<0){
625  element.y = point.GetY() - d.iconHeight / 2;
626  offset = point.GetY() + d.iconHeight / 2;
627  } else {
628  element.y = offset;
629  offset += d.iconHeight;
630  }
631  }else {
632  instance.priority = std::min(d.priority, instance.priority);
633  // TODO: should we take style into account?
634  // Qt allows to split text layout and style setup
635  element.label = textLayouter->Layout(projection, parameter,
636  d.text, d.fontSize,
637  objectWidth,
638  /*enable wrapping*/ true,
639  /*contour label*/ false);
640  element.x = point.GetX() - element.label->width / 2;
641  if (offset<0){
642  element.y = point.GetY() - element.label->height / 2;
643  offset = point.GetY() + element.label->height / 2;
644  } else {
645  element.y = offset;
646  offset += element.label->height;
647  }
648  }
649  instance.elements.push_back(element);
650  }
651 
652  labelInstances.push_back(instance);
653  }
654 
655  void RegisterContourLabel(const Projection& projection,
656  const MapParameter& parameter,
657  const PathLabelData &labelData,
658  const LabelPath &labelPath)
659  {
660  // TODO: cache label for string and font parameters
661  LabelPtr label = textLayouter->Layout(
662  projection,
663  parameter,
664  labelData.text,
665  labelData.height,
666  /* object width */ 0.0,
667  /*enable wrapping*/ false,
668  /*contour label*/ true);
669 
670  // text should be rendered with 0x0 coordinate as left baseline
671  // we want to move label little bit bottom, near to line center
672  double textBaselineOffset = label->height * 0.25;
673 
674  std::vector<Glyph<NativeGlyph>> glyphs = label->ToGlyphs();
675 
676  double pLength=labelPath.GetLength();
677  double offset=labelData.contourLabelOffset;
678 
679  while (offset+label->width < pLength){
680  double labelSpaceCount=size_t(label->width/labelData.contourLabelSpace)+1;
681 
682  double nextOffset = offset+labelSpaceCount*labelData.contourLabelSpace;
683 
684  // skip string rendering when path is too much squiggly at this offset
685  if (!labelPath.TestAngleVariance(offset,offset+label->width,M_PI_4)){
686  // skip drawing current label and let offset point to the next instance
687  offset=nextOffset;
688  continue;
689  }
690 
691  ContourLabelType cLabel;
692  cLabel.priority = labelData.priority;
693  cLabel.style = labelData.style;
694 
695 #if defined(DEBUG_LABEL_LAYOUTER)
696  cLabel.text = labelData.text;
697 #endif
698 
699  // do the magic to make sure that we don't render label upside-down
700 
701  // direction of path at the label drawing starting point
702  double initialAngle=std::abs(labelPath.AngleAtLengthDeg(offset));
703  bool upwards=initialAngle>90 && initialAngle<270;
704 
705  for (const Glyph<NativeGlyph> &glyph:glyphs){
706  double glyphOffset = upwards ?
707  offset - glyph.position.GetX() + label->width:
708  offset + glyph.position.GetX();
709  osmscout::Vertex2D point=labelPath.PointAtLength(glyphOffset);
710 
711  DoubleRectangle textBoundingBox = textLayouter->GlyphBoundingBox(glyph.glyph);
712  double w = textBoundingBox.width;
713  double h = textBoundingBox.height;
714  osmscout::Vertex2D tl(textBoundingBox.x, textBoundingBox.y);
715 
716  // glyph angle in radians
717  double angle=labelPath.AngleAtLength(upwards ? glyphOffset - w/2 : glyphOffset + w/2)*-1;
718 
719  // it is not real diagonal, but maximum distance from glyph
720  // point that can be covered after transformations
721  double diagonal=w+h+std::abs(textBaselineOffset);
722 
723  // fast check if current glyph can be visible
724  if (!layoutViewport.Intersects(DoubleRectangle{
725  point.GetX()-diagonal,
726  point.GetY()-diagonal,
727  2*diagonal,
728  2*diagonal
729  })){
730  continue;
731  }
732 
733  if (upwards) {
734  angle-=M_PI;
735  }
736  double sinA=std::sin(angle);
737  double cosA=std::cos(angle);
738 
739  Glyph<NativeGlyph> glyphCopy=glyph;
740  glyphCopy.position=osmscout::Vertex2D(point.GetX() - textBaselineOffset * sinA,
741  point.GetY() + textBaselineOffset * cosA);
742  glyphCopy.angle=angle;
743 
744  // four coordinates of glyph bounding box; x,y of top-left, top-right, bottom-right, bottom-left
745  std::array<double, 4> x{tl.GetX(), tl.GetX() + w, tl.GetX() + w, tl.GetX()};
746  std::array<double, 4> y{tl.GetY(), tl.GetY(), tl.GetY() + h, tl.GetY() + h};
747 
748  // rotate
749  for (int i=0; i<4; i++){
750  double ox = x[i];
751  double oy = y[i];
752  x[i] = ox * cosA - oy * sinA;
753  y[i] = ox * sinA + oy * cosA;
754  }
755 
756  // bounding box after rotation
757  double minX=x[0];
758  double maxX=x[0];
759  double minY=y[0];
760  double maxY=y[0];
761  for (int i=1; i<4; i++){
762  minX = std::min(minX, x[i]);
763  maxX = std::max(maxX, x[i]);
764  minY = std::min(minY, y[i]);
765  maxY = std::max(maxY, y[i]);
766  }
767  // setup glyph top-left position and dimension after rotation
768  glyphCopy.trPosition.Set(minX+glyphCopy.position.GetX(), minY+glyphCopy.position.GetY());
769  glyphCopy.trWidth = maxX - minX;
770  glyphCopy.trHeight = maxY - minY;
771 
772  cLabel.glyphs.push_back(glyphCopy);
773  }
774  if (!cLabel.glyphs.empty()) { // is some glyph visible?
775  contourLabelInstances.push_back(cLabel);
776  }
777 
778  offset=nextOffset;
779  }
780  }
781 
782  const std::vector<LabelInstanceType>& Labels() const
783  {
784  return labelInstances;
785  }
786 
787  const std::vector<ContourLabelType>& ContourLabels() const
788  {
789  return contourLabelInstances;
790  }
791 
792  private:
793  TextLayouter *textLayouter;
794  std::vector<ContourLabelType> contourLabelInstances;
795  std::vector<LabelInstanceType> labelInstances;
796  DoubleRectangle visibleViewport{0,0,0,0};
797  DoubleRectangle layoutViewport{0,0,0,0};
798  uint32_t layoutOverlap=0; // overlap [pixels] used for label layouting
799  };
800 
801 }
802 
803 #endif
void RegisterContourLabel(const Projection &projection, const MapParameter &parameter, const PathLabelData &labelData, const LabelPath &labelPath)
Definition: LabelLayouter.h:655
double ConvertWidthToPixel(double width) const
Definition: Projection.h:280
Definition: LabelLayouter.h:144
Mask(size_t rowSize)
Definition: LabelLayouter.h:205
~Mask()=default
double iconWidth
Definition: LabelLayouter.h:119
T width
Definition: LabelLayouter.h:45
Type
Definition: LabelLayouter.h:101
std::string text
The label text.
Definition: LabelLayouter.h:153
double angle
clock-wise rotation in radians
Definition: LabelLayouter.h:133
LabelData labelData
Definition: LabelLayouter.h:177
T height
Definition: LabelLayouter.h:46
Definition: LabelLayouter.h:105
const std::vector< ContourLabelType > & ContourLabels() const
Definition: LabelLayouter.h:787
size_t position
Relative position of the label.
Definition: LabelLayouter.h:110
NativeLabel label
Definition: LabelLayouter.h:147
Definition: LabelLayouter.h:87
void MarkLabelPlace(std::vector< uint64_t > &canvas, const Mask &mask, int viewportHeight) const
Definition: LabelLayouter.h:325
void Reset()
Definition: LabelLayouter.h:306
size_t priority
Priority of the entry (minimum of priority label elements)
Definition: LabelLayouter.h:185
void RegisterLabel(const Projection &projection, const MapParameter &parameter, const Vertex2D &point, const std::vector< LabelData > &data, double objectWidth=10.0)
Definition: LabelLayouter.h:609
double width
Definition: LabelLayouter.h:149
double contourLabelSpace
Definition: LabelLayouter.h:95
LabelStyleRef style
Style for drawing.
Definition: LabelLayouter.h:115
STL namespace.
bool CheckLabelCollision(const std::vector< uint64_t > &canvas, const Mask &mask, int64_t viewportHeight) const
Definition: LabelLayouter.h:312
Rectangle(T x, T y, T width, T height)
Definition: LabelLayouter.h:51
void SetLayoutOverlap(uint32_t overlap)
Definition: LabelLayouter.h:297
std::vector< Element > elements
Definition: LabelLayouter.h:187
Definition: LabelLayouter.h:172
Definition: LabelLayouter.h:175
void DrawLabels(const Projection &projection, const MapParameter &parameter, Painter *p)
Definition: LabelLayouter.h:544
OSMSCOUT_MAP_API void prepare(const IntRectangle &rect)
Type type
Definition: LabelLayouter.h:108
const std::vector< LabelInstanceType > & Labels() const
Definition: LabelLayouter.h:782
double iconHeight
Definition: LabelLayouter.h:120
std::shared_ptr< LabelType > LabelPtr
Definition: LabelLayouter.h:283
double trHeight
height after rotation
Definition: LabelLayouter.h:137
osmscout::Vertex2D trPosition
top-left position after rotation
Definition: LabelLayouter.h:135
T y
Definition: LabelLayouter.h:44
bool IsOverlay(const LabelData &labelData) const
Definition: LabelLayouter.h:337
double x
Coordinate of the left, top edge of the text / icon / symbol.
Definition: LabelLayouter.h:178
void SetViewport(const DoubleRectangle &v)
Definition: LabelLayouter.h:291
double alpha
Alpha value of the label; 0.0 = fully transparent, 1.0 = solid.
Definition: LabelLayouter.h:112
bool TestAngleVariance(double startOffset, double endOffset, double maximumAngle) const
Mask & operator=(const Mask &m)=delete
Definition: LabelLayouter.h:277
Definition: LabelLayouter.h:191
Definition: LabelLayouter.h:103
int64_t size() const
Definition: LabelLayouter.h:218
Definition: Projection.h:43
double y
Coordinate of the left, top edge of the text / icon / symbol.
Definition: LabelLayouter.h:179
std::shared_ptr< PathTextStyle > PathTextStyleRef
Definition: Styles.h:877
Definition: Area.h:38
std::shared_ptr< Label< NativeGlyph, NativeLabel > > label
Definition: LabelLayouter.h:181
std::vector< Glyph< NativeGlyph > > glyphs
Definition: LabelLayouter.h:198
osmscout::Vertex2D position
glyph baseline position
Definition: LabelLayouter.h:132
int cellFrom
Definition: LabelLayouter.h:225
double AngleAtLengthDeg(double offset) const
double GetLength() const
Definition: LabelPath.h:56
void Layout(const Projection &projection, const MapParameter &parameter)
Definition: LabelLayouter.h:342
IconStyleRef iconStyle
Icon or symbol style.
Definition: LabelLayouter.h:118
Definition: LabelLayouter.h:104
Definition: LabelLayouter.h:202
Label(Args &&... args)
Definition: LabelLayouter.h:158
Definition: LabelPath.h:42
Definition: LabelLayouter.h:98
#define OSMSCOUT_MAP_API
Definition: MapImportExport.h:45
int cellTo
Definition: LabelLayouter.h:226
double AngleAtLength(double offset) const
bool Intersects(const Rectangle< T > &other)
Definition: LabelLayouter.h:73
Definition: LabelLayouter.h:42
std::vector< uint64_t > d
Definition: LabelLayouter.h:221
PathTextStyleRef style
Definition: LabelLayouter.h:93
Definition: LabelLayouter.h:129
int rowTo
Definition: LabelLayouter.h:228
size_t priority
Definition: LabelLayouter.h:197
size_t priority
Priority of the entry.
Definition: LabelLayouter.h:90
double trWidth
width after rotation
Definition: LabelLayouter.h:136
NativeGlyph glyph
Definition: LabelLayouter.h:131
std::vector< Glyph< NativeGlyph > > ToGlyphs() const
Rectangle< double > DoubleRectangle
Definition: LabelLayouter.h:85
Label()=default
Vertex2D PointAtLength(double offset) const
std::shared_ptr< LabelStyle > LabelStyleRef
Definition: Styles.h:496
osmscout::PathTextStyleRef style
Style for drawing.
Definition: LabelLayouter.h:199
LabelLayouter(TextLayouter *textLayouter)
Definition: LabelLayouter.h:287
size_t priority
Priority of the entry.
Definition: LabelLayouter.h:109
double contourLabelOffset
Definition: LabelLayouter.h:94
static bool ContourLabelSorter(const ContourLabel< NativeGlyph > &a, const ContourLabel< NativeGlyph > &b)
Definition: LabelLayouter.h:244
double height
Definition: LabelLayouter.h:150
Rectangle< T > & Set(T nx, T ny, T nw, T nh)
Definition: LabelLayouter.h:56
int rowFrom
Definition: LabelLayouter.h:227
double fontSize
Font size to be used.
Definition: LabelLayouter.h:113
double fontSize
Font size to be used.
Definition: LabelLayouter.h:152
double height
Definition: LabelLayouter.h:92
std::string text
The label text (type==Text|PathText)
Definition: LabelLayouter.h:116
static bool LabelInstanceSorter(const LabelInstance< NativeGlyph, NativeLabel > &a, const LabelInstance< NativeGlyph, NativeLabel > &b)
Definition: LabelLayouter.h:232
std::string text
The label text (type==Text|PathText)
Definition: LabelLayouter.h:91
std::shared_ptr< IconStyle > IconStyleRef
Definition: Styles.h:975
T x
Definition: LabelLayouter.h:43