[packages/qt4] - bumped icu version to 52 - added wkhtml patch (modifications from wkhtmltopdf fork; on bcond only
qboosh
qboosh at pld-linux.org
Mon Oct 21 17:25:32 CEST 2013
commit 3583d8d70a3b67403433a8664d9f7facad0e1277
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Mon Oct 21 17:24:57 2013 +0200
- bumped icu version to 52
- added wkhtml patch (modifications from wkhtmltopdf fork; on bcond only because it affects libQtGui ABI)
qt4-wkhtml.patch | 2948 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
qt4.spec | 32 +-
2 files changed, 2966 insertions(+), 14 deletions(-)
---
diff --git a/qt4.spec b/qt4.spec
index 2fbf1ca..a406bac 100644
--- a/qt4.spec
+++ b/qt4.spec
@@ -5,18 +5,22 @@
# - check Qt ui tool
#
# Conditional build:
-%bcond_with nas # enable NAS audio support
%bcond_without static_libs # don't build static libraries
-%bcond_without cups # disable CUPS support
-%bcond_without mysql # don't build MySQL plugin
-%bcond_without odbc # don't build unixODBC plugin
-%bcond_without pgsql # don't build PostgreSQL plugin
-%bcond_without sqlite3 # don't build SQLite3 plugin
-%bcond_without sqlite # don't build SQLite2 plugin
-%bcond_without ibase # don't build ibase (InterBase/Firebird) plugin
-%bcond_without pch # disable pch in qmake
-%bcond_without gtk # don't build GTK theme integration
-%bcond_without system_phonon # don't build phonon libraries
+# -- features
+%bcond_without cups # CUPS printing support
+%bcond_with nas # NAS audio support
+%bcond_without gtk # GTK+ theme integration
+%bcond_without pch # pch (pre-compiled headers) in qmake
+%bcond_without system_phonon # phonon libraries from phonon.spec intead of qt4.spec
+%bcond_with wkhtml # WKHTMLTOPDF patch (affects QtGui ABI)
+# -- databases
+%bcond_without mysql # MySQL plugin
+%bcond_without odbc # unixODBC plugin
+%bcond_without pgsql # PostgreSQL plugin
+%bcond_without sqlite3 # SQLite3 plugin
+%bcond_without sqlite # SQLite2 plugin
+%bcond_without ibase # ibase (InterBase/Firebird) plugin
+# -- SIMD CPU instructions
%bcond_with mmx # use MMX instructions
%bcond_with 3dnow # use 3Dnow instructions
%bcond_with sse # use SSE instructions in gui/painting module
@@ -46,7 +50,7 @@
%define _withsql 1
%{!?with_sqlite3:%{!?with_sqlite:%{!?with_ibase:%{!?with_mysql:%{!?with_pgsql:%{!?with_odbc:%undefine _withsql}}}}}}
-%define icu_abi 49
+%define icu_abi 52
%define next_icu_abi %(echo $((%{icu_abi} + 1)))
Summary: The Qt GUI application framework
@@ -80,7 +84,7 @@ Patch7: %{name}-x11_fonts.patch
Patch8: %{name}-ibase.patch
Patch9: qt-x11-opensource-src-4.5.1-enable_ft_lcdfilter.patch
Patch10: webkit-no_Werror.patch
-
+Patch11: %{name}-wkhtml.patch
Patch12: fix-crash-in-assistant.patch
Patch13: improve-cups-support.patch
# backported from Qt5 (essentially)
@@ -1470,7 +1474,7 @@ Programas exemplo para o Qt versão.
%patch8 -p1
%patch9 -p1
%patch10 -p1
-
+%{?with_wkhtml:%patch11 -p1}
%patch12 -p1
%patch13 -p1
diff --git a/qt4-wkhtml.patch b/qt4-wkhtml.patch
new file mode 100644
index 0000000..85eaa00
--- /dev/null
+++ b/qt4-wkhtml.patch
@@ -0,0 +1,2948 @@
+git clone git://gitorious.org/~antialize/qt/antializes-qt.git, then checkout 4.8.4
+# check 4.8.4 commit ID on git://gitorious.org/qt/qt.git
+git diff 96311def2466dd44de64d77a1c815b22fbf68f71
+# parts related to static QtWebkit build are disabled
+
+#diff --git a/configure b/configure
+#index e3d464b..114933e 100755
+#--- a/configure
+#+++ b/configure
+#@@ -7749,12 +7749,12 @@ if [ "$CFG_GUI" = "no" ]; then
+# canBuildWebKit="no"
+# fi
+#
+#-if [ "$CFG_SHARED" = "no" ]; then
+#- echo
+#- echo "WARNING: Using static linking will disable the WebKit module."
+#- echo
+#- canBuildWebKit="no"
+#-fi
+#+#if [ "$CFG_SHARED" = "no" ]; then
+#+ # echo
+#+ # echo "WARNING: Using static linking will disable the WebKit module."
+#+ # echo
+#+ # canBuildWebKit="no"
+#+#fi
+#
+# CFG_CONCURRENT="yes"
+# if [ "$canBuildQtConcurrent" = "no" ]; then
+#diff --git a/src/3rdparty/webkit/Source/JavaScriptCore/JavaScriptCore.pro b/src/3rdparty/webkit/Source/JavaScriptCore/JavaScriptCore.pro
+#index a109179..146cb2d 100644
+#--- a/src/3rdparty/webkit/Source/JavaScriptCore/JavaScriptCore.pro
+#+++ b/src/3rdparty/webkit/Source/JavaScriptCore/JavaScriptCore.pro
+#@@ -217,6 +217,12 @@ symbian: {
+# QMAKE_CXXFLAGS.ARMCC += -OTime -O3
+# }
+#
+#+static {
+#+ !isEmpty(INSTALL_LIBS): target.path = $$INSTALL_LIBS
+#+ else: target.path = $$[QT_INSTALL_LIBS]
+#+ INSTALLS += target
+#+}
+#+
+# lessThan(QT_GCC_MAJOR_VERSION, 5) {
+# # GCC 4.5 and before
+# lessThan(QT_GCC_MINOR_VERSION, 6) {
+diff --git a/src/3rdparty/webkit/Source/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/Source/WebCore/page/FrameView.cpp
+index ef72fb7..54ff69c 100644
+--- a/src/3rdparty/webkit/Source/WebCore/page/FrameView.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/page/FrameView.cpp
+@@ -1080,7 +1080,9 @@ void FrameView::adjustMediaTypeForPrinting(bool printing)
+ if (printing) {
+ if (m_mediaTypeWhenNotPrinting.isNull())
+ m_mediaTypeWhenNotPrinting = mediaType();
+- setMediaType("print");
++
++ String mediaType = (m_frame && m_frame->settings())?m_frame->settings()->printingMediaType():"print";
++ setMediaType(mediaType);
+ } else {
+ if (!m_mediaTypeWhenNotPrinting.isNull())
+ setMediaType(m_mediaTypeWhenNotPrinting);
+diff --git a/src/3rdparty/webkit/Source/WebCore/page/PrintContext.cpp b/src/3rdparty/webkit/Source/WebCore/page/PrintContext.cpp
+index 660ad11..8dffd52 100644
+--- a/src/3rdparty/webkit/Source/WebCore/page/PrintContext.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/page/PrintContext.cpp
+@@ -26,6 +26,7 @@
+ #include "FrameView.h"
+ #include "RenderLayer.h"
+ #include "RenderView.h"
++#include "Settings.h"
+ #include <wtf/text/StringConcatenate.h>
+
+ namespace WebCore {
+@@ -182,11 +183,21 @@ void PrintContext::begin(float width, float height)
+ // This function can be called multiple times to adjust printing parameters without going back to screen mode.
+ m_isPrinting = true;
+
+- float minLayoutWidth = width * printingMinimumShrinkFactor;
+- float minLayoutHeight = height * printingMinimumShrinkFactor;
++ float minimumShrinkFactor = m_frame->settings() ?
++ m_frame->settings()->printingMinimumShrinkFactor() : 0.0f;
++ float maximumShrinkFactor = m_frame->settings() ?
++ m_frame->settings()->printingMaximumShrinkFactor() : 0.0f;
++
++ if (maximumShrinkFactor < minimumShrinkFactor || minimumShrinkFactor <= 0.0f) {
++ minimumShrinkFactor = printingMinimumShrinkFactor;
++ maximumShrinkFactor = printingMaximumShrinkFactor;
++ }
++
++ float minLayoutWidth = width * minimumShrinkFactor;
++ float minLayoutHeight = height * minimumShrinkFactor;
+
+ // This changes layout, so callers need to make sure that they don't paint to screen while in printing mode.
+- m_frame->setPrinting(true, FloatSize(minLayoutWidth, minLayoutHeight), printingMaximumShrinkFactor / printingMinimumShrinkFactor, Frame::AdjustViewSize);
++ m_frame->setPrinting(true, FloatSize(minLayoutWidth, minLayoutHeight), maximumShrinkFactor / minimumShrinkFactor, Frame::AdjustViewSize);
+ }
+
+ float PrintContext::computeAutomaticScaleFactor(const FloatSize& availablePaperSize)
+diff --git a/src/3rdparty/webkit/Source/WebCore/page/PrintContext.h b/src/3rdparty/webkit/Source/WebCore/page/PrintContext.h
+index aadff47..19f378e 100644
+--- a/src/3rdparty/webkit/Source/WebCore/page/PrintContext.h
++++ b/src/3rdparty/webkit/Source/WebCore/page/PrintContext.h
+@@ -83,6 +83,8 @@ public:
+ // (pageSizeInPixels.height() + 1) * number-of-pages - 1
+ static void spoolAllPagesWithBoundaries(Frame*, GraphicsContext&, const FloatSize& pageSizeInPixels);
+
++public:
++ const Vector<IntRect> & getPageRects() const {return m_pageRects;}
+ protected:
+ Frame* m_frame;
+ Vector<IntRect> m_pageRects;
+diff --git a/src/3rdparty/webkit/Source/WebCore/page/Settings.cpp b/src/3rdparty/webkit/Source/WebCore/page/Settings.cpp
+index 2025bd0..5414246 100644
+--- a/src/3rdparty/webkit/Source/WebCore/page/Settings.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/page/Settings.cpp
+@@ -87,6 +87,7 @@ static EditingBehaviorType editingBehaviorTypeForPlatform()
+
+ Settings::Settings(Page* page)
+ : m_page(page)
++ , m_printingMediaType("print")
+ , m_editableLinkBehavior(EditableLinkDefaultBehavior)
+ , m_textDirectionSubmenuInclusionBehavior(TextDirectionSubmenuAutomaticallyIncluded)
+ , m_passwordEchoDurationInSeconds(1)
+@@ -184,6 +185,8 @@ Settings::Settings(Page* page)
+ , m_allowDisplayOfInsecureContent(true)
+ , m_allowRunningOfInsecureContent(true)
+ , m_passwordEchoEnabled(false)
++ , m_printingMinimumShrinkFactor(0.0)
++ , m_printingMaximumShrinkFactor(0.0)
+ {
+ // A Frame may not have been created yet, so we initialize the AtomicString
+ // hash before trying to use it.
+@@ -569,6 +572,11 @@ void Settings::setApplicationChromeMode(bool mode)
+ m_inApplicationChromeMode = mode;
+ }
+
++void Settings::setPrintingMediaType(const String& type)
++{
++ m_printingMediaType = type;
++}
++
+ void Settings::setOfflineWebApplicationCacheEnabled(bool enabled)
+ {
+ m_offlineWebApplicationCacheEnabled = enabled;
+@@ -744,4 +752,15 @@ void Settings::setTiledBackingStoreEnabled(bool enabled)
+ #endif
+ }
+
++void Settings::setPrintingMinimumShrinkFactor(float printingMinimumShrinkFactor)
++{
++ m_printingMinimumShrinkFactor = printingMinimumShrinkFactor;
++}
++
++void Settings::setPrintingMaximumShrinkFactor(float printingMaximumShrinkFactor)
++{
++ m_printingMaximumShrinkFactor = printingMaximumShrinkFactor;
++}
++
++
+ } // namespace WebCore
+diff --git a/src/3rdparty/webkit/Source/WebCore/page/Settings.h b/src/3rdparty/webkit/Source/WebCore/page/Settings.h
+index 1d2a138..d827693 100644
+--- a/src/3rdparty/webkit/Source/WebCore/page/Settings.h
++++ b/src/3rdparty/webkit/Source/WebCore/page/Settings.h
+@@ -258,6 +258,9 @@ namespace WebCore {
+ void setApplicationChromeMode(bool);
+ bool inApplicationChromeMode() const { return m_inApplicationChromeMode; }
+
++ void setPrintingMediaType(const String&);
++ const String& printingMediaType() const { return m_printingMediaType; }
++
+ void setOfflineWebApplicationCacheEnabled(bool);
+ bool offlineWebApplicationCacheEnabled() const { return m_offlineWebApplicationCacheEnabled; }
+
+@@ -349,6 +352,12 @@ namespace WebCore {
+
+ void setTiledBackingStoreEnabled(bool);
+ bool tiledBackingStoreEnabled() const { return m_tiledBackingStoreEnabled; }
++
++ void setPrintingMinimumShrinkFactor(float);
++ float printingMinimumShrinkFactor() const { return m_printingMinimumShrinkFactor; }
++
++ void setPrintingMaximumShrinkFactor(float);
++ float printingMaximumShrinkFactor() const { return m_printingMaximumShrinkFactor; }
+
+ void setPaginateDuringLayoutEnabled(bool flag) { m_paginateDuringLayoutEnabled = flag; }
+ bool paginateDuringLayoutEnabled() const { return m_paginateDuringLayoutEnabled; }
+@@ -419,6 +428,7 @@ namespace WebCore {
+ String m_defaultTextEncodingName;
+ String m_ftpDirectoryTemplatePath;
+ String m_localStorageDatabasePath;
++ String m_printingMediaType;
+ KURL m_userStyleSheetLocation;
+ AtomicString m_standardFontFamily;
+ AtomicString m_fixedFontFamily;
+@@ -429,6 +439,8 @@ namespace WebCore {
+ EditableLinkBehavior m_editableLinkBehavior;
+ TextDirectionSubmenuInclusionBehavior m_textDirectionSubmenuInclusionBehavior;
+ double m_passwordEchoDurationInSeconds;
++ float m_printingMinimumShrinkFactor;
++ float m_printingMaximumShrinkFactor;
+ int m_minimumFontSize;
+ int m_minimumLogicalFontSize;
+ int m_defaultFontSize;
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+index c348870..4069687 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+@@ -73,7 +73,8 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
+ font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+ const bool smallCaps = description.smallCaps();
+ font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+- font.setStyleStrategy(QFont::ForceIntegerMetrics);
++ // Commented out to work around webkit bug 93263
++ //font.setStyleStrategy(QFont::ForceIntegerMetrics);
+
+ m_data->bold = font.bold();
+ // WebKit allows font size zero but QFont does not. We will return
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/ImageQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/ImageQt.cpp
+index 0c8ce9e..5ba54d0 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/ImageQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/graphics/qt/ImageQt.cpp
+@@ -41,6 +41,7 @@
+ #include "PlatformString.h"
+ #include "StillImageQt.h"
+ #include "qwebsettings.h"
++#include "SharedBuffer.h"
+
+ #include <QPixmap>
+ #include <QPainter>
+@@ -234,7 +235,8 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
+ }
+ }
+
+- ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc);
++ QByteArray a = QByteArray::fromRawData(data()->data(), data()->size());
++ ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc, &a);
+
+ ctxt->setCompositeOperation(previousOperator);
+
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/qt/PlatformScreenQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/qt/PlatformScreenQt.cpp
+index 4db8bd1..0f405cb 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/qt/PlatformScreenQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/qt/PlatformScreenQt.cpp
+@@ -53,11 +53,17 @@ static int screenNumber(Widget* w)
+
+ int screenDepth(Widget* w)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return 32;
++
+ return QApplication::desktop()->screen(screenNumber(w))->depth();
+ }
+
+ int screenDepthPerComponent(Widget* w)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return 8;
++
+ int depth = QApplication::desktop()->screen(0)->depth();
+ if (w) {
+ QWebPageClient* client = w->root()->hostWindow()->platformPageClient();
+@@ -86,17 +92,26 @@ int screenDepthPerComponent(Widget* w)
+
+ bool screenIsMonochrome(Widget* w)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return false;
++
+ return QApplication::desktop()->screen(screenNumber(w))->colorCount() == 2;
+ }
+
+ FloatRect screenRect(Widget* w)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return FloatRect(0,0,800,600);
++
+ QRect r = QApplication::desktop()->screenGeometry(screenNumber(w));
+ return FloatRect(r.x(), r.y(), r.width(), r.height());
+ }
+
+ FloatRect screenAvailableRect(Widget* w)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return FloatRect(0,0,800,600);
++
+ QRect r = QApplication::desktop()->availableGeometry(screenNumber(w));
+ return FloatRect(r.x(), r.y(), r.width(), r.height());
+ }
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/qt/RenderThemeQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/qt/RenderThemeQt.cpp
+index f98df88..b1fe30d 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/qt/RenderThemeQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/qt/RenderThemeQt.cpp
+@@ -178,7 +178,13 @@ RenderThemeQt::RenderThemeQt(Page* page)
+ : RenderTheme()
+ , m_page(page)
+ , m_lineEdit(0)
++ , m_fallbackStyle(0)
+ {
++ if (QApplication::type() == QApplication::Tty) {
++ m_buttonFontFamily = "sans-serif";
++ return;
++ }
++
+ QPushButton button;
+ button.setAttribute(Qt::WA_MacSmallSize);
+ QFont defaultButtonFont = QApplication::font(&button);
+@@ -339,6 +345,9 @@ bool RenderThemeQt::supportsControlTints() const
+
+ int RenderThemeQt::findFrameLineWidth(QStyle* style) const
+ {
++ if (QApplication::type()==QApplication::Tty)
++ return 1;
++
+ #ifndef QT_NO_LINEEDIT
+ if (!m_lineEdit)
+ m_lineEdit = new QLineEdit();
+@@ -445,6 +454,9 @@ Color RenderThemeQt::systemColor(int cssValueId) const
+
+ int RenderThemeQt::minimumMenuListSize(RenderStyle*) const
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return 1;
++
+ const QFontMetrics &fm = QApplication::fontMetrics();
+ return fm.width(QLatin1Char('x'));
+ }
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/qt/ScreenQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/qt/ScreenQt.cpp
+index d648c53..f844d54 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/qt/ScreenQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/qt/ScreenQt.cpp
+@@ -54,6 +54,9 @@ static QWidget* qwidgetForPage(const Page* page)
+
+ FloatRect screenRect(const Page* page)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return FloatRect(0,0,800,600);
++
+ QWidget* qw = qwidgetForPage(page);
+ if (!qw)
+ return FloatRect();
+@@ -68,6 +71,9 @@ FloatRect screenRect(const Page* page)
+
+ int screenDepth(const Page* page)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return 32;
++
+ QWidget* qw = qwidgetForPage(page);
+ if (!qw)
+ return 32;
+@@ -77,6 +83,9 @@ int screenDepth(const Page* page)
+
+ FloatRect usableScreenRect(const Page* page)
+ {
++ if (QApplication::type() == QApplication::Tty)
++ return FloatRect();
++
+ QWidget* qw = qwidgetForPage(page);
+ if (!qw)
+ return FloatRect();
+diff --git a/src/3rdparty/webkit/Source/WebCore/platform/qt/WidgetQt.cpp b/src/3rdparty/webkit/Source/WebCore/platform/qt/WidgetQt.cpp
+index 5215e66..e033279 100644
+--- a/src/3rdparty/webkit/Source/WebCore/platform/qt/WidgetQt.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/platform/qt/WidgetQt.cpp
+@@ -41,6 +41,7 @@
+ #include "QWebPageClient.h"
+ #include "ScrollView.h"
+
++#include <QApplication>
+ #include <QCoreApplication>
+ #include <QDebug>
+ #include <QPaintEngine>
+@@ -78,6 +79,9 @@ void Widget::setFocus(bool focused)
+ void Widget::setCursor(const Cursor& cursor)
+ {
+ #ifndef QT_NO_CURSOR
++ if (QApplication::type() == QApplication::Tty)
++ return;
++
+ ScrollView* view = root();
+ if (!view)
+ return;
+diff --git a/src/3rdparty/webkit/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/src/3rdparty/webkit/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+index 2e92801..1690c2f 100644
+--- a/src/3rdparty/webkit/Source/WebCore/rendering/RenderBlockLineLayout.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+@@ -956,7 +956,8 @@ void RenderBlock::layoutRunsAndFloats(bool fullLayout, bool hasInlineChild, Vect
+ repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
+ }
+
+- if (paginated) {
++ // table cell pagination is handled in RenderTableSection
++ if (paginated && !isTableCell()) {
+ int adjustment = 0;
+ adjustLinePositionForPagination(lineBox, adjustment);
+ if (adjustment) {
+diff --git a/src/3rdparty/webkit/Source/WebCore/rendering/RenderBox.cpp b/src/3rdparty/webkit/Source/WebCore/rendering/RenderBox.cpp
+index f052ee7..a5afea5 100644
+--- a/src/3rdparty/webkit/Source/WebCore/rendering/RenderBox.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/rendering/RenderBox.cpp
+@@ -804,7 +804,8 @@ void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
+
+ // The background of the box generated by the root element covers the entire canvas, so just use
+ // the RenderView's docTop/Left/Width/Height accessors.
+- paintFillLayers(paintInfo, bgColor, bgLayer, view()->docLeft(), view()->docTop(), view()->docWidth(), view()->docHeight(), BackgroundBleedNone, CompositeSourceOver, bodyObject);
++ if (bgColor.rgb() != Color::white)
++ paintFillLayers(paintInfo, bgColor, bgLayer, view()->docLeft(), view()->docTop(), view()->docWidth(), view()->docHeight(), BackgroundBleedNone, CompositeSourceOver, bodyObject);
+ }
+
+ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+diff --git a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
+index 73b0801..c34b1c2 100644
+--- a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTable.cpp
+@@ -302,11 +302,20 @@ void RenderTable::layout()
+
+ bool collapsing = collapseBorders();
+
++ // repeat header and footer on each page
++ int headHeight = 0;
++ int footHeight = 0;
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isTableSection()) {
+ child->layoutIfNeeded();
+ RenderTableSection* section = toRenderTableSection(child);
+- totalSectionLogicalHeight += section->calcRowLogicalHeight();
++ int rowHeight = section->calcRowLogicalHeight();
++ if (child == m_head) {
++ headHeight = rowHeight;
++ } else if (child == m_foot) {
++ footHeight = rowHeight;
++ }
++ totalSectionLogicalHeight += rowHeight;
+ if (collapsing)
+ section->recalcOuterBorder();
+ ASSERT(!section->needsLayout());
+@@ -320,6 +329,30 @@ void RenderTable::layout()
+ if (m_caption)
+ m_caption->layoutIfNeeded();
+
++ // Bump table to next page if we can't fit the caption, thead and first body cell
++ setPaginationStrut(0);
++ if (view()->layoutState()->pageLogicalHeight()) {
++ LayoutState* layoutState = view()->layoutState();
++ const int pageLogicalHeight = layoutState->m_pageLogicalHeight;
++ const int remainingLogicalHeight = pageLogicalHeight - layoutState->pageLogicalOffset(0) % pageLogicalHeight;
++ if (remainingLogicalHeight > 0) {
++ int requiredHeight = headHeight;
++ if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
++ requiredHeight += m_caption->logicalHeight() + m_caption->marginBefore() + m_caption->marginAfter();
++ }
++ if (m_firstBody) {
++ // FIXME: Calculate maximum required height across all cells in first body row
++ RenderTableCell* firstCell = m_firstBody->primaryCellAt(0, 0);
++ if (firstCell) {
++ requiredHeight += firstCell->contentLogicalHeight() + firstCell->paddingTop(false) + firstCell->paddingBottom(false) + vBorderSpacing();
++ }
++ }
++ if (requiredHeight > remainingLogicalHeight) {
++ setPaginationStrut(remainingLogicalHeight);
++ }
++ }
++ }
++
+ // If any table section moved vertically, we will just repaint everything from that
+ // section down (it is quite unlikely that any of the following sections
+ // did not shift).
+@@ -352,12 +385,6 @@ void RenderTable::layout()
+ computedLogicalHeight = computePercentageLogicalHeight(logicalHeightLength);
+ computedLogicalHeight = max(0, computedLogicalHeight);
+
+- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+- if (child->isTableSection())
+- // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
+- toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, computedLogicalHeight - totalSectionLogicalHeight) : 0);
+- }
+-
+ if (!m_firstBody && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
+ // Completely empty tables (with no sections or anything) should at least honor specified height
+ // in strict mode.
+@@ -377,6 +404,9 @@ void RenderTable::layout()
+ }
+ section->setLogicalLocation(sectionLogicalLeft, logicalHeight());
+
++ // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
++ section->layoutRows(section == m_firstBody ? max(0, computedLogicalHeight - totalSectionLogicalHeight) : 0, section == m_head ? 0 : headHeight, section == m_foot ? 0 : footHeight);
++
+ setLogicalHeight(logicalHeight() + section->logicalHeight());
+ section = sectionBelow(section);
+ }
+@@ -503,7 +533,59 @@ void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
+ child->paint(info, childPoint.x(), childPoint.y());
+ }
+ }
+-
++
++ bool repaintedHead = false;
++ IntPoint repaintedHeadPoint;
++ bool repaintedFoot = false;
++ IntPoint repaintedFootPoint;
++ if (view()->pageLogicalHeight()) {
++ // re-paint header/footer if table is split over multiple pages
++ if (m_head) {
++ IntPoint childPoint = flipForWritingMode(m_head, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
++ if (info.rect.y() > childPoint.y() + m_head->y()) {
++ repaintedHeadPoint = IntPoint(childPoint.x(), info.rect.y() - m_head->y());
++ repaintedHead = true;
++ dynamic_cast<RenderObject*>(m_head)->paint(info, repaintedHeadPoint.x(), repaintedHeadPoint.y());
++ }
++ }
++ if (m_foot) {
++ IntPoint childPoint = flipForWritingMode(m_foot, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
++ if (info.rect.y() + info.rect.height() < childPoint.y() + m_foot->y()) {
++ // find actual end of table on current page
++ int dy = 0;
++ const int max_dy = info.rect.y() + info.rect.height();
++ const int vspace = vBorderSpacing();
++ for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
++ if (section->isTableSection()) {
++ if (toRenderBox(section)->y() > max_dy) {
++ continue;
++ }
++ int i = 0;
++ for(RenderObject* row = section->firstChild(); row; row = row->nextSibling()) {
++ if (!row->isTableRow()) {
++ continue;
++ }
++ // get actual bottom-y position of this row - pretty complicated, how could this be simplified?
++ // note how we have to take the rowPoint and section's y-offset into account, see e.g.
++ // RenderTableSection::paint where this is also done...
++ IntPoint rowPoint = flipForWritingMode(toRenderBox(row), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
++ int row_dy = rowPoint.y() + toRenderBox(row)->y() + toRenderBox(row)->logicalHeight() + toRenderBox(section)->y();
++ if (row_dy < max_dy && row_dy > dy) {
++ dy = row_dy;
++ } else if (row_dy > max_dy) {
++ break;
++ }
++ i++;
++ }
++ }
++ }
++ repaintedFoot = true;
++ repaintedFootPoint = IntPoint(childPoint.x(), dy - m_foot->y());
++ dynamic_cast<RenderObject*>(m_foot)->paint(info, repaintedFootPoint.x(), repaintedFootPoint.y());
++ }
++ }
++ }
++
+ if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
+ // Collect all the unique border styles that we want to paint in a sorted list. Once we
+ // have all the styles sorted, we then do individual passes, painting each style of border
+@@ -522,6 +604,12 @@ void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+ if (child->isTableSection()) {
+ IntPoint childPoint = flipForWritingMode(toRenderTableSection(child), IntPoint(tx, ty), ParentToChildFlippingAdjustment);
++ // also repaint borders of header/footer if required
++ if (child == m_head && repaintedHead) {
++ childPoint = repaintedHeadPoint;
++ } else if (child == m_foot && repaintedFoot) {
++ childPoint = repaintedFootPoint;
++ }
+ child->paint(info, childPoint.x(), childPoint.y());
+ }
+ }
+diff --git a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
+index 7d414a0..6c814b3 100644
+--- a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
++++ b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.cpp
+@@ -414,7 +414,7 @@ void RenderTableSection::layout()
+ setNeedsLayout(false);
+ }
+
+-int RenderTableSection::layoutRows(int toAdd)
++int RenderTableSection::layoutRows(int toAdd, int headHeight, int footHeight)
+ {
+ #ifndef NDEBUG
+ setNeedsLayoutIsForbidden(true);
+@@ -496,12 +496,47 @@ int RenderTableSection::layoutRows(int toAdd)
+
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());
+
++ // Calculate logical row heights
++ Vector<int> logicalRowHeights;
++ logicalRowHeights.resize(totalRows);
++ for (int r = 0; r < totalRows; r++) {
++ logicalRowHeights[r] = m_rowPos[r + 1] - m_rowPos[r] - vspacing;
++ }
++
++ // Make sure that cell contents do not overlap a page break
++ if (view()->layoutState()->pageLogicalHeight()) {
++ LayoutState* layoutState = view()->layoutState();
++ int pageLogicalHeight = layoutState->m_pageLogicalHeight;
++ int pageOffset = 0;
++
++ for (int r = 0; r < totalRows; ++r) {
++ int rowLogicalOffset = m_rowPos[r] + pageOffset;
++ int remainingLogicalHeight = pageLogicalHeight - layoutState->pageLogicalOffset(rowLogicalOffset) % pageLogicalHeight;
++
++ for (int c = 0; c < nEffCols; c++) {
++ CellStruct& cs = cellAt(r, c);
++ RenderTableCell* cell = cs.primaryCell();
++
++ if (!cell || cs.inColSpan || cell->row() != r)
++ continue;
++
++ int cellRequiredHeight = cell->contentLogicalHeight() + cell->paddingTop(false) + cell->paddingBottom(false);
++ if (max(logicalRowHeights[r], cellRequiredHeight) > remainingLogicalHeight - footHeight - vspacing) {
++ pageOffset += remainingLogicalHeight + headHeight;
++ break;
++ }
++ }
++ m_rowPos[r] += pageOffset;
++ }
++ m_rowPos[totalRows] += pageOffset;
++ }
++
+ for (int r = 0; r < totalRows; r++) {
+ // Set the row's x/y position and width/height.
+ if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
+ rowRenderer->setLocation(0, m_rowPos[r]);
+ rowRenderer->setLogicalWidth(logicalWidth());
+- rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
++ rowRenderer->setLogicalHeight(logicalRowHeights[r]);
+ rowRenderer->updateLayerTransform();
+ }
+
+@@ -513,7 +548,11 @@ int RenderTableSection::layoutRows(int toAdd)
+ continue;
+
+ rindx = cell->row();
+- rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
++ if (cell->rowSpan() == 1) {
++ rHeight = logicalRowHeights[rindx];
++ } else {
++ rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
++ }
+
+ // Force percent height children to lay themselves out again.
+ // This will cause these children to grow to fill the cell.
+diff --git a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.h b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.h
+index db6edc2..9d912a0 100644
+--- a/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.h
++++ b/src/3rdparty/webkit/Source/WebCore/rendering/RenderTableSection.h
+@@ -49,7 +49,7 @@ public:
+
+ void setCellLogicalWidths();
+ int calcRowLogicalHeight();
+- int layoutRows(int logicalHeight);
++ int layoutRows(int logicalHeight, int headHeight, int footHeight);
+
+ RenderTable* table() const { return toRenderTable(parent()); }
+
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebelement.h b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebelement.h
+index 4b1a758..2ad7f1f 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebelement.h
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebelement.h
+@@ -170,6 +170,7 @@ private:
+ friend class QWebHitTestResult;
+ friend class QWebHitTestResultPrivate;
+ friend class QWebPage;
++ friend class QWebPrinter;
+
+ #if defined(WTF_USE_V8) && WTF_USE_V8
+ friend class V8::Bindings::QtWebElementRuntime;
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.cpp b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.cpp
+index 5ea7059..b0229ed 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.cpp
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.cpp
+@@ -216,6 +216,114 @@ static inline ResourceRequestCachePolicy cacheLoadControlToCachePolicy(uint cach
+ return WebCore::UseProtocolCachePolicy;
+ }
+
++#ifndef QT_NO_PRINTER
++QWebPrinterPrivate::QWebPrinterPrivate(const QWebFrame *f, QPaintDevice *printer, QPainter &p)
++ : printContext(f->d->frame)
++ , painter(p)
++ , frame(f)
++ , graphicsContext(&p)
++{
++ const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi();
++ const qreal zoomFactorY = printer->logicalDpiY() / qt_defaultDpi();
++ IntRect pageRect(0, 0,
++ int(printer->width() / zoomFactorX),
++ int(printer->height() / zoomFactorY));
++
++ printContext.begin(pageRect.width(), pageRect.height());
++ float pageHeight = 0;
++ printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
++
++ painter.scale(zoomFactorX, zoomFactorY);
++ printWidth = pageRect.width();
++}
++
++QWebPrinterPrivate::~QWebPrinterPrivate()
++{
++ printContext.end();
++}
++
++/*!
++ \class QWebPrinter
++ \since 4.7
++ \brief The QWebPrinter controls printing of a \l{QWebFrame::}
++
++ \inmodule QtWebKit
++
++ \sa QWebFrame
++*/
++QWebPrinter::QWebPrinter(const QWebFrame *frame, QPaintDevice *printer, QPainter &painter)
++ : d(new QWebPrinterPrivate(frame, printer, painter))
++{}
++
++QWebPrinter::~QWebPrinter()
++{
++ delete d;
++}
++
++/*!
++ Print a page of the frame. \a i is the number of the page to print,
++ and must be between 1 and \fn QWebPrinter::pageCount() .
++*/
++void QWebPrinter::spoolPage(int i) const
++{
++ if (i < 1 || i > d->printContext.pageCount())
++ return;
++ d->printContext.spoolPage(d->graphicsContext, i - 1, d->printWidth);
++}
++
++/*!
++ Returns the number of pages of the frame when printed.
++*/
++int QWebPrinter::pageCount() const
++{
++ return d->printContext.pageCount();
++}
++
++QPair<int, QRectF> QWebPrinter::elementLocation(const QWebElement & e)
++{
++ //Compute a mapping from node to render object once and for all
++ if (d->elementToRenderObject.empty())
++ for (WebCore::RenderObject * o=d->frame->d->frame->document()->renderer(); o; o=o->nextInPreOrder())
++ if (o->node())
++ d->elementToRenderObject[o->node()] = o;
++
++ if (!d->elementToRenderObject.contains(e.m_element))
++ return QPair<int,QRectF>(-1, QRectF());
++ const WebCore::RenderObject * ro = d->elementToRenderObject[e.m_element];
++ const Vector<IntRect> & pageRects = d->printContext.getPageRects();
++
++ WebCore::RenderView *root = toRenderView(d->frame->d->frame->document()->renderer());
++ //We need the scale factor, because pages are shrinked
++ float scale = (float)d->printWidth / (float)root->width();
++
++ QRectF r(const_cast<WebCore::RenderObject *>(ro)->absoluteBoundingBoxRect());
++
++ int low=0;
++ int high=pageRects.size();
++ int c = r.y() + r.height() / 2;
++ while(low <= high) {
++ int m = (low+high)/2;
++ if(c < pageRects[m].y())
++ high = m-1;
++ else if(c > pageRects[m].maxY())
++ low = m +1;
++ else {
++ QRectF tr = r.translated(0, -pageRects[m].y());
++ return QPair<int, QRectF>(m+1, QRect(tr.x() * scale, tr.y()*scale, tr.width()*scale, tr.height()*scale));
++ }
++
++ }
++ return QPair<int,QRectF>(-1, QRectF());
++}
++
++/*!
++ Return the painter used for printing.
++*/
++QPainter * QWebPrinter::painter() {
++ return &d->painter;
++}
++#endif //QT_NO_PRINTER
++
+ QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame,
+ WebCore::HTMLFrameOwnerElement* ownerFrameElement,
+ const WTF::String& frameName)
+@@ -1434,25 +1542,8 @@ bool QWebFrame::event(QEvent *e)
+ void QWebFrame::print(QPrinter *printer) const
+ {
+ QPainter painter;
+- if (!painter.begin(printer))
+- return;
+-
+- const qreal zoomFactorX = (qreal)printer->logicalDpiX() / qt_defaultDpi();
+- const qreal zoomFactorY = (qreal)printer->logicalDpiY() / qt_defaultDpi();
+-
+- PrintContext printContext(d->frame);
+- float pageHeight = 0;
+-
+- QRect qprinterRect = printer->pageRect();
+-
+- IntRect pageRect(0, 0,
+- int(qprinterRect.width() / zoomFactorX),
+- int(qprinterRect.height() / zoomFactorY));
+-
+- printContext.begin(pageRect.width());
+-
+- printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
+-
++ painter.begin(printer);
++ QWebPrinter p(this, printer, painter);
+ int docCopies;
+ int pageCopies;
+ if (printer->collateCopies()) {
+@@ -1469,11 +1560,12 @@ void QWebFrame::print(QPrinter *printer) const
+
+ if (fromPage == 0 && toPage == 0) {
+ fromPage = 1;
+- toPage = printContext.pageCount();
++ toPage = p.pageCount();
+ }
+ // paranoia check
+ fromPage = qMax(1, fromPage);
+- toPage = qMin(static_cast<int>(printContext.pageCount()), toPage);
++ toPage = qMin(static_cast<int>(p.pageCount()), toPage);
++
+ if (toPage < fromPage) {
+ // if the user entered a page range outside the actual number
+ // of printable pages, just return
+@@ -1486,20 +1578,15 @@ void QWebFrame::print(QPrinter *printer) const
+ toPage = tmp;
+ ascending = false;
+ }
+-
+- painter.scale(zoomFactorX, zoomFactorY);
+- GraphicsContext ctx(&painter);
+-
+ for (int i = 0; i < docCopies; ++i) {
+ int page = fromPage;
+ while (true) {
+ for (int j = 0; j < pageCopies; ++j) {
+ if (printer->printerState() == QPrinter::Aborted
+ || printer->printerState() == QPrinter::Error) {
+- printContext.end();
+ return;
+ }
+- printContext.spoolPage(ctx, page - 1, pageRect.width());
++ p.spoolPage(page);
+ if (j < pageCopies - 1)
+ printer->newPage();
+ }
+@@ -1518,8 +1605,7 @@ void QWebFrame::print(QPrinter *printer) const
+ if ( i < docCopies - 1)
+ printer->newPage();
+ }
+-
+- printContext.end();
++ painter.end();
+ }
+ #endif // QT_NO_PRINTER
+
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.h b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.h
+index 3c5a28e..99771f8 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.h
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe.h
+@@ -21,6 +21,8 @@
+ #ifndef QWEBFRAME_H
+ #define QWEBFRAME_H
+
++#define __EXTENSIVE_WKHTMLTOPDF_QT_HACK__
++
+ #include <QtCore/qobject.h>
+ #include <QtCore/qurl.h>
+ #include <QtCore/qvariant.h>
+@@ -42,6 +44,9 @@ class QPrinter;
+ QT_END_NAMESPACE
+
+ class QWebNetworkRequest;
++#ifndef QT_NO_PRINTER
++class QWebPrinterPrivate;
++#endif
+ class QWebFramePrivate;
+ class QWebPage;
+ class QWebHitTestResult;
+@@ -103,6 +108,20 @@ private:
+ friend class QWebPage;
+ };
+
++#ifndef QT_NO_PRINTER
++class QWEBKIT_EXPORT QWebPrinter {
++public:
++ QWebPrinter(const QWebFrame * frame, QPaintDevice * printer, QPainter &painter);
++ ~QWebPrinter();
++ void spoolPage(int i) const;
++ QPainter * painter();
++ int pageCount() const;
++ QPair<int, QRectF> elementLocation(const QWebElement & e);
++private:
++ QWebPrinterPrivate * d;
++};
++#endif
++
+ class QWEBKIT_EXPORT QWebFrame : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier DESIGNABLE false)
+@@ -228,6 +247,8 @@ private:
+ friend class QWebPage;
+ friend class QWebPagePrivate;
+ friend class QWebFramePrivate;
++ friend class QWebPrinterPrivate;
++ friend class QWebPrinter;
+ friend class DumpRenderTreeSupportQt;
+ friend class WebCore::WidgetPrivate;
+ friend class WebCore::FrameLoaderClientQt;
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe_p.h b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe_p.h
+index 4108972..3698eed 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe_p.h
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebframe_p.h
+@@ -35,6 +35,9 @@
+ #include "wtf/RefPtr.h"
+ #include "Frame.h"
+ #include "ViewportArguments.h"
++#include <qpainter.h>
++#include "PrintContext.h"
++#include "GraphicsContext.h"
+
+ #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
+ #include "texmap/TextureMapper.h"
+@@ -69,6 +72,19 @@ public:
+ int marginHeight;
+ };
+
++class QWebPrinterPrivate {
++public:
++ WebCore::PrintContext printContext;
++ QPainter & painter;
++ const QWebFrame * frame;
++ WebCore::GraphicsContext graphicsContext;
++ int printWidth;
++ QHash<const WebCore::Node*, const WebCore::RenderObject *> elementToRenderObject;
++
++ QWebPrinterPrivate(const QWebFrame * frame, QPaintDevice *printer, QPainter &p);
++ ~QWebPrinterPrivate();
++};
++
+ class QWebFramePrivate {
+ public:
+ QWebFramePrivate()
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.cpp b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.cpp
+index c1ef92e..dc4de39 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.cpp
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.cpp
+@@ -75,8 +75,11 @@ public:
+ QUrl userStyleSheetLocation;
+ QString defaultTextEncoding;
+ QString localStoragePath;
++ QString printingMediaType;
+ QString offlineWebApplicationCachePath;
+ qint64 offlineStorageDefaultQuota;
++ qreal printingMinimumShrinkFactor;
++ qreal printingMaximumShrinkFactor;
+
+ void apply();
+ WebCore::Settings* settings;
+@@ -229,9 +232,18 @@ void QWebSettingsPrivate::apply()
+ QString encoding = !defaultTextEncoding.isEmpty() ? defaultTextEncoding: global->defaultTextEncoding;
+ settings->setDefaultTextEncodingName(encoding);
+
++ QString type = !printingMediaType.isEmpty() ? printingMediaType : global->printingMediaType;
++ settings->setPrintingMediaType(type.isEmpty() ? "print" : type);
++
+ QString storagePath = !localStoragePath.isEmpty() ? localStoragePath : global->localStoragePath;
+ settings->setLocalStorageDatabasePath(storagePath);
+
++ float minimumShrinkFactor = printingMinimumShrinkFactor > 0.0f ? printingMinimumShrinkFactor : global->printingMinimumShrinkFactor;
++ settings->setPrintingMinimumShrinkFactor(minimumShrinkFactor);
++
++ float maximumShrinkFactor = printingMaximumShrinkFactor > 0.0f ? printingMaximumShrinkFactor : global->printingMaximumShrinkFactor;
++ settings->setPrintingMaximumShrinkFactor(maximumShrinkFactor);
++
+ value = attributes.value(QWebSettings::PrintElementBackgrounds,
+ global->attributes.value(QWebSettings::PrintElementBackgrounds));
+ settings->setShouldPrintBackgrounds(value);
+@@ -519,6 +531,8 @@ QWebSettings::QWebSettings()
+ d->attributes.insert(QWebSettings::SiteSpecificQuirksEnabled, true);
+ d->offlineStorageDefaultQuota = 5 * 1024 * 1024;
+ d->defaultTextEncoding = QLatin1String("iso-8859-1");
++ d->printingMinimumShrinkFactor = 1.25f;
++ d->printingMaximumShrinkFactor = 2.0f;
+ }
+
+ /*!
+@@ -527,6 +541,8 @@ QWebSettings::QWebSettings()
+ QWebSettings::QWebSettings(WebCore::Settings* settings)
+ : d(new QWebSettingsPrivate(settings))
+ {
++ d->printingMinimumShrinkFactor = 0.0f;
++ d->printingMaximumShrinkFactor = 0.0f;
+ d->settings = settings;
+ d->apply();
+ allSettings()->append(d);
+@@ -635,6 +651,86 @@ QString QWebSettings::defaultTextEncoding() const
+ }
+
+ /*!
++ \since 4.7
++ Specifies which media type to use when printing. If
++ left empty the default "print" will be used, other choices include "screen".
++ See \l{http://www.w3.org/TR/CSS2/media.html}{CSS Standard}, for a complete list.
++
++ \sa printingMediaType()
++*/
++void QWebSettings::setPrintingMediaType(const QString& type)
++{
++ d->printingMediaType = type;
++ d->apply();
++}
++
++/*!
++ \since 4.7
++ Returns the media type used when printing or QString() if the
++ default value is used.
++
++ \sa setPrintingMediaType()
++*/
++QString QWebSettings::printingMediaType() const
++{
++ return d->printingMediaType;
++}
++
++/*!
++ \since 4.6
++ Specifies minimum shrink fator allowed for printing. If set to 0 a
++ default value is used.
++
++ When printing, content will be shrunk to reduce page usage, it
++ will reduced by a factor between printingMinimumShrinkFactor and
++ printingMaximumShrinkFactor.
++
++ \sa printingMinimumShrinkFactor()
++ \sa setPrintingMaximumShrinkFactor()
++ \sa printingMaximumShrinkFactor()
++*/
++void QWebSettings::setPrintingMinimumShrinkFactor(qreal printingMinimumShrinkFactor)
++{
++ d->printingMinimumShrinkFactor = printingMinimumShrinkFactor;
++ d->apply();
++}
++
++/*!
++ \since 4.6
++ returns the minimum shrink factor used for printing.
++
++ \sa setPrintingMinimumShrinkFactor()
++*/
++qreal QWebSettings::printingMinimumShrinkFactor() const
++{
++ return d->printingMinimumShrinkFactor;
++}
++
++/*!
++ \since 4.6
++ Specifies maximum shrink fator allowed for printing. If set to 0 a
++ default value is used.
++
++ \sa setPrintingMinimumShrinkFactor()
++*/
++void QWebSettings::setPrintingMaximumShrinkFactor(qreal printingMaximumShrinkFactor)
++{
++ d->printingMaximumShrinkFactor = printingMaximumShrinkFactor;
++ d->apply();
++}
++
++/*!
++ \since 4.6
++ returns the maximum shrink factor used for printing.
++
++ \sa setPrintingMinimumShrinkFactor()
++*/
++qreal QWebSettings::printingMaximumShrinkFactor() const
++{
++ return d->printingMaximumShrinkFactor;
++}
++
++/*!
+ Sets the path of the icon database to \a path. The icon database is used
+ to store "favicons" associated with web sites.
+
+diff --git a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.h b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.h
+index 008035b..bb134a3 100644
+--- a/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.h
++++ b/src/3rdparty/webkit/Source/WebKit/qt/Api/qwebsettings.h
+@@ -116,6 +116,15 @@ public:
+ void setDefaultTextEncoding(const QString &encoding);
+ QString defaultTextEncoding() const;
+
++ void setPrintingMediaType(const QString &type);
++ QString printingMediaType() const;
++
++ void setPrintingMinimumShrinkFactor(qreal printingMinimumShrinkFactor);
++ qreal printingMinimumShrinkFactor() const;
++
++ void setPrintingMaximumShrinkFactor(qreal printingMaximimShrinkFactor);
++ qreal printingMaximumShrinkFactor() const;
++
+ static void setIconDatabasePath(const QString &location);
+ static QString iconDatabasePath();
+ static void clearIconDatabase();
+diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
+index 3fc65d3..6657879 100644
+--- a/src/gui/image/qpixmap.cpp
++++ b/src/gui/image/qpixmap.cpp
+@@ -134,12 +134,6 @@ extern QApplication::Type qt_appType;
+
+ void QPixmap::init(int w, int h, int type)
+ {
+- if (qt_appType == QApplication::Tty) {
+- qWarning("QPixmap: Cannot create a QPixmap when no GUI is being used");
+- data = 0;
+- return;
+- }
+-
+ if ((w > 0 && h > 0) || type == QPixmapData::BitmapType)
+ data = QPixmapData::create(w, h, (QPixmapData::PixelType) type);
+ else
+diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
+index 5950c5d..36303a0 100644
+--- a/src/gui/image/qpixmap_raster.cpp
++++ b/src/gui/image/qpixmap_raster.cpp
+@@ -47,6 +47,7 @@
+ #include "qnativeimage_p.h"
+ #include "qimage_p.h"
+ #include "qpaintengine.h"
++#include "kernel/qapplication_p.h"
+
+ #include "qbitmap.h"
+ #include "qimage.h"
+@@ -115,8 +116,10 @@ void QRasterPixmapData::resize(int width, int height)
+ #else
+ if (pixelType() == BitmapType)
+ format = QImage::Format_MonoLSB;
+- else
++ else if (qt_is_gui_used)
+ format = QNativeImage::systemFormat();
++ else
++ format = QImage::Format_RGB32;
+ #endif
+
+ image = QImage(width, height, format);
+@@ -431,7 +434,7 @@ void QRasterPixmapData::createPixmapForImage(QImage &sourceImage, Qt::ImageConve
+ ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_RGB32;
+ } else {
+- QImage::Format opaqueFormat = QNativeImage::systemFormat();
++ QImage::Format opaqueFormat = qt_is_gui_used ? QNativeImage::systemFormat() : QImage::Format_RGB32;
+ QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied;
+
+ #if !defined(QT_HAVE_NEON) && !defined(QT_ALWAYS_HAVE_SSE2)
+diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
+index 9582abf..ebaea4b 100644
+--- a/src/gui/kernel/qapplication_x11.cpp
++++ b/src/gui/kernel/qapplication_x11.cpp
+@@ -2280,6 +2280,8 @@ void qt_init(QApplicationPrivate *priv, int,
+ QSegfaultHandler::initialize(priv->argv, priv->argc);
+ #endif
+ QCursorData::initialize();
++ } else if (!QApplicationPrivate::graphics_system_name.isNull()) {
++ QApplicationPrivate::graphics_system = QGraphicsSystemFactory::create(QApplicationPrivate::graphics_system_name);
+ }
+ QFont::initialize();
+
+diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp
+index d8aefb6..37106f7 100644
+--- a/src/gui/kernel/qguiplatformplugin.cpp
++++ b/src/gui/kernel/qguiplatformplugin.cpp
+@@ -85,7 +85,7 @@ QGuiPlatformPlugin *qt_guiPlatformPlugin()
+
+ QString key = QString::fromLocal8Bit(qgetenv("QT_PLATFORM_PLUGIN"));
+ #ifdef Q_WS_X11
+- if (key.isEmpty()) {
++ if (QApplication::type() != QApplication::Tty && key.isEmpty()) {
+ switch(X11->desktopEnvironment) {
+ case DE_KDE:
+ key = QString::fromLatin1("kde");
+diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
+index cd7075e..74508b3 100644
+--- a/src/gui/painting/qpaintengine.h
++++ b/src/gui/painting/qpaintengine.h
+@@ -162,6 +162,19 @@ public:
+ virtual void drawRects(const QRect *rects, int rectCount);
+ virtual void drawRects(const QRectF *rects, int rectCount);
+
++ virtual void addHyperlink(const QRectF &r, const QUrl &url) {Q_UNUSED(r); Q_UNUSED(url);}
++ virtual void addAnchor(const QRectF &r, const QString &name) {Q_UNUSED(r); Q_UNUSED(name);}
++ virtual void addLink(const QRectF &r, const QString &anchor) {Q_UNUSED(r); Q_UNUSED(anchor);}
++ virtual void addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
++ Q_UNUSED(r); Q_UNUSED(text); Q_UNUSED(name); Q_UNUSED(multiLine); Q_UNUSED(password); Q_UNUSED(readOnly); Q_UNUSED(maxLength);
++ }
++ virtual void addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
++ Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly);
++ }
++ virtual void addRadioButton(const QRectF &r, const QString & group="", bool checked=false, const QString &name="", bool readOnly=false) {
++ Q_UNUSED(r); Q_UNUSED(checked); Q_UNUSED(name); Q_UNUSED(readOnly); Q_UNUSED(group);
++ }
++
+ virtual void drawLines(const QLine *lines, int lineCount);
+ virtual void drawLines(const QLineF *lines, int lineCount);
+
+@@ -177,6 +190,10 @@ public:
+ virtual void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
+
+ virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) = 0;
++ virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr, const QByteArray * data) {
++ Q_UNUSED(data);
++ drawPixmap(r,pm,sr);
++ }
+ virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
+ virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
+diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
+index 10ca689..d690761 100644
+--- a/src/gui/painting/qpaintengine_raster.cpp
++++ b/src/gui/painting/qpaintengine_raster.cpp
+@@ -2243,11 +2243,11 @@ namespace {
+ /*!
+ \reimp
+ */
+-void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
++void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &_img, const QRectF &_sr,
+ Qt::ImageConversionFlags)
+ {
+ #ifdef QT_DEBUG_DRAW
+- qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << sr << " image=" << img.size() << "depth=" << img.depth();
++ qDebug() << " - QRasterPaintEngine::drawImage(), r=" << r << " sr=" << _sr << " image=" << _img.size() << "depth=" << img.depth();
+ #endif
+
+ if (r.isEmpty())
+@@ -2255,6 +2255,17 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
+
+ Q_D(QRasterPaintEngine);
+ QRasterPaintEngineState *s = state();
++
++ QImage img;
++ QRectF sr=_sr;
++ if (s->matrix.isAffine()) {
++ img = _img.copy(sr.toRect()).scaled(
++ s->matrix.mapRect(r).size().toSize(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
++ sr = img.rect();
++ } else {
++ img=_img;
++ }
++
+ int sr_l = qFloor(sr.left());
+ int sr_r = qCeil(sr.right()) - 1;
+ int sr_t = qFloor(sr.top());
+diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
+index 30f986d..7836b5a 100644
+--- a/src/gui/painting/qpainter.cpp
++++ b/src/gui/painting/qpainter.cpp
+@@ -5393,7 +5393,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
+ }
+ }
+
+-void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
++void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr, const QByteArray * data)
+ {
+ #if defined QT_DEBUG_DRAW
+ if (qt_show_painter_debug_output)
+@@ -5518,7 +5518,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
+ x += d->state->matrix.dx();
+ y += d->state->matrix.dy();
+ }
+- d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh));
++ d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(sx, sy, sw, sh), data);
+ }
+ }
+
+@@ -7254,6 +7254,200 @@ void QPainter::fillRect(const QRectF &r, const QColor &color)
+ \since 4.5
+ */
+
++
++/*!
++ \fn void QPainter::addAnchor(int x, int y, int w, int h, const QString &name);
++
++ \overload
++
++ Add an anchor to the current page at the rect specified by \a x, \a y, \a w and \a h
++ named \a name.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addLink()
++
++ \since 4.7
++*/
++
++/*!
++ \fn void QPainter::addAnchor(const QRect &r, const QString &name);
++
++ \overload
++
++ Add an anchor to the current page at the rect specified by \a r named \a name.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addLink()
++
++ \since 4.7
++*/
++
++/*!
++ \fn void addAnchor(const QRectF &r, const QString &name);
++
++ \overload
++
++ Add an anchor to the current page at the rect specified by \a r named \a name.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addLink()
++
++ \since 4.7
++*/
++void QPainter::addAnchor(const QRectF &r, const QString &name)
++{
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addAnchor: Painter not active");
++ return;
++ }
++ d->engine->addAnchor(worldTransform().mapRect(r), name);
++}
++
++/*!
++ \fn void QPainter::addLink(int x, int y, int w, int h, const QString &anchor);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a x, \a y, \a w and \a h
++ linking to the anchor named \a anchor.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addAnchor()
++
++ \since 4.7
++*/
++
++/*!
++ \fn void QPainter::addLink(const QRect &r, const QString &anchor);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a r
++ linking to the anchor named \a anchor.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addAnchor()
++
++ \since 4.7
++*/
++
++/*!
++ \fn void QPainter::addLink(const QRectF &r, const QString &anchor);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a r
++ linking to the anchor named \a anchor.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \sa addAnchor()
++
++ \since 4.7
++*/
++void QPainter::addLink(const QRectF &r, const QString &anchor)
++{
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addLink: Painter not active");
++ return;
++ }
++
++ d->engine->addLink(worldTransform().mapRect(r), anchor);
++}
++
++
++/*!
++ \fn void QPainter::addHyperlink(int x, int y, int w, int h, const QUrl &url);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a x, \a y, \a w and \a h
++ linking to \a url.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \since 4.7
++*/
++
++/*!
++ \fn void QPainter::addHyperlink(const QRect &r, const QUrl &url);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a r
++ linking to \a url.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \since 4.7
++*/
++
++/*!
++ \fn void QPainter::addHyperlink(const QRectF &r, const QUrl &url);
++
++ \overload
++
++ Add a link to the current page at the rect specified by \a r
++ linking to \a url.
++
++ Note that for output formats not supporting links, currently all other then PDF,
++ this call has no effect.
++
++ \since 4.7
++*/
++void QPainter::addHyperlink(const QRectF &r, const QUrl &url)
++{
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addHyperlink: Painter not active");
++ return;
++ }
++ d->engine->addHyperlink(worldTransform().mapRect(r), url);
++}
++
++void QPainter::addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength) {
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addTextField: Painter not active");
++ return;
++ }
++ d->engine->addTextField(worldTransform().mapRect(r), text, name, multiLine, password, readOnly, maxLength);
++}
++
++void QPainter::addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addCheckBox: Painter not active");
++ return;
++ }
++ d->engine->addCheckBox(worldTransform().mapRect(r), checked, name, readOnly);
++}
++
++
++void QPainter::addRadioButton(const QRectF &r, const QString & group, bool checked, const QString &name, bool readOnly) {
++ Q_D(QPainter);
++ if (!d->engine) {
++ qWarning("QPainter::addRadioButton: Painter not active");
++ return;
++ }
++ d->engine->addRadioButton(worldTransform().mapRect(r), group, checked, name, readOnly);
++}
++
+ /*!
+ Sets the given render \a hint on the painter if \a on is true;
+ otherwise clears the render hint.
+diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
+index f0312e5..d853a9b 100644
+--- a/src/gui/painting/qpainter.h
++++ b/src/gui/painting/qpainter.h
+@@ -364,7 +364,7 @@ public:
+ inline void drawPicture(const QPoint &p, const QPicture &picture);
+ #endif
+
+- void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect);
++ void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect, const QByteArray * data=0);
+ inline void drawPixmap(const QRect &targetRect, const QPixmap &pixmap, const QRect &sourceRect);
+ inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm,
+ int sx, int sy, int sw, int sh);
+@@ -447,6 +447,22 @@ public:
+ inline void fillRect(const QRect &r, Qt::BrushStyle style);
+ inline void fillRect(const QRectF &r, Qt::BrushStyle style);
+
++ inline void addAnchor(int x, int y, int w, int h, const QString &name);
++ inline void addAnchor(const QRect &r, const QString &name);
++ void addAnchor(const QRectF &r, const QString &name);
++
++ inline void addLink(int x, int y, int w, int h, const QString &anchor);
++ inline void addLink(const QRect &r, const QString &anchor);
++ void addLink(const QRectF &r, const QString &anchor);
++
++ void addTextField(const QRectF &r, const QString &text="", const QString &name="", bool multiLine=false, bool password=false, bool readOnly=false, int maxLength=-1);
++ void addCheckBox(const QRectF &r, bool checked=false, const QString &name="", bool readOnly=false);
++ void addRadioButton(const QRectF &r, const QString & group="", bool checked=false, const QString &name="", bool readOnly=false);;
++
++ inline void addHyperlink(int x, int y, int w, int h, const QUrl &url);
++ inline void addHyperlink(const QRect &r, const QUrl &url);
++ void addHyperlink(const QRectF &r, const QUrl &url);
++
+ void eraseRect(const QRectF &);
+ inline void eraseRect(int x, int y, int w, int h);
+ inline void eraseRect(const QRect &);
+@@ -821,6 +837,35 @@ inline void QPainter::fillRect(const QRectF &r, Qt::BrushStyle style)
+ fillRect(r, QBrush(style));
+ }
+
++inline void QPainter::addAnchor(int x, int y, int w, int h, const QString &name)
++{
++ addAnchor(QRectF(x, y, w, h), name);
++}
++
++inline void QPainter::addAnchor(const QRect &r, const QString &name)
++{
++ addAnchor(QRectF(r), name);
++}
++
++inline void QPainter::addLink(int x, int y, int w, int h, const QString &anchor)
++{
++ addLink(QRectF(x, y, w, h), anchor);
++}
++
++inline void QPainter::addLink(const QRect &r, const QString &anchor)
++{
++ addLink(QRectF(r), anchor);
++}
++
++inline void QPainter::addHyperlink(int x, int y, int w, int h, const QUrl &url)
++{
++ addHyperlink(QRectF(x, y, w, h), url);
++}
++
++inline void QPainter::addHyperlink(const QRect &r, const QUrl &url)
++{
++ addHyperlink(QRectF(r), url);
++}
+
+ inline void QPainter::setBrushOrigin(int x, int y)
+ {
+diff --git a/src/gui/painting/qprintengine.h b/src/gui/painting/qprintengine.h
+index 83bbf96..809b51a 100644
+--- a/src/gui/painting/qprintengine.h
++++ b/src/gui/painting/qprintengine.h
+@@ -90,6 +90,9 @@ public:
+ PPK_SupportsMultipleCopies,
+ PPK_PaperSize = PPK_PageSize,
+
++ PPK_UseCompression,
++ PPK_ImageQuality,
++ PPK_ImageDPI,
+ PPK_CustomBase = 0xff00
+ };
+
+@@ -97,6 +100,8 @@ public:
+ virtual QVariant property(PrintEnginePropertyKey key) const = 0;
+
+ virtual bool newPage() = 0;
++ virtual void beginSectionOutline(const QString &text, const QString &anchor) {Q_UNUSED(text); Q_UNUSED(anchor);}
++ virtual void endSectionOutline() {}
+ virtual bool abort() = 0;
+
+ virtual int metric(QPaintDevice::PaintDeviceMetric) const = 0;
+diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
+index 239a94f..36eec2e 100644
+--- a/src/gui/painting/qprintengine_pdf.cpp
++++ b/src/gui/painting/qprintengine_pdf.cpp
+@@ -51,6 +51,7 @@
+ #include <qimagewriter.h>
+ #include <qbuffer.h>
+ #include <qdatetime.h>
++#include <QCryptographicHash>
+
+ #ifndef QT_NO_PRINTER
+ #include <limits.h>
+@@ -77,12 +78,6 @@ extern qint64 qt_image_id(const QImage &image);
+ // Can't use it though, as gs generates completely wrong images if this is true.
+ static const bool interpolateImages = false;
+
+-#ifdef QT_NO_COMPRESS
+-static const bool do_compress = false;
+-#else
+-static const bool do_compress = true;
+-#endif
+-
+ QPdfPage::QPdfPage()
+ : QPdf::ByteStream(true) // Enable file backing
+ {
+@@ -109,6 +104,30 @@ inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
+ return f;
+ }
+
++void QPdfEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) {
++ Q_D(QPdfEngine);
++ if (key==PPK_UseCompression)
++ d->doCompress = value.toBool();
++ else if (key==PPK_ImageQuality)
++ d->imageQuality = value.toInt();
++ else if (key==PPK_ImageDPI)
++ d->imageDPI = value.toInt();
++ else
++ QPdfBaseEngine::setProperty(key, value);
++}
++
++QVariant QPdfEngine::property(PrintEnginePropertyKey key) const {
++ Q_D(const QPdfEngine);
++ if (key==PPK_UseCompression)
++ return d->doCompress;
++ else if (key==PPK_ImageQuality)
++ return d->imageQuality;
++ else if (key==PPK_ImageDPI)
++ return d->imageDPI;
++ else
++ return QPdfBaseEngine::property(key);
++}
++
+ QPdfEngine::QPdfEngine(QPrinter::PrinterMode m)
+ : QPdfBaseEngine(*new QPdfEnginePrivate(m), qt_pdf_decide_features())
+ {
+@@ -156,6 +175,59 @@ bool QPdfEngine::begin(QPaintDevice *pdev)
+ bool QPdfEngine::end()
+ {
+ Q_D(QPdfEngine);
++
++ uint dests;
++ if (d->anchors.size()) {
++ dests = d->addXrefEntry(-1);
++ d->xprintf("<<\n");
++ for (QHash<QString, uint>::iterator i=d->anchors.begin();
++ i != d->anchors.end(); ++i) {
++ d->printAnchor(i.key());
++ d->xprintf(" %d 0 R\n", i.value());
++ }
++ d->xprintf(">>\n");
++ }
++
++ if (d->outlineRoot) {
++ d->outlineRoot->obj = d->requestObject();
++ d->writeOutlineChildren(d->outlineRoot);
++ d->addXrefEntry(d->outlineRoot->obj);
++ d->xprintf("<</Type /Outlines /First %d 0 R\n/Last %d 0 R>>\nendobj\n",
++ d->outlineRoot->firstChild->obj, d->outlineRoot->lastChild->obj);
++ }
++
++ if (d->formFields.size()) {
++ uint font = d->addXrefEntry(-1);
++ d->xprintf("<</Type/Font/Name/Helv/BaseFont/Helvetica/Subtype/Type1>>\n"
++ "endobj\n");
++ d->addXrefEntry(d->formFieldList);
++ d->xprintf("<</Fields[");
++ foreach(const uint & i, d->formFields)
++ d->xprintf("%d 0 R ",i);
++ d->xprintf("]\n"
++ "/DR<</Font<</Helv %d 0 R>>>>\n"
++ "/DA(/Helv 0 Tf 0 g)\n"
++ ">>\n"
++ "endobj\n", font);
++ }
++
++ d->catalog = d->addXrefEntry(-1);
++ d->xprintf("<<\n"
++ "/Type /Catalog\n"
++ "/Pages %d 0 R\n", d->pageRoot);
++ if (d->outlineRoot)
++ d->xprintf("/Outlines %d 0 R\n"
++ "/PageMode /UseOutlines\n", d->outlineRoot->obj);
++
++ if (d->formFields.size())
++ d->xprintf("/AcroForm %d 0 R\n", d->formFieldList);
++
++ if (d->anchors.size())
++ d->xprintf("/Dests %d 0 R\n", dests);
++
++ d->xprintf(">>\n"
++ "endobj\n");
++
+ d->writeTail();
+
+ d->stream->unsetDevice();
+@@ -165,8 +237,83 @@ bool QPdfEngine::end()
+ return true;
+ }
+
++void QPdfEngine::addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly) {
++ Q_D(QPdfEngine);
++ uint obj = d->addXrefEntry(-1);
++ char buf[256];
++ QRectF rr = d->pageMatrix().mapRect(r);
++ //Note that the pdf spec sayes that we should add some sort of default appearence atleast for yes, which we dont ghost script provides one, however acroread does not
++ if (d->formFieldList == -1) d->formFieldList = d->requestObject();
++ d->xprintf("<<\n"
++ "/Type /Annot\n"
++ "/Parrent %d 0 R\n"
++ "/Rect[", d->formFieldList);
++ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
++ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
++ d->xprintf("]\n"
++ "/FT/Btn\n"
++ "/Subtype/Widget\n"
++ "/P %d 0 R\n", d->pages.back());
++ if (checked)
++ d->xprintf("/AS /Yes\n");
++ if (!name.isEmpty()) {
++ d->xprintf("/T");
++ d->printString(name);
++ d->xprintf("\n");
++ }
++ d->xprintf("/Ff %d\n"
++ ">>\n"
++ "endobj\n",
++ (readOnly?1:0)<<0);
++ d->currentPage->annotations.push_back(obj);
++ d->formFields.push_back(obj);
++}
++
++void QPdfEngine::addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength)
++{
++ Q_D(QPdfEngine);
++ uint obj = d->addXrefEntry(-1);
++ char buf[256];
++ QRectF rr = d->pageMatrix().mapRect(r);
++ if (d->formFieldList == -1) d->formFieldList = d->requestObject();
++ d->xprintf("<<\n"
++ "/Type /Annot\n"
++ "/Parrent %d 0 R\n"
++ "/Rect[", d->formFieldList);
++ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
++ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
++ d->xprintf("]\n"
++ "/BS<</S/I>>\n"
++ "/FT/Tx\n"
++ "/Subtype/Widget\n"
++ "/P %d 0 R\n", d->pages.back());
++ if (!text.isEmpty()) {
++ d->xprintf("/V");
++ d->printString(text);
++ d->xprintf("\n");
++ }
++ if (!name.isEmpty()) {
++ d->xprintf("/T");
++ d->printString(name);
++ d->xprintf("\n");
++ }
++ if (maxLength >= 0)
++ d->xprintf("/MaxLen %d\n",maxLength);
++ d->xprintf("/DA(/Helv 12 Tf 0 g)\n"
++ "/Ff %d\n"
++ ">>\n"
++ "endobj\n",
++ (readOnly?1:0)<<0 | (password?1:0)<<13 | (multiLine?1:0)<<12
++ );
++ d->currentPage->annotations.push_back(obj);
++ d->formFields.push_back(obj);
++}
+
+-void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, const QRectF &sr)
++void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, const QRectF &sr, const QByteArray * data)
+ {
+ if (sr.isEmpty() || rectangle.isEmpty() || pixmap.isNull())
+ return;
+@@ -176,22 +323,35 @@ void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, con
+
+ QRect sourceRect = sr.toRect();
+ QPixmap pm = sourceRect != pixmap.rect() ? pixmap.copy(sourceRect) : pixmap;
+- QImage image = pm.toImage();
++ QImage unscaled = pm.toImage();
++ QImage image = unscaled;
++
++ QRectF a = d->stroker.matrix.mapRect(rectangle);
++ QRectF c = d->paperRect();
++ int maxWidth = int(a.width() / c.width() * d->width() / 72.0 * d->imageDPI);
++ int maxHeight = int(a.height() / c.height() * d->height() / 72.0 * d->imageDPI);
++ if (image.width() > maxWidth || image.height() > maxHeight)
++ image = unscaled.scaled( image.size().boundedTo( QSize(maxWidth, maxHeight) ), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
++
++ bool useScaled=true;
+ bool bitmap = true;
+- const int object = d->addImage(image, &bitmap, pm.cacheKey());
++ const int object = d->addImage(image, &bitmap, pm.cacheKey(), &unscaled, (sr == pixmap.rect()?data:0), &useScaled );
++ int width = useScaled?image.width():unscaled.width();
++ int height = useScaled?image.height():unscaled.height();
++
+ if (object < 0)
+ return;
+
+ *d->currentPage << "q\n/GSa gs\n";
+ *d->currentPage
+- << QPdf::generateMatrix(QTransform(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(),
++ << QPdf::generateMatrix(QTransform(rectangle.width() / width, 0, 0, rectangle.height() / height,
+ rectangle.x(), rectangle.y()) * (d->simplePen ? QTransform() : d->stroker.matrix));
+ if (bitmap) {
+ // set current pen as d->brush
+ d->brush = d->pen.brush();
+ }
+ setBrush();
+- d->currentPage->streamImage(image.width(), image.height(), object);
++ d->currentPage->streamImage(width, height, object);
+ *d->currentPage << "Q\n";
+
+ d->brush = b;
+@@ -301,18 +461,68 @@ QPdfEnginePrivate::QPdfEnginePrivate(QPrinter::PrinterMode m)
+ : QPdfBaseEnginePrivate(m)
+ {
+ streampos = 0;
+-
++ doCompress = true;
++ imageDPI = 1400;
++ imageQuality = 94;
+ stream = new QDataStream;
+ pageOrder = QPrinter::FirstPageFirst;
+ orientation = QPrinter::Portrait;
++ outlineRoot = NULL;
++ outlineCurrent = NULL;
+ fullPage = false;
+ }
+
+ QPdfEnginePrivate::~QPdfEnginePrivate()
+ {
++ if (outlineRoot)
++ delete outlineRoot;
+ delete stream;
+ }
+
++void QPdfEnginePrivate::printAnchor(const QString &name) {
++ QByteArray a = name.toUtf8();
++ if (a.size() >= 127)
++ a = QCryptographicHash::hash(a,QCryptographicHash::Sha1);
++ xprintf("/");
++ for (int i=0; i < a.size(); ++i) {
++ unsigned char c = a[i];
++ if (('a' <= c && c <= 'z') ||
++ ('A' <= c && c <= 'Z') ||
++ ('0' <= c && c <= '9') ||
++ c == '.' || c == '_')
++ xprintf("%c", c);
++ else if(c == 0)
++ xprintf("!");
++ else
++ xprintf("#%02x", c);
++ }
++}
++
++void QPdfEnginePrivate::writeOutlineChildren(OutlineItem * node) {
++ for (OutlineItem * i = node->firstChild; i != NULL; i = i->next)
++ i->obj = requestObject();
++ for (OutlineItem * i = node->firstChild; i != NULL; i = i->next) {
++ QPdfEnginePrivate::writeOutlineChildren(i);
++ addXrefEntry(i->obj);
++ xprintf("<</Title ");
++ printString(i->text);
++ xprintf("\n"
++ " /Parent %d 0 R\n"
++ " /Dest ", i->parent->obj);
++ printAnchor(i->anchor);
++ xprintf("\n /Count 0\n");
++ if (i->next)
++ xprintf(" /Next %d 0 R\n", i->next->obj);
++ if (i->prev)
++ xprintf(" /Prev %d 0 R\n", i->prev->obj);
++ if (i->firstChild)
++ xprintf(" /First %d 0 R\n", i->firstChild->obj);
++ if (i->lastChild)
++ xprintf(" /Last %d 0 R\n", i->lastChild->obj);
++ xprintf(">>\n"
++ "endobj\n");
++ }
++}
+
+ #ifdef USE_NATIVE_GRADIENTS
+ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject)
+@@ -520,10 +730,112 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
+ return patternObj;
+ }
+
++
++void QPdfEnginePrivate::convertImage(const QImage & image, QByteArray & imageData) {
++ int w = image.width();
++ int h = image.height();
++ imageData.resize(colorMode == QPrinter::GrayScale ? w * h : 3 * w * h);
++ uchar *data = (uchar *)imageData.data();
++ for (int y = 0; y < h; ++y) {
++ const QRgb *rgb = (const QRgb *)image.scanLine(y);
++ if (colorMode == QPrinter::GrayScale) {
++ for (int x = 0; x < w; ++x) {
++ *(data++) = qGray(*rgb);
++ ++rgb;
++ }
++ } else {
++ for (int x = 0; x < w; ++x) {
++ *(data++) = qRed(*rgb);
++ *(data++) = qGreen(*rgb);
++ *(data++) = qBlue(*rgb);
++ ++rgb;
++ }
++ }
++ }
++}
++
++#include <iostream>
++
++class jpg_header_reader {
++private:
++ const QByteArray * data;
++ int index;
++
++ class jpeg_exception {};
++
++ unsigned char next() {
++ if (index == data->size()) throw jpeg_exception();
++ return data->data()[index++];
++ }
++
++ void skip() {
++ int l = (next() << 8) + next();
++ if (l < 2) throw jpeg_exception();
++ for (int i=2; i < l; ++i) next();
++ }
++
++ void read_header() {
++ int l = (next() << 8) + next();
++ if (l < 2) throw jpeg_exception();
++ precision = next();
++ height = (next() << 8) + next();
++ width = (next() << 8) + next();
++ components = next();
++ if (l != 8 + components*3) throw jpeg_exception();
++ }
++
++public:
++ bool read(const QByteArray * d) {
++ index=0;
++ data=d;
++ try {
++ if (next() != 0xFF) throw jpeg_exception();
++ unsigned char marker = next();
++ if (marker != 0xD8) throw jpeg_exception();
++ while (true) {
++ marker = next();
++ while (marker != 0xFF) marker=next();
++ while (marker == 0xFF) marker=next();
++ switch(marker) {
++ case 0xC0:
++ case 0xC1:
++ case 0xC2:
++ case 0xC3:
++ case 0xC5:
++ case 0xC6:
++ case 0xC7:
++ case 0xC9:
++ case 0xCA:
++ case 0xCB:
++ case 0xCD:
++ case 0xCE:
++ case 0xCF:
++ read_header();
++ return true;
++ case 0xDA:
++ case 0xD9:
++ return false;
++ default:
++ skip();
++ break;
++ }
++ }
++ } catch(jpeg_exception) {
++ return false;
++ }
++ return true;
++ }
++
++ int precision, height, width, components;
++
++};
++
++
++
+ /*!
+ * Adds an image to the pdf and return the pdf-object id. Returns -1 if adding the image failed.
+ */
+-int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_no)
++int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_no, const QImage * noneScaled, const QByteArray * data, bool * useScaled)
+ {
+ if (img.isNull())
+ return -1;
+@@ -564,65 +876,97 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
+ }
+ object = writeImage(data, w, h, d, 0, 0);
+ } else {
+- QByteArray softMaskData;
+- bool dct = false;
+ QByteArray imageData;
+- bool hasAlpha = false;
+- bool hasMask = false;
+-
++ uLongf target=1024*1024*1024;
++ bool uns=false;
++ bool dct = false;
++
++ d = (colorMode == QPrinter::GrayScale) ? 8 : 32;
++
+ if (QImageWriter::supportedImageFormats().contains("jpeg") && colorMode != QPrinter::GrayScale) {
+- QBuffer buffer(&imageData);
++ QByteArray imageData2;
++
++ QBuffer buffer(&imageData2);
+ QImageWriter writer(&buffer, "jpeg");
+- writer.setQuality(94);
++ writer.setQuality(imageQuality);
+ writer.write(image);
+- dct = true;
+-
+- if (format != QImage::Format_RGB32) {
+- softMaskData.resize(w * h);
+- uchar *sdata = (uchar *)softMaskData.data();
+- for (int y = 0; y < h; ++y) {
+- const QRgb *rgb = (const QRgb *)image.scanLine(y);
+- for (int x = 0; x < w; ++x) {
+- uchar alpha = qAlpha(*rgb);
+- *sdata++ = alpha;
+- hasMask |= (alpha < 255);
+- hasAlpha |= (alpha != 0 && alpha != 255);
+- ++rgb;
+- }
+- }
++
++ if ((uLongf)imageData2.size() < target) {
++ imageData=imageData2;
++ target = imageData2.size();
++ dct = true;
++ uns=false;
+ }
+- } else {
+- imageData.resize(colorMode == QPrinter::GrayScale ? w * h : 3 * w * h);
+- uchar *data = (uchar *)imageData.data();
++ }
++
++ if (noneScaled && noneScaled->rect() != image.rect()) {
++ QByteArray imageData2;
++ convertImage(*noneScaled, imageData2);
++ uLongf len = imageData2.size();
++ uLongf destLen = len + len/100 + 13; // zlib requirement
++ Bytef* dest = new Bytef[destLen];
++ if (Z_OK == ::compress(dest, &destLen, (const Bytef*) imageData2.data(), (uLongf)len) &&
++ (uLongf)destLen < target) {
++ imageData=imageData2;
++ target=destLen;
++ dct=false;
++ uns=true;
++ }
++ delete[] dest;
++ }
++
++ {
++ QByteArray imageData2;
++ convertImage(image, imageData2);
++ uLongf len = imageData2.size();
++ uLongf destLen = len + len/100 + 13; // zlib requirement
++ Bytef* dest = new Bytef[destLen];
++ if (Z_OK == ::compress(dest, &destLen, (const Bytef*) imageData2.data(), (uLongf)len) &&
++ (uLongf)destLen < target) {
++ imageData=imageData2;
++ target=destLen;
++ dct=false;
++ uns=false;
++ }
++ delete[] dest;
++ }
++
++
++ if (colorMode != QPrinter::GrayScale && noneScaled != 0 && data != 0) {
++ jpg_header_reader header;
++ if (header.read(data)) {
++ d = header.components == 3?32:8;
++ imageData = *data;
++ target=data->size();
++ dct=true;
++ uns=true;
++ }
++ }
++
++ if (uns) {
++ w = noneScaled->width();
++ h = noneScaled->height();
++ }
++ if (useScaled) *useScaled = (uns?false:true);
++ QByteArray softMaskData;
++ bool hasAlpha = false;
++ bool hasMask = false;
++
++ if (format != QImage::Format_RGB32) {
+ softMaskData.resize(w * h);
+ uchar *sdata = (uchar *)softMaskData.data();
+ for (int y = 0; y < h; ++y) {
+- const QRgb *rgb = (const QRgb *)image.scanLine(y);
+- if (colorMode == QPrinter::GrayScale) {
+- for (int x = 0; x < w; ++x) {
+- *(data++) = qGray(*rgb);
+- uchar alpha = qAlpha(*rgb);
+- *sdata++ = alpha;
+- hasMask |= (alpha < 255);
+- hasAlpha |= (alpha != 0 && alpha != 255);
+- ++rgb;
+- }
+- } else {
+- for (int x = 0; x < w; ++x) {
+- *(data++) = qRed(*rgb);
+- *(data++) = qGreen(*rgb);
+- *(data++) = qBlue(*rgb);
+- uchar alpha = qAlpha(*rgb);
+- *sdata++ = alpha;
+- hasMask |= (alpha < 255);
+- hasAlpha |= (alpha != 0 && alpha != 255);
+- ++rgb;
+- }
++ const QRgb *rgb = (const QRgb *)(uns?noneScaled->scanLine(y):image.scanLine(y));
++ for (int x = 0; x < w; ++x) {
++ uchar alpha = qAlpha(*rgb);
++ *sdata++ = alpha;
++ hasMask |= (alpha < 255);
++ hasAlpha |= (alpha != 0 && alpha != 255);
++ ++rgb;
+ }
+ }
+- if (format == QImage::Format_RGB32)
+- hasAlpha = hasMask = false;
+ }
++
+ int maskObject = 0;
+ int softMaskObject = 0;
+ if (hasAlpha) {
+@@ -644,7 +988,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
+ }
+ maskObject = writeImage(mask, w, h, 1, 0, 0);
+ }
+- object = writeImage(imageData, w, h, colorMode == QPrinter::GrayScale ? 8 : 32,
++ object = writeImage(imageData, w, h, d,
+ maskObject, softMaskObject, dct);
+ }
+ imageCache.insert(serial_no, object);
+@@ -754,7 +1098,7 @@ void QPdfEnginePrivate::xprintf(const char* fmt, ...)
+ int QPdfEnginePrivate::writeCompressed(QIODevice *dev)
+ {
+ #ifndef QT_NO_COMPRESS
+- if (do_compress) {
++ if (doCompress) {
+ int size = QPdfPage::chunkSize();
+ int sum = 0;
+ ::z_stream zStruct;
+@@ -828,7 +1172,7 @@ int QPdfEnginePrivate::writeCompressed(QIODevice *dev)
+ int QPdfEnginePrivate::writeCompressed(const char *src, int len)
+ {
+ #ifndef QT_NO_COMPRESS
+- if(do_compress) {
++ if(doCompress) {
+ uLongf destLen = len + len/100 + 13; // zlib requirement
+ Bytef* dest = new Bytef[destLen];
+ if (Z_OK == ::compress(dest, &destLen, (const Bytef*) src, (uLongf)len)) {
+@@ -881,7 +1225,7 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
+ write(data);
+ len = data.length();
+ } else {
+- if (do_compress)
++ if (doCompress)
+ xprintf("/Filter /FlateDecode\n>>\nstream\n");
+ else
+ xprintf(">>\nstream\n");
+@@ -904,14 +1248,9 @@ void QPdfEnginePrivate::writeHeader()
+
+ writeInfo();
+
+- catalog = addXrefEntry(-1);
+ pageRoot = requestObject();
+- xprintf("<<\n"
+- "/Type /Catalog\n"
+- "/Pages %d 0 R\n"
+- ">>\n"
+- "endobj\n", pageRoot);
+-
++
++ formFieldList = -1;
+ // graphics state
+ graphicsState = addXrefEntry(-1);
+ xprintf("<<\n"
+@@ -939,17 +1278,26 @@ void QPdfEnginePrivate::writeInfo()
+ xprintf("\n/Creator ");
+ printString(creator);
+ xprintf("\n/Producer ");
+- printString(QString::fromLatin1("Qt " QT_VERSION_STR " (C) 2011 Nokia Corporation and/or its subsidiary(-ies)"));
+- QDateTime now = QDateTime::currentDateTime().toUTC();
++ printString(QString::fromLatin1("wkhtmltopdf"));
++ QDateTime now = QDateTime::currentDateTime();
+ QTime t = now.time();
+ QDate d = now.date();
+- xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
++ xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d",
+ d.year(),
+ d.month(),
+ d.day(),
+ t.hour(),
+ t.minute(),
+ t.second());
++ QDateTime fake=now;
++ fake.setTimeSpec(Qt::UTC);
++ int offset = now.secsTo(fake);
++ if (offset == 0)
++ xprintf("Z)\n");
++ else if (offset < 0)
++ xprintf("-%02d'%02d')\n", (-offset)/60/60 , ((-offset)/60) % 60);
++ else if (offset > 0)
++ xprintf("+%02d'%02d')\n", offset/60/60 , (offset/60) % 60);
+ xprintf(">>\n"
+ "endobj\n");
+ }
+@@ -1035,7 +1383,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
+ s << "<<\n"
+ "/Length1 " << fontData.size() << "\n"
+ "/Length " << length_object << "0 R\n";
+- if (do_compress)
++ if (doCompress)
+ s << "/Filter /FlateDecode\n";
+ s << ">>\n"
+ "stream\n";
+@@ -1097,6 +1445,101 @@ void QPdfEnginePrivate::writeFonts()
+ fonts.clear();
+ }
+
++
++void QPdfEngine::addHyperlink(const QRectF &r, const QUrl &url)
++{
++ Q_D(QPdfEngine);
++ char buf[256];
++ QRectF rr = d->pageMatrix().mapRect(r);
++ uint annot = d->addXrefEntry(-1);
++ QByteArray urlascii = url.toString().toLatin1();
++ int len = urlascii.size();
++ char *url_esc = new char[len * 2 + 1];
++ const char * urldata = urlascii.constData();
++ int k = 0;
++ for (int j = 0; j < len; j++, k++){
++ if (urldata[j] == '(' ||
++ urldata[j] == ')' ||
++ urldata[j] == '\\'){
++ url_esc[k] = '\\';
++ k++;
++ }
++ url_esc[k] = urldata[j];
++ }
++ url_esc[k] = 0;
++ d->xprintf("<<\n/Type /Annot\n/Subtype /Link\n/Rect [");
++ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
++ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
++ d->xprintf("]\n/Border [0 0 0]\n/A <<\n");
++ d->xprintf("/Type /Action\n/S /URI\n/URI (%s)\n", url_esc);
++ d->xprintf(">>\n>>\n");
++ d->xprintf("endobj\n");
++ d->currentPage->annotations.append(annot);
++ delete[] url_esc;
++}
++
++void QPdfEngine::addLink(const QRectF &r, const QString &anchor)
++{
++ Q_D(QPdfEngine);
++ char buf[256];
++ QRectF rr = d->pageMatrix().mapRect(r);
++ uint annot = d->addXrefEntry(-1);
++ d->xprintf("<<\n/Type /Annot\n/Subtype /Link\n/Rect [");
++ d->xprintf("%s ", qt_real_to_string(rr.left(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.top(),buf));
++ d->xprintf("%s ", qt_real_to_string(rr.right(),buf));
++ d->xprintf("%s", qt_real_to_string(rr.bottom(),buf));
++ d->xprintf("]\n/Border [0 0 0]\n/Dest ");
++ d->printAnchor(anchor);
++ d->xprintf("\n>>\n");
++ d->xprintf("endobj\n");
++ d->currentPage->annotations.append(annot);
++}
++
++void QPdfEngine::addAnchor(const QRectF &r, const QString &name)
++{
++ Q_D(QPdfEngine);
++ char buf[256];
++ QRectF rr = d->pageMatrix().mapRect(r);
++ uint anchor = d->addXrefEntry(-1);
++ d->xprintf("[%d /XYZ %s \n",
++ d->pages.size() - 1,
++ qt_real_to_string(rr.left(), buf));
++ d->xprintf("%s 0]\n",
++ qt_real_to_string(rr.bottom(), buf));
++ d->xprintf("endobj\n");
++ d->anchors[name] = anchor;
++}
++
++void QPdfEngine::beginSectionOutline(const QString &text, const QString &anchor)
++{
++ Q_D(QPdfEngine);
++ if (d->outlineCurrent == NULL) {
++ if (d->outlineRoot)
++ delete d->outlineRoot;
++ d->outlineCurrent = d->outlineRoot = new QPdfEnginePrivate::OutlineItem(QString(), QString());
++ }
++
++ QPdfEnginePrivate::OutlineItem *i = new QPdfEnginePrivate::OutlineItem(text, anchor);
++ i->parent = d->outlineCurrent;
++ i->prev = d->outlineCurrent->lastChild;
++ if (d->outlineCurrent->firstChild)
++ d->outlineCurrent->lastChild->next = i;
++ else
++ d->outlineCurrent->firstChild = i;
++ d->outlineCurrent->lastChild = i;
++ d->outlineCurrent = i;
++}
++
++void QPdfEngine::endSectionOutline()
++{
++ Q_D(QPdfEngine);
++ if (d->outlineCurrent)
++ d->outlineCurrent = d->outlineCurrent->parent;
++}
++
+ void QPdfEnginePrivate::writePage()
+ {
+ if (pages.empty())
+@@ -1167,7 +1610,7 @@ void QPdfEnginePrivate::writePage()
+ addXrefEntry(pageStream);
+ xprintf("<<\n"
+ "/Length %d 0 R\n", pageStreamLength); // object number for stream length object
+- if (do_compress)
++ if (doCompress)
+ xprintf("/Filter /FlateDecode\n");
+
+ xprintf(">>\n");
+diff --git a/src/gui/painting/qprintengine_pdf_p.h b/src/gui/painting/qprintengine_pdf_p.h
+index 9b9185a..1586caa 100644
+--- a/src/gui/painting/qprintengine_pdf_p.h
++++ b/src/gui/painting/qprintengine_pdf_p.h
+@@ -92,7 +92,12 @@ public:
+ // reimplementations QPaintEngine
+ bool begin(QPaintDevice *pdev);
+ bool end();
+- void drawPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QRectF & sr);
++
++ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr, const QByteArray * data=0);
++ void drawPixmap(const QRectF & rectangle, const QPixmap & pixmap, const QRectF & sr) {
++ drawPixmap(rectangle, pixmap, sr, 0);
++ }
++
+ void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
+ Qt::ImageConversionFlags flags = Qt::AutoColor);
+ void drawTiledPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QPointF & point);
+@@ -108,12 +113,23 @@ public:
+
+ void setBrush();
+
++ virtual void addHyperlink(const QRectF &r, const QUrl &url);
++ virtual void addAnchor(const QRectF &r, const QString &name);
++ virtual void addLink(const QRectF &r, const QString &anchor);
++ virtual void addTextField(const QRectF &r, const QString &text, const QString &name, bool multiLine, bool password, bool readOnly, int maxLength);
++ virtual void addCheckBox(const QRectF &r, bool checked, const QString &name, bool readOnly);
++
+ // ### unused, should have something for this in QPrintEngine
+ void setAuthor(const QString &author);
+ QString author() const;
+
+ void setDevice(QIODevice* dev);
+
++ void beginSectionOutline(const QString &text, const QString &anchor);
++ void endSectionOutline();
++
++ void setProperty(PrintEnginePropertyKey key, const QVariant &value);
++ QVariant property(PrintEnginePropertyKey key) const;
+ private:
+ Q_DISABLE_COPY(QPdfEngine)
+
+@@ -124,6 +140,35 @@ class QPdfEnginePrivate : public QPdfBaseEnginePrivate
+ {
+ Q_DECLARE_PUBLIC(QPdfEngine)
+ public:
++
++ class OutlineItem {
++ public:
++ OutlineItem *parent;
++ OutlineItem *next;
++ OutlineItem *prev;
++ OutlineItem *firstChild;
++ OutlineItem *lastChild;
++ uint obj;
++ QString text;
++ QString anchor;
++
++ OutlineItem(const QString &t, const QString &a):
++ parent(NULL), next(NULL), prev(NULL), firstChild(NULL), lastChild(NULL),
++ obj(0), text(t), anchor(a) {}
++ ~OutlineItem() {
++ OutlineItem *i = firstChild;
++ while(i != NULL) {
++ OutlineItem *n = i->next;
++ delete i;
++ i=n;
++ }
++ }
++ };
++
++ OutlineItem *outlineRoot;
++ OutlineItem *outlineCurrent;
++ void writeOutlineChildren(OutlineItem *node);
++
+ QPdfEnginePrivate(QPrinter::PrinterMode m);
+ ~QPdfEnginePrivate();
+
+@@ -141,7 +186,9 @@ public:
+ void writeHeader();
+ void writeTail();
+
+- int addImage(const QImage &image, bool *bitmap, qint64 serial_no);
++ void convertImage(const QImage & image, QByteArray & imageData);
++
++ int addImage(const QImage &image, bool *bitmap, qint64 serial_no, const QImage * noneScaled=0, const QByteArray * data=0, bool * useScaled=0);
+ int addConstantAlphaObject(int brushAlpha, int penAlpha = 255);
+ int addBrushPattern(const QTransform &matrix, bool *specifyColor, int *gStateObject);
+
+@@ -161,16 +208,25 @@ private:
+ void writeFonts();
+ void embedFont(QFontSubset *font);
+
++ int formFieldList;
++ QVector<uint> formFields;
+ QVector<int> xrefPositions;
+ QDataStream* stream;
+ int streampos;
+
++ bool doCompress;
++ int imageDPI;
++ int imageQuality;
++
+ int writeImage(const QByteArray &data, int width, int height, int depth,
+ int maskObject, int softMaskObject, bool dct = false);
+ void writePage();
+
+ int addXrefEntry(int object, bool printostr = true);
++
+ void printString(const QString &string);
++ void printAnchor(const QString &name);
++
+ void xprintf(const char* fmt, ...);
+ inline void write(const QByteArray &data) {
+ stream->writeRawData(data.constData(), data.size());
+@@ -183,6 +239,8 @@ private:
+
+ // various PDF objects
+ int pageRoot, catalog, info, graphicsState, patternColorSpace;
++ QVector<uint> dests;
++ QHash<QString, uint> anchors;
+ QVector<uint> pages;
+ QHash<qint64, uint> imageCache;
+ QHash<QPair<uint, uint>, uint > alphaCache;
+diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
+index 134447c..2c58619 100644
+--- a/src/gui/painting/qprinter.cpp
++++ b/src/gui/painting/qprinter.cpp
+@@ -933,6 +933,39 @@ void QPrinter::setOutputFileName(const QString &fileName)
+ d->addToManualSetList(QPrintEngine::PPK_OutputFileName);
+ }
+
++/*!
++ Add a section to the document outline. All following sections will be added
++ to as subsections to this section, until endSectionOutline() has been called.
++
++ \a name is the name of the added section. \a anchor is the name of an anchor
++ indicating the beginning of the section. This anchor must be added by calling
++ QPainter::addAnchor().
++
++ Note that for output formats not supporting outlines, currently all other then PDF,
++ this call has no effect.
++
++ \sa endSectionOutline() QPainter::addAnchor()
++
++ \since 4.7
++*/
++void QPrinter::beginSectionOutline(const QString &name, const QString &anchor)
++{
++ Q_D(QPrinter);
++ d->printEngine->beginSectionOutline(name, anchor);
++}
++
++/*!
++ End the current section.
++
++ \sa beginSectionOutline()
++
++ \since 4.7
++*/
++void QPrinter::endSectionOutline()
++{
++ Q_D(QPrinter);
++ d->printEngine->endSectionOutline();
++}
+
+ /*!
+ Returns the name of the program that sends the print output to the
+diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h
+index f133a5d..46baf8c 100644
+--- a/src/gui/painting/qprinter.h
++++ b/src/gui/painting/qprinter.h
+@@ -147,6 +147,9 @@ public:
+ enum PrinterOption { PrintToFile, PrintSelection, PrintPageRange };
+ #endif // QT3_SUPPORT
+
++ void beginSectionOutline(const QString &text, const QString &anchor);
++ void endSectionOutline();
++
+ void setOutputFormat(OutputFormat format);
+ OutputFormat outputFormat() const;
+
+diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp
+index 52ce9a7..eddbb80 100644
+--- a/src/gui/styles/qstyle.cpp
++++ b/src/gui/styles/qstyle.cpp
+@@ -47,6 +47,7 @@
+ #include "qpixmapcache.h"
+ #include "qstyleoption.h"
+ #include "private/qstyle_p.h"
++#include "private/qapplication_p.h"
+ #ifndef QT_NO_DEBUG
+ #include "qdebug.h"
+ #endif
+@@ -2229,7 +2230,7 @@ QPalette QStyle::standardPalette() const
+ {
+ #ifdef Q_WS_X11
+ QColor background;
+- if (QX11Info::appDepth() > 8)
++ if (!qt_is_gui_used || QX11Info::appDepth() > 8)
+ background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey
+ else
+ background = QColor(192, 192, 192);
+diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp
+index f512992..9ee9096 100644
+--- a/src/svg/qsvggenerator.cpp
++++ b/src/svg/qsvggenerator.cpp
+@@ -103,6 +103,7 @@ public:
+
+ afterFirstUpdate = false;
+ numGradients = 0;
++ clip = false;
+ }
+
+ QSize size;
+@@ -129,6 +130,9 @@ public:
+
+ QString currentGradientName;
+ int numGradients;
++ QString stateString;
++ QString oldStateString;
++ bool clip;
+
+ struct _attributes {
+ QString document_title;
+@@ -141,6 +145,18 @@ public:
+ QString dashPattern, dashOffset;
+ QString fill, fillOpacity;
+ } attributes;
++
++ void emitState() {
++ if (stateString == oldStateString) return;
++
++ // close old state and start a new one...
++ if (afterFirstUpdate)
++ *stream << "</g>\n\n";
++
++ *stream << stateString;
++ afterFirstUpdate = true;
++ oldStateString = stateString;
++ }
+ };
+
+ static inline QPaintEngine::PaintEngineFeatures svgEngineFeatures()
+@@ -322,7 +338,7 @@ public:
+ }
+
+
+- void qpenToSvg(const QPen &spen)
++ void qpenToSvg(const QPen &spen, QTextStream & s)
+ {
+ QString width;
+
+@@ -330,7 +346,7 @@ public:
+
+ switch (spen.style()) {
+ case Qt::NoPen:
+- stream() << QLatin1String("stroke=\"none\" ");
++ s << QLatin1String("stroke=\"none\" ");
+
+ d_func()->attributes.stroke = QLatin1String("none");
+ d_func()->attributes.strokeOpacity = QString();
+@@ -344,8 +360,8 @@ public:
+ d_func()->attributes.stroke = color;
+ d_func()->attributes.strokeOpacity = colorOpacity;
+
+- stream() << QLatin1String("stroke=\"")<<color<< QLatin1String("\" ");
+- stream() << QLatin1String("stroke-opacity=\"")<<colorOpacity<< QLatin1String("\" ");
++ s << QLatin1String("stroke=\"")<<color<< QLatin1String("\" ");
++ s << QLatin1String("stroke-opacity=\"")<<colorOpacity<< QLatin1String("\" ");
+ }
+ break;
+ case Qt::DashLine:
+@@ -368,10 +384,10 @@ public:
+ d_func()->attributes.dashPattern = dashPattern;
+ d_func()->attributes.dashOffset = dashOffset;
+
+- stream() << QLatin1String("stroke=\"")<<color<< QLatin1String("\" ");
+- stream() << QLatin1String("stroke-opacity=\"")<<colorOpacity<< QLatin1String("\" ");
+- stream() << QLatin1String("stroke-dasharray=\"")<<dashPattern<< QLatin1String("\" ");
+- stream() << QLatin1String("stroke-dashoffset=\"")<<dashOffset<< QLatin1String("\" ");
++ s << QLatin1String("stroke=\"")<<color<< QLatin1String("\" ");
++ s << QLatin1String("stroke-opacity=\"")<<colorOpacity<< QLatin1String("\" ");
++ s << QLatin1String("stroke-dasharray=\"")<<dashPattern<< QLatin1String("\" ");
++ s << QLatin1String("stroke-dashoffset=\"")<<dashOffset<< QLatin1String("\" ");
+ break;
+ }
+ default:
+@@ -380,50 +396,50 @@ public:
+ }
+
+ if (spen.widthF() == 0)
+- stream() <<"stroke-width=\"1\" ";
++ s <<"stroke-width=\"1\" ";
+ else
+- stream() <<"stroke-width=\"" << spen.widthF() << "\" ";
++ s <<"stroke-width=\"" << spen.widthF() << "\" ";
+
+ switch (spen.capStyle()) {
+ case Qt::FlatCap:
+- stream() << "stroke-linecap=\"butt\" ";
++ s << "stroke-linecap=\"butt\" ";
+ break;
+ case Qt::SquareCap:
+- stream() << "stroke-linecap=\"square\" ";
++ s << "stroke-linecap=\"square\" ";
+ break;
+ case Qt::RoundCap:
+- stream() << "stroke-linecap=\"round\" ";
++ s << "stroke-linecap=\"round\" ";
+ break;
+ default:
+ qWarning("Unhandled cap style");
+ }
+ switch (spen.joinStyle()) {
+ case Qt::MiterJoin:
+- stream() << "stroke-linejoin=\"miter\" "
++ s << "stroke-linejoin=\"miter\" "
+ "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
+ break;
+ case Qt::BevelJoin:
+- stream() << "stroke-linejoin=\"bevel\" ";
++ s << "stroke-linejoin=\"bevel\" ";
+ break;
+ case Qt::RoundJoin:
+- stream() << "stroke-linejoin=\"round\" ";
++ s << "stroke-linejoin=\"round\" ";
+ break;
+ case Qt::SvgMiterJoin:
+- stream() << "stroke-linejoin=\"miter\" "
++ s << "stroke-linejoin=\"miter\" "
+ "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
+ break;
+ default:
+ qWarning("Unhandled join style");
+ }
+ }
+- void qbrushToSvg(const QBrush &sbrush)
++ void qbrushToSvg(const QBrush &sbrush, QTextStream & s)
+ {
+ d_func()->brush = sbrush;
+ switch (sbrush.style()) {
+ case Qt::SolidPattern: {
+ QString color, colorOpacity;
+ translate_color(sbrush.color(), &color, &colorOpacity);
+- stream() << "fill=\"" << color << "\" "
++ s << "fill=\"" << color << "\" "
+ "fill-opacity=\""
+ << colorOpacity << "\" ";
+ d_func()->attributes.fill = color;
+@@ -434,22 +450,22 @@ public:
+ saveLinearGradientBrush(sbrush.gradient());
+ d_func()->attributes.fill = QString::fromLatin1("url(#%1)").arg(d_func()->currentGradientName);
+ d_func()->attributes.fillOpacity = QString();
+- stream() << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
++ s << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
+ break;
+ case Qt::RadialGradientPattern:
+ saveRadialGradientBrush(sbrush.gradient());
+ d_func()->attributes.fill = QString::fromLatin1("url(#%1)").arg(d_func()->currentGradientName);
+ d_func()->attributes.fillOpacity = QString();
+- stream() << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
++ s << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
+ break;
+ case Qt::ConicalGradientPattern:
+ saveConicalGradientBrush(sbrush.gradient());
+ d_func()->attributes.fill = QString::fromLatin1("url(#%1)").arg(d_func()->currentGradientName);
+ d_func()->attributes.fillOpacity = QString();
+- stream() << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
++ s << QLatin1String("fill=\"url(#") << d_func()->currentGradientName << QLatin1String(")\" ");
+ break;
+ case Qt::NoBrush:
+- stream() << QLatin1String("fill=\"none\" ");
++ s << QLatin1String("fill=\"none\" ");
+ d_func()->attributes.fill = QLatin1String("none");
+ d_func()->attributes.fillOpacity = QString();
+ return;
+@@ -458,7 +474,7 @@ public:
+ break;
+ }
+ }
+- void qfontToSvg(const QFont &sfont)
++ void qfontToSvg(const QFont &sfont, QTextStream & s)
+ {
+ Q_D(QSvgPaintEngine);
+
+@@ -488,12 +504,23 @@ public:
+ d->attributes.font_family = d->font.family();
+ d->attributes.font_style = d->font.italic() ? QLatin1String("italic") : QLatin1String("normal");
+
+- *d->stream << "font-family=\"" << d->attributes.font_family << "\" "
+- "font-size=\"" << d->attributes.font_size << "\" "
+- "font-weight=\"" << d->attributes.font_weight << "\" "
+- "font-style=\"" << d->attributes.font_style << "\" "
+- << endl;
++ s << "font-family=\"" << d->attributes.font_family << "\" "
++ "font-size=\"" << d->attributes.font_size << "\" "
++ "font-weight=\"" << d->attributes.font_weight << "\" "
++ "font-style=\"" << d->attributes.font_style << "\" "
++ << endl;
++ }
++
++ void setViewBoxClip(bool clip) {
++ Q_D(QSvgPaintEngine);
++ d->clip = clip;
+ }
++
++ bool viewBoxClip() const {
++ Q_D(const QSvgPaintEngine);
++ return d->clip;
++ }
++
+ };
+
+ class QSvgGeneratorPrivate
+@@ -808,6 +835,27 @@ int QSvgGenerator::metric(QPaintDevice::PaintDeviceMetric metric) const
+ return 0;
+ }
+
++/*!
++ \property QSvgGenerator::resolution
++ \brief do not draw objects outside the viewBox
++ \since 4.7
++
++ When specified objects drawn compleatly outsite the viewBox
++ are not include in the output SVG.
++
++ \sa viewBox
++*/
++
++bool QSvgGenerator::viewBoxClip() const {
++ Q_D(const QSvgGenerator);
++ return d->engine->viewBoxClip();
++}
++
++void QSvgGenerator::setViewBoxClip(bool clip) {
++ Q_D(QSvgGenerator);
++ d->engine->setViewBoxClip(clip);
++}
++
+ /*****************************************************************************
+ * class QSvgPaintEngine
+ */
+@@ -908,10 +956,13 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
+ const QRectF &sr,
+ Qt::ImageConversionFlag flags)
+ {
+- //Q_D(QSvgPaintEngine);
++ Q_D(QSvgPaintEngine);
+
+ Q_UNUSED(sr);
+ Q_UNUSED(flags);
++ if (d->clip && !d->matrix.mapRect(r).intersects(d->viewBox)) return;
++ d->emitState();
++
+ stream() << "<image ";
+ stream() << "x=\""<<r.x()<<"\" "
+ "y=\""<<r.y()<<"\" "
+@@ -932,53 +983,35 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
+ void QSvgPaintEngine::updateState(const QPaintEngineState &state)
+ {
+ Q_D(QSvgPaintEngine);
+- QPaintEngine::DirtyFlags flags = state.state();
+-
+- // always stream full gstate, which is not required, but...
+- flags |= QPaintEngine::AllDirty;
+-
+- // close old state and start a new one...
+- if (d->afterFirstUpdate)
+- *d->stream << "</g>\n\n";
+-
+- *d->stream << "<g ";
+
+- if (flags & QPaintEngine::DirtyBrush) {
+- qbrushToSvg(state.brush());
+- }
+-
+- if (flags & QPaintEngine::DirtyPen) {
+- qpenToSvg(state.pen());
+- }
+-
+- if (flags & QPaintEngine::DirtyTransform) {
+- d->matrix = state.matrix();
+- *d->stream << "transform=\"matrix(" << d->matrix.m11() << ','
+- << d->matrix.m12() << ','
+- << d->matrix.m21() << ',' << d->matrix.m22() << ','
+- << d->matrix.dx() << ',' << d->matrix.dy()
+- << ")\""
+- << endl;
+- }
+-
+- if (flags & QPaintEngine::DirtyFont) {
+- qfontToSvg(state.font());
+- }
+-
+- if (flags & QPaintEngine::DirtyOpacity) {
+- if (!qFuzzyIsNull(state.opacity() - 1))
+- stream() << "opacity=\""<<state.opacity()<<"\" ";
+- }
+-
+- *d->stream << '>' << endl;
+-
+- d->afterFirstUpdate = true;
++ d->stateString="";
++ QTextStream stateStream(&d->stateString);
++ stateStream << "<g ";
++ qbrushToSvg(state.brush(), stateStream);
++ qpenToSvg(state.pen(), stateStream);
++
++ d->matrix = state.matrix();
++ stateStream << "transform=\"matrix(" << d->matrix.m11() << ','
++ << d->matrix.m12() << ','
++ << d->matrix.m21() << ',' << d->matrix.m22() << ','
++ << d->matrix.dx() << ',' << d->matrix.dy()
++ << ")\""
++ << endl;
++ qfontToSvg(state.font(), stateStream);
++
++ if (!qFuzzyIsNull(state.opacity() - 1))
++ stateStream << "opacity=\""<<state.opacity()<<"\" ";
++
++ stateStream << '>' << endl;
+ }
+
+ void QSvgPaintEngine::drawPath(const QPainterPath &p)
+ {
+ Q_D(QSvgPaintEngine);
+
++ if (d->clip && !d->matrix.mapRect(p.boundingRect()).intersects(d->viewBox)) return;
++ d->emitState();
++
+ *d->stream << "<path vector-effect=\""
+ << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none")
+ << "\" fill-rule=\""
+@@ -1024,12 +1057,15 @@ void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount,
+ {
+ Q_ASSERT(pointCount >= 2);
+
+- //Q_D(QSvgPaintEngine);
++ Q_D(QSvgPaintEngine);
+
+ QPainterPath path(points[0]);
+ for (int i=1; i<pointCount; ++i)
+ path.lineTo(points[i]);
+
++ if (d->clip && !d->matrix.mapRect(path.boundingRect()).intersects(d->viewBox)) return;
++ d->emitState();
++
+ if (mode == PolylineMode) {
+ stream() << "<polyline fill=\"none\" vector-effect=\""
+ << (state->pen().isCosmetic() ? "non-scaling-stroke" : "none")
+@@ -1051,6 +1087,12 @@ void QSvgPaintEngine::drawTextItem(const QPointF &pt, const QTextItem &textItem)
+ if (d->pen.style() == Qt::NoPen)
+ return;
+
++ if (d->clip) {
++ QRectF b=painter()->boundingRect( QRectF(pt, QSize()) , Qt::AlignLeft, textItem.text());
++ if (!d->matrix.mapRect(b).intersects(d->viewBox)) return;
++ }
++ d->emitState();
++
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ QString s = QString::fromRawData(ti.chars, ti.num_chars);
+
+@@ -1060,7 +1102,7 @@ void QSvgPaintEngine::drawTextItem(const QPointF &pt, const QTextItem &textItem)
+ "stroke=\"none\" "
+ "xml:space=\"preserve\" "
+ "x=\"" << pt.x() << "\" y=\"" << pt.y() << "\" ";
+- qfontToSvg(textItem.font());
++ qfontToSvg(textItem.font(), *d->stream);
+ *d->stream << " >"
+ << Qt::escape(s)
+ << "</text>"
+diff --git a/src/svg/qsvggenerator.h b/src/svg/qsvggenerator.h
+index 7981f28..2197ad8 100644
+--- a/src/svg/qsvggenerator.h
++++ b/src/svg/qsvggenerator.h
+@@ -96,6 +96,9 @@ public:
+
+ void setResolution(int dpi);
+ int resolution() const;
++
++ void setViewBoxClip(bool clip);
++ bool viewBoxClip() const;
+ protected:
+ QPaintEngine *paintEngine() const;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
+index 4b8000d..6d52696 100644
+--- a/tools/configure/configureapp.cpp
++++ b/tools/configure/configureapp.cpp
+@@ -2381,9 +2381,9 @@ bool Configure::checkAvailability(const QString &part)
+ available = qmakeSpec == "win32-msvc2005" || qmakeSpec == "win32-msvc2008" ||
+ qmakeSpec == "win32-msvc2010" || qmakeSpec == "win32-msvc2012" || qmakeSpec.startsWith("win32-g++");
+ if (dictionary[ "SHARED" ] == "no") {
+- cout << endl << "WARNING: Using static linking will disable the WebKit module." << endl
+- << endl;
+- available = false;
++ // cout << endl << "WARNING: Using static linking will disable the WebKit module." << endl
++ // << endl;
++ // available = false;
+ }
+ } else if (part == "AUDIO_BACKEND") {
+ available = true;
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/qt4.git/commitdiff/3583d8d70a3b67403433a8664d9f7facad0e1277
More information about the pld-cvs-commit
mailing list