2006-06-30 21:42:41 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2006 by Luigi Toscano <luigi.toscano@tiscali.it> *
|
2008-11-15 12:33:05 +00:00
|
|
|
* Copyright (C) 2008 by Pino Toscano <pino@kde.org> *
|
2006-06-30 21:42:41 +00:00
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "utils.h"
|
2008-11-15 12:33:05 +00:00
|
|
|
#include "utils_p.h"
|
2006-06-30 21:42:41 +00:00
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
#include "debug_p.h"
|
2015-10-20 22:04:49 +00:00
|
|
|
#include "settings_core.h"
|
|
|
|
|
2006-10-29 15:21:03 +00:00
|
|
|
#include <QtCore/QRect>
|
2009-06-09 00:45:02 +00:00
|
|
|
#include <QApplication>
|
|
|
|
#include <QDesktopWidget>
|
2008-05-18 23:03:17 +00:00
|
|
|
#include <QImage>
|
2008-11-15 12:33:05 +00:00
|
|
|
#include <QIODevice>
|
2016-01-30 17:15:07 +00:00
|
|
|
#include <QWindow>
|
|
|
|
#include <QScreen>
|
2006-10-29 15:08:18 +00:00
|
|
|
|
2014-10-06 18:02:48 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2006-10-29 15:08:18 +00:00
|
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
|
|
#include <IOKit/graphics/IOGraphicsLib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
using namespace Okular;
|
2006-06-30 21:42:41 +00:00
|
|
|
|
2006-09-21 08:45:36 +00:00
|
|
|
QRect Utils::rotateRect( const QRect & source, int width, int height, int orientation )
|
2006-06-30 21:42:41 +00:00
|
|
|
{
|
|
|
|
QRect ret;
|
|
|
|
|
|
|
|
// adapt the coordinates of the boxes to the rotation
|
|
|
|
switch ( orientation )
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ret = QRect( width - source.y() - source.height(), source.x(),
|
|
|
|
source.height(), source.width() );
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ret = QRect( width - source.x() - source.width(), height - source.y() - source.height(),
|
|
|
|
source.width(), source.height() );
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
ret = QRect( source.y(), height - source.x() - source.width(),
|
|
|
|
source.height(), source.width() );
|
|
|
|
break;
|
|
|
|
case 0: // no modifications
|
|
|
|
default: // other cases
|
|
|
|
ret = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2006-10-29 15:08:18 +00:00
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
#if !defined(Q_OS_MAC)
|
2009-06-09 00:45:02 +00:00
|
|
|
|
2014-01-13 00:15:55 +00:00
|
|
|
QSizeF Utils::realDpi(QWidget* widgetOnScreen)
|
|
|
|
{
|
2016-01-30 17:15:07 +00:00
|
|
|
const QScreen* screen = widgetOnScreen && widgetOnScreen->window() && widgetOnScreen->window()->windowHandle()
|
|
|
|
? widgetOnScreen->window()->windowHandle()->screen()
|
|
|
|
: qGuiApp->primaryScreen();
|
2014-01-13 00:15:55 +00:00
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
if (screen)
|
|
|
|
{
|
|
|
|
const QSizeF res(screen->physicalDotsPerInchX(), screen->physicalDotsPerInchY());
|
|
|
|
if (res.width() > 0 && res.height() > 0) {
|
|
|
|
if (qAbs(res.width() - res.height()) / qMin(res.height(), res.width()) < 0.05) {
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
qCDebug(OkularCoreDebug) << "QScreen calculation returned a non square dpi." << res << ". Falling back";
|
2014-05-15 18:18:22 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-20 20:30:49 +00:00
|
|
|
}
|
2016-01-30 17:15:07 +00:00
|
|
|
return QSizeF(72, 72);
|
2014-01-13 00:15:55 +00:00
|
|
|
}
|
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
#else
|
2006-10-29 15:08:18 +00:00
|
|
|
/*
|
|
|
|
* Code copied from http://developer.apple.com/qa/qa2001/qa1217.html
|
|
|
|
*/
|
|
|
|
// Handy utility function for retrieving an int from a CFDictionaryRef
|
|
|
|
static int GetIntFromDictionaryForKey( CFDictionaryRef desc, CFStringRef key )
|
|
|
|
{
|
|
|
|
CFNumberRef value;
|
|
|
|
int num = 0;
|
|
|
|
if ( (value = (CFNumberRef)CFDictionaryGetValue(desc, key)) == NULL || CFGetTypeID(value) != CFNumberGetTypeID())
|
|
|
|
return 0;
|
|
|
|
CFNumberGetValue(value, kCFNumberIntType, &num);
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2006-11-27 08:13:47 +00:00
|
|
|
static CGDisplayErr GetDisplayDPI( CFDictionaryRef displayModeDict, CGDirectDisplayID displayID,
|
|
|
|
double *horizontalDPI, double *verticalDPI )
|
2006-10-29 15:08:18 +00:00
|
|
|
{
|
|
|
|
CGDisplayErr err = kCGErrorFailure;
|
|
|
|
io_connect_t displayPort;
|
|
|
|
CFDictionaryRef displayDict;
|
|
|
|
|
|
|
|
// Grab a connection to IOKit for the requested display
|
|
|
|
displayPort = CGDisplayIOServicePort( displayID );
|
|
|
|
if ( displayPort != MACH_PORT_NULL )
|
|
|
|
{
|
|
|
|
// Find out what IOKit knows about this display
|
|
|
|
displayDict = IODisplayCreateInfoDictionary(displayPort, 0);
|
|
|
|
if ( displayDict != NULL )
|
|
|
|
{
|
|
|
|
const double mmPerInch = 25.4;
|
|
|
|
double horizontalSizeInInches =
|
|
|
|
(double)GetIntFromDictionaryForKey(displayDict,
|
|
|
|
CFSTR(kDisplayHorizontalImageSize)) / mmPerInch;
|
|
|
|
double verticalSizeInInches =
|
|
|
|
(double)GetIntFromDictionaryForKey(displayDict,
|
|
|
|
CFSTR(kDisplayVerticalImageSize)) / mmPerInch;
|
|
|
|
|
|
|
|
// Make sure to release the dictionary we got from IOKit
|
|
|
|
CFRelease(displayDict);
|
|
|
|
|
|
|
|
// Now we can calculate the actual DPI
|
|
|
|
// with information from the displayModeDict
|
|
|
|
*horizontalDPI =
|
|
|
|
(double)GetIntFromDictionaryForKey( displayModeDict, kCGDisplayWidth )
|
|
|
|
/ horizontalSizeInInches;
|
|
|
|
*verticalDPI = (double)GetIntFromDictionaryForKey( displayModeDict,
|
|
|
|
kCGDisplayHeight ) / verticalSizeInInches;
|
|
|
|
err = CGDisplayNoErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
double Utils::realDpiX()
|
2006-11-27 08:13:47 +00:00
|
|
|
{
|
2006-10-29 15:08:18 +00:00
|
|
|
double x,y;
|
|
|
|
CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
|
|
|
|
kCGDirectMainDisplay,
|
|
|
|
&x, &y );
|
|
|
|
|
|
|
|
return err == CGDisplayNoErr ? x : 72.0;
|
|
|
|
}
|
|
|
|
|
2016-01-30 17:15:07 +00:00
|
|
|
double Utils::realDpiY()
|
2006-11-27 08:13:47 +00:00
|
|
|
{
|
2006-10-29 15:08:18 +00:00
|
|
|
double x,y;
|
|
|
|
CGDisplayErr err = GetDisplayDPI( CGDisplayCurrentMode(kCGDirectMainDisplay),
|
|
|
|
kCGDirectMainDisplay,
|
|
|
|
&x, &y );
|
|
|
|
|
|
|
|
return err == CGDisplayNoErr ? y : 72.0;
|
|
|
|
}
|
2009-06-09 00:45:02 +00:00
|
|
|
|
2014-01-13 00:15:55 +00:00
|
|
|
QSizeF Utils::realDpi(QWidget*)
|
|
|
|
{
|
|
|
|
return QSizeF(realDpiX(), realDpiY());
|
|
|
|
}
|
2006-10-29 15:08:18 +00:00
|
|
|
#endif
|
2008-05-18 23:03:17 +00:00
|
|
|
|
2015-10-20 22:07:35 +00:00
|
|
|
inline static bool isPaperColor( QRgb argb, QRgb paperColor ) {
|
|
|
|
return ( argb & 0xFFFFFF ) == ( paperColor & 0xFFFFFF); // ignore alpha
|
2008-05-18 23:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedRect Utils::imageBoundingBox( const QImage * image )
|
|
|
|
{
|
|
|
|
if ( !image )
|
|
|
|
return NormalizedRect();
|
|
|
|
|
2015-10-20 22:07:35 +00:00
|
|
|
const int width = image->width();
|
|
|
|
const int height = image->height();
|
|
|
|
const QRgb paperColor = SettingsCore::paperColor().rgb();
|
2008-05-18 23:03:17 +00:00
|
|
|
int left, top, bottom, right, x, y;
|
|
|
|
|
|
|
|
#ifdef BBOX_DEBUG
|
|
|
|
QTime time;
|
|
|
|
time.start();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Scan pixels for top non-white
|
|
|
|
for ( top = 0; top < height; ++top )
|
|
|
|
for ( x = 0; x < width; ++x )
|
2015-10-20 22:07:35 +00:00
|
|
|
if ( !isPaperColor( image->pixel( x, top ), paperColor ) )
|
2008-05-18 23:03:17 +00:00
|
|
|
goto got_top;
|
|
|
|
return NormalizedRect( 0, 0, 0, 0 ); // the image is blank
|
|
|
|
got_top:
|
|
|
|
left = right = x;
|
|
|
|
|
|
|
|
// Scan pixels for bottom non-white
|
|
|
|
for ( bottom = height-1; bottom >= top; --bottom )
|
|
|
|
for ( x = width-1; x >= 0; --x )
|
2015-10-20 22:07:35 +00:00
|
|
|
if ( !isPaperColor( image->pixel( x, bottom ), paperColor ) )
|
2008-05-18 23:03:17 +00:00
|
|
|
goto got_bottom;
|
|
|
|
Q_ASSERT( 0 ); // image changed?!
|
|
|
|
got_bottom:
|
|
|
|
if ( x < left )
|
|
|
|
left = x;
|
|
|
|
if ( x > right )
|
|
|
|
right = x;
|
|
|
|
|
|
|
|
// Scan for leftmost and rightmost (we already found some bounds on these):
|
|
|
|
for ( y = top; y <= bottom && ( left > 0 || right < width-1 ); ++y )
|
|
|
|
{
|
|
|
|
for ( x = 0; x < left; ++x )
|
2015-10-20 22:07:35 +00:00
|
|
|
if ( !isPaperColor( image->pixel( x, y ), paperColor ) )
|
2008-05-18 23:03:17 +00:00
|
|
|
left = x;
|
|
|
|
for ( x = width-1; x > right+1; --x )
|
2015-10-20 22:07:35 +00:00
|
|
|
if ( !isPaperColor( image->pixel( x, y ), paperColor ) )
|
2008-05-18 23:03:17 +00:00
|
|
|
right = x;
|
|
|
|
}
|
|
|
|
|
|
|
|
NormalizedRect bbox( QRect( left, top, ( right - left + 1), ( bottom - top + 1 ) ),
|
|
|
|
image->width(), image->height() );
|
|
|
|
|
|
|
|
#ifdef BBOX_DEBUG
|
2014-09-11 17:36:01 +00:00
|
|
|
qCDebug(OkularCoreDebug) << "Computed bounding box" << bbox << "in" << time.elapsed() << "ms";
|
2008-05-18 23:03:17 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return bbox;
|
|
|
|
}
|
2008-11-15 12:33:05 +00:00
|
|
|
|
|
|
|
void Okular::copyQIODevice( QIODevice *from, QIODevice *to )
|
|
|
|
{
|
|
|
|
QByteArray buffer( 65536, '\0' );
|
|
|
|
qint64 read = 0;
|
|
|
|
qint64 written = 0;
|
|
|
|
while ( ( read = from->read( buffer.data(), buffer.size() ) ) > 0 )
|
|
|
|
{
|
|
|
|
written = to->write( buffer.constData(), read );
|
|
|
|
if ( read != written )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-12-29 22:27:30 +00:00
|
|
|
|
|
|
|
QTransform Okular::buildRotationMatrix(Rotation rotation)
|
|
|
|
{
|
|
|
|
QTransform matrix;
|
|
|
|
matrix.rotate( (int)rotation * 90 );
|
|
|
|
|
|
|
|
switch ( rotation )
|
|
|
|
{
|
|
|
|
case Rotation90:
|
|
|
|
matrix.translate( 0, -1 );
|
|
|
|
break;
|
|
|
|
case Rotation180:
|
|
|
|
matrix.translate( -1, -1 );
|
|
|
|
break;
|
|
|
|
case Rotation270:
|
|
|
|
matrix.translate( -1, 0 );
|
|
|
|
break;
|
|
|
|
default: ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return matrix;
|
|
|
|
}
|
2014-01-13 00:47:31 +00:00
|
|
|
|
|
|
|
/* kate: replace-tabs on; indent-width 4; */
|