libosmscout 1.1.1
Loading...
Searching...
No Matches
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
32
34
35#include <iostream>
36
37namespace osmscout {
38
39#ifdef OSMSCOUT_DEBUG_LABEL_LAYOUTER
40constexpr bool debugLabelLayouter = true;
41#else
42constexpr bool debugLabelLayouter = false;
43#endif
44
46 {
47 public:
48 size_t priority{0};
49 std::string text;
50 double height;
54 };
55
57 {
58 public:
59 enum Type
60 {
64 };
65 public:
67 size_t priority{0};
68 size_t position{0};
69
70 double alpha{1.0};
71 double fontSize{0};
72
74 std::string text;
75
77 double iconWidth{0};
78 double iconHeight{0};
79
80 public:
81 LabelData() = default;
82 ~LabelData() = default;
83 };
84
85 class OSMSCOUT_MAP_API ContourLabelPositioner CLASS_FINAL
86 {
87 public:
88 struct Position
89 {
90 size_t labelCount;
91 double offset;
92 double labelSpace;
93 };
94 public:
96 const MapParameter& parameter,
97 const PathLabelData &labelData,
98 double pathLength,
99 double labelWidth) const;
100 };
101
102 template<class NativeGlyph>
103 class Glyph {
104 public:
105 NativeGlyph glyph;
106 Vertex2D position;
107 double angle{0};
108
109 Vertex2D trPosition{0,0};
110 double trWidth{0};
111 double trHeight{0};
112 };
113
117 template<class NativeGlyph, class NativeLabel>
118 class Label
119 {
120 public:
121 NativeLabel label;
122
123 double width{-1};
124 double height{-1};
125
126 double fontSize{1};
127 std::string text;
128
129 Label() = default;
130
131 template<typename... Args>
132 explicit Label(Args&&... args):
133 label(std::forward<Args>(args)...)
134 {}
135
142 std::vector<Glyph<NativeGlyph>> ToGlyphs() const;
143 };
144
145 template<class NativeGlyph, class NativeLabel>
147 {
148 public:
149 struct Element
150 {
152 double x;
153 double y;
154 std::shared_ptr<Label<NativeGlyph, NativeLabel>>
156 };
157
158 public:
159 ObjectFileRef ref;
160 size_t priority{std::numeric_limits<size_t>::max()};
161 // TODO: move priority from label to element
162 std::vector<Element> elements;
163 };
164
165 template<class NativeGlyph>
167 {
168 public:
169#ifdef OSMSCOUT_DEBUG_LABEL_LAYOUTER
170 std::string text;
171 double offset;
172 Vertex2D start;
173#endif
174 ObjectFileRef ref;
175 size_t priority;
176 std::vector<Glyph<NativeGlyph>> glyphs;
178 };
179
180 template <class NativeGlyph, class NativeLabel>
183 {
184 if (a.priority != b.priority) {
185 return a.priority < b.priority;
186 }
187
188 return a.ref < b.ref;
189 }
190
191 template <class NativeGlyph>
194 {
195
196 if (a.priority != b.priority) {
197 return a.priority < b.priority;
198 }
199
200 if (a.ref != b.ref) {
201 return a.ref < b.ref;
202 }
203
204 return a.glyphs[0].trPosition.GetX() < b.glyphs[0].trPosition.GetX();
205 }
206
228 template <class NativeGlyph, class NativeLabel, class TextLayouter>
230 {
231
232 public:
235 using LabelPtr = std::shared_ptr<LabelType>;
237
238 public:
239 explicit LabelLayouter(TextLayouter *textLayouter):
240 textLayouter(textLayouter)
241 {};
242
244 {
245 visibleViewport = v;
246 SetLayoutOverlap(layoutOverlap);
247 }
248
249 void SetLayoutOverlap(uint32_t overlap)
250 {
251 layoutOverlap = overlap;
252 layoutViewport.width = visibleViewport.width + (overlap * 2);
253 layoutViewport.height = visibleViewport.height + (overlap * 2);
254 layoutViewport.x = visibleViewport.x - overlap;
255 layoutViewport.y = visibleViewport.y - overlap;
256 }
257
258 void Reset()
259 {
260 contourLabelInstances.clear();
261 labelInstances.clear();
262 }
263
264 // Something is an overlay, if its alpha is <0.8
265 static bool IsOverlay(const LabelData &labelData)
266 {
267 return labelData.alpha < 0.8;
268 }
269
278 struct LayoutJob {
280
286
287 std::vector<ContourLabelType> allSortedContourLabels;
288 std::vector<LabelInstanceType> allSortedLabels;
289
290 ScreenMask iconCanvas;
291 ScreenMask labelCanvas;
292 ScreenMask overlayCanvas;
293
295 const Projection& projection,
296 const MapParameter& parameter):
298 iconPadding(projection.ConvertWidthToPixel(parameter.GetIconPadding())),
299 labelPadding(projection.ConvertWidthToPixel(parameter.GetLabelPadding())),
300 shieldLabelPadding(projection.ConvertWidthToPixel(parameter.GetPlateLabelPadding())),
301 contourLabelPadding(projection.ConvertWidthToPixel(parameter.GetContourLabelPadding())),
302 overlayLabelPadding(projection.ConvertWidthToPixel(parameter.GetOverlayLabelPadding())),
306 {
307 }
308
309 LayoutJob(const LayoutJob&) = delete;
310 LayoutJob(LayoutJob&&) = delete;
311 ~LayoutJob() = default;
312 LayoutJob& operator=(const LayoutJob&) = delete;
314
315 void Swap(std::vector<LabelInstanceType> &labelInstances,
316 std::vector<ContourLabelType> &contourLabelInstances)
317 {
318 std::swap(allSortedLabels, labelInstances);
319 std::swap(allSortedContourLabels, contourLabelInstances);
320 }
321
323 {
324 // sort labels by priority and position (to be deterministic)
325 std::stable_sort(allSortedLabels.begin(),
326 allSortedLabels.end(),
328 std::stable_sort(allSortedContourLabels.begin(),
331 }
332
333 double GetLabelPadding(const LabelData &labelData) const
334 {
335 if (labelData.type==LabelData::Icon || labelData.type==LabelData::Symbol) {
336 return iconPadding;
337 }
338
339 if (IsOverlay(labelData)) {
340 return overlayLabelPadding;
341 }
342
343 if (dynamic_cast<const ShieldStyle*>(labelData.style.get())!=nullptr){
344 return shieldLabelPadding;
345 }
346
347 return labelPadding;
348 }
349
350 ScreenMask* GetCanvas(LabelData data) {
351 if (data.type==LabelData::Icon || data.type==LabelData::Symbol){
352 return &iconCanvas;
353 }
354
355 if (IsOverlay(data)) {
356 return &overlayCanvas;
357 }
358
359 return &labelCanvas;
360 }
361
362 void ProcessLabelInstance(const LabelInstanceType &currentLabel,
363 std::vector<LabelInstanceType> &labelInstances)
364
365 {
366 size_t elementCount = currentLabel.elements.size(); // Number of elements in label
367 std::vector<ScreenRectMask> masks(elementCount); // Vector of masks of each individual object
368 std::vector<ScreenMask*> canvases(elementCount, nullptr); // Corresponding canvas for each label or null (if collision)
369
370 // List of elements to be rendered (no collision)
371 std::vector<typename LabelInstance<NativeGlyph, NativeLabel>::Element> visibleElements;
372
373 for (size_t eli=0; eli < elementCount; eli++) {
374 const typename LabelInstance<NativeGlyph, NativeLabel>::Element& element = currentLabel.elements[eli];
375 ScreenRectMask &mask=masks[eli];
376 ScreenMask *canvas=GetCanvas(element.labelData);
377 double padding=GetLabelPadding(element.labelData);
378
379 ScreenPixelRectangle rectangle{(int)(element.x - layoutViewport.x - padding),
380 (int)(element.y - layoutViewport.y - padding),
381 0, 0 };
382
384 if (element.labelData.iconStyle->IsOverlay()) {
385 rectangle.width = 0;
386 rectangle.height = 0;
387 }
388 else {
389 rectangle.width = element.labelData.iconWidth + 2*padding;
390 rectangle.height = element.labelData.iconHeight + 2*padding;
391 }
392
393 if constexpr (debugLabelLayouter) {
394 if (element.labelData.type == LabelData::Icon) {
395 std::cout << "Test icon " << element.labelData.iconStyle->GetIconName() <<
396 " prio " << currentLabel.priority;
397 } else {
398 std::cout << "Test symbol " << element.labelData.iconStyle->GetSymbol()->GetName() <<
399 " prio " << currentLabel.priority;
400 }
401 }
402 }
403 else {
404 if constexpr (debugLabelLayouter) {
405 std::cout << "Test " << (IsOverlay(element.labelData) ? "overlay " : "")
406 << "label prio " << currentLabel.priority << ": "
407 << element.labelData.text;
408 }
409
410 rectangle.width = element.label->width + 2*padding;
411 rectangle.height = element.label->height + 2*padding;
412 }
413
414 mask=ScreenRectMask(layoutViewport.width,
415 rectangle);
416
417 bool collision = canvas->HasCollision(mask);
418
419 if (!collision) {
420 visibleElements.push_back(element);
421 canvases[eli]=canvas;
422 }
423
424 if constexpr (debugLabelLayouter) {
425 std::cout << " -> " << (collision ? "skipped" : "added") << std::endl;
426 // p->DrawRectangle(rectangle.x, rectangle.y,
427 // rectangle.width, rectangle.height,
428 // collision ? Color(0.8, 0, 0, 0.8): Color(0, 0.8, 0, 0.8));
429 }
430 }
431
432 if (!visibleElements.empty()) {
433 LabelInstanceType instanceCopy{currentLabel.ref,currentLabel.priority, visibleElements};
434 labelInstances.push_back(instanceCopy);
435
436 // mark all labels at once (elements of single label may have no padding)
437
438 for (size_t eli=0; eli < elementCount; eli++) {
439 if (canvases[eli] != nullptr) {
440 canvases[eli]->AddMask(masks[eli]);
441 }
442 }
443 }
444 }
445
446 void ProcessLabelContourLabel(const ContourLabelType &currentContourLabel,
447 std::vector<ContourLabelType> &contourLabelInstances)
448 {
449 int glyphCnt=currentContourLabel.glyphs.size();
450
451 if constexpr (debugLabelLayouter) {
452 std::cout << "Test contour label prio " << currentContourLabel.priority << ": " << currentContourLabel.text;
453 }
454
455 std::vector<ScreenRectMask> masks(glyphCnt);
456
457 bool collision=false;
458 for (int gi=0; gi<glyphCnt; gi++) {
459 auto glyph=currentContourLabel.glyphs[gi];
461 (int)(glyph.trPosition.GetX() - layoutViewport.x - contourLabelPadding),
462 (int)(glyph.trPosition.GetY() - layoutViewport.y - contourLabelPadding),
463 (int)(glyph.trWidth + 2*contourLabelPadding),
464 (int)(glyph.trHeight + 2*contourLabelPadding)
465 };
466
467 masks[gi]=ScreenRectMask(layoutViewport.width,
468 rect);
469
470 if (labelCanvas.HasCollision(masks[gi])) {
471 collision=true;
472 break;
473 }
474 }
475
476 if (!collision) {
477 for (int gi=0; gi<glyphCnt; gi++) {
478 labelCanvas.AddMask(masks[gi]);
479 }
480
481 contourLabelInstances.push_back(currentContourLabel);
482 }
483
484 if constexpr (debugLabelLayouter) {
485 std::cout << " -> " << (collision ? "skipped" : "added") << std::endl;
486 }
487 };
488
489 void ProcessLabels(std::vector<LabelInstanceType> &labelInstances,
490 std::vector<ContourLabelType> &contourLabelInstances)
491 {
492 labelInstances.reserve(allSortedLabels.size());
493 contourLabelInstances.reserve(allSortedContourLabels.size());
494
495 // Get first entries
496
497 auto labelIter = allSortedLabels.begin();
498 auto contourLabelIter = allSortedContourLabels.begin();
499
500 // While both lists are not completely processed...
501 // Process first all contour labels of a priority and then all normal labels of the same priority
502
503 while (labelIter != allSortedLabels.end() &&
504 contourLabelIter != allSortedContourLabels.end()) {
505
506 if (contourLabelIter->priority<=labelIter->priority) {
507 ProcessLabelContourLabel(*contourLabelIter, contourLabelInstances);
508 contourLabelIter++;
509 }
510 else {
511 ProcessLabelInstance(*labelIter, labelInstances);
512 labelIter++;
513 }
514
515 }
516
517 // Process all the rest... (there should only be one of the two lists left)
518
519 while (contourLabelIter != allSortedContourLabels.end()) {
520 ProcessLabelContourLabel(*contourLabelIter, contourLabelInstances);
521 contourLabelIter++;
522 }
523
524 while (labelIter != allSortedLabels.end()) {
525 ProcessLabelInstance(*labelIter, labelInstances);
526 labelIter++;
527 }
528 }
529 };
530
531 void Layout(const Projection& projection,
532 const MapParameter& parameter)
533 {
534 // compute collisions, hide some labels
535 LayoutJob job(layoutViewport, projection, parameter);
536 job.Swap(labelInstances, contourLabelInstances);
537 job.SortLabels();
538 job.ProcessLabels(labelInstances, contourLabelInstances);
539 }
540
541 template<class Painter>
542 void DrawTextLabels(const Projection& /*projection*/,
543 const MapParameter& /*parameter*/,
544 Painter */*p*/) const
545 {
546
547 }
548
578 template<class Painter>
579 void DrawLabels(const Projection& projection,
580 const MapParameter& parameter,
581 Painter *p)
582 {
583 // draw symbols and icons first, then standard labels and then overlays
584 std::vector<const typename LabelInstanceType::Element*> textElements;
585 std::vector<const typename LabelInstanceType::Element*> overlayElements;
586
587 for (const LabelInstanceType &inst : Labels()){
588 for (const typename LabelInstanceType::Element &el : inst.elements) {
589 ScreenVectorRectangle elementRectangle;
591 elementRectangle.Set(el.x, el.y, el.label->width, el.label->height);
592 }else{
593 elementRectangle.Set(el.x, el.y, el.labelData.iconWidth, el.labelData.iconHeight);
594 }
595
596 if (!visibleViewport.Intersects(elementRectangle)){
597 continue;
598 }
599
601 p->DrawSymbol(projection,
602 parameter,
603 *(el.labelData.iconStyle->GetSymbol()),
604 Vertex2D(el.x + el.labelData.iconWidth/2,
605 el.y + el.labelData.iconHeight/2),
606 1.0);
607
608 } else if (el.labelData.type==LabelData::Icon){
609 p->DrawIcon(el.labelData.iconStyle.get(),
610 Vertex2D(el.x + el.labelData.iconWidth/2,
611 el.y + el.labelData.iconHeight/2),
614
615 } else {
616 // postpone text elements
617 if (IsOverlay(el.labelData)){
618 overlayElements.push_back(&el);
619 }else {
620 textElements.push_back(&el);
621 }
622 }
623 }
624 }
625
626 // draw postponed text elements
627 for (const typename LabelInstanceType::Element *el : textElements) {
628 p->DrawLabel(projection, parameter,
629 ScreenVectorRectangle(el->x, el->y, el->label->width, el->label->height),
630 el->labelData, el->label->label);
631 }
632
633 for (const typename LabelInstanceType::Element *el : overlayElements) {
634 p->DrawLabel(projection, parameter,
635 ScreenVectorRectangle(el->x, el->y, el->label->width, el->label->height),
636 el->labelData, el->label->label);
637 }
638
639 for (const ContourLabelType& label : ContourLabels()){
640 p->DrawGlyphs(projection,
641 parameter,
642 label.style,
643 label.glyphs);
644 }
645 }
646
647 // should be made private
648 void ProcessLabel(const Projection& projection,
649 const MapParameter& parameter,
650 const Vertex2D& point,
651 LabelInstanceType& instance,
652 double& offset,
653 const LabelData& data,
654 double objectWidth)
655 {
657
658 element.labelData=data;
659
661 instance.priority = std::min(data.priority, instance.priority);
662 element.x = point.GetX() - data.iconWidth / 2;
663 if (offset<0){
664 element.y = point.GetY() - data.iconHeight / 2;
665 offset = point.GetY() + data.iconHeight / 2;
666 }
667 else {
668 element.y = offset;
669 offset += data.iconHeight;
670 }
671 }
672 else {
673 instance.priority = std::min(data.priority, instance.priority);
674 // TODO: should we take style into account?
675 // Qt allows to split text layout and style setup
676 element.label = textLayouter->Layout(projection, parameter,
677 data.text, data.fontSize,
678 objectWidth,
679 /*enable wrapping*/ true,
680 /*contour label*/ false);
681 element.x = point.GetX() - element.label->width / 2;
682 if (offset<0){
683 element.y = point.GetY() - element.label->height / 2;
684 offset = point.GetY() + element.label->height / 2;
685 }
686 else {
687 element.y = offset;
688 offset += element.label->height;
689 }
690 }
691
692 instance.elements.push_back(element);
693 }
694
695 void RegisterLabel(const Projection& projection,
696 const MapParameter& parameter,
697 const ObjectFileRef& ref,
698 const Vertex2D& point,
699 const LabelData& data,
700 double objectWidth = 10.0)
701 {
702 LabelInstanceType instance;
703
704 instance.ref=ref;
705
706 double offset=-1;
707 ProcessLabel(projection,
708 parameter,
709 point,
710 instance,
711 offset,
712 data,
713 objectWidth);
714
715 labelInstances.push_back(instance);
716 }
717
718 void RegisterLabel(const Projection& projection,
719 const MapParameter& parameter,
720 const ObjectFileRef& ref,
721 const Vertex2D& point,
722 const std::vector<LabelData>& data,
723 double objectWidth = 10.0)
724 {
725 LabelInstanceType instance;
726
727 instance.ref=ref;
728
729 double offset=-1;
730 for (const auto& d : data) {
731 ProcessLabel(projection,
732 parameter,
733 point,
734 instance,
735 offset,
736 d,
737 objectWidth);
738 }
739
740 labelInstances.push_back(instance);
741 }
742
743 void RegisterContourLabel(const Projection& projection,
744 const MapParameter& parameter,
745 const ObjectFileRef& ref,
746 const PathLabelData &labelData,
747 const LabelPath &labelPath)
748 {
749 // TODO: cache label for string and font parameters
750 LabelPtr label=textLayouter->Layout(projection,
751 parameter,
752 labelData.text,
753 labelData.height,
754 /* object width */ 0.0,
755 /*enable wrapping*/ false,
756 /*contour label*/ true);
757
758 // text should be rendered with 0x0 coordinate as left baseline
759 // we want to move label a bit to the bottom, near to line center
760 double textBaselineOffset = label->height * 0.25;
761
762 std::vector<Glyph<NativeGlyph>> glyphs = label->ToGlyphs();
763 double pathLength=labelPath.GetLength();
764 ContourLabelPositioner positioner;
765 ContourLabelPositioner::Position position=positioner.calculatePositions(projection,
766 parameter,
767 labelData,
768 pathLength,
769 label->width);
770
771 double offset=position.offset;
772 size_t currentCount=1;
773 while (currentCount<=position.labelCount){
774 double nextOffset=offset+label->width+position.labelSpace;
775
776 currentCount++;
777
778 // skip string rendering when path is too much squiggly at this offset
779 if (!labelPath.TestAngleVariance(offset,offset+label->width,M_PI_4)){
780 // skip drawing current label and let offset point to the next instance
781 offset=nextOffset;
782 continue;
783 }
784
785 ContourLabelType cLabel;
786
787 cLabel.ref = ref;
788 cLabel.priority = labelData.priority;
789 cLabel.style = labelData.style;
790
791 if constexpr (debugLabelLayouter) {
792 cLabel.text = labelData.text;
793 cLabel.offset = offset;
794 cLabel.start = labelPath.PointAtLength(0);
795 }
796
797 // do the magic to make sure that we don't render label upside-down
798
799 // direction of path at the label drawing starting point
800 double initialAngle=std::abs(labelPath.AngleAtLengthDeg(offset));
801 bool upwards=initialAngle>90 && initialAngle<270;
802
803
804 for (const Glyph<NativeGlyph> &glyph:glyphs){
805 double glyphOffset = upwards ?
806 offset - glyph.position.GetX() + label->width:
807 offset + glyph.position.GetX();
808 osmscout::Vertex2D point=labelPath.PointAtLength(glyphOffset);
809
810 ScreenVectorRectangle textBoundingBox = textLayouter->GlyphBoundingBox(glyph.glyph);
811 double w = textBoundingBox.width;
812 double h = textBoundingBox.height;
813 osmscout::Vertex2D tl(textBoundingBox.x, textBoundingBox.y);
814
815 // glyph angle in radians
816 double angle=labelPath.AngleAtLength(upwards ? glyphOffset - w/2 : glyphOffset + w/2)*-1;
817
818 // it is not real diagonal, but maximum distance from glyph
819 // point that can be covered after transformations
820 double diagonal=w+h+std::abs(textBaselineOffset);
821
822 // fast check if current glyph can be visible
823 if (!layoutViewport.Intersects(ScreenVectorRectangle{
824 point.GetX()-diagonal,
825 point.GetY()-diagonal,
826 2*diagonal,
827 2*diagonal
828 })){
829 continue;
830 }
831
832 if (upwards) {
833 angle-=M_PI;
834 }
835 double sinA=std::sin(angle);
836 double cosA=std::cos(angle);
837
838 Glyph<NativeGlyph> glyphCopy=glyph;
839 glyphCopy.position=osmscout::Vertex2D(point.GetX() - textBaselineOffset * sinA,
840 point.GetY() + textBaselineOffset * cosA);
841 glyphCopy.angle=angle;
842
843 // four coordinates of glyph bounding box; x,y of top-left, top-right, bottom-right, bottom-left
844 std::array<double, 4> x{tl.GetX(), tl.GetX() + w, tl.GetX() + w, tl.GetX()};
845 std::array<double, 4> y{tl.GetY(), tl.GetY(), tl.GetY() + h, tl.GetY() + h};
846
847 // rotate
848 for (int i=0; i<4; i++){
849 double ox = x[i];
850 double oy = y[i];
851 x[i] = ox * cosA - oy * sinA;
852 y[i] = ox * sinA + oy * cosA;
853 }
854
855 // bounding box after rotation
856 double minX=x[0];
857 double maxX=x[0];
858 double minY=y[0];
859 double maxY=y[0];
860 for (int i=1; i<4; i++){
861 minX = std::min(minX, x[i]);
862 maxX = std::max(maxX, x[i]);
863 minY = std::min(minY, y[i]);
864 maxY = std::max(maxY, y[i]);
865 }
866 // setup glyph top-left position and dimension after rotation
867 glyphCopy.trPosition=Vertex2D(minX+glyphCopy.position.GetX(),
868 minY+glyphCopy.position.GetY());
869 glyphCopy.trWidth = maxX - minX;
870 glyphCopy.trHeight = maxY - minY;
871
872 cLabel.glyphs.push_back(glyphCopy);
873 }
874 if (!cLabel.glyphs.empty()) { // is some glyph visible?
875 contourLabelInstances.push_back(cLabel);
876 }
877
878 offset=nextOffset;
879 }
880 }
881
882 const std::vector<LabelInstanceType>& Labels() const
883 {
884 return labelInstances;
885 }
886
887 const std::vector<ContourLabelType>& ContourLabels() const
888 {
889 return contourLabelInstances;
890 }
891
892 private:
893 TextLayouter *textLayouter;
894 std::vector<ContourLabelType> contourLabelInstances;
895 std::vector<LabelInstanceType> labelInstances;
896 ScreenVectorRectangle visibleViewport{0,0,0,0};
897 ScreenVectorRectangle layoutViewport{0,0,0,0};
898 uint32_t layoutOverlap=0; // overlap [pixels] used for label layouting
899 };
900
901}
902
903#endif
#define OSMSCOUT_MAP_API
Definition MapImportExport.h:45
Definition Area.h:88
Position calculatePositions(const Projection &projection, const MapParameter &parameter, const PathLabelData &labelData, double pathLength, double labelWidth) const
Definition LabelLayouter.h:167
std::vector< Glyph< NativeGlyph > > glyphs
Vector of glyphs of the label text (see text).
Definition LabelLayouter.h:176
osmscout::PathTextStyleRef style
Style for drawing the text of the label.
Definition LabelLayouter.h:177
size_t priority
Priority of the label.
Definition LabelLayouter.h:175
ObjectFileRef ref
Definition LabelLayouter.h:174
Definition LabelLayouter.h:103
double trHeight
Definition LabelLayouter.h:111
Vertex2D trPosition
Definition LabelLayouter.h:109
CairoNativeGlyph glyph
Definition LabelLayouter.h:105
double trWidth
Definition LabelLayouter.h:110
double angle
Definition LabelLayouter.h:107
Vertex2D position
Definition LabelLayouter.h:106
Definition LabelLayouter.h:57
IconStyleRef iconStyle
Icon or symbol style.
Definition LabelLayouter.h:76
size_t priority
Priority of the entry.
Definition LabelLayouter.h:67
double alpha
Alpha value of the label; 0.0 = fully transparent, 1.0 = solid.
Definition LabelLayouter.h:70
std::string text
The label text (type==Text|PathText).
Definition LabelLayouter.h:74
Type
Definition LabelLayouter.h:60
@ Text
Definition LabelLayouter.h:63
@ Symbol
Definition LabelLayouter.h:62
@ Icon
Definition LabelLayouter.h:61
double iconWidth
Definition LabelLayouter.h:77
Type type
Definition LabelLayouter.h:66
LabelStyleRef style
Style for drawing.
Definition LabelLayouter.h:73
double fontSize
Font size to be used.
Definition LabelLayouter.h:71
double iconHeight
Definition LabelLayouter.h:78
size_t position
Relative position of the label.
Definition LabelLayouter.h:68
Definition LabelLayouter.h:119
std::vector< Glyph< NativeGlyph > > ToGlyphs() const
Label(Args &&... args)
Definition LabelLayouter.h:132
double fontSize
Definition LabelLayouter.h:126
double width
Definition LabelLayouter.h:123
Label()=default
std::string text
Definition LabelLayouter.h:127
CairoNativeLabel label
Definition LabelLayouter.h:121
double height
Definition LabelLayouter.h:124
Definition LabelLayouter.h:147
ObjectFileRef ref
Definition LabelLayouter.h:159
std::vector< Element > elements
Definition LabelLayouter.h:162
const std::vector< ContourLabelType > & ContourLabels() const
Definition LabelLayouter.h:887
void Layout(const Projection &projection, const MapParameter &parameter)
Definition LabelLayouter.h:531
ContourLabel< NativeGlyph > ContourLabelType
Definition LabelLayouter.h:233
void Reset()
Definition LabelLayouter.h:258
void RegisterLabel(const Projection &projection, const MapParameter &parameter, const ObjectFileRef &ref, const Vertex2D &point, const LabelData &data, double objectWidth=10.0)
Definition LabelLayouter.h:695
void SetViewport(const ScreenVectorRectangle &v)
Definition LabelLayouter.h:243
void RegisterContourLabel(const Projection &projection, const MapParameter &parameter, const ObjectFileRef &ref, const PathLabelData &labelData, const LabelPath &labelPath)
Definition LabelLayouter.h:743
void ProcessLabel(const Projection &projection, const MapParameter &parameter, const Vertex2D &point, LabelInstanceType &instance, double &offset, const LabelData &data, double objectWidth)
Definition LabelLayouter.h:648
void RegisterLabel(const Projection &projection, const MapParameter &parameter, const ObjectFileRef &ref, const Vertex2D &point, const std::vector< LabelData > &data, double objectWidth=10.0)
Definition LabelLayouter.h:718
void DrawLabels(const Projection &projection, const MapParameter &parameter, Painter *p)
Definition LabelLayouter.h:579
void SetLayoutOverlap(uint32_t overlap)
Definition LabelLayouter.h:249
static bool IsOverlay(const LabelData &labelData)
Definition LabelLayouter.h:265
std::shared_ptr< LabelType > LabelPtr
Definition LabelLayouter.h:235
Label< NativeGlyph, NativeLabel > LabelType
Definition LabelLayouter.h:234
const std::vector< LabelInstanceType > & Labels() const
Definition LabelLayouter.h:882
LabelLayouter(TextLayouter *textLayouter)
Definition LabelLayouter.h:239
void DrawTextLabels(const Projection &, const MapParameter &, Painter *) const
Definition LabelLayouter.h:542
LabelInstance< NativeGlyph, NativeLabel > LabelInstanceType
Definition LabelLayouter.h:236
Definition LabelPath.h:44
double AngleAtLength(double offset) const
bool TestAngleVariance(double startOffset, double endOffset, double maximumAngle) const
Vertex2D PointAtLength(double offset) const
double GetLength() const
Definition LabelPath.h:57
double AngleAtLengthDeg(double offset) const
Definition LabelLayouter.h:46
double contourLabelSpace
Definition LabelLayouter.h:53
size_t priority
Priority of the entry.
Definition LabelLayouter.h:48
std::string text
The label text (type==Text|PathText).
Definition LabelLayouter.h:49
double contourLabelOffset
Definition LabelLayouter.h:52
PathTextStyleRef style
Definition LabelLayouter.h:51
double height
Definition LabelLayouter.h:50
Definition Projection.h:46
Definition Styles.h:640
Definition Area.h:39
std::shared_ptr< PathTextStyle > PathTextStyleRef
Definition Styles.h:890
static bool ContourLabelSorter(const ContourLabel< NativeGlyph > &a, const ContourLabel< NativeGlyph > &b)
Definition LabelLayouter.h:192
constexpr bool debugLabelLayouter
Definition LabelLayouter.h:42
std::shared_ptr< LabelStyle > LabelStyleRef
Definition Styles.h:499
std::shared_ptr< IconStyle > IconStyleRef
Definition Styles.h:987
static bool LabelInstanceSorter(const LabelInstance< NativeGlyph, NativeLabel > &a, const LabelInstance< NativeGlyph, NativeLabel > &b)
Definition LabelLayouter.h:181
STL namespace.
Definition PositionAgent.h:65
double labelSpace
Space between individual labels.
Definition LabelLayouter.h:92
double offset
Offset of the first label.
Definition LabelLayouter.h:91
size_t labelCount
Number of labels rendered.
Definition LabelLayouter.h:90
Definition LabelLayouter.h:150
std::shared_ptr< Label< NativeGlyph, NativeLabel > > label
Definition LabelLayouter.h:155
double y
Coordinate of the left, top edge of the text / icon / symbol.
Definition LabelLayouter.h:153
double x
Coordinate of the left, top edge of the text / icon / symbol.
Definition LabelLayouter.h:152
LabelData labelData
Definition LabelLayouter.h:151
LayoutJob(const LayoutJob &)=delete
LayoutJob & operator=(LayoutJob &&)=delete
void ProcessLabelInstance(const LabelInstanceType &currentLabel, std::vector< LabelInstanceType > &labelInstances)
Definition LabelLayouter.h:362
double GetLabelPadding(const LabelData &labelData) const
Definition LabelLayouter.h:333
ScreenVectorRectangle layoutViewport
Definition LabelLayouter.h:279
double shieldLabelPadding
Definition LabelLayouter.h:283
ScreenMask overlayCanvas
Definition LabelLayouter.h:292
double iconPadding
Definition LabelLayouter.h:281
std::vector< LabelInstanceType > allSortedLabels
Definition LabelLayouter.h:288
ScreenMask * GetCanvas(LabelData data)
Definition LabelLayouter.h:350
double overlayLabelPadding
Definition LabelLayouter.h:285
double labelPadding
Definition LabelLayouter.h:282
std::vector< ContourLabelType > allSortedContourLabels
Definition LabelLayouter.h:287
LayoutJob(const ScreenVectorRectangle &layoutViewport, const Projection &projection, const MapParameter &parameter)
Definition LabelLayouter.h:294
ScreenMask iconCanvas
Definition LabelLayouter.h:290
void Swap(std::vector< LabelInstanceType > &labelInstances, std::vector< ContourLabelType > &contourLabelInstances)
Definition LabelLayouter.h:315
ScreenMask labelCanvas
Definition LabelLayouter.h:291
void SortLabels()
Definition LabelLayouter.h:322
double contourLabelPadding
Definition LabelLayouter.h:284
void ProcessLabelContourLabel(const ContourLabelType &currentContourLabel, std::vector< ContourLabelType > &contourLabelInstances)
Definition LabelLayouter.h:446
LayoutJob & operator=(const LayoutJob &)=delete
LayoutJob(LayoutJob &&)=delete
void ProcessLabels(std::vector< LabelInstanceType > &labelInstances, std::vector< ContourLabelType > &contourLabelInstances)
Definition LabelLayouter.h:489
Definition LabelLayouterHelper.h:38
int height
Definition LabelLayouterHelper.h:42
int width
Definition LabelLayouterHelper.h:41
Definition LabelLayouterHelper.h:73
double x
Definition LabelLayouterHelper.h:74
double y
Definition LabelLayouterHelper.h:75
double width
Definition LabelLayouterHelper.h:76
ScreenVectorRectangle & Set(double nx, double ny, double nw, double nh)
Definition LabelLayouterHelper.h:90
double height
Definition LabelLayouterHelper.h:77