+void DecodeTrace::draw_annotations(vector<pv::data::decode::Annotation> annotations,
+ QPainter &p, int h, const ViewItemPaintParams &pp, int y,
+ size_t base_colour, int row_title_width)
+{
+ using namespace pv::data::decode;
+
+ vector<Annotation> a_block;
+ int p_end = INT_MIN;
+
+ double samples_per_pixel, pixels_offset;
+ tie(pixels_offset, samples_per_pixel) =
+ get_pixels_offset_samples_per_pixel();
+
+ // Sort the annotations by start sample so that decoders
+ // can't confuse us by creating annotations out of order
+ stable_sort(annotations.begin(), annotations.end(),
+ [](const Annotation &a, const Annotation &b) {
+ return a.start_sample() < b.start_sample(); });
+
+ // Gather all annotations that form a visual "block" and draw them as such
+ for (const Annotation &a : annotations) {
+
+ const int a_start = a.start_sample() / samples_per_pixel - pixels_offset;
+ const int a_end = a.end_sample() / samples_per_pixel - pixels_offset;
+ const int a_width = a_end - a_start;
+
+ const int delta = a_end - p_end;
+
+ bool a_is_separate = false;
+
+ // Annotation wider than the threshold for a useful label width?
+ if (a_width >= min_useful_label_width_) {
+ for (const QString &ann_text : a.annotations()) {
+ const int w = p.boundingRect(QRectF(), 0, ann_text).width();
+ // Annotation wide enough to fit a label? Don't put it in a block then
+ if (w <= a_width) {
+ a_is_separate = true;
+ break;
+ }
+ }
+ }
+
+ // Were the previous and this annotation more than a pixel apart?
+ if ((abs(delta) > 1) || a_is_separate) {
+ // Block was broken, draw annotations that form the current block
+ if (a_block.size() == 1) {
+ draw_annotation(a_block.front(), p, h, pp, y, base_colour,
+ row_title_width);
+ }
+ else
+ draw_annotation_block(a_block, p, h, y, base_colour);
+
+ a_block.clear();
+ }
+
+ if (a_is_separate) {
+ draw_annotation(a, p, h, pp, y, base_colour, row_title_width);
+ // Next annotation must start a new block. delta will be > 1
+ // because we set p_end to INT_MIN but that's okay since
+ // a_block will be empty, so nothing will be drawn
+ p_end = INT_MIN;
+ } else {
+ a_block.push_back(a);
+ p_end = a_end;
+ }
+ }
+
+ if (a_block.size() == 1)
+ draw_annotation(a_block.front(), p, h, pp, y, base_colour,
+ row_title_width);
+ else
+ draw_annotation_block(a_block, p, h, y, base_colour);
+}
+