compile
[kdegraphics.git] / okular / core / utils.cpp
blob93cf76446baebdb7447e5ed35779f90e603cb791
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 ***************************************************************************/
11 #include "utils.h"
12 #include "utils_p.h"
14 #include <QtCore/QRect>
15 #include <QImage>
16 #include <QIODevice>
18 #ifdef Q_WS_X11
19 #include <QX11Info>
20 #endif
22 #ifdef Q_WS_MAC
23 #include <ApplicationServices/ApplicationServices.h>
24 #include <IOKit/graphics/IOGraphicsLib.h>
25 #endif
29 using namespace Okular;
31 QRect Utils::rotateRect( const QRect & source, int width, int height, int orientation )
33 QRect ret;
35 // adapt the coordinates of the boxes to the rotation
36 switch ( orientation )
38 case 1:
39 ret = QRect( width - source.y() - source.height(), source.x(),
40 source.height(), source.width() );
41 break;
42 case 2:
43 ret = QRect( width - source.x() - source.width(), height - source.y() - source.height(),
44 source.width(), source.height() );
45 break;
46 case 3:
47 ret = QRect( source.y(), height - source.x() - source.width(),
48 source.height(), source.width() );
49 break;
50 case 0: // no modifications
51 default: // other cases
52 ret = source;
55 return ret;
58 #if defined(Q_WS_X11)
60 double Utils::dpiX()
62 return QX11Info::appDpiX();
65 double Utils::dpiY()
67 return QX11Info::appDpiY();
70 #elif defined(Q_WS_MAC)
72 * Code copied from http://developer.apple.com/qa/qa2001/qa1217.html
74 // Handy utility function for retrieving an int from a CFDictionaryRef
75 static int GetIntFromDictionaryForKey( CFDictionaryRef desc, CFStringRef key )
77 CFNumberRef value;
78 int num = 0;
79 if ( (value = (CFNumberRef)CFDictionaryGetValue(desc, key)) == NULL || CFGetTypeID(value) != CFNumberGetTypeID())
80 return 0;
81 CFNumberGetValue(value, kCFNumberIntType, &num);
82 return num;
85 static CGDisplayErr GetDisplayDPI( CFDictionaryRef displayModeDict, CGDirectDisplayID displayID,
86 double *horizontalDPI, double *verticalDPI )
88 CGDisplayErr err = kCGErrorFailure;
89 io_connect_t displayPort;
90 CFDictionaryRef displayDict;
92 // Grab a connection to IOKit for the requested display
93 displayPort = CGDisplayIOServicePort( displayID );
94 if ( displayPort != MACH_PORT_NULL )
96 // Find out what IOKit knows about this display
97 displayDict = IODisplayCreateInfoDictionary(displayPort, 0);
98 if ( displayDict != NULL )
100 const double mmPerInch = 25.4;
101 double horizontalSizeInInches =
102 (double)GetIntFromDictionaryForKey(displayDict,
103 CFSTR(kDisplayHorizontalImageSize)) / mmPerInch;
104 double verticalSizeInInches =
105 (double)GetIntFromDictionaryForKey(displayDict,
106 CFSTR(kDisplayVerticalImageSize)) / mmPerInch;
108 // Make sure to release the dictionary we got from IOKit
109 CFRelease(displayDict);
111 // Now we can calculate the actual DPI
112 // with information from the displayModeDict
113 *horizontalDPI =
114 (double)GetIntFromDictionaryForKey( displayModeDict, kCGDisplayWidth )
115 / horizontalSizeInInches;
116 *verticalDPI = (double)GetIntFromDictionaryForKey( displayModeDict,
117 kCGDisplayHeight ) / verticalSizeInInches;
118 err = CGDisplayNoErr;
121 return err;
124 double Utils::dpiX()
126 double x,y;
127 CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
128 kCGDirectMainDisplay,
129 &x, &y );
131 return err == CGDisplayNoErr ? x : 72.0;
134 double Utils::dpiY()
136 double x,y;
137 CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
138 kCGDirectMainDisplay,
139 &x, &y );
141 return err == CGDisplayNoErr ? y : 72.0;
143 #else
144 #include <QDesktopWidget>
146 double Utils::dpiX()
148 return QDesktopWidget().physicalDpiX();
151 double Utils::dpiY()
153 return QDesktopWidget().physicalDpiY();
155 #endif
157 inline static bool isWhite( QRgb argb ) {
158 return ( argb & 0xFFFFFF ) == 0xFFFFFF; // ignore alpha
161 NormalizedRect Utils::imageBoundingBox( const QImage * image )
163 if ( !image )
164 return NormalizedRect();
166 int width = image->width();
167 int height = image->height();
168 int left, top, bottom, right, x, y;
170 #ifdef BBOX_DEBUG
171 QTime time;
172 time.start();
173 #endif
175 // Scan pixels for top non-white
176 for ( top = 0; top < height; ++top )
177 for ( x = 0; x < width; ++x )
178 if ( !isWhite( image->pixel( x, top ) ) )
179 goto got_top;
180 return NormalizedRect( 0, 0, 0, 0 ); // the image is blank
181 got_top:
182 left = right = x;
184 // Scan pixels for bottom non-white
185 for ( bottom = height-1; bottom >= top; --bottom )
186 for ( x = width-1; x >= 0; --x )
187 if ( !isWhite( image->pixel( x, bottom ) ) )
188 goto got_bottom;
189 Q_ASSERT( 0 ); // image changed?!
190 got_bottom:
191 if ( x < left )
192 left = x;
193 if ( x > right )
194 right = x;
196 // Scan for leftmost and rightmost (we already found some bounds on these):
197 for ( y = top; y <= bottom && ( left > 0 || right < width-1 ); ++y )
199 for ( x = 0; x < left; ++x )
200 if ( !isWhite( image->pixel( x, y ) ) )
201 left = x;
202 for ( x = width-1; x > right+1; --x )
203 if ( !isWhite( image->pixel( x, y ) ) )
204 right = x;
207 NormalizedRect bbox( QRect( left, top, ( right - left + 1), ( bottom - top + 1 ) ),
208 image->width(), image->height() );
210 #ifdef BBOX_DEBUG
211 kDebug() << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
212 #endif
214 return bbox;
217 void Okular::copyQIODevice( QIODevice *from, QIODevice *to )
219 QByteArray buffer( 65536, '\0' );
220 qint64 read = 0;
221 qint64 written = 0;
222 while ( ( read = from->read( buffer.data(), buffer.size() ) ) > 0 )
224 written = to->write( buffer.constData(), read );
225 if ( read != written )
226 break;