1 /*
2     Copyright © 2008-13 Qtrac Ltd. All rights reserved.
3     This program or module is free software: you can redistribute it
4     and/or modify it under the terms of the GNU General Public License
5     as published by the Free Software Foundation, either version 2 of
6     the License, or (at your option) any later version. This program is
7     distributed in the hope that it will be useful, but WITHOUT ANY
8     WARRANTY; without even the implied warranty of MERCHANTABILITY or
9     FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10     for more details.
11 */
12 
13 #include "generic.hpp"
14 #include <QMimeData>
15 #include <QRectF>
16 #include <QPainter>
17 #include <QPen>
18 #include <QPixmapCache>
19 #include <QUrl>
20 
21 const QSize SwatchSize(24, 24);
22 
23 
scaleRect(int dpi,QRectF * rect)24 void scaleRect(int dpi, QRectF *rect)
25 {
26     if (dpi == POINTS_PER_INCH)
27         return;
28     qreal x1;
29     qreal y1;
30     qreal x2;
31     qreal y2;
32     rect->getCoords(&x1, &y1, &x2, &y2);
33     qreal factor = dpi / static_cast<qreal>(POINTS_PER_INCH);
34     x1 *= factor;
35     y1 *= factor;
36     x2 *= factor;
37     y2 *= factor;
38     rect->setCoords(x1, y1, x2, y2);
39 }
40 
41 
pointValueForPixelOffset(const double dpi,int px)42 int pointValueForPixelOffset(const double dpi, int px)
43 {
44     const double inches = px / dpi;
45     return qRound(inches * POINTS_PER_INCH);
46 }
47 
48 
pixelOffsetForPointValue(const double dpi,int pt)49 int pixelOffsetForPointValue(const double dpi, int pt)
50 {
51     const double inches = pt / static_cast<double>(POINTS_PER_INCH);
52     return qRound(inches * dpi);
53 }
54 
55 
rectForMargins(const int width,const int height,const int top,const int bottom,const int left,const int right)56 QRectF rectForMargins(const int width, const int height, const int top,
57         const int bottom, const int left, const int right)
58 {
59     return QRectF(QPointF(left, top),
60                   QPointF(width - right, height - bottom));
61 }
62 
63 
unorderedRange(int end,int start)64 Ranges unorderedRange(int end, int start)
65 {
66     Q_ASSERT(end >= start);
67     Ranges ranges;
68     while (start < end)
69         ranges.insert(start++);
70     return ranges;
71 }
72 
73 
colorSwatch(const QColor & color)74 QPixmap colorSwatch(const QColor &color)
75 {
76     QString key = QString("COLORSWATCH:%1").arg(color.name());
77     QPixmap pixmap(SwatchSize);
78 #if QT_VERSION >= 0x040600
79     if (!QPixmapCache::find(key, &pixmap)) {
80 #else
81     if (!QPixmapCache::find(key, pixmap)) {
82 #endif
83         pixmap.fill(Qt::transparent);
84         {
85             QPainter painter(&pixmap);
86             painter.setRenderHints(QPainter::Antialiasing);
87             painter.setPen(Qt::NoPen);
88             painter.setBrush(color);
89             painter.drawEllipse(0, 0, SwatchSize.width(),
90                                 SwatchSize.height());
91         }
92         QPixmapCache::insert(key, pixmap);
93     }
94     return pixmap;
95 }
96 
97 
98 QPixmap brushSwatch(const Qt::BrushStyle style, const QColor &color)
99 {
100     QString key = QString("BRUSHSTYLESWATCH:%1:%2:%3")
101         .arg(static_cast<int>(style)).arg(color.name()).arg(color.alpha());
102     QPixmap pixmap(SwatchSize);
103 #if QT_VERSION >= 0x040600
104     if (!QPixmapCache::find(key, &pixmap)) {
105 #else
106     if (!QPixmapCache::find(key, pixmap)) {
107 #endif
108         pixmap.fill(Qt::transparent);
109         {
110             QPainter painter(&pixmap);
111             painter.setRenderHint(QPainter::Antialiasing);
112             painter.setPen(Qt::NoPen);
113             painter.setBrush(QBrush(color, style));
114             painter.drawRect(0, 0, SwatchSize.width(),
115                              SwatchSize.height());
116         }
117         QPixmapCache::insert(key, pixmap);
118     }
119     return pixmap;
120 }
121 
122 
123 QPixmap penStyleSwatch(const Qt::PenStyle style, const QColor &color)
124 {
125     QString key = QString("PENSTYLESWATCH:%1:%2")
126         .arg(static_cast<int>(style)).arg(color.name());
127     QPixmap pixmap(SwatchSize);
128 #if QT_VERSION >= 0x040600
129     if (!QPixmapCache::find(key, &pixmap)) {
130 #else
131     if (!QPixmapCache::find(key, pixmap)) {
132 #endif
133         pixmap.fill(Qt::transparent);
134         {
135             QPainter painter(&pixmap);
136             QPen pen(style);
137             pen.setColor(color);
138             pen.setWidth(2);
139             painter.setPen(pen);
140             const int Y = SwatchSize.height() / 2;
141             painter.drawLine(0, Y, SwatchSize.width(), Y);
142         }
143         QPixmapCache::insert(key, pixmap);
144     }
145     return pixmap;
146 }
147 
148 
149 const TextBoxList getTextBoxes(PdfPage page, const QRectF &rect)
150 {
151     TextBoxList boxes;
152     foreach (Poppler::TextBox *box, page->textList()) {
153         PdfTextBox box_ptr(box);
154         if (rect.isEmpty() || rect.contains(box_ptr->boundingBox()))
155             boxes.append(box_ptr);
156     }
157     return boxes;
158 }
159 
160 
161 const QString strippedFilename(const QString &filename)
162 {
163     const QString FilePrefix("file://");
164     QString filename_ = filename;
165     if (filename_.startsWith(FilePrefix))
166         filename_ = filename_.mid(FilePrefix.length());
167 #ifdef Q_WS_WIN
168     if (filename_.startsWith("/"))
169         filename_ = filename_.mid(1);
170 #endif
171     return filename_.trimmed();
172 }
173 
174 
175 const QStringList droppedFilenames(const QMimeData *mimeData)
176 {
177     QStringList filenames;
178     QString text = mimeData->text();
179     if (!text.isEmpty()) {
180         filenames = text.split("\n");
181         for (int i = 0; i < filenames.count(); ++i)
182             filenames[i] = strippedFilename(filenames.at(i));
183     }
184     else {
185         foreach (const QUrl &url, mimeData->urls())
186             filenames << strippedFilename(url.toString());
187     }
188     return filenames;
189 }
190 
191 // Returns a copy of pageRect reduced if necessary to have the same
192 // aspect ratio as pixmapSize.
193 const QRect resizeRect(const QRect &pageRect, const QSize &pixmapSize)
194 {
195     double ratio = pixmapSize.width() /
196             static_cast<double>(pixmapSize.height());
197     double height = pageRect.height();
198     double width = ratio * height;
199     if (width > pageRect.width()) {
200         width = pageRect.width();
201         height = width / ratio;
202     }
203     QRect rect(pageRect);
204     rect.setWidth(width);
205     rect.setHeight(height);
206     return rect;
207 }
208