]> sigrok.org Git - pulseview.git/blob - pv/view/decode/annotation.cpp
4ad04f23caf34b155d0f938e18bc7d338de73e16
[pulseview.git] / pv / view / decode / annotation.cpp
1 /*
2  * This file is part of the PulseView project.
3  *
4  * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 extern "C" {
22 #include <libsigrokdecode/libsigrokdecode.h>
23 }
24
25 #include <extdef.h>
26
27 #include <algorithm>
28
29 #include <QPainter>
30
31 #include "annotation.h"
32
33 using namespace boost;
34 using namespace std;
35
36 namespace pv {
37 namespace view {
38 namespace decode {
39
40 const double Annotation::EndCapWidth = 5;
41
42 Annotation::Annotation(const srd_proto_data *const pdata) :
43         _start_sample(pdata->start_sample),
44         _end_sample(pdata->end_sample)
45 {
46         const char *const *annotations = (char**)pdata->data;
47         while(*annotations) {
48                 _annotations.push_back(QString(*annotations));
49                 annotations++;
50         }
51 }
52
53 void Annotation::paint(QPainter &p, QColor fill, QColor outline,
54         QColor text_color, int text_height, int left, int right,
55         double samples_per_pixel, double pixels_offset, int y)
56 {
57         const int h = (text_height * 3) / 2;
58
59         const double start = _start_sample / samples_per_pixel -
60                 pixels_offset;
61         const double end = _end_sample / samples_per_pixel -
62                 pixels_offset;
63
64         if (start > right || end < left)
65                 return;
66
67         const double cap_width = min((end - start) / 2, EndCapWidth);
68
69         QPointF pts[] = {
70                 QPointF(start, y + .5f),
71                 QPointF(start + cap_width, y + .5f - h / 2),
72                 QPointF(end - cap_width, y + .5f - h / 2),
73                 QPointF(end, y + .5f),
74                 QPointF(end - cap_width, y + .5f + h / 2),
75                 QPointF(start + cap_width, y + .5f + h / 2)
76         };
77
78         p.setPen(outline);
79         p.setBrush(fill);
80         p.drawConvexPolygon(pts, countof(pts));
81
82         if (_annotations.empty())
83                 return;
84
85         QRectF rect(start + cap_width, y - h / 2,
86                 end - start - cap_width * 2, h);
87         p.setPen(text_color);
88
89         // Try to find an annotation that will fit
90         QString best_annotation;
91         int best_width = 0;
92
93         BOOST_FOREACH(QString &a, _annotations) {
94                 const int w = p.boundingRect(QRectF(), 0, a).width();
95                 if (w <= rect.width() && w > best_width)
96                         best_annotation = a, best_width = w;
97         }
98
99         if (best_annotation.isEmpty())
100                 best_annotation = _annotations.back();
101
102         // If not ellide the last in the list
103         p.drawText(rect, Qt::AlignCenter, p.fontMetrics().elidedText(
104                 best_annotation, Qt::ElideRight, rect.width()));
105 }
106
107 } // namespace decode
108 } // namespace view
109 } // namespace pv