• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegraphics API Reference
  • KDE Home
  • Contact Us
 

okular

  • sources
  • kde-4.14
  • kdegraphics
  • okular
  • core
utils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2006 by Luigi Toscano <luigi.toscano@tiscali.it> *
3  * Copyright (C) 2008 by Pino Toscano <pino@kde.org> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  ***************************************************************************/
10 
11 #include "utils.h"
12 #include "utils_p.h"
13 
14 #include <QtCore/QRect>
15 #include <QApplication>
16 #include <QDesktopWidget>
17 #include <QImage>
18 #include <QIODevice>
19 
20 #ifdef Q_WS_X11
21  #include "config-okular.h"
22  #if HAVE_LIBKSCREEN
23  #include <kscreen/config.h>
24  #include <kscreen/edid.h>
25  #endif
26  #include <QX11Info>
27 #endif
28 
29 #ifdef Q_WS_MAC
30 #include <ApplicationServices/ApplicationServices.h>
31 #include <IOKit/graphics/IOGraphicsLib.h>
32 #endif
33 
34 
35 
36 using namespace Okular;
37 
38 QRect Utils::rotateRect( const QRect & source, int width, int height, int orientation )
39 {
40  QRect ret;
41 
42  // adapt the coordinates of the boxes to the rotation
43  switch ( orientation )
44  {
45  case 1:
46  ret = QRect( width - source.y() - source.height(), source.x(),
47  source.height(), source.width() );
48  break;
49  case 2:
50  ret = QRect( width - source.x() - source.width(), height - source.y() - source.height(),
51  source.width(), source.height() );
52  break;
53  case 3:
54  ret = QRect( source.y(), height - source.x() - source.width(),
55  source.height(), source.width() );
56  break;
57  case 0: // no modifications
58  default: // other cases
59  ret = source;
60  }
61 
62  return ret;
63 }
64 
65 #if defined(Q_WS_X11)
66 
67 double Utils::dpiX()
68 {
69  return QX11Info::appDpiX();
70 }
71 
72 double Utils::dpiY()
73 {
74  return QX11Info::appDpiY();
75 }
76 
77 double Utils::realDpiX()
78 {
79  const QDesktopWidget* w = QApplication::desktop();
80  if (w->width() > 0 && w->widthMM() > 0) {
81  kDebug() << "Pix:" << w->width() << "MM:" << w->widthMM();
82  return (double(w->width()) * 25.4) / double(w->widthMM());
83  } else {
84  return dpiX();
85  }
86 }
87 
88 double Utils::realDpiY()
89 {
90  const QDesktopWidget* w = QApplication::desktop();
91  if (w->height() > 0 && w->heightMM() > 0) {
92  kDebug() << "Pix:" << w->height() << "MM:" << w->heightMM();
93  return (double(w->height()) * 25.4) / double(w->heightMM());
94  } else {
95  return dpiY();
96  }
97 }
98 
99 QSizeF Utils::realDpi(QWidget* widgetOnScreen)
100 {
101  if (widgetOnScreen)
102  {
103  // Firstly try to retrieve DPI via LibKScreen
104 #if HAVE_LIBKSCREEN
105  KScreen::Config* config = KScreen::Config::current();
106  if (config) {
107  KScreen::OutputList outputs = config->outputs();
108  QPoint globalPos = widgetOnScreen->parentWidget() ?
109  widgetOnScreen->mapToGlobal(widgetOnScreen->pos()):
110  widgetOnScreen->pos();
111  QRect widgetRect(globalPos, widgetOnScreen->size());
112 
113  KScreen::Output* selectedOutput = 0;
114  int maxArea = 0;
115  Q_FOREACH(KScreen::Output *output, outputs)
116  {
117  if (output->currentMode())
118  {
119  QRect outputRect(output->pos(),output->currentMode()->size());
120  QRect intersection = outputRect.intersected(widgetRect);
121  int area = intersection.width()*intersection.height();
122  if (area > maxArea)
123  {
124  maxArea = area;
125  selectedOutput = output;
126  }
127  }
128  }
129 
130  if (selectedOutput)
131  {
132  kDebug() << "Found widget at output #" << selectedOutput->id();
133  QRect outputRect(selectedOutput->pos(),selectedOutput->currentMode()->size());
134  QSize szMM = selectedOutput->sizeMm();
135  kDebug() << "Output size is (mm) " << szMM;
136  kDebug() << "Output rect is " << outputRect;
137  if (selectedOutput->edid()) {
138  kDebug() << "EDID WxH (cm): " << selectedOutput->edid()->width() << 'x' << selectedOutput->edid()->height();
139  }
140  if (szMM.width() > 0 && szMM.height() > 0 && outputRect.width() > 0 && outputRect.height() > 0
141  && selectedOutput->edid()
142  && qAbs(static_cast<int>(selectedOutput->edid()->width()*10) - szMM.width()) < 10
143  && qAbs(static_cast<int>(selectedOutput->edid()->height()*10) - szMM.height()) < 10)
144  {
145  // sizes in EDID seem to be consistent
146  QSizeF res(static_cast<qreal>(outputRect.width())*25.4/szMM.width(),
147  static_cast<qreal>(outputRect.height())*25.4/szMM.height());
148  if (!selectedOutput->isHorizontal())
149  {
150  kDebug() << "Output is vertical, transposing DPI rect";
151  res.transpose();
152  }
153  if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.05) {
154  return res;
155  } else {
156  kDebug() << "KScreen calculation returned a non square dpi." << res << ". Falling back";
157  }
158  }
159  }
160  else
161  {
162  kDebug() << "Didn't find a KScreen selectedOutput to calculate DPI. Falling back";
163  }
164  }
165  else
166  {
167  kDebug() << "Didn't find a KScreen config to calculate DPI. Falling back";
168  }
169 #endif
170  }
171  // this is also fallback for LibKScreen branch if KScreen::Output
172  // for particular widget was not found
173  QSizeF res = QSizeF(realDpiX(), realDpiY());
174  if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.05) {
175  return res;
176  } else {
177  kDebug() << "QDesktopWidget calculation returned a non square dpi." << res << ". Falling back";
178  }
179 
180  res = QSizeF(dpiX(), dpiY());
181  if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.05) {
182  return res;
183  } else {
184  kDebug() << "QX11Info returned a non square dpi." << res << ". Falling back";
185  }
186 
187  res = QSizeF(72, 72);
188  return res;
189 }
190 
191 #elif defined(Q_WS_MAC)
192  /*
193  * Code copied from http://developer.apple.com/qa/qa2001/qa1217.html
194  */
195  // Handy utility function for retrieving an int from a CFDictionaryRef
196  static int GetIntFromDictionaryForKey( CFDictionaryRef desc, CFStringRef key )
197  {
198  CFNumberRef value;
199  int num = 0;
200  if ( (value = (CFNumberRef)CFDictionaryGetValue(desc, key)) == NULL || CFGetTypeID(value) != CFNumberGetTypeID())
201  return 0;
202  CFNumberGetValue(value, kCFNumberIntType, &num);
203  return num;
204  }
205 
206  static CGDisplayErr GetDisplayDPI( CFDictionaryRef displayModeDict, CGDirectDisplayID displayID,
207  double *horizontalDPI, double *verticalDPI )
208  {
209  CGDisplayErr err = kCGErrorFailure;
210  io_connect_t displayPort;
211  CFDictionaryRef displayDict;
212 
213  // Grab a connection to IOKit for the requested display
214  displayPort = CGDisplayIOServicePort( displayID );
215  if ( displayPort != MACH_PORT_NULL )
216  {
217  // Find out what IOKit knows about this display
218  displayDict = IODisplayCreateInfoDictionary(displayPort, 0);
219  if ( displayDict != NULL )
220  {
221  const double mmPerInch = 25.4;
222  double horizontalSizeInInches =
223  (double)GetIntFromDictionaryForKey(displayDict,
224  CFSTR(kDisplayHorizontalImageSize)) / mmPerInch;
225  double verticalSizeInInches =
226  (double)GetIntFromDictionaryForKey(displayDict,
227  CFSTR(kDisplayVerticalImageSize)) / mmPerInch;
228 
229  // Make sure to release the dictionary we got from IOKit
230  CFRelease(displayDict);
231 
232  // Now we can calculate the actual DPI
233  // with information from the displayModeDict
234  *horizontalDPI =
235  (double)GetIntFromDictionaryForKey( displayModeDict, kCGDisplayWidth )
236  / horizontalSizeInInches;
237  *verticalDPI = (double)GetIntFromDictionaryForKey( displayModeDict,
238  kCGDisplayHeight ) / verticalSizeInInches;
239  err = CGDisplayNoErr;
240  }
241  }
242  return err;
243  }
244 
245 double Utils::dpiX()
246 {
247  double x,y;
248  CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
249  kCGDirectMainDisplay,
250  &x, &y );
251 
252  return err == CGDisplayNoErr ? x : 72.0;
253 }
254 
255 double Utils::dpiY()
256 {
257  double x,y;
258  CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
259  kCGDirectMainDisplay,
260  &x, &y );
261 
262  return err == CGDisplayNoErr ? y : 72.0;
263 }
264 
265 double Utils::realDpiX()
266 {
267  return dpiX();
268 }
269 
270 double Utils::realDpiY()
271 {
272  return dpiY();
273 }
274 
275 QSizeF Utils::realDpi(QWidget*)
276 {
277  return QSizeF(realDpiX(), realDpiY());
278 }
279 #else
280 
281 double Utils::dpiX()
282 {
283  return QDesktopWidget().physicalDpiX();
284 }
285 
286 double Utils::dpiY()
287 {
288  return QDesktopWidget().physicalDpiY();
289 }
290 
291 double Utils::realDpiX()
292 {
293  return dpiX();
294 }
295 
296 double Utils::realDpiY()
297 {
298  return dpiY();
299 }
300 
301 QSizeF Utils::realDpi(QWidget*)
302 {
303  return QSizeF(realDpiX(), realDpiY());
304 }
305 #endif
306 
307 inline static bool isWhite( QRgb argb ) {
308  return ( argb & 0xFFFFFF ) == 0xFFFFFF; // ignore alpha
309 }
310 
311 NormalizedRect Utils::imageBoundingBox( const QImage * image )
312 {
313  if ( !image )
314  return NormalizedRect();
315 
316  int width = image->width();
317  int height = image->height();
318  int left, top, bottom, right, x, y;
319 
320 #ifdef BBOX_DEBUG
321  QTime time;
322  time.start();
323 #endif
324 
325  // Scan pixels for top non-white
326  for ( top = 0; top < height; ++top )
327  for ( x = 0; x < width; ++x )
328  if ( !isWhite( image->pixel( x, top ) ) )
329  goto got_top;
330  return NormalizedRect( 0, 0, 0, 0 ); // the image is blank
331 got_top:
332  left = right = x;
333 
334  // Scan pixels for bottom non-white
335  for ( bottom = height-1; bottom >= top; --bottom )
336  for ( x = width-1; x >= 0; --x )
337  if ( !isWhite( image->pixel( x, bottom ) ) )
338  goto got_bottom;
339  Q_ASSERT( 0 ); // image changed?!
340 got_bottom:
341  if ( x < left )
342  left = x;
343  if ( x > right )
344  right = x;
345 
346  // Scan for leftmost and rightmost (we already found some bounds on these):
347  for ( y = top; y <= bottom && ( left > 0 || right < width-1 ); ++y )
348  {
349  for ( x = 0; x < left; ++x )
350  if ( !isWhite( image->pixel( x, y ) ) )
351  left = x;
352  for ( x = width-1; x > right+1; --x )
353  if ( !isWhite( image->pixel( x, y ) ) )
354  right = x;
355  }
356 
357  NormalizedRect bbox( QRect( left, top, ( right - left + 1), ( bottom - top + 1 ) ),
358  image->width(), image->height() );
359 
360 #ifdef BBOX_DEBUG
361  kDebug() << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
362 #endif
363 
364  return bbox;
365 }
366 
367 void Okular::copyQIODevice( QIODevice *from, QIODevice *to )
368 {
369  QByteArray buffer( 65536, '\0' );
370  qint64 read = 0;
371  qint64 written = 0;
372  while ( ( read = from->read( buffer.data(), buffer.size() ) ) > 0 )
373  {
374  written = to->write( buffer.constData(), read );
375  if ( read != written )
376  break;
377  }
378 }
379 
380 QTransform Okular::buildRotationMatrix(Rotation rotation)
381 {
382  QTransform matrix;
383  matrix.rotate( (int)rotation * 90 );
384 
385  switch ( rotation )
386  {
387  case Rotation90:
388  matrix.translate( 0, -1 );
389  break;
390  case Rotation180:
391  matrix.translate( -1, -1 );
392  break;
393  case Rotation270:
394  matrix.translate( -1, 0 );
395  break;
396  default: ;
397  }
398 
399  return matrix;
400 }
401 
402 /* kate: replace-tabs on; indent-width 4; */
QIODevice
QTransform
QWidget
Okular::Utils::dpiY
static double dpiY()
Return the vertical DPI of the main display.
Definition: utils.cpp:286
Okular::Rotation
Rotation
A rotation.
Definition: global.h:44
QSize::width
int width() const
QPaintDevice::physicalDpiX
int physicalDpiX() const
QPaintDevice::physicalDpiY
int physicalDpiY() const
QByteArray
Okular::Utils::realDpiX
static double realDpiX()
Return the real horizontal DPI of the main display.
Definition: utils.cpp:291
QWidget::mapToGlobal
QPoint mapToGlobal(const QPoint &pos) const
Okular::NormalizedRect
NormalizedRect is a helper class which stores the coordinates of a normalized rect, which is a rectangle of.
Definition: area.h:105
QRect::height
int height() const
QRect::x
int x() const
QRect::y
int y() const
Okular::Rotation180
Rotated 180 degrees clockwise.
Definition: global.h:48
QPaintDevice::heightMM
int heightMM() const
QPoint
Okular::Utils::rotateRect
static QRect rotateRect(const QRect &source, int width, int height, int orientation)
Rotate the rect source in the area width x height with the specified orientation .
Definition: utils.cpp:38
QTime
Okular::Utils::dpiX
static double dpiX()
Return the horizontal DPI of the main display.
Definition: utils.cpp:281
QWidget::width
width
utils.h
QWidget::size
size
QRect
QImage::pixel
QRgb pixel(int x, int y) const
QTime::elapsed
int elapsed() const
QTransform::translate
QTransform & translate(qreal dx, qreal dy)
QDesktopWidget
QImage::width
int width() const
Okular::Utils::imageBoundingBox
static NormalizedRect imageBoundingBox(const QImage *image)
Compute the smallest rectangle that contains all non-white pixels in image), in normalized [0...
Definition: utils.cpp:311
QByteArray::constData
const char * constData() const
QPaintDevice::widthMM
int widthMM() const
QWidget::pos
pos
QIODevice::read
qint64 read(char *data, qint64 maxSize)
Okular::Rotation270
Rotated 2700 degrees clockwise.
Definition: global.h:49
QRect::intersected
QRect intersected(const QRect &rectangle) const
QSize
QX11Info::appDpiX
int appDpiX(int screen)
QX11Info::appDpiY
int appDpiY(int screen)
QImage
QSizeF::transpose
void transpose()
Okular::copyQIODevice
void copyQIODevice(QIODevice *from, QIODevice *to)
Definition: utils.cpp:367
QTransform::rotate
QTransform & rotate(qreal angle, Qt::Axis axis)
Okular::Rotation90
Rotated 90 degrees clockwise.
Definition: global.h:47
Okular::buildRotationMatrix
QTransform buildRotationMatrix(Rotation rotation)
Return a rotation matrix corresponding to the rotation enumeration.
Definition: utils.cpp:380
QRect::width
int width() const
QSizeF
QApplication::desktop
QDesktopWidget * desktop()
QWidget::parentWidget
QWidget * parentWidget() const
utils_p.h
QByteArray::data
char * data()
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
QTime::start
void start()
QImage::height
int height() const
QSizeF::height
qreal height() const
QByteArray::size
int size() const
Okular::Utils::realDpi
static QSizeF realDpi(QWidget *widgetOnScreen)
Return the real DPI of the display containing given widget.
Definition: utils.cpp:301
QSizeF::width
qreal width() const
QWidget::height
height
isWhite
static bool isWhite(QRgb argb)
Definition: utils.cpp:307
Okular::Utils::realDpiY
static double realDpiY()
Return the real vertical DPI of the main display.
Definition: utils.cpp:296
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:19:25 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

okular

Skip menu "okular"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdegraphics API Reference

Skip menu "kdegraphics API Reference"
  •     libkdcraw
  •     libkexiv2
  •     libkipi
  •     libksane
  • okular

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal