diff options
187 files changed, 9524 insertions, 1767 deletions
@@ -24,6 +24,7 @@ $basedir =~ s=\\=/=g; my %modules = ( # path to module name map "QtGui" => "$basedir/src/gui", "QtOpenGL" => "$basedir/src/opengl", + "QtOpenVG" => "$basedir/src/openvg", "QtCore" => "$basedir/src/corelib", "QtXml" => "$basedir/src/xml", "QtXmlPatterns" => "$basedir/src/xmlpatterns", @@ -309,8 +310,6 @@ sub syncHeader { $header =~ s=\\=/=g; return copyFile($iheader, $header) if($copy); - my $iheader_no_basedir = $iheader; - $iheader_no_basedir =~ s,^$basedir/?,,; unless(-e "$header") { my $header_dir = dirname($header); mkpath $header_dir, 0777; @@ -691,6 +690,7 @@ foreach (@modules_to_sync) { $master_contents .= "#include <QtXml/QtXml>\n" if("$_" eq "xml"); $master_contents .= "#include <QtXmlPatterns/QtXmlPatterns>\n" if("$_" eq "xmlpatterns"); $master_contents .= "#include <QtOpenGL/QtOpenGL>\n" if("$_" eq "opengl"); + $master_contents .= "#include <QtOpenVG/QtOpenVG>\n" if("$_" eq "openvg"); } } } @@ -800,10 +800,9 @@ foreach (@modules_to_sync) { my $class = $_; if ($class =~ m/::/) { $class =~ s,::,/,g; - $class = "../" . $class; } $class_lib_map_contents .= "QT_CLASS_LIB($_, $lib, $header_base)\n"; - $header_copies++ if(syncHeader("$out_basedir/include/$lib/$class", $header, 0)); + $header_copies++ if(syncHeader("$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0)); } } else { @headers = ( "$out_basedir/include/$lib/private/$header" ); @@ -825,7 +824,6 @@ foreach (@modules_to_sync) { my $class = $_; if ($class =~ m/::/) { $class =~ s,::,/,g; - $class = "../" . $class; } my $class_header = fixPaths("$out_basedir/include/$lib/$class", $current_dir) . " "; @@ -846,25 +844,27 @@ foreach (@modules_to_sync) { $master_contents .= "#endif\n"; unless($showonly) { - #generate the "master" include file - my $master_include = "$out_basedir/include/$lib/$lib"; - $pri_install_files .= fixPaths($master_include, "$modules{$lib}") . " "; #get the master file installed too - if(-e "$master_include") { - open MASTERINCLUDE, "<$master_include"; - local $/; - binmode MASTERINCLUDE; - my $oldmaster = <MASTERINCLUDE>; - close MASTERINCLUDE; - $oldmaster =~ s/\r//g; # remove \r's , so comparison is ok on all platforms - $master_include = 0 if($oldmaster eq $master_contents); - } - if($master_include && $master_contents) { - my $master_dir = dirname($master_include); - mkpath $master_dir, 0777; - print "header (master) created for $lib\n"; - open MASTERINCLUDE, ">$master_include"; - print MASTERINCLUDE "$master_contents"; - close MASTERINCLUDE; + unless ($lib eq "phonon") { + #generate the "master" include file + my $master_include = "$out_basedir/include/$lib/$lib"; + $pri_install_files .= fixPaths($master_include, "$modules{$lib}") . " "; #get the master file installed too + if($master_include && -e "$master_include") { + open MASTERINCLUDE, "<$master_include"; + local $/; + binmode MASTERINCLUDE; + my $oldmaster = <MASTERINCLUDE>; + close MASTERINCLUDE; + $oldmaster =~ s/\r//g; # remove \r's , so comparison is ok on all platforms + $master_include = 0 if($oldmaster eq $master_contents); + } + if($master_include && $master_contents) { + my $master_dir = dirname($master_include); + mkpath $master_dir, 0777; + print "header (master) created for $lib\n"; + open MASTERINCLUDE, ">$master_include"; + print MASTERINCLUDE "$master_contents"; + close MASTERINCLUDE; + } } #handle the headers.pri for each module diff --git a/config.tests/unix/egl/egl.cpp b/config.tests/unix/egl/egl.cpp new file mode 100644 index 0000000..0c7f32c --- /dev/null +++ b/config.tests/unix/egl/egl.cpp @@ -0,0 +1,10 @@ +#include <EGL/egl.h> + +int main(int, char **) +{ + EGLint x = 0; + EGLDisplay dpy = 0; + EGLContext ctx = 0; + eglDestroyContext(dpy, ctx); + return 0; +} diff --git a/config.tests/unix/egl/egl.pro b/config.tests/unix/egl/egl.pro new file mode 100644 index 0000000..f04d053 --- /dev/null +++ b/config.tests/unix/egl/egl.pro @@ -0,0 +1,10 @@ +SOURCES = egl.cpp + +for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p +} + +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL + +CONFIG -= qt diff --git a/config.tests/unix/egl4gles1/egl4gles1.cpp b/config.tests/unix/egl4gles1/egl4gles1.cpp new file mode 100644 index 0000000..c1acb90 --- /dev/null +++ b/config.tests/unix/egl4gles1/egl4gles1.cpp @@ -0,0 +1,10 @@ +#include <GLES/egl.h> + +int main(int, char **) +{ + EGLint x = 0; + EGLDisplay dpy = 0; + EGLContext ctx = 0; + eglDestroyContext(dpy, ctx); + return 0; +} diff --git a/config.tests/unix/egl4gles1/egl4gles1.pro b/config.tests/unix/egl4gles1/egl4gles1.pro new file mode 100644 index 0000000..667ea8e --- /dev/null +++ b/config.tests/unix/egl4gles1/egl4gles1.pro @@ -0,0 +1,10 @@ +SOURCES = egl4gles1.cpp + +for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p +} + +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL + +CONFIG -= qt diff --git a/config.tests/unix/opengles1/opengles1.cpp b/config.tests/unix/opengles1/opengles1.cpp index a0060b4..de690c9 100644 --- a/config.tests/unix/opengles1/opengles1.cpp +++ b/config.tests/unix/opengles1/opengles1.cpp @@ -1,10 +1,8 @@ #include <GLES/gl.h> -#include <GLES/egl.h> int main(int, char **) { GLfloat a = 1.0f; - eglInitialize(0, 0, 0); glColor4f(a, a, a, a); glClear(GL_COLOR_BUFFER_BIT); diff --git a/config.tests/unix/opengles1cl/opengles1cl.cpp b/config.tests/unix/opengles1cl/opengles1cl.cpp index f864276..23ae710 100644 --- a/config.tests/unix/opengles1cl/opengles1cl.cpp +++ b/config.tests/unix/opengles1cl/opengles1cl.cpp @@ -1,10 +1,8 @@ #include <GLES/gl.h> -#include <GLES/egl.h> int main(int, char **) { GLfixed a = 0; - eglInitialize(0, 0, 0); glColor4x(a, a, a, a); glClear(GL_COLOR_BUFFER_BIT); diff --git a/config.tests/unix/opengles2/opengles2.cpp b/config.tests/unix/opengles2/opengles2.cpp index 493530d..63c7b35 100644 --- a/config.tests/unix/opengles2/opengles2.cpp +++ b/config.tests/unix/opengles2/opengles2.cpp @@ -1,9 +1,7 @@ -#include <EGL/egl.h> #include <GLES2/gl2.h> int main(int, char **) { - eglInitialize(0, 0, 0); glUniform1f(1, GLfloat(1.0)); glClear(GL_COLOR_BUFFER_BIT); diff --git a/config.tests/unix/openvg/openvg.cpp b/config.tests/unix/openvg/openvg.cpp new file mode 100644 index 0000000..8f763cd --- /dev/null +++ b/config.tests/unix/openvg/openvg.cpp @@ -0,0 +1,16 @@ +// There is some variation in OpenVG engines as to what case +// the VG includes use. The Khronos reference implementation +// for OpenVG 1.1 uses upper case, so we treat that as canonical. +#if defined(QT_LOWER_CASE_VG_INCLUDES) +#include <vg/openvg.h> +#else +#include <VG/openvg.h> +#endif + +int main(int, char **) +{ + VGint i; + i = 2; + vgFlush(); + return 0; +} diff --git a/config.tests/unix/openvg/openvg.pro b/config.tests/unix/openvg/openvg.pro new file mode 100644 index 0000000..8dd227b --- /dev/null +++ b/config.tests/unix/openvg/openvg.pro @@ -0,0 +1,11 @@ +SOURCES += openvg.cpp + +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG + +lower_case_includes { + DEFINES += QT_LOWER_CASE_VG_INCLUDES +} + +CONFIG -= qt diff --git a/config.tests/unix/shivavg/shivavg.cpp b/config.tests/unix/shivavg/shivavg.cpp new file mode 100644 index 0000000..b5d3291 --- /dev/null +++ b/config.tests/unix/shivavg/shivavg.cpp @@ -0,0 +1,10 @@ +#include <vg/openvg.h> + +int main(int, char **) +{ + VGint i; + i = 2; + vgFlush(); + vgDestroyContextSH(); + return 0; +} diff --git a/config.tests/unix/shivavg/shivavg.pro b/config.tests/unix/shivavg/shivavg.pro new file mode 100644 index 0000000..0c1bd07 --- /dev/null +++ b/config.tests/unix/shivavg/shivavg.pro @@ -0,0 +1,7 @@ +SOURCES += shivavg.cpp + +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG + +CONFIG -= qt @@ -588,6 +588,11 @@ CFG_XRANDR=runtime CFG_XRENDER=auto CFG_MITSHM=auto CFG_OPENGL=auto +CFG_OPENVG=no +CFG_OPENVG_LC_INCLUDES=no +CFG_OPENVG_SHIVA=no +CFG_EGL=no +CFG_EGL_GLES_INCLUDES=no CFG_SSE=auto CFG_FONTCONFIG=auto CFG_QWS_FREETYPE=auto @@ -889,6 +894,16 @@ while [ "$#" -gt 0 ]; do VAL=$1 fi ;; + -openvg) + VAR=openvg + # this option may or may not be followed by an argument + if [ -z "$2" ] || echo "$2" | grep '^-' >/dev/null 2>&1; then + VAL=yes + else + shift; + VAL=$1 + fi + ;; -hostprefix) VAR=`echo $1 | sed "s,^-\(.*\),\1,"` # this option may or may not be followed by an argument @@ -1133,6 +1148,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + openvg) + if [ "$VAL" = "auto" ] || [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_OPENVG="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; graphicssystem) if [ "$PLATFORM_QWS" = "yes" ]; then echo "Error: Graphics System plugins are not supported on QWS." @@ -3495,7 +3517,12 @@ Qt/X11 only: to force the use of the Desktop (OpenGL 1.x or 2.x), OpenGL ES 1.x Common profile, 1.x Common Lite profile or 2.x APIs instead. On X11, the EGL API will be used - to manage GL contexts in the case of OpenGL ES. + to manage GL contexts in the case of OpenGL ES + + -no-openvg ........ Do not support OpenVG. + + -openvg ........... Enable OpenVG support. + Requires EGL support, typically supplied by an OpenGL + or other graphics implementation. $SMN -no-sm ............. Do not support X Session Management. $SMY -sm ................ Support X Session Management, links in -lSM -lICE. @@ -4142,11 +4169,7 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; done fi if [ "$PLATFORM_MAC" = "yes" ]; then - if [ "$PLATFORM" = "macx-icc" ]; then - echo "export MACOSX_DEPLOYMENT_TARGET = 10.4" >> "$mkfile" - else - echo "export MACOSX_DEPLOYMENT_TARGET = 10.3" >> "$mkfile" - fi + echo "export MACOSX_DEPLOYMENT_TARGET = 10.4" >> "$mkfile" echo "CARBON_LFLAGS =-framework ApplicationServices" >>"$mkfile" echo "CARBON_CFLAGS =-fconstant-cfstrings" >>"$mkfile" EXTRA_LFLAGS="$EXTRA_LFLAGS \$(CARBON_LFLAGS)" @@ -4700,6 +4723,27 @@ if [ "$PLATFORM_MAC" = "yes" -a ! -z "$QT_NAMESPACE" ]; then fi if [ "$PLATFORM_X11" = "yes" -o "$PLATFORM_QWS" = "yes" ]; then + + # detect EGL support + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl" "EGL (EGL/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + # EGL specified by QMAKE_*_EGL, included with <EGL/egl.h> + CFG_EGL=yes + CFG_EGL_GLES_INCLUDES=no + elif "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl4gles1" "EGL (GLES/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + # EGL specified by QMAKE_*_EGL, included with <GLES/egl.h> + CFG_EGL=yes + CFG_EGL_GLES_INCLUDES=yes + fi + if ( [ "$CFG_OPENGL" = "es1" ] || [ "$CFG_OPENGL" = "es1cl" ] || [ "$CFG_OPENGL" = "es2" ] ) && [ "$CFG_EGL" != "yes" ] && [ "$PLATFORM_X11" = "yes" ]; then + echo "The EGL functionality test failed!" + echo " EGL is required for OpenGL ES on X11 to manage contexts & surfaces." + echo " You might need to modify the include and library search paths by editing" + echo " QMAKE_INCDIR_EGL, QMAKE_LIBDIR_EGL and QMAKE_LIBS_EGL in" + echo " ${XQMAKESPEC}." + exit 1 + fi + + # auto-detect Glib support if [ "$CFG_GLIB" != "no" ]; then if [ -n "$PKG_CONFIG" ]; then @@ -4829,8 +4873,8 @@ if [ "$PLATFORM_X11" = "yes" ]; then if [ $? != "0" ]; then echo "The OpenGL ES 1.x Common Lite Profile functionality test failed!" echo " You might need to modify the include and library search paths by editing" - echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" - echo " ${XQMAKESPEC}." + echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" + echo " ${XQMAKESPEC}." exit 1 fi elif [ "$CFG_OPENGL" = "es1" ]; then @@ -4839,8 +4883,8 @@ if [ "$PLATFORM_X11" = "yes" ]; then if [ $? != "0" ]; then echo "The OpenGL ES 1.x functionality test failed!" echo " You might need to modify the include and library search paths by editing" - echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" - echo " ${XQMAKESPEC}." + echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" + echo " ${XQMAKESPEC}." exit 1 fi elif [ "$CFG_OPENGL" = "es2" ]; then @@ -4849,8 +4893,8 @@ if [ "$PLATFORM_X11" = "yes" ]; then if [ $? != "0" ]; then echo "The OpenGL ES 2.0 functionality test failed!" echo " You might need to modify the include and library search paths by editing" - echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" - echo " ${XQMAKESPEC}." + echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" + echo " ${XQMAKESPEC}." exit 1 fi elif [ "$CFG_OPENGL" = "desktop" ]; then @@ -4859,8 +4903,8 @@ if [ "$PLATFORM_X11" = "yes" ]; then if [ $? != "0" ]; then echo "The OpenGL functionality test failed!" echo " You might need to modify the include and library search paths by editing" - echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" - echo " ${XQMAKESPEC}." + echo " QMAKE_INCDIR_OPENGL, QMAKE_LIBDIR_OPENGL and QMAKE_LIBS_OPENGL in" + echo " ${XQMAKESPEC}." exit 1 fi case "$PLATFORM" in @@ -5515,6 +5559,33 @@ if [ "$CFG_OPENSSL" != "no" ]; then fi fi +# detect OpenVG support +if [ "$CFG_OPENVG" != "no" ]; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/openvg" "OpenVG" $L_FLAGS $I_FLAGS $l_FLAGS $CONFIG_ARG; then + if [ "$CFG_OPENVG" = "auto" ]; then + CFG_OPENVG=yes + fi + elif "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG lower_case_includes" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/openvg" "OpenVG (lc includes)" $L_FLAGS $I_FLAGS $l_FLAGS $CONFIG_ARG; then + if [ "$CFG_OPENVG" = "auto" ]; then + CFG_OPENVG=yes + fi + CFG_OPENVG_LC_INCLUDES=yes + else + if [ "$CFG_OPENVG" != "auto" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then + echo "$CFG_OPENVG was specified for OpenVG but cannot be enabled due to functionality tests!" + echo " Turn on verbose messaging (-v) to $0 to see the final report." + echo " If you believe this message is in error you may use the continue" + echo " switch (-continue) to $0 to continue." + exit 101 + else + CFG_OPENVG=no + fi + fi + if [ "$CFG_OPENVG" == "yes" ] && "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/shivavg" "ShivaVG" $L_FLAGS $I_FLAGS $l_FLAGS $CONFIG_ARG; then + CFG_OPENVG_SHIVA=yes + fi +fi + if [ "$CFG_PTMALLOC" != "no" ]; then # build ptmalloc, copy .a file to lib/ echo "Building ptmalloc. Please wait..." @@ -5612,13 +5683,9 @@ case "$PLATFORM,$CFG_MAC_COCOA" in QMakeVar set QMAKE_MACOSX_DEPLOYMENT_TARGET 10.5 CFG_QT3SUPPORT="no" ;; - macx-icc,*) - # Intel CC, Carbon - QMakeVar set QMAKE_MACOSX_DEPLOYMENT_TARGET 10.4 - ;; macx*,no) # gcc, Carbon - QMakeVar set QMAKE_MACOSX_DEPLOYMENT_TARGET 10.3 + QMakeVar set QMAKE_MACOSX_DEPLOYMENT_TARGET 10.4 ;; esac @@ -5644,6 +5711,30 @@ else QT_CONFIG="$QT_CONFIG accessibility" fi +# enable egl +if [ "$CFG_EGL" = "no" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EGL" +else + QT_CONFIG="$QT_CONFIG egl" + if [ "$CFG_EGL_GLES_INCLUDES" = "yes" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_GLES_EGL" + fi +fi + +# enable openvg +if [ "$CFG_OPENVG" = "no" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENVG" +else + QT_CONFIG="$QT_CONFIG openvg" + if [ "$CFG_OPENVG_LC_INCLUDES" = "yes" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_LOWER_CASE_VG_INCLUDES" + fi + if [ "$CFG_OPENVG_SHIVA" = "yes" ]; then + QT_CONFIG="$QT_CONFIG shivavg" + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_SHIVAVG" + fi +fi + # enable opengl if [ "$CFG_OPENGL" = "no" ]; then QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENGL" @@ -6074,7 +6165,7 @@ fi # On Mac, set the minimum deployment target for the different architechtures # using the Xarch compiler option when supported (10.5 and up). On 10.4 the -# deployment version is set to 10.3 globally using the QMAKE_MACOSX_DEPLOYMENT_TARGET +# deployment version is set to 10.4 globally using the QMAKE_MACOSX_DEPLOYMENT_TARGET # env. variable. "-cocoa" on the command line means Cocoa is used in 32-bit mode also, # in this case fall back on QMAKE_MACOSX_DEPLOYMENT_TARGET which will be set to 10.5. if [ "$PLATFORM_MAC" = "yes" ] && [ "$CFG_MAC_XARCH" != "no" ] && [ "$COMMANDLINE_MAC_COCOA" != "yes" ]; then @@ -6085,10 +6176,10 @@ if [ "$PLATFORM_MAC" = "yes" ] && [ "$CFG_MAC_XARCH" != "no" ] && [ "$COMMANDLIN QMakeVar add QMAKE_OBJECTIVE_CFLAGS_X86 "-arch i386 -Xarch_i386 -mmacosx-version-min=10.4" fi if echo "$CFG_MAC_ARCHS" | grep '\<ppc\>' > /dev/null 2>&1; then - QMakeVar add QMAKE_CFLAGS "-Xarch_ppc -mmacosx-version-min=10.3" - QMakeVar add QMAKE_CXXFLAGS "-Xarch_ppc -mmacosx-version-min=10.3" - QMakeVar add QMAKE_LFLAGS "-Xarch_ppc -mmacosx-version-min=10.3" - QMakeVar add QMAKE_OBJECTIVE_CFLAGS_PPC "-arch ppc -Xarch_ppc -mmacosx-version-min=10.3" + QMakeVar add QMAKE_CFLAGS "-Xarch_ppc -mmacosx-version-min=10.4" + QMakeVar add QMAKE_CXXFLAGS "-Xarch_ppc -mmacosx-version-min=10.4" + QMakeVar add QMAKE_LFLAGS "-Xarch_ppc -mmacosx-version-min=10.4" + QMakeVar add QMAKE_OBJECTIVE_CFLAGS_PPC "-arch ppc -Xarch_ppc -mmacosx-version-min=10.4" fi if echo "$CFG_MAC_ARCHS" | grep '\<x86_64\>' > /dev/null 2>&1; then QMakeVar add QMAKE_CFLAGS "-Xarch_x86_64 -mmacosx-version-min=10.5" @@ -6993,6 +7084,20 @@ elif [ "$CFG_OPENGL" = "es2" ]; then else echo "OpenGL support ...... no" fi +if [ "$CFG_EGL" != "no" ]; then + if [ "$CFG_EGL_GLES_INCLUDES" != "no" ]; then + echo "EGL support ......... yes <GLES/egl.h>" + else + echo "EGL support ......... yes <EGL/egl.h>" + fi +fi +if [ "$CFG_OPENVG" ]; then + if [ "$CFG_OPENVG_SHIVA" = "yes" ]; then + echo "OpenVG support ...... ShivaVG" + else + echo "OpenVG support ...... $CFG_OPENVG" + fi +fi if [ "$PLATFORM_X11" = "yes" ]; then echo "NAS sound support ... $CFG_NAS" echo "XShape support ...... $CFG_XSHAPE" diff --git a/doc/src/diagrams/frozencolumn/tableview-overlay.svg b/doc/src/diagrams/frozencolumn/tableview-overlay.svg new file mode 100644 index 0000000..fafdc23 --- /dev/null +++ b/doc/src/diagrams/frozencolumn/tableview-overlay.svg @@ -0,0 +1,240 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="744.09448819" + height="1052.3622047" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="table.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs + id="defs4"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.98994949" + inkscape:cx="388.18807" + inkscape:cy="731.8625" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:window-width="1920" + inkscape:window-height="1125" + inkscape:window-x="-4" + inkscape:window-y="-4" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#f2f2f2;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + id="rect2385" + width="517.14294" + height="358.57147" + x="97.142853" + y="190.93361" + ry="2.5253813" /> + <rect + style="opacity:1;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect2387" + width="51.42857" + height="355.71429" + x="98.571426" + y="193.79076" /> + <rect + style="opacity:1;fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect3159" + width="515.71429" + height="12.857142" + x="98.571426" + y="192.36218" /> + <rect + style="opacity:1;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect3161" + width="464.28571" + height="10" + x="150" + y="538.07648" /> + <rect + style="opacity:1;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect3163" + width="10.00007" + height="330.00003" + x="603.57141" + y="206.6479" /> + <rect + style="opacity:1;fill:#99ff55;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.10637689px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" + id="rect3167" + width="84.8367" + height="344.89362" + x="150.47162" + y="192.41537" + ry="3.0295234" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 340.92648,197.77313 L 377.79705,175.0447 L 405.07117,175.0447" + id="path3193" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="407.09146" + y="177.57007" + id="text3195"><tspan + sodipodi:role="line" + x="407.09146" + y="177.57007" + id="tspan3199">horizontal header</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 320.72343,426.0676 L 232.84016,619.51182 L 209.10158,620.01689" + id="path3205" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="117.1777" + y="622.5423" + id="text3207"><tspan + sodipodi:role="line" + id="tspan3209" + x="117.1777" + y="622.5423">viewport</tspan></text> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1" + id="path3215" + sodipodi:cx="320.78656" + sodipodi:cy="426.0676" + sodipodi:rx="1.8309015" + sodipodi:ry="1.8940361" + d="M 322.61746,426.0676 A 1.8309015,1.8940361 0 1 1 318.95566,426.0676 A 1.8309015,1.8940361 0 1 1 322.61746,426.0676 z" /> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1" + id="path3217" + sodipodi:cx="341.24216" + sodipodi:cy="197.64687" + sodipodi:rx="1.1995561" + sodipodi:ry="1.1364216" + d="M 342.44171,197.64687 A 1.1995561,1.1364216 0 1 1 340.0426,197.64687 A 1.1995561,1.1364216 0 1 1 342.44171,197.64687 z" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 109.09647,228.07771 L 137.38075,156.35687 L 176.7767,156.35687" + id="path3219" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="177.94707" + y="158.76218" + id="text3221"><tspan + sodipodi:role="line" + x="177.94707" + y="158.76218" + id="tspan3229">vertical header</tspan></text> + <path + sodipodi:type="arc" + style="fill:#000000;fill-opacity:1" + id="path3233" + sodipodi:cx="109.03334" + sodipodi:cy="228.26711" + sodipodi:rx="1.4520943" + sodipodi:ry="1.3258252" + d="M 110.48543,228.26711 A 1.4520943,1.3258252 0 1 1 107.58125,228.26711 A 1.4520943,1.3258252 0 1 1 110.48543,228.26711 z" /> + <path + sodipodi:type="arc" + id="path3239" + style="fill:#000000;stroke:none" + sodipodi:cx="608.61688" + sodipodi:cy="466.47372" + sodipodi:rx="1.5" + sodipodi:ry="1.5" + d="M 610.11688,466.47372 A 1.5,1.5 0 1 1 607.11688,466.47372 A 1.5,1.5 0 1 1 610.11688,466.47372 z" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 608.61691,466.47371 C 679.32759,523.04225 576.29203,608.40014 576.29203,608.40014 C 576.29203,608.40014 594.00783,590.22921 587.58437,566.25655 C 581.16091,542.28388 564.87674,543.54891 564.87674,543.54891 L 565.68543,542.74022" + id="path3241" /> + <path + sodipodi:type="arc" + id="path3243" + style="fill:#000000;stroke:none" + sodipodi:cx="565.18036" + sodipodi:cy="543.49786" + sodipodi:rx="1.5" + sodipodi:ry="1.5" + d="M 566.68036,543.49786 A 1.5,1.5 0 1 1 563.68036,543.49786 A 1.5,1.5 0 1 1 566.68036,543.49786 z" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 576.78572,607.8979 C 576.78572,607.8979 585.44643,599.23718 576.78572,607.8979 z" + id="path3247" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="435.89288" + y="615.66577" + id="text3251"><tspan + sodipodi:role="line" + id="tspan3253" + x="435.89288" + y="615.66577">scrollbars</tspan></text> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 536.70668,615.02926 L 559.18257,614.96613 C 559.18257,614.96613 569.50507,615.1871 576.48143,608.21073" + id="path3257" /> + <path + sodipodi:type="arc" + id="path3261" + style="fill:#000000;stroke:none" + sodipodi:cx="198.74751" + sodipodi:cy="310.65768" + sodipodi:rx="1.5" + sodipodi:ry="1.5" + d="M 200.24751,310.65768 A 1.5,1.5 0 1 1 197.24751,310.65768 A 1.5,1.5 0 1 1 200.24751,310.65768 z" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 198.74751,310.65768 C 301.278,280.60564 301.278,280.60564 301.278,280.60564 L 333.85542,280.60564" + id="path3263" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + x="337.64349" + y="281.36328" + id="text3265"><tspan + sodipodi:role="line" + id="tspan3267" + x="337.64349" + y="281.36328">second QTableView</tspan></text> + </g> +</svg> diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc index 184ac27..1f20b91 100644 --- a/doc/src/examples.qdoc +++ b/doc/src/examples.qdoc @@ -172,6 +172,7 @@ \o \l{itemviews/dirview}{Dir View} \o \l{itemviews/editabletreemodel}{Editable Tree Model}\raisedaster \o \l{itemviews/fetchmore}{Fetch More}\raisedaster + \o \l{itemviews/frozencolumn}{Frozen Column}\raisedaster \o \l{itemviews/pixelator}{Pixelator}\raisedaster \o \l{itemviews/puzzle}{Puzzle} \o \l{itemviews/simpledommodel}{Simple DOM Model}\raisedaster diff --git a/doc/src/examples/frozencolumn.qdoc b/doc/src/examples/frozencolumn.qdoc new file mode 100644 index 0000000..e5a3b59 --- /dev/null +++ b/doc/src/examples/frozencolumn.qdoc @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example itemviews/frozencolumn + \title Frozen Column Example + + This example demonstrates how to freeze a column within a QTableView. + + \image frozencolumn-example.png "Screenshot of the example" + + We use Qt's model/view framework to implement a table with its first + column frozen. This technique can be aplied to several columns or rows, + as long as they are on the edge of the table. + + The model/view framework allows for one model to be displayed in different + ways using multiple views. For this example, we use two views on the same + model - two \l {QTableView}{table views} sharing one model. The frozen + column is a child of the main tableview, and we provide the desired visual + effect using an overlay technique which will be described step by step in + the coming sections. + + \image frozencolumn-tableview.png + + + \section1 FreezeTableWidget Class Definition + + The \c FreezeTableWidget class has a constructor and a destructor. Also, it + has two private members: the table view that we will use as an overlay, and + the shared model for both table views. Two slots are added to help keep the + section sizes in sync, as well as a function to readjust the frozen + column's geometry. In addition, we reimplement two functions: + \l{QAbstractItemView::}{resizeEvent()} and \l{QTableView::}{moveCursor()}. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.h Widget definition + + \note QAbstractItemView is \l{QTableView}'s ancestor. + + + \section1 FreezeTableWidget Class Implementation + + The constructor takes \a model as an argument and creates a table view that + we will use to display the frozen column. Then, within the constructor, we + invoke the \c init() function to set up the frozen column. Finally, we + connect the \l{QHeaderView::sectionResized()} signals (for horizontal and + vertical headers) to the appropriate slots. This ensures that our frozen + column's sections are in sync with the headers. We also connect the + vertical scrollbars together so that the frozen column scrolls vertically + with the rest of our table. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp constructor + + + In the \c init() function, we ensure that the overlay table view + responsible for displaying the frozen column, is set up properly. This + means that this table view, \c frozenTableView, has to have the same model + as the main table view. However, the difference here is: \c frozenTableView's + only visible column is its first column; we hide the others using + \l{QTableView::}{setColumnHidden()} + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp init part1 + + + In terms of the frozen column's z-order, we stack it on top of the + viewport. This is achieved by calling \l{QWidget::}{stackUnder()} on the + viewport. For appearance's sake, we prevent the column from stealing focus + from the main tableview. Also, we make sure that both views share the same + selection model, so only one cell can be selected at a time. A few other + tweaks are done to make our application look good and behave consistently + with the main tableview. Note that we called \c updateFrozenTableGeometry() + to make the column occupy the correct spot. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp init part2 + + When you resize the frozen column, the same column on the main table view + must resize accordingly, to provide seamless integration. This is + accomplished by getting the new size of the column from the \c newSize + value from the \l{QHeaderView::}{sectionResized()} signal, emitted by both + the horizontal and vertical header. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp sections + + Since the width of the frozen column is modified, we adjust the geometry of + the widget accordingly by invoking \c updateFrozenTableGeometry(). This + function is further explained below. + + In our reimplementation of QTableView::resizeEvent(), we call + \c updateFrozenTableGeometry() after invoking the base class + implementation. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp resize + + When navigating around the table with the keyboard, we need to ensure that + the current selection does not disappear behind the frozen column. To + synchronize this, we reimplement QTableView::moveCursor() and adjust the + scrollbar positions if needed, after calling the base class implementation. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp navigate + + The frozen column's geometry calculation is based on the geometry of the + table underneath, so it always appears in the right place. Using the + QFrame::frameWidth() function helps to calculate this geometry correctly, + no matter which style is used. We rely on the geometry of the viewport and + headers to set the boundaries for the frozen column. + + \snippet examples/itemviews/frozencolumn/freezetablewidget.cpp geometry + +*/ + diff --git a/doc/src/images/frozencolumn-example.png b/doc/src/images/frozencolumn-example.png Binary files differnew file mode 100644 index 0000000..66b5c10 --- /dev/null +++ b/doc/src/images/frozencolumn-example.png diff --git a/doc/src/images/frozencolumn-tableview.png b/doc/src/images/frozencolumn-tableview.png Binary files differnew file mode 100644 index 0000000..d829ff5 --- /dev/null +++ b/doc/src/images/frozencolumn-tableview.png diff --git a/doc/src/modules.qdoc b/doc/src/modules.qdoc index d47b1e6..947304f 100644 --- a/doc/src/modules.qdoc +++ b/doc/src/modules.qdoc @@ -55,6 +55,7 @@ \row \o \l{QtGui} \o Graphical user interface (GUI) components \row \o \l{QtNetwork} \o Classes for network programming \row \o \l{QtOpenGL} \o OpenGL support classes + \row \o \l{QtOpenVG} \o OpenVG support classes \row \o \l{QtScript} \o Classes for evaluating Qt Scripts \row \o \l{QtScriptTools} \o Additional Qt Script components \row \o \l{QtSql} \o Classes for database integration using SQL diff --git a/doc/src/qtopengl.qdoc b/doc/src/qtopengl.qdoc index 69d33bb..f60ef89 100644 --- a/doc/src/qtopengl.qdoc +++ b/doc/src/qtopengl.qdoc @@ -44,7 +44,7 @@ \title QtOpenGL Module \contentspage Qt's Modules \previouspage QtNetwork - \nextpage QtSql + \nextpage QtOpenVG \ingroup modules \brief The QtOpenGL module offers classes that make it easy to diff --git a/doc/src/qtopenvg.qdoc b/doc/src/qtopenvg.qdoc new file mode 100644 index 0000000..ad036ef --- /dev/null +++ b/doc/src/qtopenvg.qdoc @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \module QtOpenVG + \title QtOpenVG Module + \contentspage Qt's Modules + \previouspage QtOpenGL + \nextpage QtSql + \ingroup modules + + \brief The QtOpenVG module offers classes that make it easy to + use OpenVG in Qt applications. + + From the OpenVG 1.1 Specification: + + \quotation + + OpenVG is an application programming interface (API) for hardware-accelerated two- + dimensional vector and raster graphics developed under the auspices of the Khronos + Group (www.khronos.org). It provides a device-independent and vendor-neutral interface + for sophisticated 2D graphical applications, while allowing device manufacturers to + provide hardware acceleration where appropriate. + + \endquotation + + The specification, and a reference implementation of it are available from the + \l{http://www.khronos.org/registry/vg/}{Khronos Group}. + + \bold{Note:} Khronos and OpenVG are trademarks of The Khronos Group Inc. OpenGL is a + registered trademark, and OpenGL ES is a trademark, of Silicon Graphics, Inc. + + + The Qt OpenVG module makes it easy to use OpenVG in Qt applications. + */ diff --git a/doc/src/snippets/code/src_gui_painting_qpen.cpp b/doc/src/snippets/code/src_gui_painting_qpen.cpp index 538fa09..b5995f7 100644 --- a/doc/src/snippets/code/src_gui_painting_qpen.cpp +++ b/doc/src/snippets/code/src_gui_painting_qpen.cpp @@ -25,7 +25,7 @@ QVector<qreal> dashes; qreal space = 4; dashes << 1 << space << 3 << space << 9 << space - << 27 << space << 9; + << 27 << space << 9 << space; pen.setDashPattern(dashes); //! [2] @@ -36,6 +36,6 @@ QPen pen; QVector<qreal> dashes; qreal space = 4; dashes << 1 << space << 3 << space << 9 << space - << 27 << space << 9; + << 27 << space << 9 << space; pen.setDashPattern(dashes); //! [3] diff --git a/examples/declarative/minehunt/minehunt.pro b/examples/declarative/minehunt/minehunt.pro index 08b6254..01791b1 100644 --- a/examples/declarative/minehunt/minehunt.pro +++ b/examples/declarative/minehunt/minehunt.pro @@ -1,6 +1,7 @@ SOURCES = main.cpp QT += script declarative +contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl target.path = $$[QT_INSTALL_EXAMPLES]/declarative/minehunt sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minehunt.pro diff --git a/examples/itemviews/frozencolumn/freezetablewidget.cpp b/examples/itemviews/frozencolumn/freezetablewidget.cpp new file mode 100644 index 0000000..7a9a8df --- /dev/null +++ b/examples/itemviews/frozencolumn/freezetablewidget.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "freezetablewidget.h" + +//! [constructor] +FreezeTableWidget::FreezeTableWidget(QAbstractItemModel * model) +{ + setModel(model); + frozenTableView = new QTableView(this); + + init(); + + //connect the headers and scrollbars of both tableviews together + connect(horizontalHeader(),SIGNAL(sectionResized ( int ,int,int )), this, + SLOT(updateSectionWidth(int, int, int))); + connect(verticalHeader(),SIGNAL(sectionResized ( int ,int,int )), this, + SLOT(updateSectionHeight(int, int, int))); + + connect(frozenTableView->verticalScrollBar(), SIGNAL(valueChanged(int)), + verticalScrollBar(), SLOT(setValue(int))); + connect(verticalScrollBar(), SIGNAL(valueChanged(int)), + frozenTableView->verticalScrollBar(), SLOT(setValue(int))); + + +} +//! [constructor] + +FreezeTableWidget::~FreezeTableWidget() +{ + delete frozenTableView; +} + +//! [init part1] +void FreezeTableWidget::init() +{ + frozenTableView->setModel(model()); + frozenTableView->setFocusPolicy(Qt::NoFocus); + frozenTableView->verticalHeader()->hide(); + frozenTableView->horizontalHeader()->setResizeMode(QHeaderView::Fixed); + + viewport()->stackUnder(frozenTableView); +//! [init part1] + +//! [init part2] + frozenTableView->setStyleSheet("QTableView { border: none;" + "background-color: #8EDE21;}"); //for demo purposes + frozenTableView->setSelectionModel(selectionModel()); + for(int col=1; col<model()->columnCount(); col++) + frozenTableView->setColumnHidden(col, true); + + frozenTableView->setColumnWidth(0, columnWidth(0) ); + + frozenTableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + frozenTableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + frozenTableView->show(); + + updateFrozenTableGeometry(); + + setHorizontalScrollMode(ScrollPerPixel); + setVerticalScrollMode(ScrollPerPixel); + frozenTableView->setVerticalScrollMode(ScrollPerPixel); +} +//! [init part2] + + +//! [sections] +void FreezeTableWidget::updateSectionWidth(int logicalIndex, int, int newSize) +{ + if(logicalIndex==0){ + frozenTableView->setColumnWidth(0,newSize); + updateFrozenTableGeometry(); + } +} + +void FreezeTableWidget::updateSectionHeight(int logicalIndex, int, int newSize) +{ + frozenTableView->setRowHeight(logicalIndex, newSize); +} +//! [sections] + + +//! [resize] +void FreezeTableWidget::resizeEvent(QResizeEvent * event) +{ + QTableView::resizeEvent(event); + updateFrozenTableGeometry(); + } +//! [resize] + + +//! [navigate] +QModelIndex FreezeTableWidget::moveCursor(CursorAction cursorAction, + Qt::KeyboardModifiers modifiers) +{ + QModelIndex current = QTableView::moveCursor(cursorAction, modifiers); + + if(cursorAction == MoveLeft && current.column()>0 + && visualRect(current).topLeft().x() < frozenTableView->columnWidth(0) ){ + + const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x() + - frozenTableView->columnWidth(0); + horizontalScrollBar()->setValue(newValue); + } + return current; +} +//! [navigate] + + +//! [geometry] +void FreezeTableWidget::updateFrozenTableGeometry() +{ + frozenTableView->setGeometry( verticalHeader()->width()+frameWidth(), + frameWidth(), columnWidth(0), + viewport()->height()+horizontalHeader()->height()); +} +//! [geometry] + + diff --git a/examples/itemviews/frozencolumn/freezetablewidget.h b/examples/itemviews/frozencolumn/freezetablewidget.h new file mode 100644 index 0000000..2abae47 --- /dev/null +++ b/examples/itemviews/frozencolumn/freezetablewidget.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef FREEZETABLEWIDGET_H +#define FREEZETABLEWIDGET_H + +#include <QTableView> + +//! [Widget definition] +class FreezeTableWidget : public QTableView { + Q_OBJECT + +public: + FreezeTableWidget(QAbstractItemModel * model); + ~FreezeTableWidget(); + + +protected: + virtual void resizeEvent(QResizeEvent *event); + virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers); + +private: + QTableView *frozenTableView; + void init(); + void updateFrozenTableGeometry(); + + +private slots: + void updateSectionWidth(int logicalIndex,int, int newSize); + void updateSectionHeight(int logicalIndex, int, int newSize); + +}; +//! [Widget definition] +#endif diff --git a/examples/itemviews/frozencolumn/frozencolumn.pro b/examples/itemviews/frozencolumn/frozencolumn.pro new file mode 100644 index 0000000..361de5b --- /dev/null +++ b/examples/itemviews/frozencolumn/frozencolumn.pro @@ -0,0 +1,9 @@ +HEADERS += freezetablewidget.h +SOURCES += main.cpp freezetablewidget.cpp +RESOURCES += grades.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/itemviews/frozencolumn +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/itemviews/frozencolumn +INSTALLS += target sources diff --git a/examples/itemviews/frozencolumn/grades.qrc b/examples/itemviews/frozencolumn/grades.qrc new file mode 100644 index 0000000..5f16d56 --- /dev/null +++ b/examples/itemviews/frozencolumn/grades.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/" > + <file>grades.txt</file> + </qresource> +</RCC> diff --git a/examples/itemviews/frozencolumn/grades.txt b/examples/itemviews/frozencolumn/grades.txt new file mode 100644 index 0000000..4b55b473 --- /dev/null +++ b/examples/itemviews/frozencolumn/grades.txt @@ -0,0 +1,35 @@ + France , Norway , YDS , UK(tech.), UK(adj.) , UIAA , Ger , Australia , Finland , Brazil + +1, , 5.2, , , I , I , , , Isup +2, , 5.3, , , II , II , 11, , II +3, 3, 5.4, , , III , III , 12, , IIsup +4, 4, 5.5, 4a , VD , IV , IV , 12, , III +5a , 5-, 5.6, , S , V- , V , 13, 5-, IIIsup +5b , 5, 5.7, 4b , HS , V , VI , 14, 5, IV + , , , 4c , , V+ , , 15, , +5c , 5+, 5.8, , VS , VI- , VIIa , 16, 5, IVsup +6a , 6-, 5.9, 5a , HVS , VI , VIIb , 17, , V +6a+ , 6-/6 , 5.10a , , E1 , VI+ , VIIc , 18, 6-, VI +6b , , 5.10b , 5b , , , , 19, , VI/VI+ +6b+ , 6, 5.10c , , E2 , VII- , VIIIa , 20, 6, VIsup/VI+ +6c , 6+, 5.10d , 5c , , VII , VIIIb , 21, , VIsup +6c+ , 7-, 5.11a , , E3 , VII+ , VIIIc , 22, 6, 7a +6c+ , 7, 5.11b , , , , , 23, , 7b +7a , 7+, 5.11c , 6a , E4 , VIII- , IXa , 24, 7-, 7c +7a , 7+/8- , 5.11d , , , VIII , IXb , , , 7c +7a+ , 8-, 5.12a , , E5 , VIII+ , IXc , 25, 7, 8a +7b , 8, 5.12b , 6b , , , , 26, 8-, 8b +7b+ , 8/8+ , 5.12c , , E6 , IX- , Xa , 27, 8, 8c +7c , 8+, 5.12d , 6c , , IX , Xb , 28, 8, 9a +7c+ , 9-, 5.13a , , E7 , IX+ , Xc , 29, 9-, 9b +8a , , 5.13b , , , , , , 9, 9c +8a+ , 9-/9 , 5.13c , 7a , , X- , , 30, 9, 10a +8b , 9, 5.13d , , E8 , X , , 31, 10-, 10b +8b+ , 9/9+ , 5.14a , , , X+ , , 32, 10, 10c +8c , 9+, 5.14b , 7b , , , , 33, 10, 11a +8c+ , 10-, 5.14c , , E9 , XI- , , 34, 11-, 11b +9a , 10, 5.14d , 7c , , XI , , 35, 11, 11c +9a+ , , 5.15a , , , XI+ , , , , 12a +9b , , 5.15b , , , , , , , 12b + +# Wikipedia contributors. Grade (climbing). Wikipedia, The Free Encyclopedia. May 15, 2009, 20:42 UTC. Available at: http://en.wikipedia.org/w/index.php?title=Grade_(climbing)&oldid=290165724. Accessed May 28, 2009. diff --git a/examples/itemviews/frozencolumn/main.cpp b/examples/itemviews/frozencolumn/main.cpp new file mode 100644 index 0000000..fdefd73 --- /dev/null +++ b/examples/itemviews/frozencolumn/main.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QApplication> +#include <QStandardItemModel> +#include <QFile> + +#include "freezetablewidget.h" + +int main( int argc, char** argv ) +{ + + Q_INIT_RESOURCE(grades); + + + QApplication app( argc, argv ); + QStandardItemModel *model=new QStandardItemModel(); + + + QFile file(":/grades.txt"); + QString line; + QStringList list; + if (file.open(QFile::ReadOnly)) { + line = file.readLine(200); + list= line.simplified().split(","); + model->setHorizontalHeaderLabels(list); + + int row=0; + QStandardItem *newItem=0; + while(file.canReadLine()){ + line = file.readLine(200); + if(!line.startsWith("#") && line.contains(",")){ + list= line.simplified().split(","); + for(int col=0; col<list.length(); col++){ + newItem = new QStandardItem(list.at(col)); + model->setItem(row ,col, newItem); + } + row++; + } + } + } + file.close(); + + FreezeTableWidget *tableView = new FreezeTableWidget(model); + + tableView->setWindowTitle(QObject::tr("Frozen Column Example")); + tableView->resize(560,680); + tableView->show(); + return app.exec(); +} + diff --git a/examples/itemviews/itemviews.pro b/examples/itemviews/itemviews.pro index 6202bbc..7dcf0f6 100644 --- a/examples/itemviews/itemviews.pro +++ b/examples/itemviews/itemviews.pro @@ -8,6 +8,7 @@ SUBDIRS = addressbook \ dirview \ editabletreemodel \ fetchmore \ + frozencolumn \ pixelator \ puzzle \ simpledommodel \ diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index ff87c74..fa84841 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -13,12 +13,15 @@ QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] QMAKE_INCDIR_OPENGL = /usr/X11R6/include QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib +QMAKE_INCDIR_EGL = +QMAKE_LIBDIR_EGL = QMAKE_LIBS = QMAKE_LIBS_DYNLOAD = -ldl QMAKE_LIBS_X11 = -lXext -lX11 -lm QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_NIS = -lnsl +QMAKE_LIBS_EGL = -lEGL QMAKE_LIBS_OPENGL = -lGLU -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread diff --git a/mkspecs/features/egl.prf b/mkspecs/features/egl.prf new file mode 100644 index 0000000..22002c3 --- /dev/null +++ b/mkspecs/features/egl.prf @@ -0,0 +1,3 @@ +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBDIR_EGL): LIBS += -L$$QMAKE_LIBDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 02336af..9d6a884 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -36,7 +36,7 @@ INCLUDEPATH = $$QMAKE_INCDIR_QT $$INCLUDEPATH #prepending prevents us from picki win32:INCLUDEPATH += $$QMAKE_INCDIR_QT/ActiveQt # As order does matter for static libs, we reorder the QT variable here -TMPLIBS = declarative webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml opengl gui network core +TMPLIBS = declarative webkit phonon dbus testlib script scripttools svg qt3support sql xmlpatterns xml opengl openvg gui network core for(QTLIB, $$list($$TMPLIBS)) { contains(QT, $$QTLIB): QT_ORDERED += $$QTLIB } @@ -140,6 +140,7 @@ for(QTLIB, $$list($$lower($$unique(QT)))) { else:isEqual(QTLIB, xml):qlib = QtXml else:isEqual(QTLIB, xmlpatterns):qlib = QtXmlPatterns else:isEqual(QTLIB, opengl):qlib = QtOpenGL + else:isEqual(QTLIB, openvg):qlib = QtOpenVG else:isEqual(QTLIB, sql):qlib = QtSql else:isEqual(QTLIB, core):qlib = QtCore else:isEqual(QTLIB, canvas):qlib = QtCanvas diff --git a/mkspecs/features/unix/openvg.prf b/mkspecs/features/unix/openvg.prf new file mode 100644 index 0000000..7bd7fbe --- /dev/null +++ b/mkspecs/features/unix/openvg.prf @@ -0,0 +1,3 @@ +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): QMAKE_LIBDIR += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $QMAKE_LIBS_OPENVG diff --git a/mkspecs/features/win32/openvg.prf b/mkspecs/features/win32/openvg.prf new file mode 100644 index 0000000..d4aa296 --- /dev/null +++ b/mkspecs/features/win32/openvg.prf @@ -0,0 +1,3 @@ +QMAKE_LIBS += $$QMAKE_LIBS_OPENVG +QMAKE_LFLAGS += $$QMAKE_LFLAGS_OPENVG + diff --git a/mkspecs/linux-g++-x11egl/qmake.conf b/mkspecs/linux-g++-x11egl/qmake.conf index e9e5abc..50c1d68 100644 --- a/mkspecs/linux-g++-x11egl/qmake.conf +++ b/mkspecs/linux-g++-x11egl/qmake.conf @@ -12,6 +12,10 @@ include(../common/g++.conf) include(../common/linux.conf)
load(qt_config)
+QMAKE_INCDIR_EGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
+QMAKE_LIBDIR_EGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/LinuxPC/Lib
+QMAKE_LIBS_EGL = -lGLESv2 -lEGL
+
QMAKE_INCDIR_OPENGL = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
QMAKE_INCDIR_OPENGL_QT = $(HOME)/opengles2/SDKPackage/Builds/OGLES2/Include
diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index c80d73b..896e3b8 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -36,7 +36,10 @@ #include <QMetaEnum> #include <QUrl> #include <QEvent> -#include <phonon> + +#include <Phonon/AudioOutput> +#include <Phonon/MediaObject> +#include <Phonon/VideoWidget> using namespace Phonon; diff --git a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp b/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp index 5691c9c..76f20b1 100644 --- a/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp +++ b/src/3rdparty/webkit/WebCore/plugins/mac/PluginViewMac.cpp @@ -397,7 +397,10 @@ void PluginView::updatePluginWidget() IntRect oldWindowRect = m_windowRect; IntRect oldClipRect = m_clipRect; - m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); + m_windowRect = frameView->contentsToWindow(frameRect()); + IntPoint offset = topLevelOffsetFor(platformPluginWidget()); + m_windowRect.move(offset.x(), offset.y()); + m_clipRect = windowClipRect(); m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); @@ -624,10 +627,6 @@ Point PluginView::globalMousePosForPlugin() const Point pos; GetGlobalMouse(&pos); - IntPoint offset = topLevelOffsetFor(platformPluginWidget()); - pos.h -= offset.x(); - pos.v -= offset.y(); - float scaleFactor = tigerOrBetter() ? HIGetScaleFactor() : 1; pos.h = short(pos.h * scaleFactor); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index c0508c8..fe6f64f 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -279,6 +279,10 @@ namespace QT_NAMESPACE {} # endif #endif +#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) +#error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." +#endif + #if defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN) # undef Q_OS_UNIX #elif !defined(Q_OS_UNIX) @@ -1148,6 +1152,11 @@ class QDataStream; # else # define Q_OPENGL_EXPORT Q_DECL_IMPORT # endif +# if defined(QT_BUILD_OPENVG_LIB) +# define Q_OPENVG_EXPORT Q_DECL_EXPORT +# else +# define Q_OPENVG_EXPORT Q_DECL_IMPORT +# endif # if defined(QT_BUILD_XML_LIB) # define Q_XML_EXPORT Q_DECL_EXPORT # else @@ -1188,6 +1197,7 @@ class QDataStream; # define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT # define Q_CANVAS_EXPORT Q_DECL_IMPORT # define Q_OPENGL_EXPORT Q_DECL_IMPORT +# define Q_OPENVG_EXPORT Q_DECL_IMPORT # define Q_XML_EXPORT Q_DECL_IMPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_IMPORT # define Q_SCRIPT_EXPORT Q_DECL_IMPORT @@ -1214,6 +1224,7 @@ class QDataStream; # define Q_SVG_EXPORT Q_DECL_EXPORT # define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT # define Q_OPENGL_EXPORT Q_DECL_EXPORT +# define Q_OPENVG_EXPORT Q_DECL_EXPORT # define Q_XML_EXPORT Q_DECL_EXPORT # define Q_XMLPATTERNS_EXPORT Q_DECL_EXPORT # define Q_SCRIPT_EXPORT Q_DECL_EXPORT @@ -2260,7 +2271,8 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #define QT_MODULE_TEST 0x04000 #define QT_MODULE_DBUS 0x08000 #define QT_MODULE_SCRIPTTOOLS 0x10000 -#define QT_MODULE_DECLARATIVE 0x20000 +#define QT_MODULE_OPENVG 0x20000 +#define QT_MODULE_DECLARATIVE 0x40000 /* Qt editions */ #define QT_EDITION_CONSOLE (QT_MODULE_CORE \ @@ -2280,6 +2292,7 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); | QT_MODULE_GUI \ | QT_MODULE_NETWORK \ | QT_MODULE_OPENGL \ + | QT_MODULE_OPENVG \ | QT_MODULE_SQL \ | QT_MODULE_XML \ | QT_MODULE_XMLPATTERNS \ @@ -2324,6 +2337,9 @@ QT_LICENSED_MODULE(Network) #if (QT_EDITION & QT_MODULE_OPENGL) QT_LICENSED_MODULE(OpenGL) #endif +#if (QT_EDITION & QT_MODULE_OPENVG) +QT_LICENSED_MODULE(OpenVG) +#endif #if (QT_EDITION & QT_MODULE_SQL) QT_LICENSED_MODULE(Sql) #endif diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 144436c..4743a47 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -558,24 +558,8 @@ static bool _q_isMacHidden(const QString &path) FSRef fsRef; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), - kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); - } else -#endif - { - QFileInfo fi(path); - FSRef parentRef; - err = FSPathMakeRef(reinterpret_cast<const UInt8 *>(fi.absoluteDir().absolutePath().toUtf8().constData()), - &parentRef, 0); - if (err == noErr) { - QString fileName = fi.fileName(); - err = FSMakeFSRefUnicode(&parentRef, fileName.length(), - reinterpret_cast<const UniChar *>(fileName.unicode()), - kTextEncodingUnknown, &fsRef); - } - } + err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), + kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); if (err != noErr) return false; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index b0247f8..e6a471c 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -643,8 +643,8 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) /*! Sends \a event to \a receiver: \a {receiver}->event(\a event). Returns the value that is returned from the receiver's event - handler. Note that this function is called for all events send to - any object is all threads. + handler. Note that this function is called for all events sent to + any object in any thread. For certain types of events (e.g. mouse and key events), the event will be propagated to the receiver's parent and so on up to diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index fd7ddef..83dd869 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -240,7 +240,7 @@ void QState::assignProperty(QObject *object, const char *name, } /*! - Returns this state group's error state. + Returns this state's error state. \sa QStateMachine::errorState(), QStateMachine::setErrorState() */ @@ -253,7 +253,9 @@ QAbstractState *QState::errorState() const /*! Sets this state's error state to be the given \a state. If the error state is not set, or if it is set to 0, the state will inherit its parent's error - state recursively. + state recursively. If no error state is set for the state itself or any of + its ancestors, an error will cause the machine to stop executing and an error + will be printed to the console. \sa QStateMachine::setErrorState(), QStateMachine::errorState() */ diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 682dd97..bf3ee31 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -156,16 +156,14 @@ QT_BEGIN_NAMESPACE transitions, e.g., \l{QSignalTransition}s as in this example. See the QState class description for further details. - If an error is encountered, the machine will enter the - \l{errorState}{error state}, which is a special state created by - the machine. The types of errors possible are described by the + If an error is encountered, the machine will look for an + \l{errorState}{error state}, and if one is available, it will + enter this state. The types of errors possible are described by the \l{QStateMachine::}{Error} enum. After the error state is entered, the type of the error can be retrieved with error(). The execution - of the state graph will not stop when the error state is entered. - So it is possible to handle the error, for instance, by connecting - to the \l{QAbstractState::}{entered()} signal of the error state. - It is also possible to set a custom error state with - setErrorState(). + of the state graph will not stop when the error state is entered. If + no error state applies to the erroneous state, the machine will stop + executing and an error message will be printed to the console. \omit This stuff will be moved elsewhere This is @@ -238,7 +236,6 @@ QStateMachinePrivate::QStateMachinePrivate() error = QStateMachine::NoError; globalRestorePolicy = QStateMachine::DoNotRestoreProperties; rootState = 0; - initialErrorStateForRoot = 0; signalEventGenerator = 0; #ifndef QT_NO_ANIMATION animationsEnabled = true; @@ -984,27 +981,25 @@ void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArra QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) { - // If the user sets the root state's error state to 0, we return the initial error state - if (context == 0) - return initialErrorStateForRoot; - // Find error state recursively in parent hierarchy if not set explicitly for context state QAbstractState *errorState = 0; - - QState *s = qobject_cast<QState*>(context); - if (s) - errorState = s->errorState(); + if (context != 0) { + QState *s = qobject_cast<QState*>(context); + if (s != 0) + errorState = s->errorState(); - if (!errorState) - errorState = findErrorState(context->parentState()); + if (errorState == 0) + errorState = findErrorState(context->parentState()); + } return errorState; } void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext) { + Q_Q(QStateMachine); + error = errorCode; - switch (errorCode) { case QStateMachine::NoInitialStateError: Q_ASSERT(currentContext != 0); @@ -1036,16 +1031,19 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta QAbstractState *currentErrorState = findErrorState(currentContext); // Avoid infinite loop if the error state itself has an error - if (currentContext == currentErrorState) { - Q_ASSERT(currentContext != initialErrorStateForRoot); // RootErrorState is broken - currentErrorState = initialErrorStateForRoot; - } + if (currentContext == currentErrorState) + currentErrorState = 0; - Q_ASSERT(currentErrorState != 0); Q_ASSERT(currentErrorState != rootState); - - QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); - addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); + + if (currentErrorState != 0) { + QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); + addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); + } else { + qWarning("Unrecoverable error detected in running state machine: %s", + qPrintable(errorString)); + q->stop(); + } } #ifndef QT_NO_ANIMATION @@ -1148,9 +1146,6 @@ void QStateMachinePrivate::_q_start() return; } QAbstractState *initial = rootState->initialState(); - if (initial == 0) - setError(QStateMachine::NoInitialStateError, rootState); - configuration.clear(); qDeleteAll(internalEventQueue); internalEventQueue.clear(); @@ -1483,27 +1478,6 @@ QStateMachine::~QStateMachine() namespace { -class RootErrorState : public QAbstractState -{ -public: - RootErrorState(QState *parent) - : QAbstractState(parent) - { - setObjectName(QString::fromLatin1("DefaultErrorState")); - } - - void onEntry(QEvent *) - { - QAbstractStatePrivate *d = QAbstractStatePrivate::get(this); - QStateMachine *machine = d->machine(); - - qWarning("Unrecoverable error detected in running state machine: %s", - qPrintable(machine->errorString())); - } - - void onExit(QEvent *) {} -}; - class RootState : public QState { public: @@ -1526,9 +1500,7 @@ QState *QStateMachine::rootState() const Q_D(const QStateMachine); if (!d->rootState) { const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0); - const_cast<QStateMachinePrivate*>(d)->initialErrorStateForRoot = new RootErrorState(d->rootState); d->rootState->setParent(const_cast<QStateMachine*>(this)); - d->rootState->setErrorState(d->initialErrorStateForRoot); } return d->rootState; } @@ -1552,17 +1524,13 @@ QAbstractState *QStateMachine::errorState() const If the erroneous state has an error state set, this will be entered by the machine. If no error state has been set, the state machine will search the parent hierarchy recursively for an error state. The error state of the root state can thus be seen as a global error state that - applies for the states for which a more specific error state has not been set. + applies for all states for which a more specific error state has not been set. Before entering the error state, the state machine will set the error code returned by error() and - error message returned by errorString(). - - The default error state will print a warning to the console containing the information returned by - errorString(). By setting a new error state on either the state machine itself, or on specific - states, you can fine tune error handling in the state machine. + error message returned by errorString(). - If the root state's error state is set to 0, or if the error state selected by the machine itself - contains an error, the default error state will be used. + If there is no error state available for the erroneous state, the state machine will print a + warning message on the console and stop executing. \sa QState::setErrorState(), rootState() */ diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index f3c6a27..1335b93 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -175,7 +175,6 @@ public: QString errorString; QSet<QAbstractState *> pendingErrorStates; QSet<QAbstractState *> pendingErrorStatesForDefaultEntry; - QAbstractState *initialErrorStateForRoot; #ifndef QT_NO_ANIMATION bool animationsEnabled; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index cbdd32c..8c1a0ff 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -1011,21 +1011,17 @@ static QString macMonthName(int month, bool short_format) if (month < 0 || month > 11) return QString(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDateFormatterRef> formatter - = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), - kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); - QCFType<CFArrayRef> values - = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, - short_format ? kCFDateFormatterShortMonthSymbols - : kCFDateFormatterMonthSymbols)); - if (values != 0) { - CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month)); - return QCFString::toQString(cfstring); - } + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values + = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortMonthSymbols + : kCFDateFormatterMonthSymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month)); + return QCFString::toQString(cfstring); } -#endif return QString(); } @@ -1035,20 +1031,16 @@ static QString macDayName(int day, bool short_format) if (day < 1 || day > 7) return QString(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDateFormatterRef> formatter - = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), - kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); - QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, - short_format ? kCFDateFormatterShortWeekdaySymbols - : kCFDateFormatterWeekdaySymbols)); - if (values != 0) { - CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7)); - return QCFString::toQString(cfstring); - } + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortWeekdaySymbols + : kCFDateFormatterWeekdaySymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7)); + return QCFString::toQString(cfstring); } -#endif return QString(); } diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 2082794..b4fe070 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2154,48 +2154,42 @@ bool QRectF::contains(const QRectF &r) const QRectF QRectF::operator|(const QRectF &r) const { - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - if (l1 == r1) // null rect + if (isNull()) return r; + if (r.isNull()) + return *this; - qreal l2 = r.xp; - qreal r2 = r.xp; - if (r.w < 0) - l2 += r.w; + qreal left = xp; + qreal right = xp; + if (w < 0) + left += w; else - r2 += r.w; - if (l2 == r2) // null rect - return *this; + right += w; - qreal t1 = yp; - qreal b1 = yp; + if (r.w < 0) { + left = qMin(left, r.xp + r.w); + right = qMax(right, r.xp); + } else { + left = qMin(left, r.xp); + right = qMax(right, r.xp + r.w); + } + + qreal top = yp; + qreal bottom = yp; if (h < 0) - t1 += h; + top += h; else - b1 += h; - if (t1 == b1) // null rect - return r; + bottom += h; - qreal t2 = r.yp; - qreal b2 = r.yp; - if (r.h < 0) - t2 += r.h; - else - b2 += r.h; - if (t2 == b2) // null rect - return *this; + if (r.h < 0) { + top = qMin(top, r.yp + r.h); + bottom = qMax(bottom, r.yp); + } else { + top = qMin(top, r.yp); + bottom = qMax(bottom, r.yp + r.h); + } - QRectF tmp; - tmp.xp = qMin(l1, l2); - tmp.yp = qMin(t1, t2); - tmp.w = qMax(r1, r2) - tmp.xp; - tmp.h = qMax(b1, b2) - tmp.yp; - return tmp; + return QRectF(left, top, right - left, bottom - top); } /*! diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 0740fe5..efdc24d 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -653,7 +653,7 @@ inline QRectF::QRectF(const QRect &r) } inline bool QRectF::isNull() const -{ return qIsNull(w) && qIsNull(h); } +{ return w == 0. && h == 0.; } inline bool QRectF::isEmpty() const { return w <= 0. || h <= 0.; } diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm index 65f9ab9..5646300 100644 --- a/src/gui/accessible/qaccessible_mac.mm +++ b/src/gui/accessible/qaccessible_mac.mm @@ -1232,10 +1232,8 @@ static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute return QAccessible::Value; else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) return QAccessible::Help; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) return QAccessible::Description; -#endif else return -1; } @@ -1442,17 +1440,13 @@ static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interfac qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute)); qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute)); qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute)); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute)); -#endif // Append these names if the QInterafceItem returns any data for them. appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface); appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface); appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface); -#endif appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface); appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface); appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface); @@ -1705,12 +1699,10 @@ static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef eve Returns the top-level window for an interface, which is the closest ancestor interface that has the Window role. (Can also be a sheet or a drawer) */ -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface) { return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute)); } -#endif /* Returns the tab buttons for an interface. @@ -1888,10 +1880,8 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) { return handleChildrenAttribute(next_ref, event, interface); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) { return handleTopLevelUIElementAttribute(next_ref, event, interface); -#endif } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) { return handleWindowAttribute(next_ref, event, interface); } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) { @@ -1981,7 +1971,7 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) { return handleSubroleAttribute(next_ref, event, interface); } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) && !defined(QT_MAC_USE_COCOA) +#if !defined(QT_MAC_USE_COCOA) if (HICopyAccessibilityRoleDescription) { const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0); SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, @@ -2005,14 +1995,12 @@ static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, } else { handleStringAttribute(event, text, interface); } -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) { const QAccessible::Role role = interface.role(); const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var); handleStringAttribute(event, text, interface); } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) { return CallNextEventHandler(next_ref, event); -#endif } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) { const QAccessible::Role role = interface.role(); const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var); diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm index 9c7a09b..1936de5 100644 --- a/src/gui/dialogs/qcolordialog_mac.mm +++ b/src/gui/dialogs/qcolordialog_mac.mm @@ -54,11 +54,19 @@ typedef float CGFloat; // Should only not be defined on 32-bit platforms #endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 +@protocol NSWindowDelegate <NSObject> +- (void)windowDidResize:(NSNotification *)notification; +- (BOOL)windowShouldClose:(id)window; +@end +#endif + QT_USE_NAMESPACE @class QCocoaColorPanelDelegate; -@interface QCocoaColorPanelDelegate : NSObject { +@interface QCocoaColorPanelDelegate : NSObject<NSWindowDelegate> { NSColorPanel *mColorPanel; NSView *mStolenContentView; NSButton *mOkButton; @@ -74,8 +82,6 @@ QT_USE_NAMESPACE okButton:(NSButton *)okButton cancelButton:(NSButton *)cancelButton priv:(QColorDialogPrivate *)priv; -- (BOOL)windowShouldClose:(id)window; -- (void)windowDidResize:(NSNotification *)notification; - (void)colorChanged:(NSNotification *)notification; - (void)relayout; - (void)onOkClicked; diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index e7d2f43..3dc3c00 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -78,7 +78,9 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -@protocol NSWindowDelegate <NSObject> @end +@protocol NSWindowDelegate <NSObject> +- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; +@end #endif diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index b3fb0fd..b7fa420 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -45,6 +45,7 @@ #include <QtGui/qdialogbuttonbox.h> #include "private/qlabel_p.h" +#include "private/qapplication_p.h" #include <QtCore/qlist.h> #include <QtCore/qdebug.h> #include <QtGui/qstyle.h> @@ -73,8 +74,6 @@ extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp QT_BEGIN_NAMESPACE -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); - enum Button { Old_Ok = 1, Old_Cancel = 2, Old_Yes = 3, Old_No = 4, Old_Abort = 5, Old_Retry = 6, Old_Ignore = 7, Old_YesAll = 8, Old_NoAll = 9, Old_ButtonMask = 0xFF, NewButtonMask = 0xFFFFFC00 }; diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp index 2c1c2e3..3fdea54 100644 --- a/src/gui/dialogs/qwizard.cpp +++ b/src/gui/dialogs/qwizard.cpp @@ -560,6 +560,7 @@ public: void enableUpdates(); void _q_emitCustomButtonClicked(); void _q_updateButtonStates(); + void _q_handleFieldObjectDestroyed(QObject *); void setStyle(QStyle *style); #ifdef Q_WS_MAC static QPixmap findDefaultBackgroundPixmap(); @@ -731,6 +732,8 @@ void QWizardPrivate::cleanupPagesNotInHistory() void QWizardPrivate::addField(const QWizardField &field) { + Q_Q(QWizard); + QWizardField myField = field; myField.resolve(defaultPropertyTable); @@ -744,15 +747,23 @@ void QWizardPrivate::addField(const QWizardField &field) if (myField.mandatory && !myField.changedSignal.isEmpty()) QObject::connect(myField.object, myField.changedSignal, myField.page, SLOT(_q_maybeEmitCompleteChanged())); + QObject::connect( + myField.object, SIGNAL(destroyed(QObject *)), q, + SLOT(_q_handleFieldObjectDestroyed(QObject *))); } void QWizardPrivate::removeFieldAt(int index) { + Q_Q(QWizard); + const QWizardField &field = fields.at(index); fieldIndexMap.remove(field.name); if (field.mandatory && !field.changedSignal.isEmpty()) QObject::disconnect(field.object, field.changedSignal, field.page, SLOT(_q_maybeEmitCompleteChanged())); + QObject::disconnect( + field.object, SIGNAL(destroyed(QObject *)), q, + SLOT(_q_handleFieldObjectDestroyed(QObject *))); fields.remove(index); } @@ -1595,6 +1606,20 @@ void QWizardPrivate::_q_updateButtonStates() enableUpdates(); } +void QWizardPrivate::_q_handleFieldObjectDestroyed(QObject *object) +{ + QVector<QWizardField>::iterator it = fields.begin(); + while (it != fields.end()) { + const QWizardField &field = *it; + if (field.object == object) { + fieldIndexMap.remove(field.name); + it = fields.erase(it); + } else { + ++it; + } + } +} + void QWizardPrivate::setStyle(QStyle *style) { for (int i = 0; i < QWizard::NButtons; i++) @@ -1607,66 +1632,6 @@ void QWizardPrivate::setStyle(QStyle *style) #ifdef Q_WS_MAC -#ifdef Q_WS_MAC32 -QT_BEGIN_INCLUDE_NAMESPACE -#include <QuickTime/QuickTime.h> -QT_END_INCLUDE_NAMESPACE -typedef OSErr (*PtrQTNewDataReferenceFromCFURL)(CFURLRef, UInt32, Handle*, OSType*); -typedef OSErr (*PtrGetGraphicsImporterForDataRefWithFlags)(Handle, OSType, ComponentInstance*, long); -typedef ComponentResult (*PtrGraphicsImportSetFlags)(GraphicsImportComponent, long); -typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32); - -static PtrQTNewDataReferenceFromCFURL ptrQTNewDataReferenceFromCFURL = 0; -static PtrGetGraphicsImporterForDataRefWithFlags ptrGetGraphicsImporterForDataRefWithFlags = 0; -static PtrGraphicsImportSetFlags ptrGraphicsImportSetFlags = 0; -static PtrGraphicsImportCreateCGImage ptrGraphicsImportCreateCGImage = 0; - -static bool resolveQuickTimeSymbols() -{ - if (ptrQTNewDataReferenceFromCFURL == 0) { - QLibrary library(QLatin1String("/System/Library/Frameworks/QuickTime.framework/QuickTime")); - ptrQTNewDataReferenceFromCFURL = reinterpret_cast<PtrQTNewDataReferenceFromCFURL>(library.resolve("QTNewDataReferenceFromCFURL")); - ptrGetGraphicsImporterForDataRefWithFlags = reinterpret_cast<PtrGetGraphicsImporterForDataRefWithFlags>(library.resolve("GetGraphicsImporterForDataRefWithFlags")); - ptrGraphicsImportSetFlags = reinterpret_cast<PtrGraphicsImportSetFlags>(library.resolve("GraphicsImportSetFlags")); - ptrGraphicsImportCreateCGImage = reinterpret_cast<PtrGraphicsImportCreateCGImage>(library.resolve("GraphicsImportCreateCGImage")); - } - - return ptrQTNewDataReferenceFromCFURL != 0 && ptrGetGraphicsImporterForDataRefWithFlags != 0 - && ptrGraphicsImportSetFlags != 0 && ptrGraphicsImportCreateCGImage != 0; -} - - -static QPixmap quicktimeTiff(const CFURLRef url) -{ - if (!resolveQuickTimeSymbols()) - return QPixmap(); - - QCFType <CGImageRef> imageRef = 0; - Handle dataRef; - OSType dataRefType; - GraphicsImportComponent gi; - ComponentResult result; - result = ptrQTNewDataReferenceFromCFURL(url, 0, &dataRef, &dataRefType); - if (dataRef != 0) { - OSStatus err = ptrGetGraphicsImporterForDataRefWithFlags(dataRef, dataRefType, &gi, 0); - if (err == noErr && gi) { - result = ptrGraphicsImportSetFlags(gi, (kGraphicsImporterDontDoGammaCorrection - + kGraphicsImporterDontUseColorMatching)); - if (!result) - result = ptrGraphicsImportCreateCGImage(gi, &imageRef, 0); - if (result) - qWarning("Qt: Problem reading TIFF image %ld(%s:%d)", result, __FILE__, __LINE__); - DisposeHandle(dataRef); - CloseComponent(gi); - } - } - - if (imageRef) - return QPixmap::fromMacCGImageRef(imageRef); - return QPixmap(); -} -#endif // Q_WS_MAC32 - QPixmap QWizardPrivate::findDefaultBackgroundPixmap() { QCFType<CFURLRef> url; @@ -1678,22 +1643,13 @@ QPixmap QWizardPrivate::findDefaultBackgroundPixmap() if (bundle) { url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("tif"), 0); if (url) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0); - QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - if (image) { - int width = CGImageGetWidth(image); - int height = CGImageGetHeight(image); - if (width == ExpectedImageWidth && height == ExpectedImageHeight) - return QPixmap::fromMacCGImageRef(image); - } - } else -#endif - { -#ifdef Q_WS_MAC32 - return quicktimeTiff(url); -#endif + QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0); + QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); + if (image) { + int width = CGImageGetWidth(image); + int height = CGImageGetHeight(image); + if (width == ExpectedImageWidth && height == ExpectedImageHeight) + return QPixmap::fromMacCGImageRef(image); } } } diff --git a/src/gui/dialogs/qwizard.h b/src/gui/dialogs/qwizard.h index 1d1a9b5..d1f9cf7 100644 --- a/src/gui/dialogs/qwizard.h +++ b/src/gui/dialogs/qwizard.h @@ -197,6 +197,7 @@ private: Q_DECLARE_PRIVATE(QWizard) Q_PRIVATE_SLOT(d_func(), void _q_emitCustomButtonClicked()) Q_PRIVATE_SLOT(d_func(), void _q_updateButtonStates()) + Q_PRIVATE_SLOT(d_func(), void _q_handleFieldObjectDestroyed(QObject *)) friend class QWizardPage; }; diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri new file mode 100644 index 0000000..651507f --- /dev/null +++ b/src/gui/egl/egl.pri @@ -0,0 +1,28 @@ +HEADERS += \ + egl/qegl_p.h \ + egl/qeglproperties_p.h + +SOURCES += \ + egl/qegl.cpp \ + egl/qeglproperties.cpp + +contains(QT_CONFIG, wince*): SOURCES += egl/qegl_wince.cpp + +unix { + embedded { + SOURCES += egl/qegl_qws.cpp + } else { + symbian { + SOURCES += egl/qegl_symbian.cpp + } else { + SOURCES += egl/qegl_x11.cpp + } + } +} + +for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p +} + +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp new file mode 100644 index 0000000..89d9d1b --- /dev/null +++ b/src/gui/egl/qegl.cpp @@ -0,0 +1,403 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include <QtCore/qdebug.h> +#include "qegl_p.h" + +QT_BEGIN_NAMESPACE + +QEglContext::QEglContext() + : apiType(QEgl::OpenGL) + , dpy(EGL_NO_DISPLAY) + , ctx(EGL_NO_CONTEXT) + , surf(EGL_NO_SURFACE) + , cfg(0) + , share(false) + , current(false) + , reserved(0) +{ +} + +QEglContext::~QEglContext() +{ + destroy(); +} + +bool QEglContext::isValid() const +{ + return (ctx != EGL_NO_CONTEXT); +} + +bool QEglContext::isSharing() const +{ + return share; +} + +bool QEglContext::isCurrent() const +{ + return current; +} + +// Open the EGL display associated with "device". +bool QEglContext::openDisplay(QPaintDevice *device) +{ + if (dpy == EGL_NO_DISPLAY) + dpy = defaultDisplay(device); + return (dpy != EGL_NO_DISPLAY); +} + +// Choose a configuration that matches "properties". +bool QEglContext::chooseConfig + (const QEglProperties& properties, QEgl::PixelFormatMatch match) +{ + QEglProperties props(properties); + do { + // Get the number of matching configurations for this set of properties. + EGLint matching = 0; + if (!eglChooseConfig(dpy, props.properties(), 0, 256, &matching) || !matching) + continue; + + // If we want the best pixel format, then return the first + // matching configuration. + if (match == QEgl::BestPixelFormat) { + eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching); + if (matching < 1) + continue; + return true; + } + + // Fetch all of the matching configurations and find the + // first that matches the pixel format we wanted. + EGLint size = matching; + EGLConfig *configs = new EGLConfig [size]; + eglChooseConfig(dpy, props.properties(), configs, size, &matching); + for (EGLint index = 0; index < size; ++index) { + EGLint red, green, blue, alpha; + eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red); + eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green); + eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue); + eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha); + if (red == props.value(EGL_RED_SIZE) && + green == props.value(EGL_GREEN_SIZE) && + blue == props.value(EGL_BLUE_SIZE) && + (props.value(EGL_ALPHA_SIZE) == 0 || + alpha == props.value(EGL_ALPHA_SIZE))) { + cfg = configs[index]; + delete [] configs; + return true; + } + } + delete [] configs; + } while (props.reduceConfiguration()); + +#ifdef EGL_BIND_TO_TEXTURE_RGBA + // Don't report an error just yet if we failed to get a pbuffer + // configuration with texture rendering. Only report failure if + // we cannot get any pbuffer configurations at all. + if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE && + props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE) +#endif + { + qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration"; + qWarning() << "Requested:" << props.toString(); + qWarning() << "Available:"; + dumpAllConfigs(); + } + return false; +} + +// Create the EGLContext. +bool QEglContext::createContext(QEglContext *shareContext) +{ + // We need to select the correct API before calling eglCreateContext(). +#ifdef EGL_OPENGL_ES_API + if (apiType == QEgl::OpenGL) + eglBindAPI(EGL_OPENGL_ES_API); +#endif +#ifdef EGL_OPENVG_API + if (apiType == QEgl::OpenVG) + eglBindAPI(EGL_OPENVG_API); +#endif + + // Create a new context for the configuration. + QEglProperties contextProps; +#if defined(QT_OPENGL_ES_2) + if (apiType == QEgl::OpenGL) + contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); +#endif + if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) + shareContext = 0; + if (shareContext) { + ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties()); + if (ctx == EGL_NO_CONTEXT) { + qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); + shareContext = 0; + } + } + if (ctx == EGL_NO_CONTEXT) { + ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties()); + if (ctx == EGL_NO_CONTEXT) { + qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError()); + return false; + } + } + share = (shareContext != 0); + return true; +} + +// Recreate the surface for a paint device because the native id has changed. +bool QEglContext::recreateSurface(QPaintDevice *device) +{ + // Bail out if the surface has not been created for the first time yet. + if (surf == EGL_NO_SURFACE) + return true; + + // Destroy the old surface. + eglDestroySurface(dpy, surf); + surf = EGL_NO_SURFACE; + + // Create a new one. + return createSurface(device); +} + +// Destroy the EGL surface object. +void QEglContext::destroySurface() +{ + if (surf != EGL_NO_SURFACE) { + eglDestroySurface(dpy, surf); + surf = EGL_NO_SURFACE; + } +} + +// Destroy the context. Note: this does not destroy the surface. +void QEglContext::destroy() +{ + if (ctx != EGL_NO_CONTEXT) + eglDestroyContext(dpy, ctx); + dpy = EGL_NO_DISPLAY; + ctx = EGL_NO_CONTEXT; + surf = EGL_NO_SURFACE; + cfg = 0; + share = false; +} + +bool QEglContext::makeCurrent() +{ + if (ctx == EGL_NO_CONTEXT) { + qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; + return false; + } + + current = true; + + bool ok = eglMakeCurrent(dpy, surf, surf, ctx); + if (!ok) + qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError()); + return ok; +} + +bool QEglContext::doneCurrent() +{ + // If the context is invalid, we assume that an error was reported + // when makeCurrent() was called. + if (ctx == EGL_NO_CONTEXT) + return false; + + current = false; + + // We need to select the correct API before calling eglMakeCurrent() + // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG + // contexts active at the same time. +#ifdef EGL_OPENGL_ES_API + if (apiType == QEgl::OpenGL) + eglBindAPI(EGL_OPENGL_ES_API); +#endif +#ifdef EGL_OPENVG_API + if (apiType == QEgl::OpenVG) + eglBindAPI(EGL_OPENVG_API); +#endif + + bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ok) + qWarning() << "QEglContext::doneCurrent():" << errorString(eglGetError()); + return ok; +} + +bool QEglContext::swapBuffers() +{ + if(ctx == EGL_NO_CONTEXT) + return false; + + bool ok = eglSwapBuffers(dpy, surf); + if (!ok) + qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); + return ok; +} + +// Wait for native rendering operations to complete before starting +// to use OpenGL/OpenVG operations. +void QEglContext::waitNative() +{ +#ifdef EGL_CORE_NATIVE_ENGINE + eglWaitNative(EGL_CORE_NATIVE_ENGINE); +#endif +} + +// Wait for client OpenGL/OpenVG operations to complete before +// using native rendering operations. +void QEglContext::waitClient() +{ +#ifdef EGL_OPENGL_ES_API + if (apiType == QEgl::OpenGL) { + eglBindAPI(EGL_OPENGL_ES_API); + eglWaitClient(); + } +#else + if (apiType == QEgl::OpenGL) + eglWaitGL(); +#endif +#ifdef EGL_OPENVG_API + if (apiType == QEgl::OpenVG) { + eglBindAPI(EGL_OPENVG_API); + eglWaitClient(); + } +#endif +} + +// Query the actual size of the EGL surface. +QSize QEglContext::surfaceSize() const +{ + int w, h; + eglQuerySurface(dpy, surf, EGL_WIDTH, &w); + eglQuerySurface(dpy, surf, EGL_HEIGHT, &h); + return QSize(w, h); +} + +// Query the value of a configuration attribute. +bool QEglContext::configAttrib(int name, EGLint *value) const +{ + return eglGetConfigAttrib(dpy, cfg, name, value); +} + +// Retrieve all of the properties on "cfg". If zero, return +// the context's configuration. +QEglProperties QEglContext::configProperties(EGLConfig cfg) const +{ + if (!cfg) + cfg = config(); + QEglProperties props; + for (int name = 0x3020; name <= 0x304F; ++name) { + EGLint value; + if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value)) + props.setValue(name, value); + } + eglGetError(); // Clear the error state. + return props; +} + +// Initialize and return the default display. +EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device) +{ + static EGLDisplay dpy = EGL_NO_DISPLAY; + if (dpy == EGL_NO_DISPLAY) { + dpy = getDisplay(device); + if (dpy == EGL_NO_DISPLAY) { + qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display"; + return EGL_NO_DISPLAY; + } + if (!eglInitialize(dpy, NULL, NULL)) { + qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(eglGetError()); + return EGL_NO_DISPLAY; + } +#ifdef EGL_OPENGL_ES_API + eglBindAPI(EGL_OPENGL_ES_API); +#endif + } + return dpy; +} + +// Return the error string associated with a specific code. +QString QEglContext::errorString(EGLint code) +{ + static const char * const errors[] = { + "Success (0x3000)", // No tr + "Not initialized (0x3001)", // No tr + "Bad access (0x3002)", // No tr + "Bad alloc (0x3003)", // No tr + "Bad attribute (0x3004)", // No tr + "Bad config (0x3005)", // No tr + "Bad context (0x3006)", // No tr + "Bad current surface (0x3007)", // No tr + "Bad display (0x3008)", // No tr + "Bad match (0x3009)", // No tr + "Bad native pixmap (0x300A)", // No tr + "Bad native window (0x300B)", // No tr + "Bad parameter (0x300C)", // No tr + "Bad surface (0x300D)", // No tr + "Context lost (0x300E)" // No tr + }; + if (code >= 0x3000 && code <= 0x300E) { + return QString::fromLatin1(errors[code - 0x3000]); + } else { + return QLatin1String("0x") + QString::number(int(code), 16); + } +} + +// Dump all of the EGL configurations supported by the system. +void QEglContext::dumpAllConfigs() +{ + QEglProperties props; + EGLint count = 0; + if (!eglGetConfigs(dpy, 0, 0, &count) || count < 1) + return; + EGLConfig *configs = new EGLConfig [count]; + eglGetConfigs(dpy, configs, count, &count); + for (EGLint index = 0; index < count; ++index) { + props = configProperties(configs[index]); + qWarning() << props.toString(); + } + delete [] configs; +} + +QT_END_NAMESPACE diff --git a/src/opengl/qegl_p.h b/src/gui/egl/qegl_p.h index 4e46965..89949e2 100644 --- a/src/opengl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenGL module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -46,25 +46,20 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists for the convenience -// of the QGLWidget class. This header file may change from +// This file is not part of the Qt API. It exists for the convenience of +// the QGLWidget and QVGWidget classes. This header file may change from // version to version without notice, or even be removed. // // We mean it. // -#include "QtCore/qvarlengtharray.h" -#include "QtCore/qsize.h" -#include "QtGui/qimage.h" +#include <QtCore/qsize.h> +#include <QtGui/qimage.h> -#if defined(QT_OPENGL_ES) || defined(QT_OPENVG) +#include "qeglproperties_p.h" QT_BEGIN_INCLUDE_NAMESPACE -#if defined(QT_OPENGL_ES_2) || defined(QT_OPENVG) -#include <EGL/egl.h> -#else -#include <GLES/egl.h> -#endif + #if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED) #undef EGLNativeWindowType #undef EGLNativePixmapType @@ -76,69 +71,27 @@ typedef NativeDisplayType EGLNativeDisplayType; #endif QT_END_INCLUDE_NAMESPACE -class QX11Info; -class QPaintDevice; -class QImage; -class QPixmap; -class QWidget; - QT_BEGIN_NAMESPACE -class Q_OPENGL_EXPORT QEglProperties -{ -public: - QEglProperties(); - QEglProperties(const QEglProperties& other) : props(other.props) {} - ~QEglProperties() {} - - int value(int name) const; - void setValue(int name, int value); - bool removeValue(int name); - - const int *properties() const { return props.constData(); } - - void setPixelFormat(QImage::Format pixelFormat); -#ifdef Q_WS_X11 - void setVisualFormat(const QX11Info *xinfo); -#endif - void setRenderableType(int api); - - bool reduceConfiguration(); - - QString toString() const; - -private: - QVarLengthArray<int> props; -}; - -class Q_OPENGL_EXPORT QEglContext +class Q_GUI_EXPORT QEglContext { public: QEglContext(); ~QEglContext(); - enum API - { - OpenGL, - OpenVG - }; - - enum PixelFormatMatch - { - ExactPixelFormat, - BestPixelFormat - }; - bool isValid() const; bool isSharing() const; + bool isCurrent() const; + + QEgl::API api() const { return apiType; } + void setApi(QEgl::API api) { apiType = api; } - void setApi(QEglContext::API api) { apiType = api; } bool openDisplay(QPaintDevice *device); - bool chooseConfig(const QEglProperties& properties, PixelFormatMatch match = ExactPixelFormat); + bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); bool createContext(QEglContext *shareContext = 0); - bool createSurface(QPaintDevice *device); + bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0); bool recreateSurface(QPaintDevice *device); - void setSurface(EGLSurface surface) { surf = surface; } + void destroySurface(); void destroy(); @@ -153,29 +106,30 @@ public: bool configAttrib(int name, EGLint *value) const; - void clearError() const { eglGetError(); } - - QEglContext::API api() const { return apiType; } + static void clearError() { eglGetError(); } + static EGLint error() { return eglGetError(); } + static QString errorString(EGLint code); EGLDisplay display() const { return dpy; } EGLContext context() const { return ctx; } EGLSurface surface() const { return surf; } + void setSurface(EGLSurface surface) { surf = surface; } EGLConfig config() const { return cfg; } QEglProperties configProperties(EGLConfig cfg = 0) const; static EGLDisplay defaultDisplay(QPaintDevice *device); - static QString errorString(int code); void dumpAllConfigs(); private: - QEglContext::API apiType; + QEgl::API apiType; EGLDisplay dpy; EGLContext ctx; EGLSurface surf; EGLConfig cfg; bool share; + bool current; void *reserved; // For extension data in future versions. static EGLDisplay getDisplay(QPaintDevice *device); @@ -183,6 +137,4 @@ private: QT_END_NAMESPACE -#endif // QT_OPENGL_ES || QT_OPENVG - #endif // QEGL_P_H diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp new file mode 100644 index 0000000..69eaf1b --- /dev/null +++ b/src/gui/egl/qegl_qws.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include "qegl_p.h" + +#if !defined(QT_NO_EGL) + +#include <qscreen_qws.h> +#include <qscreenproxy_qws.h> +#include <qapplication.h> +#include <qdesktopwidget.h> + +QT_BEGIN_NAMESPACE + +// Create the surface for a QPixmap, QImage, or QWidget. +// We don't have QGLScreen to create EGL surfaces for us, +// so surface creation needs to be done in QtOpenGL or +// QtOpenVG for Qt/Embedded. +bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +{ + Q_UNUSED(device); + Q_UNUSED(properties); + return false; +} + +EGLDisplay QEglContext::getDisplay(QPaintDevice *device) +{ + Q_UNUSED(device); + return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); +} + +static QScreen *screenForDevice(QPaintDevice *device) +{ + QScreen *screen = qt_screen; + if (!screen) + return 0; + if (screen->classId() == QScreen::MultiClass) { + int screenNumber; + if (device && device->devType() == QInternal::Widget) + screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); + else + screenNumber = 0; + screen = screen->subScreens()[screenNumber]; + } + while (screen->classId() == QScreen::ProxyClass) { + screen = static_cast<QProxyScreen *>(screen)->screen(); + } + return screen; +} + +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + if (!dev) + return; + + // Find the QGLScreen for this paint device. + QScreen *screen = screenForDevice(dev); + if (!screen) + return; + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(screen->pixelFormat()); +} + +QT_END_NAMESPACE + +#endif // !QT_NO_EGL diff --git a/src/opengl/qegl_qws.cpp b/src/gui/egl/qegl_symbian.cpp index 89bee09..16a72a1 100644 --- a/src/opengl/qegl_qws.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenGL module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -44,58 +44,26 @@ #include <QtGui/qwidget.h> #include "qegl_p.h" -#if defined(QT_OPENGL_ES) || defined(QT_OPENVG) - -#include <qglscreen_qws.h> -#include <qscreenproxy_qws.h> -#include <private/qglwindowsurface_qws_p.h> -#include <qapplication.h> -#include <qdesktopwidget.h> +#include <coecntrl.h> QT_BEGIN_NAMESPACE -static QGLScreen *glScreenForDevice(QPaintDevice *device) +bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { - QScreen *screen = qt_screen; - if (screen->classId() == QScreen::MultiClass) { - int screenNumber; - if (device && device->devType() == QInternal::Widget) - screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); - else - screenNumber = 0; - screen = screen->subScreens()[screenNumber]; - } - while (screen->classId() == QScreen::ProxyClass) { - screen = static_cast<QProxyScreen *>(screen)->screen(); - } - if (screen->classId() == QScreen::GLClass) - return static_cast<QGLScreen *>(screen); - else - return 0; -} - -// Create the surface for a QPixmap, QImage, or QWidget. -bool QEglContext::createSurface(QPaintDevice *device) -{ - // Get the screen surface functions, which are used to create native ids. - QGLScreen *glScreen = glScreenForDevice(device); - if (!glScreen) - return false; - QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions(); - if (!funcs) - return false; - // Create the native drawable for the paint device. int devType = device->devType(); EGLNativePixmapType pixmapDrawable = 0; EGLNativeWindowType windowDrawable = 0; bool ok; if (devType == QInternal::Pixmap) { - ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable); - } else if (devType == QInternal::Image) { - ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable); + pixmapDrawable = 0; + ok = (pixmapDrawable != 0); + } else if (devType == QInternal::Widget) { + QWidget *w = static_cast<QWidget *>(device); + windowDrawable = (EGLNativeWindowType)(w->winId()->DrawableWindow()); + ok = (windowDrawable != 0); } else { - ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable); + ok = false; } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); @@ -103,6 +71,11 @@ bool QEglContext::createSurface(QPaintDevice *device) } // Create the EGL surface to draw into, based on the native drawable. + const int *props; + if (properties) + props = properties->properties(); + else + props = 0; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0); else @@ -116,10 +89,21 @@ bool QEglContext::createSurface(QPaintDevice *device) EGLDisplay QEglContext::getDisplay(QPaintDevice *device) { - Q_UNUSED(device); - return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); + EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (dpy == EGL_NO_DISPLAY) + qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY"); + return dpy; } -QT_END_NAMESPACE +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(QImage::Format_RGB32); +} -#endif // QT_OPENGL_ES || QT_OPENVG + +QT_END_NAMESPACE diff --git a/src/opengl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp index b978bc6..7bcbcf8 100644 --- a/src/opengl/qegl_wince.cpp +++ b/src/gui/egl/qegl_wince.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenGL module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -44,14 +44,12 @@ #include <QtGui/qwidget.h> #include "qegl_p.h" -#if defined(QT_OPENGL_ES) || defined(QT_OPENVG) - #include <windows.h> QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device) +bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -73,10 +71,15 @@ bool QEglContext::createSurface(QPaintDevice *device) } // Create the EGL surface to draw into, based on the native drawable. + const int *props; + if (properties) + props = properties->properties(); + else + props = 0; if (devType == QInternal::Widget) - surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0); + surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else - surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0); + surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props); if (surf == EGL_NO_SURFACE) { qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); return false; @@ -87,19 +90,27 @@ bool QEglContext::createSurface(QPaintDevice *device) EGLDisplay QEglContext::getDisplay(QPaintDevice *device) { EGLDisplay dpy = 0; - HWND win = ((QWidget*)device)->winId(); - HDC myDc = GetDC(win); - if (!myDc) { - qWarning("QEglContext::defaultDisplay(): WinCE display is not open"); - } - dpy = eglGetDisplay(EGLNativeDisplayType(myDc)); - if (dpy == EGL_NO_DISPLAY) { - qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY"); - dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + HWND win = (static_cast<QWidget*>(device))->winId(); + HDC myDc = GetDC(win); + if (!myDc) { + qWarning("QEglContext::defaultDisplay(): WinCE display is not open"); + } + dpy = eglGetDisplay(EGLNativeDisplayType(myDc)); + if (dpy == EGL_NO_DISPLAY) { + qWarning("QEglContext::defaultDisplay(): Falling back to EGL_DEFAULT_DISPLAY"); + dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); } return dpy; } -QT_END_NAMESPACE +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(QImage::Format_RGB16); // XXX +} -#endif // QT_OPENGL_ES || QT_OPENVG +QT_END_NAMESPACE diff --git a/src/opengl/qegl_x11egl.cpp b/src/gui/egl/qegl_x11.cpp index 23d1ac6..be89efe 100644 --- a/src/opengl/qegl_x11egl.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenGL module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -45,17 +45,13 @@ #include <QtCore/qdebug.h> #include "qegl_p.h" -#if defined(QT_OPENGL_ES) || defined(QT_OPENVG) - -#if defined(Q_WS_X11) #include <QtGui/qx11info_x11.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#endif QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device) +bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -77,11 +73,15 @@ bool QEglContext::createSurface(QPaintDevice *device) } // Create the EGL surface to draw into, based on the native drawable. + const int *props; + if (properties) + props = properties->properties(); + else + props = 0; if (devType == QInternal::Widget) - surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0); + surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else - surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0); - + surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props); if (surf == EGL_NO_SURFACE) { qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:" << errorString(eglGetError()); @@ -128,6 +128,17 @@ void QEglProperties::setVisualFormat(const QX11Info *xinfo) setValue(EGL_ALPHA_SIZE, 0); // XXX } -QT_END_NAMESPACE +extern const QX11Info *qt_x11Info(const QPaintDevice *pd); + +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + if (!dev) + return; + if (dev->devType() == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setVisualFormat(qt_x11Info(dev)); +} -#endif // QT_OPENGL_ES || QT_OPENVG +QT_END_NAMESPACE diff --git a/src/opengl/qegl.cpp b/src/gui/egl/qeglproperties.cpp index 61c7427..e0ae8a6 100644 --- a/src/opengl/qegl.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenGL module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -39,358 +39,12 @@ ** ****************************************************************************/ -#include <QtGui/qpaintdevice.h> -#include <QtGui/qpixmap.h> -#include <QtGui/qwidget.h> -#include <QtCore/qdebug.h> -#include "qegl_p.h" - -#if defined(QT_OPENGL_ES) || defined(QT_OPENVG) +#include "qeglproperties_p.h" QT_BEGIN_NAMESPACE -QEglContext::QEglContext() -{ - apiType = OpenGL; - dpy = EGL_NO_DISPLAY; - ctx = EGL_NO_CONTEXT; - surf = EGL_NO_SURFACE; - cfg = 0; - share = false; - reserved = 0; -} - -QEglContext::~QEglContext() -{ - destroy(); -} - -bool QEglContext::isValid() const -{ - return (ctx != EGL_NO_CONTEXT); -} - -bool QEglContext::isSharing() const -{ - return share; -} - -// Open the EGL display associated with "device". -bool QEglContext::openDisplay(QPaintDevice *device) -{ - if (dpy == EGL_NO_DISPLAY) - dpy = defaultDisplay(device); - return (dpy != EGL_NO_DISPLAY); -} - -// Choose a configuration that matches "properties". -bool QEglContext::chooseConfig - (const QEglProperties& properties, PixelFormatMatch match) -{ - QEglProperties props(properties); - EGLConfig *configs; - EGLint matching, size; - do { - // Get the number of matching configurations for this set of properties. - matching = 0; - if (!eglChooseConfig(dpy, props.properties(), 0, 256, &matching) || !matching) - continue; - - // If we want the best pixel format, then return the first - // matching configuration. - if (match == BestPixelFormat) { - eglChooseConfig(dpy, props.properties(), &cfg, 1, &matching); - if (matching < 1) - continue; - return true; - } - - // Fetch all of the matching configurations and find the - // first that matches the pixel format we wanted. - size = matching; - configs = new EGLConfig [size]; - eglChooseConfig(dpy, props.properties(), configs, size, &matching); - for (EGLint index = 0; index < size; ++index) { - EGLint red, green, blue, alpha; - eglGetConfigAttrib(dpy, configs[index], EGL_RED_SIZE, &red); - eglGetConfigAttrib(dpy, configs[index], EGL_GREEN_SIZE, &green); - eglGetConfigAttrib(dpy, configs[index], EGL_BLUE_SIZE, &blue); - eglGetConfigAttrib(dpy, configs[index], EGL_ALPHA_SIZE, &alpha); - if (red == props.value(EGL_RED_SIZE) && - green == props.value(EGL_GREEN_SIZE) && - blue == props.value(EGL_BLUE_SIZE) && - (props.value(EGL_ALPHA_SIZE) == 0 || - alpha == props.value(EGL_ALPHA_SIZE))) { - cfg = configs[index]; - delete [] configs; - return true; - } - } - delete [] configs; - } while (props.reduceConfiguration()); - -#ifdef EGL_BIND_TO_TEXTURE_RGBA - // Don't report an error just yet if we failed to get a pbuffer - // configuration with texture rendering. Only report failure if - // we cannot get any pbuffer configurations at all. - if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE && - props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE) -#endif - { - qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration"; - qWarning() << "Requested:" << props.toString(); - qWarning() << "Available:"; - dumpAllConfigs(); - } - return false; -} - -// Create the EGLContext. -bool QEglContext::createContext(QEglContext *shareContext) -{ - // We need to select the correct API before calling eglCreateContext(). -#ifdef EGL_OPENGL_ES_API - if (apiType == OpenGL) - eglBindAPI(EGL_OPENGL_ES_API); -#endif -#ifdef EGL_OPENVG_API - if (apiType == OpenVG) - eglBindAPI(EGL_OPENVG_API); -#endif - - // Create a new context for the configuration. - QEglProperties contextProps; -#if defined(QT_OPENGL_ES_2) - if (apiType == OpenGL) - contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); -#endif - if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) - shareContext = 0; - if (shareContext) { - ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties()); - if (ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); - shareContext = 0; - } - } - if (ctx == EGL_NO_CONTEXT) { - ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties()); - if (ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError()); - return false; - } - } - share = (shareContext != 0); - return true; -} - -// Recreate the surface for a paint device because the native id has changed. -bool QEglContext::recreateSurface(QPaintDevice *device) -{ - // Bail out if the surface has not been created for the first time yet. - if (surf == EGL_NO_SURFACE) - return true; - - // Destroy the old surface. - eglDestroySurface(dpy, surf); - - // Create a new one. - return createSurface(device); -} - -void QEglContext::destroy() -{ - if (ctx != EGL_NO_CONTEXT) - eglDestroyContext(dpy, ctx); - dpy = EGL_NO_DISPLAY; - ctx = EGL_NO_CONTEXT; - surf = EGL_NO_SURFACE; - cfg = 0; - share = false; -} - -bool QEglContext::makeCurrent() -{ - if(ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; - return false; - } - - bool ok = eglMakeCurrent(dpy, surf, surf, ctx); - if (!ok) { - EGLint err = eglGetError(); - qWarning() << "QEglContext::makeCurrent():" << errorString(err); - } - return ok; -} - -bool QEglContext::doneCurrent() -{ - // If the context is invalid, we assume that an error was reported - // when makeCurrent() was called. - if (ctx == EGL_NO_CONTEXT) - return false; - - // We need to select the correct API before calling eglMakeCurrent() - // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG - // contexts active at the same time. -#ifdef EGL_OPENGL_ES_API - if (apiType == OpenGL) - eglBindAPI(EGL_OPENGL_ES_API); -#endif -#ifdef EGL_OPENVG_API - if (apiType == OpenVG) - eglBindAPI(EGL_OPENVG_API); -#endif - - bool ok = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!ok) { - EGLint err = eglGetError(); - qWarning() << "QEglContext::doneCurrent():" << errorString(err); - } - return ok; -} - -bool QEglContext::swapBuffers() -{ - if(ctx == EGL_NO_CONTEXT) - return false; - - bool ok = eglSwapBuffers(dpy, surf); - if (!ok) { - EGLint err = eglGetError(); - qWarning() << "QEglContext::swapBuffers():" << errorString(err); - } - return ok; -} - -// Wait for native rendering operations to complete before starting -// to use OpenGL/OpenVG operations. -void QEglContext::waitNative() -{ -#ifdef EGL_CORE_NATIVE_ENGINE - eglWaitNative(EGL_CORE_NATIVE_ENGINE); -#endif -} - -// Wait for client OpenGL/OpenVG operations to complete before -// using native rendering operations. -void QEglContext::waitClient() -{ -#ifdef EGL_OPENGL_ES_API - if (apiType == OpenGL) { - eglBindAPI(EGL_OPENGL_ES_API); - eglWaitClient(); - } -#else - if (apiType == OpenGL) - eglWaitGL(); -#endif -#ifdef EGL_OPENVG_API - if (apiType == OpenVG) { - eglBindAPI(EGL_OPENVG_API); - eglWaitClient(); - } -#endif -} - -// Query the actual size of the EGL surface. -QSize QEglContext::surfaceSize() const -{ - int w, h; - eglQuerySurface(dpy, surf, EGL_WIDTH, &w); - eglQuerySurface(dpy, surf, EGL_HEIGHT, &h); - return QSize(w, h); -} - -// Query the value of a configuration attribute. -bool QEglContext::configAttrib(int name, EGLint *value) const -{ - return eglGetConfigAttrib(dpy, cfg, name, value); -} - -// Retrieve all of the properties on "cfg". If zero, return -// the context's configuration. -QEglProperties QEglContext::configProperties(EGLConfig cfg) const -{ - if (!cfg) - cfg = config(); - QEglProperties props; - for (int name = 0x3020; name <= 0x304F; ++name) { - EGLint value; - if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value)) - props.setValue(name, value); - } - eglGetError(); // Clear the error state. - return props; -} - -// Initialize and return the default display. -EGLDisplay QEglContext::defaultDisplay(QPaintDevice *device) -{ - static EGLDisplay dpy = EGL_NO_DISPLAY; - if (dpy == EGL_NO_DISPLAY) { - dpy = getDisplay(device); - if (dpy == EGL_NO_DISPLAY) { - qWarning() << "QEglContext::defaultDisplay(): Cannot open EGL display"; - return EGL_NO_DISPLAY; - } - if (!eglInitialize(dpy, NULL, NULL)) { - EGLint err = eglGetError(); - qWarning() << "QEglContext::defaultDisplay(): Cannot initialize EGL display:" << errorString(err); - return EGL_NO_DISPLAY; - } -#ifdef EGL_OPENGL_ES_API - eglBindAPI(EGL_OPENGL_ES_API); -#endif - } - return dpy; -} - -// Return the error string associated with a specific code. -QString QEglContext::errorString(int code) -{ - static const char * const errors[] = { - "Success (0x3000)", // No tr - "Not initialized (0x3001)", // No tr - "Bad access (0x3002)", // No tr - "Bad alloc (0x3003)", // No tr - "Bad attribute (0x3004)", // No tr - "Bad config (0x3005)", // No tr - "Bad context (0x3006)", // No tr - "Bad current surface (0x3007)", // No tr - "Bad display (0x3008)", // No tr - "Bad match (0x3009)", // No tr - "Bad native pixmap (0x300A)", // No tr - "Bad native window (0x300B)", // No tr - "Bad parameter (0x300C)", // No tr - "Bad surface (0x300D)", // No tr - "Context lost (0x300E)" // No tr - }; - if (code >= 0x3000 && code <= 0x300E) { - return QString::fromLatin1(errors[code - 0x3000]); - } else { - return QLatin1String("0x") + QString::number(code, 16); - } -} - -// Dump all of the EGL configurations supported by the system. -void QEglContext::dumpAllConfigs() -{ - QEglProperties props; - EGLint count = 0; - if (!eglGetConfigs(dpy, 0, 0, &count)) - return; - if (count < 1) - return; - EGLConfig *configs = new EGLConfig [count]; - eglGetConfigs(dpy, configs, count, &count); - for (EGLint index = 0; index < count; ++index) { - props = configProperties(configs[index]); - qWarning() << props.toString(); - } - delete [] configs; -} +#include <QtCore/qdebug.h> +#include <QtCore/qstringlist.h> // Initialize a property block. QEglProperties::QEglProperties() @@ -455,10 +109,10 @@ int QEglProperties::value(int name) const case EGL_MAX_PBUFFER_PIXELS: case EGL_NATIVE_VISUAL_ID: case EGL_NONE: - qWarning("QEglProperties::value() - Attibute %d does not affect config selection", name); + // Attribute does not affect config selection. return EGL_DONT_CARE; default: - qWarning("QEglProperties::value() - Attibute %d is unknown in EGL <=1.4", name); + // Attribute is unknown in EGL <= 1.4. return EGL_DONT_CARE; } } @@ -532,18 +186,18 @@ void QEglProperties::setPixelFormat(QImage::Format pixelFormat) setValue(EGL_ALPHA_SIZE, alpha); } -void QEglProperties::setRenderableType(int api) +void QEglProperties::setRenderableType(QEgl::API api) { #if defined(EGL_RENDERABLE_TYPE) #if defined(QT_OPENGL_ES_2) - if (api == QEglContext::OpenGL) + if (api == QEgl::OpenGL) setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); #elif defined(QT_OPENGL_ES) - if (api == QEglContext::OpenGL) + if (api == QEgl::OpenGL) setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); #endif #if defined(EGL_OPENVG_BIT) - if (api == QEglContext::OpenVG) + if (api == QEgl::OpenVG) setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT); #endif #else @@ -839,4 +493,4 @@ QString QEglProperties::toString() const QT_END_NAMESPACE -#endif // QT_OPENGL_ES || QT_OPENVG + diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h new file mode 100644 index 0000000..3570f80 --- /dev/null +++ b/src/gui/egl/qeglproperties_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPROPERTIES_P_H +#define QEGLPROPERTIES_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QGLWidget class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qvarlengtharray.h> +#include <QtGui/qimage.h> + +QT_BEGIN_INCLUDE_NAMESPACE + +#if defined(QT_GLES_EGL) +#include <GLES/egl.h> +#else +#include <EGL/egl.h> +#endif + +#if defined(Q_WS_X11) +// If <EGL/egl.h> included <X11/Xlib.h>, then the global namespace +// may have been polluted with X #define's. The following makes sure +// the X11 headers were included properly and then cleans things up. +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#undef Bool +#undef Status +#undef None +#undef KeyPress +#undef KeyRelease +#undef FocusIn +#undef FocusOut +#undef Type +#undef FontChange +#undef CursorShape +#endif + +QT_END_INCLUDE_NAMESPACE + +QT_BEGIN_NAMESPACE + +namespace QEgl { + enum API + { + OpenGL, + OpenVG + }; + + enum PixelFormatMatch + { + ExactPixelFormat, + BestPixelFormat + }; +}; + +class QX11Info; +class QPaintDevice; + +class Q_GUI_EXPORT QEglProperties +{ +public: + QEglProperties(); + QEglProperties(const QEglProperties& other) : props(other.props) {} + ~QEglProperties() {} + + int value(int name) const; + void setValue(int name, int value); + bool removeValue(int name); + bool isEmpty() const { return props[0] == EGL_NONE; } + + const int *properties() const { return props.constData(); } + + void setPixelFormat(QImage::Format pixelFormat); +#ifdef Q_WS_X11 + void setVisualFormat(const QX11Info *xinfo); +#endif + void setRenderableType(QEgl::API api); + + void setPaintDeviceFormat(QPaintDevice *dev); + + bool reduceConfiguration(); + + QString toString() const; + +private: + QVarLengthArray<int> props; +}; + +QT_END_NAMESPACE + +#endif // QEGLPROPERTIES_P_H diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 57269ce..07ebb8c 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -839,7 +839,7 @@ bool QGraphicsProxyWidget::event(QEvent *event) // ### Qt 4.5: this code must also go into a reimplementation // of inputMethodEvent(). QWidget *focusWidget = d->widget->focusWidget(); - if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) + if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) QApplication::sendEvent(focusWidget, event); break; } diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 329fb01..b77bfdc 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -35,6 +35,8 @@ include(util/util.pri) include(statemachine/statemachine.pri) include(math3d/math3d.pri) +contains(QT_CONFIG, egl): include(egl/egl.pri) + embedded: QT += network QMAKE_LIBS += $$QMAKE_LIBS_GUI diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index edae29a..fa407c7 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -54,7 +54,7 @@ #ifdef Q_WS_MAC #include <private/qt_mac_p.h> -#include <Carbon/Carbon.h> +#include <private/qt_cocoa_helpers_mac_p.h> #endif QT_BEGIN_NAMESPACE @@ -178,8 +178,8 @@ QPixmapIconEngine::~QPixmapIconEngine() void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { QSize pixmapSize = rect.size(); -#if defined(Q_WS_MAC) && !defined(Q_WS_MAC64) - pixmapSize *= (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) ? HIGetScaleFactor() : 1; +#if defined(Q_WS_MAC) + pixmapSize *= qt_mac_get_scalefactor(); #endif painter->drawPixmap(rect, pixmap(pixmapSize, mode, state)); } diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index bb8f98a..e3fb27a 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -52,6 +52,10 @@ #include <qwidget.h> #endif +#ifdef Q_WS_MAC +#include <private/qpaintengine_mac_p.h> +#endif + QT_BEGIN_NAMESPACE #ifdef Q_WS_WIN @@ -225,15 +229,14 @@ QImage::Format QNativeImage::systemFormat() #elif defined(Q_WS_MAC) -QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *) +QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* isTextBuffer */, QWidget *widget) : image(width, height, format) { - cgColorSpace = CGColorSpaceCreateDeviceRGB(); + cgColorSpace = QCoreGraphicsPaintEngine::macDisplayColorSpace(widget); uint cgflags = kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; + cgflags |= kCGBitmapByteOrder32Host; #endif cg = CGBitmapContextCreate(image.bits(), width, height, 8, image.bytesPerLine(), cgColorSpace, cgflags); diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index b40694a..c281fe9 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -119,14 +119,9 @@ CGImageRef qt_mac_image_to_cgimage(const QImage &image) CGDataProviderCreateWithData(0, image.bits(), image.bytesPerLine() * image.height(), 0); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo cgflags = kCGImageAlphaPremultipliedFirst; + cgflags |= kCGBitmapByteOrder32Host; #endif CGImageRef cgImage = CGImageCreate(image.width(), image.height(), bitsPerColor, bitsPerPixel, @@ -645,14 +640,9 @@ void QMacPixmapData::macCreateCGImageRef() pixels, bytesPerRow * h, qt_mac_cgimage_data_free); validDataPointers.insert(this); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo cgflags = kCGImageAlphaPremultipliedFirst; + cgflags |= kCGBitmapByteOrder32Host; #endif cg_data = CGImageCreate(w, h, 8, 32, bytesPerRow, colorspace, cgflags, provider, 0, 0, kCGRenderingIntentDefault); @@ -893,38 +883,6 @@ static void qt_mac_grabDisplayRect(CGDirectDisplayID display, const QRect &displ ptrCGLDestroyContext(glContextObj); // and destroy the context } -static CGImageRef qt_mac_createImageFromBitmapContext(CGContextRef c) -{ - void *rasterData = CGBitmapContextGetData(c); - const int width = CGBitmapContextGetBytesPerRow(c), - height = CGBitmapContextGetHeight(c); - size_t imageDataSize = width*height; - - if(!rasterData) - return 0; - - // Create the data provider from the image data, using - // the image releaser function releaseBitmapContextImageData. - CGDataProviderRef dataProvider = CGDataProviderCreateWithData(0, rasterData, - imageDataSize, - qt_mac_cgimage_data_free); - - if(!dataProvider) - return 0; - - uint bitmapInfo = 0; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if(CGBitmapContextGetBitmapInfo) - bitmapInfo = CGBitmapContextGetBitmapInfo(c); - else -#endif - bitmapInfo = CGBitmapContextGetAlphaInfo(c); - return CGImageCreate(width, height, CGBitmapContextGetBitsPerComponent(c), - CGBitmapContextGetBitsPerPixel(c), CGBitmapContextGetBytesPerRow(c), - CGBitmapContextGetColorSpace(c), bitmapInfo, dataProvider, - 0, true, kCGRenderingIntentDefault); -} - // Returns a pixmap containing the screen contents at rect. static QPixmap qt_mac_grabScreenRect(const QRect &rect) { @@ -958,19 +916,8 @@ static QPixmap qt_mac_grabScreenRect(const QRect &rect) rect.height(), 8, bytewidth, QCoreGraphicsPaintEngine::macGenericColorSpace(), kCGImageAlphaNoneSkipFirst); - -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap); - return QPixmap::fromMacCGImageRef(image); - } else -#endif - { - QCFType<CGImageRef> image = qt_mac_createImageFromBitmapContext(bitmap); - if (!image) - return QPixmap(); - return QPixmap::fromMacCGImageRef(image); - } + QCFType<CGImageRef> image = CGBitmapContextCreateImage(bitmap); + return QPixmap::fromMacCGImageRef(image); } #ifndef QT_MAC_USE_COCOA // no QuickDraw in 64-bit mode @@ -1043,18 +990,12 @@ Qt::HANDLE QPixmap::macQDHandle() const SetRect(&rect, 0, 0, d->w, d->h); unsigned long qdformat = k32ARGBPixelFormat; GWorldFlags qdflags = 0; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - //we play such games so we can use the same buffer in CG as QD this - //makes our merge much simpler, at some point the hacks will go away - //because QD will be removed, but until that day this keeps them coexisting - if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) - qdformat = k32BGRAPixelFormat; -#if 0 - qdflags |= kNativeEndianPixMap; -#endif - } -#endif + //we play such games so we can use the same buffer in CG as QD this + //makes our merge much simpler, at some point the hacks will go away + //because QD will be removed, but until that day this keeps them coexisting + if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) + qdformat = k32BGRAPixelFormat; + if(NewGWorldFromPtr(&d->qd_data, qdformat, &rect, 0, 0, qdflags, (char*)d->pixels, d->bytesPerRow) != noErr) qWarning("Qt: internal: QPixmap::init error (%d %d %d %d)", rect.left, rect.top, rect.right, rect.bottom); diff --git a/src/gui/inputmethod/qmacinputcontext_mac.cpp b/src/gui/inputmethod/qmacinputcontext_mac.cpp index 9fce64c..2e9ee08 100644 --- a/src/gui/inputmethod/qmacinputcontext_mac.cpp +++ b/src/gui/inputmethod/qmacinputcontext_mac.cpp @@ -56,13 +56,6 @@ extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); # define typeByteCount typeSInt32 #endif -static QTextFormat qt_mac_compose_format() -{ - QTextCharFormat ret; - ret.setFontUnderline(true); - return ret; -} - QMacInputContext::QMacInputContext(QObject *parent) : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0), keydownEvent(0) @@ -72,7 +65,7 @@ QMacInputContext::QMacInputContext(QObject *parent) QMacInputContext::~QMacInputContext() { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(textDocument) DeleteTSMDocument(textDocument); #endif @@ -81,7 +74,7 @@ QMacInputContext::~QMacInputContext() void QMacInputContext::createTextDocument() { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(!textDocument) { InterfaceTypeList itl = { kUnicodeDocument }; NewTSMDocument(1, itl, &textDocument, SRefCon(this)); @@ -98,7 +91,7 @@ QString QMacInputContext::language() void QMacInputContext::mouseHandler(int pos, QMouseEvent *e) { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(e->type() != QEvent::MouseButtonPress) return; @@ -107,11 +100,21 @@ void QMacInputContext::mouseHandler(int pos, QMouseEvent *e) if (pos < 0 || pos > currentText.length()) reset(); // ##### handle mouse position +#else + Q_UNUSED(pos); + Q_UNUSED(e); #endif } #if !defined QT_MAC_USE_COCOA +static QTextFormat qt_mac_compose_format() +{ + QTextCharFormat ret; + ret.setFontUnderline(true); + return ret; +} + void QMacInputContext::reset() { if (recursionGuard) @@ -134,12 +137,12 @@ bool QMacInputContext::isComposing() const { return composing; } -#endif +#endif void QMacInputContext::setFocusWidget(QWidget *w) { createTextDocument(); -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(w) ActivateTSMDocument(textDocument); else @@ -149,6 +152,7 @@ void QMacInputContext::setFocusWidget(QWidget *w) } +#ifndef QT_MAC_USE_COCOA static EventTypeSpec input_events[] = { { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, { kEventClassTextInput, kEventTextInputOffsetToPos }, @@ -156,11 +160,12 @@ static EventTypeSpec input_events[] = { }; static EventHandlerUPP input_proc_handlerUPP = 0; static EventHandlerRef input_proc_handler = 0; +#endif void QMacInputContext::initialize() { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(!input_proc_handler) { input_proc_handlerUPP = NewEventHandlerUPP(QMacInputContext::globalEventProcessor); InstallEventHandler(GetApplicationEventTarget(), input_proc_handlerUPP, @@ -173,7 +178,7 @@ QMacInputContext::initialize() void QMacInputContext::cleanup() { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA if(input_proc_handler) { RemoveEventHandler(input_proc_handler); input_proc_handler = 0; @@ -198,7 +203,7 @@ void QMacInputContext::setLastKeydownEvent(EventRef event) OSStatus QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void *) { -#ifdef Q_WS_MAC32 +#ifndef QT_MAC_USE_COCOA QScopedLoopLevelCounter loopLevelCounter(QApplicationPrivate::instance()->threadData); SRefCon refcon = 0; @@ -360,6 +365,8 @@ QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void } if(!handled_event) //let the event go through return eventNotHandledErr; +#else + Q_UNUSED(event); #endif return noErr; //we eat the event } diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index f1b0d19..4652b91 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -2238,7 +2238,7 @@ QListViewItem QStaticListViewBase::indexToListViewItem(const QModelIndex &index) { if (flowPositions.isEmpty() || segmentPositions.isEmpty() - || index.row() > flowPositions.count()) + || index.row() >= flowPositions.count()) return QListViewItem(); const int segment = qBinarySearch<int>(segmentStartRows, index.row(), diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 7219fed..463d6ef 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -463,15 +463,12 @@ static inline bool isAlien(QWidget *widget) // ######## move to QApplicationPrivate // Default application palettes and fonts (per widget type) - -typedef QHash<QByteArray, QPalette> PaletteHash; Q_GLOBAL_STATIC(PaletteHash, app_palettes) PaletteHash *qt_app_palettes_hash() { return app_palettes(); } -typedef QHash<QByteArray, QFont> FontHash; Q_GLOBAL_STATIC(FontHash, app_fonts) FontHash *qt_app_fonts_hash() { diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index ace5d1d..ca826b0 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -164,7 +164,6 @@ QT_BEGIN_NAMESPACE //for qt_mac.h QPaintDevice *qt_mac_safe_pdev = 0; QList<QMacWindowChangeEvent*> *QMacWindowChangeEvent::change_events = 0; -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp /***************************************************************************** Internal variables and functions @@ -527,9 +526,9 @@ void qt_mac_update_os_settings() for(int i = 0; mac_widget_fonts[i].qt_class; i++) { QFont fnt = qfontForThemeFont(mac_widget_fonts[i].font_key); bool set_font = true; - QHash<QByteArray, QFont> *hash = qt_app_fonts_hash(); + FontHash *hash = qt_app_fonts_hash(); if (!hash->isEmpty()) { - QHash<QByteArray, QFont>::const_iterator it + FontHash::const_iterator it = hash->constFind(mac_widget_fonts[i].qt_class); if (it != hash->constEnd()) set_font = (fnt != *it); @@ -628,10 +627,9 @@ void QApplicationPrivate::initializeWidgetPaletteHash() } bool set_palette = true; - extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp - QHash<QByteArray, QPalette> *phash = qt_app_palettes_hash(); + PaletteHash *phash = qt_app_palettes_hash(); if (!phash->isEmpty()) { - QHash<QByteArray, QPalette>::const_iterator it + PaletteHash::const_iterator it = phash->constFind(mac_widget_colors[i].qt_class); if (it != phash->constEnd()) set_palette = (pal != *it); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index a9e5d60..95b4fe5 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -200,6 +200,12 @@ public: { --threadData->loopLevel; } }; +typedef QHash<QByteArray, QFont> FontHash; +FontHash *qt_app_fonts_hash(); + +typedef QHash<QByteArray, QPalette> PaletteHash; +PaletteHash *qt_app_palettes_hash(); + class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate { Q_DECLARE_PUBLIC(QApplication) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index babc5df..2704987 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -1305,9 +1305,9 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, } if (kdeColors) { - const QSettings &theKdeSettings = - QSettings(QApplicationPrivate::kdeHome() - + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + const QSettings theKdeSettings( + QApplicationPrivate::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); // Setup KDE palette QColor color; @@ -1357,9 +1357,9 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, } // Use KDE3 or KDE4 color settings if present if (kdeColors) { - const QSettings &theKdeSettings = - QSettings(QApplicationPrivate::kdeHome() - + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); + const QSettings theKdeSettings( + QApplicationPrivate::kdeHome() + + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); QColor color = kdeColor(QLatin1String("selectBackground"), theKdeSettings); if (!color.isValid()) diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 353d815..ab96d58 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -259,14 +259,13 @@ static void cleanupCocoaApplicationDelegate() onApplicationChangedActivation(false); } -class QDesktopWidgetImplementation; - (void)applicationDidChangeScreenParameters:(NSNotification *)notification { Q_UNUSED(notification); QDesktopWidgetImplementation::instance()->onResize(); } -- (void)setReflectionDelegate:(NSObject *)oldDelegate +- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate { [oldDelegate retain]; [reflectionDelegate release]; diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h index 3931f16..5aa98df 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac_p.h @@ -97,7 +97,14 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate); #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 -@protocol NSApplicationDelegate <NSObject> @end +@protocol NSApplicationDelegate <NSObject> +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; +- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames; +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender; +- (void)applicationDidBecomeActive:(NSNotification *)notification; +- (void)applicationDidResignActive:(NSNotification *)notification; +@end #endif @@ -106,7 +113,7 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate); QApplicationPrivate *qtPrivate; NSMenu *dockMenu; QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader; - id <NSApplicationDelegate> reflectionDelegate; + NSObject <NSApplicationDelegate> *reflectionDelegate; bool inLaunch; } + (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate; @@ -115,6 +122,6 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate); - (QApplicationPrivate *)qAppPrivate; - (void)setMenuLoader:(QT_MANGLE_NAMESPACE(QCocoaMenuLoader)*)menuLoader; - (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader; -- (void)setReflectionDelegate:(NSObject *)oldDelegate; +- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate; @end #endif diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index 266cf88..bdc7ecb 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -55,6 +55,12 @@ extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview. QT_END_NAMESPACE QT_USE_NAMESPACE + +@interface NSWindow (QtCoverForHackWithCategory) ++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; +@end + + @implementation QT_MANGLE_NAMESPACE(QCocoaPanel) - (BOOL)canBecomeKeyWindow diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 9c1dce5..7084416 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -58,6 +58,10 @@ extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview. QT_END_NAMESPACE QT_USE_NAMESPACE +@interface NSWindow (QtCoverForHackWithCategory) ++ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask; +@end + @implementation NSWindow (QT_MANGLE_NAMESPACE(QWidgetIntegration)) - (id)QT_MANGLE_NAMESPACE(qt_initWithQWidget):(QWidget*)widget contentRect:(NSRect)rect styleMask:(NSUInteger)mask; diff --git a/src/gui/kernel/qcocoawindowdelegate_mac_p.h b/src/gui/kernel/qcocoawindowdelegate_mac_p.h index b171b47..1e1d668 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac_p.h +++ b/src/gui/kernel/qcocoawindowdelegate_mac_p.h @@ -63,15 +63,8 @@ QT_FORWARD_DECLARE_CLASS(QWidget) QT_FORWARD_DECLARE_CLASS(QSize) QT_FORWARD_DECLARE_CLASS(QWidgetData) -@interface QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) : NSObject { - QHash<NSWindow *, QWidget *> *m_windowHash; - QHash<NSDrawer *, QWidget *> *m_drawerHash; -} -+ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate; -- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget; -- (void)resignDelegateForWindow:(NSWindow *)window; -- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget; -- (void)resignDelegateForDrawer:(NSDrawer *)drawer; +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 +@protocol NSWindowDelegate <NSObject> - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; - (void)windowDidMiniaturize:(NSNotification*)notification; - (void)windowDidResize:(NSNotification *)notification; @@ -83,6 +76,25 @@ QT_FORWARD_DECLARE_CLASS(QWidgetData) - (void)windowDidResignMain:(NSNotification*)notification; - (void)windowDidBecomeKey:(NSNotification*)notification; - (void)windowDidResignKey:(NSNotification*)notification; +@end + +@protocol NSDrawerDelegate <NSObject> +- (NSSize)drawerWillResizeContents:(NSDrawer *)sender toSize:(NSSize)contentSize; +@end + +#endif + + + +@interface QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) : NSObject<NSWindowDelegate, NSDrawerDelegate> { + QHash<NSWindow *, QWidget *> *m_windowHash; + QHash<NSDrawer *, QWidget *> *m_drawerHash; +} ++ (QT_MANGLE_NAMESPACE(QCocoaWindowDelegate)*)sharedDelegate; +- (void)becomeDelegteForWindow:(NSWindow *)window widget:(QWidget *)widget; +- (void)resignDelegateForWindow:(NSWindow *)window; +- (void)becomeDelegateForDrawer:(NSDrawer *)drawer widget:(QWidget *)widget; +- (void)resignDelegateForDrawer:(NSDrawer *)drawer; - (void)dumpMaximizedStateforWidget:(QWidget*)qwidget window:(NSWindow *)window; - (void)syncSizeForWidget:(QWidget *)qwidget toSize:(const QSize &)newSize @@ -90,6 +102,5 @@ QT_FORWARD_DECLARE_CLASS(QWidgetData) - (NSSize)closestAcceptableSizeForWidget:(QWidget *)qwidget window:(NSWindow *)window withNewSize:(NSSize)proposedSize; - (QWidget *)qt_qwidgetForWindow:(NSWindow *)window; -- (void)checkForMove:(const NSRect &)newRect forWidget:(QWidget *)qwidget; @end #endif diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp index ebacc2f..31c66e4 100644 --- a/src/gui/kernel/qmime_mac.cpp +++ b/src/gui/kernel/qmime_mac.cpp @@ -68,11 +68,6 @@ #include "qmap.h" #include <private/qt_mac_p.h> -#ifdef Q_WS_MAC32 -#include <QuickTime/QuickTime.h> -#include "qlibrary.h" -#endif - QT_BEGIN_NAMESPACE extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp @@ -507,6 +502,9 @@ QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mim #ifdef Q_WS_MAC32 +#include <QuickTime/QuickTime.h> +#include <qlibrary.h> + typedef ComponentResult (*PtrGraphicsImportSetDataHandle)(GraphicsImportComponent, Handle); typedef ComponentResult (*PtrGraphicsImportCreateCGImage)(GraphicsImportComponent, CGImageRef*, UInt32); typedef ComponentResult (*PtrGraphicsExportSetInputCGImage)(GraphicsExportComponent, CGImageRef); @@ -684,33 +682,11 @@ QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteA return ret; const QByteArray &a = data.first(); QCFType<CGImageRef> image; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CFDataRef> data = CFDataCreateWithBytesNoCopy(0, - reinterpret_cast<const UInt8 *>(a.constData()), - a.size(), kCFAllocatorNull); - QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(data, 0); - image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); - } else -#endif - { -#ifdef Q_WS_MAC32 - if (resolveMimeQuickTimeSymbols()) { - Handle tiff = NewHandle(a.size()); - memcpy(*tiff, a.constData(), a.size()); - GraphicsImportComponent graphicsImporter; - ComponentResult result = OpenADefaultComponent(GraphicsImporterComponentType, - kQTFileTypeTIFF, &graphicsImporter); - if (!result) - result = ptrGraphicsImportSetDataHandle(graphicsImporter, tiff); - if (!result) - result = ptrGraphicsImportCreateCGImage(graphicsImporter, &image, - kGraphicsImportCreateCGImageUsingCurrentSettings); - CloseComponent(graphicsImporter); - DisposeHandle(tiff); - } -#endif - } + QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0, + reinterpret_cast<const UInt8 *>(a.constData()), + a.size(), kCFAllocatorNull); + QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0); + image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); if (image != 0) ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage()); diff --git a/src/gui/kernel/qsound_mac.mm b/src/gui/kernel/qsound_mac.mm index 43965d1..a8ee516 100644 --- a/src/gui/kernel/qsound_mac.mm +++ b/src/gui/kernel/qsound_mac.mm @@ -80,14 +80,19 @@ protected: QT_END_NAMESPACE +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 +@protocol NSSoundDelegate <NSObject> +-(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool; +@end +#endif + QT_USE_NAMESPACE -@interface QMacSoundDelegate : NSObject { +@interface QMacSoundDelegate : NSObject<NSSoundDelegate> { QSound *qSound; // may be null. QAuServerMac* server; -} +} -(id)initWithQSound:(QSound*)sound:(QAuServerMac*)server; --(void)sound:(NSSound *)sound didFinishPlaying:(BOOL)aBool; @end @implementation QMacSoundDelegate diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 5e5e0dc..f5f381e 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1166,4 +1166,13 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) return context; } +CGFloat qt_mac_get_scalefactor() +{ +#ifndef QT_MAC_USE_COCOA + return HIGetScaleFactor(); +#else + return [[NSScreen mainScreen] userSpaceScaleFactor]; +#endif +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 5156b9c..7b975f5 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -161,6 +161,8 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow); +CGFloat qt_mac_get_scalefactor(); + #ifdef __OBJC__ inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) { return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index ad80f15..88dc73f 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -505,16 +505,9 @@ static void qt_mac_release_window_group(WindowGroupRef group) SInt32 qt_mac_get_group_level(WindowClass wclass) { SInt32 group_level; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - CGWindowLevel tmpLevel; - GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); - group_level = tmpLevel; - } else -#endif - { - GetWindowGroupLevel(GetWindowGroupOfClass(wclass), &group_level); - } + CGWindowLevel tmpLevel; + GetWindowGroupLevelOfType(GetWindowGroupOfClass(wclass), kWindowGroupLevelActive, &tmpLevel); + group_level = tmpLevel; return group_level; } #endif @@ -736,11 +729,8 @@ static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowProxyEndDrag }, { kEventClassWindow, kEventWindowResizeCompleted }, { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassWindow, kEventWindowGetRegion }, -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 { kEventClassWindow, kEventWindowGetClickModality }, -#endif { kEventClassWindow, kEventWindowTransitionCompleted }, { kEventClassMouse, kEventMouseDown } }; @@ -770,7 +760,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, QWidget *widget = qt_mac_find_window(wid); if(!widget) { handled_event = false; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 } else if(ekind == kEventWindowGetClickModality) { // Carbon will send us kEventWindowGetClickModality before every // mouse press / release event. By returning 'true', we tell Carbon @@ -781,7 +770,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, // By also setting the current modal window back into the event, we // help Carbon determining which window is supposed to be raised. handled_event = qApp->activePopupWidget() ? true : false; -#endif } else if(ekind == kEventWindowClose) { widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); QMenuBar::macUpdateMenuBar(); @@ -904,87 +892,78 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, SetEventParameter(mouseUpEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pos), &pos); SendEventToApplication(mouseUpEvent); ReleaseEvent(mouseUpEvent); - } else if(ekind == kEventWindowBoundsChanging || ekind == kEventWindowBoundsChanged) { - // Panther doesn't send Changing for sheets, only changed, so only - // bother handling Changed event if we are on 10.3 and we are a - // sheet. - if (ekind == kEventWindowBoundsChanged - && (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 - || !(widget->windowFlags() & Qt::Sheet))) { - handled_event = false; + } else if(ekind == kEventWindowBoundsChanging) { + UInt32 flags = 0; + GetEventParameter(event, kEventParamAttributes, typeUInt32, 0, + sizeof(flags), 0, &flags); + Rect nr; + GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0, + sizeof(nr), 0, &nr); + + QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top); + + QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData(); + if (tlwExtra && tlwExtra->isSetGeometry == 1) { + widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove); } else { - UInt32 flags = 0; - GetEventParameter(event, kEventParamAttributes, typeUInt32, 0, - sizeof(flags), 0, &flags); - Rect nr; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0, - sizeof(nr), 0, &nr); - - QRect newRect(nr.left, nr.top, nr.right - nr.left, nr.bottom - nr.top); - - QTLWExtra * const tlwExtra = widget->d_func()->maybeTopData(); - if (tlwExtra && tlwExtra->isSetGeometry == 1) { - widget->d_func()->setGeometry_sys_helper(newRect.left(), newRect.top(), newRect.width(), newRect.height(), tlwExtra->isMove); - } else { - //implicitly removes the maximized bit - if((widget->data->window_state & Qt::WindowMaximized) && - IsWindowInStandardState(wid, 0, 0)) { - widget->data->window_state &= ~Qt::WindowMaximized; - QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state - | Qt::WindowMaximized)); - QApplication::sendSpontaneousEvent(widget, &e); + //implicitly removes the maximized bit + if((widget->data->window_state & Qt::WindowMaximized) && + IsWindowInStandardState(wid, 0, 0)) { + widget->data->window_state &= ~Qt::WindowMaximized; + QWindowStateChangeEvent e(Qt::WindowStates(widget->data->window_state + | Qt::WindowMaximized)); + QApplication::sendSpontaneousEvent(widget, &e); - } + } - handled_event = false; - const QRect oldRect = widget->data->crect; - if((flags & kWindowBoundsChangeOriginChanged)) { - if(nr.left != oldRect.x() || nr.top != oldRect.y()) { - widget->data->crect.moveTo(nr.left, nr.top); - QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft()); - QApplication::sendSpontaneousEvent(widget, &qme); - } + handled_event = false; + const QRect oldRect = widget->data->crect; + if((flags & kWindowBoundsChangeOriginChanged)) { + if(nr.left != oldRect.x() || nr.top != oldRect.y()) { + widget->data->crect.moveTo(nr.left, nr.top); + QMoveEvent qme(widget->data->crect.topLeft(), oldRect.topLeft()); + QApplication::sendSpontaneousEvent(widget, &qme); } - if((flags & kWindowBoundsChangeSizeChanged)) { - if (widget->isWindow()) { - QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size()); - int dh = newSize.height() - newRect.height(); - int dw = newSize.width() - newRect.width(); - if (dw != 0 || dh != 0) { - handled_event = true; // We want to change the bounds, so we handle the event - - // set the rect, so we can also do the resize down below (yes, we need to resize). - newRect.setBottom(newRect.bottom() + dh); - newRect.setRight(newRect.right() + dw); - - nr.left = newRect.x(); - nr.top = newRect.y(); - nr.right = nr.left + newRect.width(); - nr.bottom = nr.top + newRect.height(); - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr); - } + } + if((flags & kWindowBoundsChangeSizeChanged)) { + if (widget->isWindow()) { + QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size()); + int dh = newSize.height() - newRect.height(); + int dw = newSize.width() - newRect.width(); + if (dw != 0 || dh != 0) { + handled_event = true; // We want to change the bounds, so we handle the event + + // set the rect, so we can also do the resize down below (yes, we need to resize). + newRect.setBottom(newRect.bottom() + dh); + newRect.setRight(newRect.right() + dw); + + nr.left = newRect.x(); + nr.top = newRect.y(); + nr.right = nr.left + newRect.width(); + nr.bottom = nr.top + newRect.height(); + SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), &nr); } + } - if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) { - widget->data->crect.setSize(newRect.size()); - HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height()); - - // If the WA_StaticContents attribute is set we can optimize the resize - // by only repainting the newly exposed area. We do this by disabling - // painting when setting the size of the view. The OS will invalidate - // the newly exposed area for us. - const bool staticContents = widget->testAttribute(Qt::WA_StaticContents); - const HIViewRef view = qt_mac_nativeview_for(widget); - if (staticContents) - HIViewSetDrawingEnabled(view, false); - HIViewSetFrame(view, &bounds); - if (staticContents) - HIViewSetDrawingEnabled(view, true); - - QResizeEvent qre(newRect.size(), oldRect.size()); - QApplication::sendSpontaneousEvent(widget, &qre); - qt_event_request_window_change(widget); - } + if (oldRect.width() != newRect.width() || oldRect.height() != newRect.height()) { + widget->data->crect.setSize(newRect.size()); + HIRect bounds = CGRectMake(0, 0, newRect.width(), newRect.height()); + + // If the WA_StaticContents attribute is set we can optimize the resize + // by only repainting the newly exposed area. We do this by disabling + // painting when setting the size of the view. The OS will invalidate + // the newly exposed area for us. + const bool staticContents = widget->testAttribute(Qt::WA_StaticContents); + const HIViewRef view = qt_mac_nativeview_for(widget); + if (staticContents) + HIViewSetDrawingEnabled(view, false); + HIViewSetFrame(view, &bounds); + if (staticContents) + HIViewSetDrawingEnabled(view, true); + + QResizeEvent qre(newRect.size(), oldRect.size()); + QApplication::sendSpontaneousEvent(widget, &qre); + qt_event_request_window_change(widget); } } } @@ -1703,17 +1682,11 @@ void QWidgetPrivate::determineWindowClass() bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); if (framelessWindow) { if(wclass == kDocumentWindowClass) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - wattr |= kWindowNoTitleBarAttribute; - else - wclass = kPlainWindowClass; + wattr |= kWindowNoTitleBarAttribute; } else if(wclass == kFloatingWindowClass) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - wattr |= kWindowNoTitleBarAttribute; - else - wclass = kToolbarWindowClass; + wattr |= kWindowNoTitleBarAttribute; } else if (wclass == kMovableModalWindowClass) { - wclass = kModalWindowClass; + wclass = kModalWindowClass; } } else { if(wclass != kModalWindowClass) @@ -2011,14 +1984,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Carbon(OSWindowRef windowRef) if (!desktop) SetAutomaticControlDragTrackingEnabledForWindow(windowRef, true); HIWindowChangeFeatures(windowRef, kWindowCanCollapse, 0); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - if (wattr & kWindowHideOnSuspendAttribute) - HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0); - else - HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden); - } -#endif + if (wattr & kWindowHideOnSuspendAttribute) + HIWindowChangeAvailability(windowRef, kHIWindowExposeHidden, 0); + else + HIWindowChangeAvailability(windowRef, 0, kHIWindowExposeHidden); if ((flags & Qt::WindowStaysOnTopHint)) ChangeWindowAttributes(windowRef, kWindowNoAttributes, kWindowHideOnSuspendAttribute); if (qt_mac_is_macdrawer(q) && parentWidget) @@ -2906,21 +2875,10 @@ void QWidgetPrivate::setWindowFilePath_sys(const QString &filePath) } // Set the proxy regardless, since this is our way of clearing it as well, but ignore the // return value as well. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - if (validRef) { - status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); - } else { - status = RemoveWindowProxy(qt_mac_window_for(q)); - } + if (validRef) { + status = HIWindowSetProxyFSRef(qt_mac_window_for(q), &ref); } else { - // Convert to an FSSpec and set it. It's deprecated but it works for where we don't have the other call. - if (validRef) { - FSSpec fsspec; - FSGetCatalogInfo(&ref, kFSCatInfoNone, 0, 0, &fsspec, 0); - status = SetWindowProxyFSSpec(qt_mac_window_for(q), &fsspec); - } else { - status = RemoveWindowProxy(qt_mac_window_for(q)); - } + status = RemoveWindowProxy(qt_mac_window_for(q)); } if (status != noErr) qWarning("QWidget::setWindowFilePath: Error setting proxyicon for path (%s):%ld", @@ -3128,16 +3086,9 @@ void QWidgetPrivate::update_sys(const QRect &r) if (updateRedirectedToGraphicsProxyWidget(q, updateRect)) return; #ifndef QT_MAC_USE_COCOA -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - dirtyOnWidget += updateRect; - HIRect r = CGRectMake(x, y, w, h); - HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true); - } else - #endif - { - q->update(QRegion(updateRect)); - } + dirtyOnWidget += updateRect; + HIRect r = CGRectMake(x, y, w, h); + HIViewSetNeedsDisplayInRect(qt_mac_nativeview_for(q), &r, true); #else [qt_mac_nativeview_for(q) setNeedsDisplayInRect:NSMakeRect(x, y, w, h)]; #endif @@ -4294,32 +4245,14 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) OSViewRef view = qt_mac_nativeview_for(q); #ifndef QT_MAC_USE_COCOA HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height()); -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); - if (err) { - // The only parameter that can go wrong, is the rect. - qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect"); - scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0), - qMin(r.width(), q->width()), qMin(r.height(), q->height())); - _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); - } - } else { - if (HIViewGetNeedsDisplay(view)) { - q->update(valid_rect ? r : q->rect()); - return; - } - HIRect scrollrect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - OSStatus err = HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy); - if (err) { - // The only parameter that can go wrong, is the rect. - qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect"); - scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0), - qMin(r.width(), q->width()), qMin(r.height(), q->height())); - HIViewScrollRect(view, valid_rect ? &scrollrect : 0, dx, dy); - } + OSStatus err = _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); + if (err) { + // The only parameter that can go wrong, is the rect. + qWarning("QWidget::scroll: Your rectangle was too big for the widget, clipping rect"); + scrollrect = CGRectMake(qMax(r.x(), 0), qMax(r.y(), 0), + qMin(r.width(), q->width()), qMin(r.height(), q->height())); + _HIViewScrollRectWithOptions(view, valid_rect ? &scrollrect : 0, dx, dy, kHIViewScrollRectAdjustInvalid); } -# endif #else NSRect scrollRect = valid_rect ? NSMakeRect(r.x(), r.y(), r.width(), r.height()) : NSMakeRect(0, 0, q->width(), q->height()); @@ -4347,20 +4280,9 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } - // ### Scroll the dirty regions as well, the following is not correct. - QRegion displayRegion = r.isNull() ? dirtyOnWidget : (dirtyOnWidget & r); - const QVector<QRect> &rects = dirtyOnWidget.rects(); - const QVector<QRect>::const_iterator end = rects.end(); - QVector<QRect>::const_iterator it = rects.begin(); - while (it != end) { - const QRect rect = *it; - const NSRect dirtyRect = NSMakeRect(rect.x() + dx, rect.y() + dy, - rect.width(), rect.height()); - [view setNeedsDisplayInRect:dirtyRect]; - ++it; - } - [view scrollRect:scrollRect by:NSMakeSize(dx, dy)]; - // Yes, we potentially send a duplicate area, but I think Cocoa can handle it. + NSSize deltaSize = NSMakeSize(dx, dy); + [view translateRectsNeedingDisplayInRect:scrollRect by:deltaSize]; + [view scrollRect:scrollRect by:deltaSize]; [view setNeedsDisplayInRect:deltaXRect]; [view setNeedsDisplayInRect:deltaYRect]; #endif // QT_MAC_USE_COCOA @@ -4871,11 +4793,9 @@ void QWidgetPrivate::macUpdateMetalAttribute() if (layout) layout->updateHIToolBarStatus(); ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalAttribute, 0); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); + ChangeWindowAttributes(qt_mac_window_for(q), kWindowMetalNoContentSeparatorAttribute, 0); } else { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); + ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalNoContentSeparatorAttribute); ChangeWindowAttributes(qt_mac_window_for(q), 0, kWindowMetalAttribute); if (layout) layout->updateHIToolBarStatus(); diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index d3b4157..34bc578 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -258,7 +258,10 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn) bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget) { const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft())); - return windowSurface->scroll(QRect(pos, rect.size()), dx, dy); + const QRect tlwRect(QRect(pos, rect.size())); + if (dirty.intersects(tlwRect)) + return false; // We don't want to scroll junk. + return windowSurface->scroll(tlwRect, dx, dy); } void QWidgetBackingStore::releaseBuffer() diff --git a/src/gui/painting/qpaintdevice_mac.cpp b/src/gui/painting/qpaintdevice_mac.cpp index 92ca52d..7de56ac 100644 --- a/src/gui/painting/qpaintdevice_mac.cpp +++ b/src/gui/painting/qpaintdevice_mac.cpp @@ -142,14 +142,9 @@ Q_GUI_EXPORT CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) if (pdev->devType() == QInternal::Pixmap) { const QPixmap *pm = static_cast<const QPixmap*>(pdev); CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint flags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - flags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; #endif CGContextRef ret = 0; diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index 282cce8..793460f 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -102,14 +102,9 @@ QMacCGContext::QMacCGContext(QPainter *p) extern CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice); CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint flags = kCGImageAlphaPremultipliedFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - flags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; #endif const QImage *image = (const QImage *) pe->paintDevice(); @@ -528,23 +523,12 @@ static void qt_mac_dispose_pattern(void *info) inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features() { - QPaintEngine::PaintEngineFeatures ret(QPaintEngine::AllFeatures - & ~QPaintEngine::PaintOutsidePaintEvent - & ~QPaintEngine::PerspectiveTransform - & ~QPaintEngine::ConicalGradientFill - & ~QPaintEngine::LinearGradientFill - & ~QPaintEngine::RadialGradientFill - & ~QPaintEngine::BrushStroke); - -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - ; - } else -#endif - { - ret &= ~QPaintEngine::BlendModes; - } - return ret; + return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent + & ~QPaintEngine::PerspectiveTransform + & ~QPaintEngine::ConicalGradientFill + & ~QPaintEngine::LinearGradientFill + & ~QPaintEngine::RadialGradientFill + & ~QPaintEngine::BrushStroke); } QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine() @@ -994,22 +978,8 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); image = qt_mac_create_imagemask(pm, sr); } else if (differentSize) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QCFType<CGImageRef> img = pm.toMacCGImageRef(); - image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); - } else -#endif - { - const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); - const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm.data); - quint32 *pantherData = pmData->pixels + sy * (pmData->bytesPerRow / 4) + sx; - QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, pantherData, sw*sh*pmData->bytesPerRow, 0); - image = CGImageCreate(sw, sh, 8, 32, pmData->bytesPerRow, - macGenericColorSpace(), - kCGImageAlphaPremultipliedFirst, provider, 0, 0, - kCGRenderingIntentDefault); - } + QCFType<CGImageRef> img = pm.toMacCGImageRef(); + image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); } else { image = (CGImageRef)pm.macCGHandle(); } @@ -1031,11 +1001,7 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag else image = new QImage(img); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNone; -#else - CGImageAlphaInfo cgflags = kCGImageAlphaNone; -#endif switch (image->format()) { case QImage::Format_ARGB32_Premultiplied: cgflags = kCGImageAlphaPremultipliedFirst; @@ -1048,9 +1014,8 @@ CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imag default: break; } -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) && defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; +#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version + cgflags |= kCGBitmapByteOrder32Host; #endif QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image, static_cast<const QImage *>(image)->bits(), @@ -1078,27 +1043,9 @@ void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, con const QImage *image; QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image); CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); - if (QRectF(0, 0, img.width(), img.height()) != sr) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), - sr.width(), sr.height())); - } else -#endif - { - int sx = qRound(sr.x()); - int sy = qRound(sr.y()); - int sw = qRound(sr.width()); - int sh = qRound(sr.height()); - // Make another CGImage based on the part that we need. - const uchar *pantherData = image->scanLine(sy) + sx * sizeof(uint); - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, pantherData, - sw * sh * image->bytesPerLine(), 0); - cgimage = CGImageCreate(sw, sh, 8, 32, image->bytesPerLine(), - macGenericColorSpace(), - CGImageGetAlphaInfo(cgimage), dataProvider, 0, false, kCGRenderingIntentDefault); - } - } + if (QRectF(0, 0, img.width(), img.height()) != sr) + cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), + sr.width(), sr.height())); qt_mac_drawCGImage(d->hd, &rect, cgimage); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 37f7b6d..37a88a3 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1322,6 +1322,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) delete s->clip; s->clip = clip; + s->clip->enabled = true; s->flags.has_clip_ownership = true; } else { // intersect clip with current clip @@ -1338,6 +1339,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) s->clip->setClipRect(base->clipRect & clipRect); else s->clip->setClipRegion(base->clipRegion & clipRect); + s->clip->enabled = true; } else { QPaintEngineEx::clip(rect, op); return; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 6953e04..34305c2 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2545,6 +2545,9 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op) Q_D(QPainter); if (d->extended) { + if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) + op = Qt::ReplaceClip; + if (!d->engine) { qWarning("QPainter::setClipRect: Painter not active"); return; @@ -2598,6 +2601,9 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) return; } + if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) + op = Qt::ReplaceClip; + if (d->extended) { d->state->clipEnabled = true; d->extended->clip(rect, op); @@ -2606,9 +2612,6 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) return; } - if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) - op = Qt::ReplaceClip; - d->state->clipRegion = rect; d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) @@ -2651,6 +2654,9 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) return; } + if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) + op = Qt::ReplaceClip; + if (d->extended) { d->state->clipEnabled = true; d->extended->clip(r, op); @@ -2659,9 +2665,6 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) return; } - if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) - op = Qt::ReplaceClip; - d->state->clipRegion = r; d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) @@ -3048,6 +3051,9 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) return; } + if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) + op = Qt::ReplaceClip; + if (d->extended) { d->state->clipEnabled = true; d->extended->clip(path, op); @@ -3056,11 +3062,6 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) return; } - - - if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) - op = Qt::ReplaceClip; - d->state->clipPath = path; d->state->clipOperation = op; if (op == Qt::NoClip || op == Qt::ReplaceClip) diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index a94c91d..6850841 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -462,8 +462,8 @@ QVector<qreal> QPen::dashPattern() const Sets the dash pattern for this pen to the given \a pattern. This implicitly converts the style of the pen to Qt::CustomDashLine. - The pattern must be specified as an even number of entries where - the entries 1, 3, 5... are the dashes and 2, 4, 6... are the + The pattern must be specified as an even number of positive entries + where the entries 1, 3, 5... are the dashes and 2, 4, 6... are the spaces. For example: \table 100% diff --git a/src/gui/painting/qprintengine_mac.mm b/src/gui/painting/qprintengine_mac.mm index 255a0a1..1c4505f 100644 --- a/src/gui/painting/qprintengine_mac.mm +++ b/src/gui/painting/qprintengine_mac.mm @@ -92,16 +92,8 @@ bool QMacPrintEngine::begin(QPaintDevice *dev) } OSStatus status = noErr; #ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format) - : PMSessionBeginCGDocument(d->session, d->settings, d->format); - } else -# endif - { - status = d->shouldSuppressStatus() ? PMSessionBeginDocumentNoDialog(d->session, d->settings, d->format) - : PMSessionBeginDocument(d->session, d->settings, d->format); - } + status = d->shouldSuppressStatus() ? PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format) + : PMSessionBeginCGDocument(d->session, d->settings, d->format); #else status = PMSessionBeginCGDocumentNoDialog(d->session, d->settings, d->format); #endif @@ -468,23 +460,6 @@ void QMacPrintEnginePrivate::initialize() #endif #ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_4) -# endif - { - if(paintEngine->type() == QPaintEngine::CoreGraphics) { - CFStringRef strings[1] = { kPMGraphicsContextCoreGraphics }; - QCFType<CFArrayRef> contextArray = CFArrayCreate(kCFAllocatorDefault, - reinterpret_cast<const void **>(strings), - 1, &kCFTypeArrayCallBacks); - OSStatus err = PMSessionSetDocumentFormatGeneration(session, kPMDocumentFormatPDF, - contextArray, 0); - if(err != noErr) { - qWarning("QMacPrintEngine::initialize: Cannot set format generation to PDF: %ld", err); - state = QPrinter::Error; - } - } - } if (!settingsOK || !formatOK) { qWarning("QMacPrintEngine::initialize: Unable to initialize QPainter"); state = QPrinter::Error; @@ -551,19 +526,7 @@ bool QMacPrintEnginePrivate::newPage_helper() CGContextRef cgContext; OSStatus err = noErr; -#ifndef QT_MAC_USE_COCOA -# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - err = PMSessionGetCGGraphicsContext(session, &cgContext); - } else -# endif - { - err = PMSessionGetGraphicsContext(session, kPMGraphicsContextCoreGraphics, - reinterpret_cast<void **>(&cgContext)); - } -#else err = PMSessionGetCGGraphicsContext(session, &cgContext); -#endif if(err != noErr) { qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); state = QPrinter::Error; diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp index 9cf94b2..c84271c 100644 --- a/src/gui/painting/qprinterinfo_mac.cpp +++ b/src/gui/painting/qprinterinfo_mac.cpp @@ -172,16 +172,9 @@ bool QPrinterInfo::isDefault() const QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const { -#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4) - return QList<QPrinter::PaperSize>(); -#else - if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_4) - return QList<QPrinter::PaperSize>(); - const Q_D(QPrinterInfo); - PMPrinter cfPrn = PMPrinterCreateFromPrinterID( - QCFString::toCFStringRef(d->m_name)); + PMPrinter cfPrn = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(d->m_name)); if (!cfPrn) return QList<QPrinter::PaperSize>(); @@ -211,7 +204,6 @@ QList<QPrinter::PaperSize> QPrinterInfo::supportedPaperSizes() const PMRelease(cfPrn); return paperList; -#endif // MAC_OS_X_VERSION_MAX_ALLOWED } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 8499811..852d3fd 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -150,7 +150,6 @@ bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e) if (e->type() == QEvent::ApplicationPaletteChange) { // Only do this the first time since this will also // generate applicationPaletteChange events - extern QHash<QByteArray, QPalette> *qt_app_palettes_hash(); //qapplication.cpp if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) { QGtk::applyCustomPaletteHash(); } diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 262fbcb..f88d90a 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -50,6 +50,7 @@ #define QMAC_QAQUASTYLE_SIZE_CONSTRAIN //#define DEBUG_SIZE_CONSTRAINT +#include <private/qapplication_p.h> #include <private/qcombobox_p.h> #include <private/qmacstylepixmaps_mac_p.h> #include <private/qpaintengine_mac_p.h> @@ -103,7 +104,6 @@ QT_BEGIN_NAMESPACE extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp // The following constants are used for adjusting the size // of push buttons so that they are drawn inside their bounds. @@ -581,11 +581,7 @@ QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background. *****************************************************************************/ static inline int qt_mac_hitheme_tab_version() { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - return 1; -#endif - return 0; + return 1; } static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect()) @@ -1471,8 +1467,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti } // Tiger broke reverse scroll bars so put them back and "fake it" - if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft) - && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) { tdi->attributes &= ~kThemeTrackRightToLeft; tdi->value = tdi->max - slider->sliderPosition; } @@ -2027,22 +2022,10 @@ QMacStyle::~QMacStyle() QPixmap QMacStylePrivate::generateBackgroundPattern() const { QPixmap px(4, 4); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - QMacCGContext cg(&px); - HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); - const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); - CGContextFillRect(cg, cgRect); - } else -#endif - { -#ifndef QT_MAC_NO_QUICKDRAW - QMacSavedPortInfo port(&px); - SetThemeBackground(kThemeBrushDialogBackgroundActive, px.depth(), true); - const Rect qdRect = { 0, 0, px.width(), px.height() }; - EraseRect(&qdRect); -#endif - } + QMacCGContext cg(&px); + HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); + const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); + CGContextFillRect(cg, cgRect); return px; } @@ -2052,14 +2035,13 @@ QPixmap QMacStylePrivate::generateBackgroundPattern() const */ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset, const QBrush &brush) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) QPoint dummy; const QPaintDevice *target = painter->device(); const QPaintDevice *redirected = QPainter::redirected(target, &dummy); const bool usePainter = redirected && redirected != target; const QRegion translated = rgn.translated(offset); - if (!usePainter && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 && qt_mac_backgroundPattern + if (!usePainter && qt_mac_backgroundPattern && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { painter->setClipRegion(translated); @@ -2078,9 +2060,7 @@ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint } CGContextRestoreGState(cg); - } else -#endif - { + } else { const QRect rect(translated.boundingRect()); painter->setClipRegion(translated); painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); @@ -3318,27 +3298,14 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { HIRect hirect = qt_hirectForQRect(twf->rect); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - HIThemeTabPaneDrawInfo tpdi; - tpdi.version = qt_mac_hitheme_tab_version(); - tpdi.state = tds; - tpdi.direction = getTabDirection(twf->shape); - tpdi.size = kHIThemeTabSizeNormal; - if (tpdi.version == 1) { - tpdi.kind = kHIThemeTabKindNormal; - tpdi.adornment = kHIThemeTabPaneAdornmentNormal; - } - HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); - } else -#endif - { - HIThemeGroupBoxDrawInfo gdi; - gdi.version = qt_mac_hitheme_version; - gdi.state = tds; - gdi.kind = kHIThemeGroupBoxKindSecondary; - HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); - } + HIThemeTabPaneDrawInfo tpdi; + tpdi.version = qt_mac_hitheme_tab_version(); + tpdi.state = tds; + tpdi.direction = getTabDirection(twf->shape); + tpdi.size = kHIThemeTabSizeNormal; + tpdi.kind = kHIThemeTabKindNormal; + tpdi.adornment = kHIThemeTabPaneAdornmentNormal; + HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); } break; case PE_PanelScrollAreaCorner: { @@ -3362,7 +3329,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai QWindowsStyle::drawPrimitive(pe, opt, p, w); break; } - // Use the Leopard style only if the status bar is the status bar for a // QMainWindow with a unifed toolbar. if (w == 0 || w->parent() == 0 || qobject_cast<QMainWindow *>(w->parent()) == 0 || @@ -4812,10 +4778,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex // similar when I have an upside down scroll bar // because on Tiger I only "fake" the reverse stuff. bool reverseHorizontal = (slider->direction == Qt::RightToLeft - && slider->orientation == Qt::Horizontal - && (!slider->upsideDown - || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 - && slider->upsideDown))); + && slider->orientation == Qt::Horizontal); if ((reverseHorizontal && slider->activeSubControls == SC_ScrollBarAddLine) || (!reverseHorizontal @@ -5450,11 +5413,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart : kControlDownButtonPart; if (slider->direction == Qt::RightToLeft - && slider->orientation == Qt::Horizontal - && (!slider->upsideDown - || (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 - && slider->upsideDown)) - ) { + && slider->orientation == Qt::Horizontal) { if (cpc == kControlDownButtonPart) cpc = kControlUpButtonPart; else if (cpc == kControlUpButtonPart) @@ -5772,11 +5731,6 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, break; case QStyle::CT_TabBarTab: if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { - bool newStyleTabs = -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) - QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? true : -#endif - false; const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware(); @@ -5784,86 +5738,61 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; if (vertTabs) sz.transpose(); - if (newStyleTabs) { - int defaultTabHeight; - int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK) - QFontMetrics fm = opt->fontMetrics; - switch (AquaSize) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - if (tab->documentMode) - defaultTabHeight = 23; - else - defaultTabHeight = 21; - break; - case QAquaSizeSmall: - defaultTabHeight = 18; - break; - case QAquaSizeMini: - defaultTabHeight = 16; - break; - } - - bool setWidth = false; - if (differentFont || !tab->icon.isNull()) { - sz.rheight() = qMax(defaultTabHeight, sz.height()); - } else { - QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); - sz.rheight() = qMax(defaultTabHeight, textSize.height()); - sz.rwidth() = textSize.width() + defaultExtraSpace; - setWidth = true; - } + int defaultTabHeight; + int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK) + QFontMetrics fm = opt->fontMetrics; + switch (AquaSize) { + case QAquaSizeUnknown: + case QAquaSizeLarge: + if (tab->documentMode) + defaultTabHeight = 23; + else + defaultTabHeight = 21; + break; + case QAquaSizeSmall: + defaultTabHeight = 18; + break; + case QAquaSizeMini: + defaultTabHeight = 16; + break; + } + bool setWidth = false; + if (differentFont || !tab->icon.isNull()) { + sz.rheight() = qMax(defaultTabHeight, sz.height()); + } else { + QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); + sz.rheight() = qMax(defaultTabHeight, textSize.height()); + sz.rwidth() = textSize.width() + defaultExtraSpace; + setWidth = true; + } - if (vertTabs) - sz.transpose(); + if (vertTabs) + sz.transpose(); - int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); - int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); + int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); + int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); - int widgetWidth = 0; - int widgetHeight = 0; - int padding = 0; - if (tab->leftButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->leftButtonSize.width(); - widgetHeight += tab->leftButtonSize.height(); - } - if (tab->rightButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->rightButtonSize.width(); - widgetHeight += tab->rightButtonSize.height(); - } + int widgetWidth = 0; + int widgetHeight = 0; + int padding = 0; + if (tab->leftButtonSize.isValid()) { + padding += 8; + widgetWidth += tab->leftButtonSize.width(); + widgetHeight += tab->leftButtonSize.height(); + } + if (tab->rightButtonSize.isValid()) { + padding += 8; + widgetWidth += tab->rightButtonSize.width(); + widgetHeight += tab->rightButtonSize.height(); + } - if (vertTabs) { - sz.setHeight(sz.height() + widgetHeight + padding); - sz.setWidth(qMax(sz.width(), maxWidgetWidth)); - } else { - if (setWidth) - sz.setWidth(sz.width() + widgetWidth + padding); - sz.setHeight(qMax(sz.height(), maxWidgetHeight)); - } + if (vertTabs) { + sz.setHeight(sz.height() + widgetHeight + padding); + sz.setWidth(qMax(sz.width(), maxWidgetWidth)); } else { - SInt32 tabh = sz.height(); - SInt32 overlap = 0; - switch (AquaSize) { - default: - case QAquaSizeUnknown: - case QAquaSizeLarge: - GetThemeMetric(kThemeLargeTabHeight, &tabh); - GetThemeMetric(kThemeMetricTabFrameOverlap, &overlap); - break; - case QAquaSizeMini: - GetThemeMetric(kThemeMetricMiniTabHeight, &tabh); - GetThemeMetric(kThemeMetricMiniTabFrameOverlap, &overlap); - break; - case QAquaSizeSmall: - GetThemeMetric(kThemeSmallTabHeight, &tabh); - GetThemeMetric(kThemeMetricSmallTabFrameOverlap, &overlap); - break; - } - tabh += overlap; - if (sz.height() < tabh) - sz.rheight() = tabh; + if (setWidth) + sz.setWidth(sz.width() + widgetWidth + padding); + sz.setHeight(qMax(sz.height(), maxWidgetHeight)); } } break; @@ -6152,11 +6081,9 @@ QIcon QMacStyle::standardIconImplementation(StandardPixmap standardIcon, const Q case SP_TrashIcon: iconType = kTrashIcon; break; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) case SP_ComputerIcon: iconType = kComputerIcon; break; -#endif case SP_DriveFDIcon: iconType = kGenericFloppyIcon; break; diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 283c37a..7a75a7d 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -1047,7 +1047,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QRect ir = subElementRect(SE_PushButtonContents, option, 0); QStyleOptionButton newBtn = *btn; newBtn.rect = QStyle::visualRect(option->direction, option->rect, - QRect(ir.right() - mbiw - 2, (option->rect.height()/2) - (mbih/2), + QRect(ir.right() - mbiw - 2, + option->rect.top() + (option->rect.height()/2) - (mbih/2), mbiw + 1, mbih + 1)); proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); } @@ -1655,7 +1656,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle if (sub & SC_ComboBoxArrow) { QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); XPThemeData theme(widget, painter, QLatin1String("COMBOBOX")); - theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); + theme.rect = subRect; partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT; if (!(cmb->state & State_Enabled)) diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 09e5b93..b0eae1f 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -3358,6 +3358,10 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con res = 0; break; + case PM_ButtonDefaultIndicator: + res = 0; + break; + default: res = QWindowsStyle::pixelMetric(pm, option, widget); } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 3f65e42..8d5b460 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -442,7 +442,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp -#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_WS_MAC) +#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index f596449..2f6788f 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE int qt_mac_pixelsize(const QFontDef &def, int dpi); //qfont_mac.cpp int qt_mac_pointsize(const QFontDef &def, int dpi); //qfont_mac.cpp +#ifndef QT_MAC_USE_COCOA static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont) { ByteCount length = 0; @@ -81,6 +82,7 @@ qDebug() << "first char" << hex << unicodeRange[0]; for (int i = 0; i < systems.count(); ++i) family->writingSystems[systems.at(i)] = QtFontFamily::Supported; } +#endif static void initializeDb() { diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index b80e52d..76132df 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -540,14 +540,9 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph) im.fill(0); CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst; + cgflags |= kCGBitmapByteOrder32Host; #endif CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, @@ -1019,11 +1014,6 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph | kATSLineDisableAllJustification ; - if (!(flags & QTextEngine::DesignMetrics)) { - layopts |= kATSLineFractDisable | kATSLineUseDeviceMetrics - | kATSLineDisableAutoAdjustDisplayPos; - } - if (fontDef.styleStrategy & QFont::NoAntialias) layopts |= kATSLineNoAntiAliasing; @@ -1436,14 +1426,9 @@ QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful) im.fill(0xff000000); CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) uint cgflags = kCGImageAlphaNoneSkipFirst; #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - if(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) - cgflags |= kCGBitmapByteOrder32Host; -#endif -#else - CGImageAlphaInfo cgflags = kCGImageAlphaNoneSkipFirst; + cgflags |= kCGBitmapByteOrder32Host; #endif CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), 8, im.bytesPerLine(), colorspace, diff --git a/src/gui/util/qsystemtrayicon_mac.mm b/src/gui/util/qsystemtrayicon_mac.mm index 370bc0c..b733db5 100644 --- a/src/gui/util/qsystemtrayicon_mac.mm +++ b/src/gui/util/qsystemtrayicon_mac.mm @@ -124,12 +124,20 @@ QT_USE_NAMESPACE -(void)mousePressed:(NSEvent *)mouseEvent; @end -@interface QNSMenu : NSMenu { + +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 + +@protocol NSMenuDelegate <NSObject> +-(void)menuNeedsUpdate:(NSMenu*)menu; +@end +#endif + + +@interface QNSMenu : NSMenu <NSMenuDelegate> { QMenu *qmenu; } -(QMenu*)menu; -(id)initWithQMenu:(QMenu*)qmenu; --(void)menuNeedsUpdate:(QNSMenu*)menu; -(void)selectedAction:(id)item; @end @@ -455,10 +463,11 @@ private: } return self; } --(QMenu*)menu { - return qmenu; +-(QMenu*)menu { + return qmenu; } --(void)menuNeedsUpdate:(QNSMenu*)menu { +-(void)menuNeedsUpdate:(NSMenu*)nsmenu { + QNSMenu *menu = static_cast<QNSMenu *>(nsmenu); emit static_cast<QSystemTrayIconQMenu*>(menu->qmenu)->doAboutToShow(); for(int i = [menu numberOfItems]-1; i >= 0; --i) [menu removeItemAtIndex:i]; diff --git a/src/gui/widgets/qcocoamenu_mac_p.h b/src/gui/widgets/qcocoamenu_mac_p.h index cd53692..8eb6fba 100644 --- a/src/gui/widgets/qcocoamenu_mac_p.h +++ b/src/gui/widgets/qcocoamenu_mac_p.h @@ -56,16 +56,23 @@ QT_FORWARD_DECLARE_CLASS(QMenu) -@interface QT_MANGLE_NAMESPACE(QCocoaMenu) : NSMenu -{ - QMenu *qmenu; -} -- (id)initWithQMenu:(QMenu*)menu; +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 + +@protocol NSMenuDelegate <NSObject> - (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item; - (void)menuWillOpen:(NSMenu*)menu; - (void)menuWillClose:(NSMenu*)menu; - (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier whichItem:(NSMenuItem**)outItem; +@end + +#endif + +@interface QT_MANGLE_NAMESPACE(QCocoaMenu) : NSMenu <NSMenuDelegate> +{ + QMenu *qmenu; +} +- (id)initWithQMenu:(QMenu*)menu; - (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action; @end #endif diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index ad6f3db..1ca878d 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -59,6 +59,7 @@ #ifndef QT_NO_IM #include "qinputcontext.h" #endif +#include <private/qapplication_p.h> #include <private/qcombobox_p.h> #include <private/qabstractitemmodel_p.h> #include <private/qabstractscrollarea_p.h> @@ -77,8 +78,6 @@ #endif QT_BEGIN_NAMESPACE -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); - QComboBoxPrivate::QComboBoxPrivate() : QWidgetPrivate(), model(0), diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index 3125304..cbfa5bf 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -924,43 +924,41 @@ static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delt return delta; } -int QDockAreaLayoutInfo::separatorMove(int index, int delta, QVector<QLayoutStruct> *cache) +int QDockAreaLayoutInfo::separatorMove(int index, int delta) { #ifndef QT_NO_TABBAR Q_ASSERT(!tabbed); #endif - if (cache->isEmpty()) { - QVector<QLayoutStruct> &list = *cache; - list.resize(item_list.size()); - for (int i = 0; i < item_list.size(); ++i) { - const QDockAreaLayoutItem &item = item_list.at(i); - QLayoutStruct &ls = list[i]; - Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem)); - if (item.skip()) { - ls.empty = true; - } else { - ls.empty = false; - ls.pos = item.pos; - ls.size = item.size; - ls.minimumSize = pick(o, item.minimumSize()); - ls.maximumSize = pick(o, item.maximumSize()); - } + QVector<QLayoutStruct> list(item_list.size()); + for (int i = 0; i < list.size(); ++i) { + const QDockAreaLayoutItem &item = item_list.at(i); + QLayoutStruct &ls = list[i]; + Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem)); + if (item.skip()) { + ls.empty = true; + } else { + const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + ls.empty = false; + ls.pos = item.pos; + ls.size = item.size + separatorSpace; + ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace; + ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace; + } } - QVector<QLayoutStruct> list = *cache; - - delta = separatorMoveHelper(list, index, delta, sep); + //the separator space has been added to the size, so we pass 0 as a parameter + delta = separatorMoveHelper(list, index, delta, 0 /*separator*/); - for (int i = 0; i < item_list.size(); ++i) { + for (int i = 0; i < list.size(); ++i) { QDockAreaLayoutItem &item = item_list[i]; if (item.skip()) continue; QLayoutStruct &ls = list[i]; - item.size = ls.size; + const int separatorSpace = item.hasFixedSize(o) ? 0 : sep; + item.size = ls.size - separatorSpace; item.pos = ls.pos; - if (item.subinfo != 0) { item.subinfo->rect = itemRect(i); item.subinfo->fitItems(); @@ -1974,7 +1972,6 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> } else { int dummy; stream >> item.pos >> item.size >> dummy >> dummy; - // qDebug() << widget << item.pos << item.size; if (!testing) { widget->setFloating(false); widget->setVisible(flags & StateFlagVisible); @@ -3115,31 +3112,29 @@ QRegion QDockAreaLayout::separatorRegion() const } int QDockAreaLayout::separatorMove(QList<int> separator, const QPoint &origin, - const QPoint &dest, - QVector<QLayoutStruct> *cache) + const QPoint &dest) { int delta = 0; int index = separator.last(); + + if (separator.count() > 1) { QDockAreaLayoutInfo *info = this->info(separator); delta = pick(info->o, dest - origin); if (delta != 0) - delta = info->separatorMove(index, delta, cache); + delta = info->separatorMove(index, delta); info->apply(false); return delta; } - if (cache->isEmpty()) { - QVector<QLayoutStruct> &list = *cache; + QVector<QLayoutStruct> list; - if (index == QInternal::LeftDock || index == QInternal::RightDock) - getGrid(0, &list); - else - getGrid(&list, 0); - } + if (index == QInternal::LeftDock || index == QInternal::RightDock) + getGrid(0, &list); + else + getGrid(&list, 0); - QVector<QLayoutStruct> list = *cache; int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock ? 0 : 1; Qt::Orientation o = index == QInternal::LeftDock || index == QInternal::RightDock diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h index 137aeba..771aa52 100644 --- a/src/gui/widgets/qdockarealayout_p.h +++ b/src/gui/widgets/qdockarealayout_p.h @@ -181,7 +181,7 @@ public: void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const; QRegion separatorRegion() const; - int separatorMove(int index, int delta, QVector<QLayoutStruct> *cache); + int separatorMove(int index, int delta); QLayoutItem *itemAt(int *x, int index) const; QLayoutItem *takeAt(int *x, int index); @@ -277,8 +277,7 @@ public: void paintSeparators(QPainter *p, QWidget *widget, const QRegion &clip, const QPoint &mouse) const; QRegion separatorRegion() const; - int separatorMove(QList<int> separator, const QPoint &origin, const QPoint &dest, - QVector<QLayoutStruct> *cache); + int separatorMove(QList<int> separator, const QPoint &origin, const QPoint &dest); void updateSeparatorWidgets() const; QLayoutItem *itemAt(int *x, int index) const; diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp index cf259fb..4350520 100644 --- a/src/gui/widgets/qdockwidget.cpp +++ b/src/gui/widgets/qdockwidget.cpp @@ -59,6 +59,7 @@ #include "qdockwidget_p.h" #include "qmainwindowlayout_p.h" #ifdef Q_WS_MAC +#include <private/qapplication_p.h> #include <private/qt_mac_p.h> #include <qmacstyle_mac.h> #endif @@ -67,8 +68,6 @@ QT_BEGIN_NAMESPACE extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); // qwidget.cpp -extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp - static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature) { return (priv->features & feature) == feature; } diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 10e07d3..526e7a5 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1304,30 +1304,15 @@ bool QMainWindowLayout::separatorMove(const QPoint &pos) if (movingSeparator.isEmpty()) return false; movingSeparatorPos = pos; - separatorMoveTimer->start(); + separatorMoveTimer.start(0, this); return true; } -void QMainWindowLayout::doSeparatorMove() -{ - if (movingSeparator.isEmpty()) - return; - if (movingSeparatorOrigin == movingSeparatorPos) - return; - - layoutState = savedState; - layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin, - movingSeparatorPos, - &separatorMoveCache); - movingSeparatorPos = movingSeparatorOrigin; -} - bool QMainWindowLayout::endSeparatorMove(const QPoint&) { bool result = !movingSeparator.isEmpty(); movingSeparator.clear(); savedState.clear(); - separatorMoveCache.clear(); return result; } @@ -1687,10 +1672,6 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) #ifndef QT_NO_TABBAR sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow); #endif - separatorMoveTimer = new QTimer(this); - separatorMoveTimer->setSingleShot(true); - separatorMoveTimer->setInterval(0); - connect(separatorMoveTimer, SIGNAL(timeout()), this, SLOT(doSeparatorMove())); #ifndef QT_NO_TABWIDGET for (int i = 0; i < QInternal::DockCount; ++i) @@ -1982,6 +1963,27 @@ bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const #endif } +void QMainWindowLayout::timerEvent(QTimerEvent *e) +{ +#ifndef QT_NO_DOCKWIDGET + if (e->timerId() == separatorMoveTimer.timerId()) { + //let's move the separators + separatorMoveTimer.stop(); + if (movingSeparator.isEmpty()) + return; + if (movingSeparatorOrigin == movingSeparatorPos) + return; + + layoutState = savedState; + layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin, + movingSeparatorPos); + movingSeparatorPos = movingSeparatorOrigin; + } +#endif + QLayout::timerEvent(e); +} + + QT_END_NAMESPACE #endif // QT_NO_MAINWINDOW diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 03bae2f..6632be7 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -329,18 +329,16 @@ OSStatus QMainWindowLayout::qtmacToolbarDelegate(EventHandlerCallRef, EventRef e void QMainWindowLayout::updateHIToolBarStatus() { bool useMacToolbar = layoutState.mainWindow->unifiedTitleAndToolBarOnMac(); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { #ifndef QT_MAC_USE_COCOA - if (useMacToolbar) { - ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow), - kWindowUnifiedTitleAndToolbarAttribute, 0); - } else { - ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow), - 0, kWindowUnifiedTitleAndToolbarAttribute); - } -#endif - macWindowToolbarShow(layoutState.mainWindow, useMacToolbar); + if (useMacToolbar) { + ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow), + kWindowUnifiedTitleAndToolbarAttribute, 0); + } else { + ChangeWindowAttributes(qt_mac_window_for(layoutState.mainWindow), + 0, kWindowUnifiedTitleAndToolbarAttribute); } +#endif + macWindowToolbarShow(layoutState.mainWindow, useMacToolbar); layoutState.mainWindow->setUpdatesEnabled(false); // reduces a little bit of flicker, not all though if (!useMacToolbar) { diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index f5fcbda..26f8633 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -61,6 +61,7 @@ #include "QtGui/qtabbar.h" #include "QtCore/qvector.h" #include "QtCore/qset.h" +#include "QtCore/qbasictimer.h" #include "private/qlayoutengine_p.h" #include "qdockarealayout_p.h" @@ -165,6 +166,8 @@ public: void setDockOptions(QMainWindow::DockOptions opts); bool usesHIToolBar(QToolBar *toolbar) const; + void timerEvent(QTimerEvent *e); + // status bar QLayoutItem *statusbar; @@ -243,8 +246,7 @@ public: QList<int> movingSeparator; QPoint movingSeparatorOrigin, movingSeparatorPos; - QTimer *separatorMoveTimer; - QVector<QLayoutStruct> separatorMoveCache; + QBasicTimer separatorMoveTimer; bool startSeparatorMove(const QPoint &pos); bool separatorMove(const QPoint &pos); @@ -298,7 +300,6 @@ private slots: void animationFinished(QWidget *widget); void allAnimationsFinished(); #ifndef QT_NO_DOCKWIDGET - void doSeparatorMove(); #ifndef QT_NO_TABBAR void tabChanged(); #endif diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 73af174..c92b8cf 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -62,12 +62,9 @@ x11 { contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles1cl)|contains(QT_CONFIG, opengles2) { SOURCES += qgl_x11egl.cpp \ qglpixelbuffer_egl.cpp \ - qgl_egl.cpp \ - qegl.cpp \ - qegl_x11egl.cpp + qgl_egl.cpp - HEADERS += qegl_p.h \ - qgl_egl_p.h + HEADERS += qgl_egl_p.h } else { SOURCES += qgl_x11.cpp \ @@ -93,13 +90,10 @@ win32:!wince*: { wince*: { SOURCES += qgl_wince.cpp \ qglpixelbuffer_egl.cpp \ - qgl_egl.cpp \ - qegl.cpp \ - qegl_wince.cpp + qgl_egl.cpp HEADERS += qgl_cl_p.h \ qgl_egl_p.h \ - qegl_p.h } embedded { @@ -108,15 +102,12 @@ embedded { qglpixelbuffer_egl.cpp \ qglscreen_qws.cpp \ qglwindowsurface_qws.cpp \ - qegl.cpp \ - qegl_qws.cpp \ qgl_egl.cpp HEADERS += qglpaintdevice_qws_p.h \ qglscreen_qws.h \ qglwindowsurface_qws_p.h \ - qgl_egl_p.h \ - qegl_p.h + qgl_egl_p.h contains(QT_CONFIG, fontconfig) { include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) diff --git a/src/opengl/qgl_egl_p.h b/src/opengl/qgl_egl_p.h index 2fb2e8f..d54036d 100644 --- a/src/opengl/qgl_egl_p.h +++ b/src/opengl/qgl_egl_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include "qegl_p.h" +#include <QtGui/private/qegl_p.h> QT_BEGIN_NAMESPACE diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp index 3b6ad63..a71a734 100644 --- a/src/opengl/qgl_qws.cpp +++ b/src/opengl/qgl_qws.cpp @@ -116,6 +116,57 @@ void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device) props.setPixelFormat(glScreen->pixelFormat()); } +static bool qt_egl_create_surface + (QEglContext *context, QPaintDevice *device, + const QEglProperties *properties = 0) +{ + // Get the screen surface functions, which are used to create native ids. + QGLScreen *glScreen = glScreenForDevice(device); + if (!glScreen) + return false; + QGLScreenSurfaceFunctions *funcs = glScreen->surfaceFunctions(); + if (!funcs) + return false; + + // Create the native drawable for the paint device. + int devType = device->devType(); + EGLNativePixmapType pixmapDrawable = 0; + EGLNativeWindowType windowDrawable = 0; + bool ok; + if (devType == QInternal::Pixmap) { + ok = funcs->createNativePixmap(static_cast<QPixmap *>(device), &pixmapDrawable); + } else if (devType == QInternal::Image) { + ok = funcs->createNativeImage(static_cast<QImage *>(device), &pixmapDrawable); + } else { + ok = funcs->createNativeWindow(static_cast<QWidget *>(device), &windowDrawable); + } + if (!ok) { + qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); + return false; + } + + // Create the EGL surface to draw into, based on the native drawable. + const int *props; + if (properties) + props = properties->properties(); + else + props = 0; + EGLSurface surf; + if (devType == QInternal::Widget) { + surf = eglCreateWindowSurface + (context->display(), context->config(), windowDrawable, props); + } else { + surf = eglCreatePixmapSurface + (context->display(), context->config(), pixmapDrawable, props); + } + if (surf == EGL_NO_SURFACE) { + qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); + return false; + } + context->setSurface(surf); + return true; +} + bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); @@ -131,7 +182,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // Get the display and initialize it. d->eglContext = new QEglContext(); - d->eglContext->setApi(QEglContext::OpenGL); + d->eglContext->setApi(QEgl::OpenGL); if (!d->eglContext->openDisplay(device())) { delete d->eglContext; d->eglContext = 0; @@ -142,7 +193,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) QEglProperties configProps; qt_egl_add_platform_config(configProps, device()); qt_egl_set_format(configProps, devType, d->glFormat); - configProps.setRenderableType(QEglContext::OpenGL); + configProps.setRenderableType(QEgl::OpenGL); // Search for a matching configuration, reducing the complexity // each time until we get something that matches. @@ -168,8 +219,10 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval()); #endif - // Create the EGL surface to draw into. - if (!d->eglContext->createSurface(device())) { + // Create the EGL surface to draw into. We cannot use + // QEglContext::createSurface() because it does not have + // access to the QGLScreen. + if (!qt_egl_create_surface(d->eglContext, device())) { delete d->eglContext; d->eglContext = 0; return false; diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp index 47dc2d4..afe26ab 100644 --- a/src/opengl/qgl_wince.cpp +++ b/src/opengl/qgl_wince.cpp @@ -140,7 +140,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // Get the display and initialize it. d->eglContext = new QEglContext(); - d->eglContext->setApi(QEglContext::OpenGL); + d->eglContext->setApi(QEgl::OpenGL); if (!d->eglContext->openDisplay(device())) { delete d->eglContext; d->eglContext = 0; @@ -151,7 +151,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) QEglProperties configProps; qt_egl_add_platform_config(configProps, device()); qt_egl_set_format(configProps, devType, d->glFormat); - configProps.setRenderableType(QEglContext::OpenGL); + configProps.setRenderableType(QEgl::OpenGL); // Search for a matching configuration, reducing the complexity // each time until we get something that matches. diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 7fdbfbd..9db3a30 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -77,7 +77,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) // Get the display and initialize it. d->eglContext = new QEglContext(); - d->eglContext->setApi(QEglContext::OpenGL); + d->eglContext->setApi(QEgl::OpenGL); if (!d->eglContext->openDisplay(device())) { delete d->eglContext; d->eglContext = 0; @@ -88,11 +88,11 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) QEglProperties configProps; qt_egl_set_format(configProps, devType, d->glFormat); qt_egl_add_platform_config(configProps, device()); - configProps.setRenderableType(QEglContext::OpenGL); + configProps.setRenderableType(QEgl::OpenGL); // Search for a matching configuration, reducing the complexity // each time until we get something that matches. - if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) { + if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) { delete d->eglContext; d->eglContext = 0; return false; diff --git a/src/opengl/qglpixelbuffer_egl.cpp b/src/opengl/qglpixelbuffer_egl.cpp index fca1a31..38e4f74 100644 --- a/src/opengl/qglpixelbuffer_egl.cpp +++ b/src/opengl/qglpixelbuffer_egl.cpp @@ -63,7 +63,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge { // Create the EGL context. ctx = new QEglContext(); - ctx->setApi(QEglContext::OpenGL); + ctx->setApi(QEgl::OpenGL); // Open the EGL display. if (!ctx->openDisplay(0)) { @@ -82,13 +82,13 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge #if QGL_RENDER_TEXTURE textureFormat = EGL_TEXTURE_RGBA; configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat); + ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat); if (!ok) { // Try again with RGB texture rendering. textureFormat = EGL_TEXTURE_RGB; configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA); configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat); + ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat); if (!ok) { // One last try for a pbuffer with no texture rendering. configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB); @@ -99,7 +99,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge textureFormat = EGL_NONE; #endif if (!ok) { - if (!ctx->chooseConfig(configProps, QEglContext::BestPixelFormat)) { + if (!ctx->chooseConfig(configProps, QEgl::BestPixelFormat)) { delete ctx; ctx = 0; return false; @@ -208,7 +208,7 @@ bool QGLPixelBuffer::hasOpenGLPbuffers() return false; QEglProperties configProps; qt_egl_set_format(configProps, QInternal::Pbuffer, QGLFormat::defaultFormat()); - configProps.setRenderableType(QEglContext::OpenGL); + configProps.setRenderableType(QEgl::OpenGL); return ctx.chooseConfig(configProps); } diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index e173a8d..638bfb3 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -768,7 +768,7 @@ public: bool isFastRect(const QRectF &r); void drawImageAsPath(const QRectF &r, const QImage &img, const QRectF &sr); - void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy); + void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset); void drawOffscreenPath(const QPainterPath &path); @@ -4222,13 +4222,15 @@ void QOpenGLPaintEnginePrivate::drawImageAsPath(const QRectF &r, const QImage &i brush_origin = old_brush_origin; } -void QOpenGLPaintEnginePrivate::drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy) +void QOpenGLPaintEnginePrivate::drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, + const QPointF &offset) { QBrush old_brush = cbrush; QPointF old_brush_origin = brush_origin; QTransform brush_matrix = QTransform::fromTranslate(r.left(), r.top()); brush_matrix.scale(sx, sy); + brush_matrix.translate(-offset.x(), -offset.y()); cbrush = QBrush(img); cbrush.setTransform(brush_matrix); @@ -4305,7 +4307,7 @@ void QOpenGLPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QR } } -void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &) +void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &offset) { Q_D(QOpenGLPaintEngine); @@ -4315,7 +4317,7 @@ void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con int rw = qCeil(r.width()); int rh = qCeil(r.height()); if (rw < pm.width() && rh < pm.height()) { - drawTiledPixmap(r, pm.copy(0, 0, rw, rh), QPointF()); + drawTiledPixmap(r, pm.copy(0, 0, rw, rh), offset); return; } @@ -4324,11 +4326,11 @@ void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con if (d->composition_mode > QPainter::CompositionMode_Plus || (d->high_quality_antialiasing && !d->isFastRect(r))) { if (scaled.isNull()) - d->drawTiledImageAsPath(r, pm.toImage(), 1, 1); + d->drawTiledImageAsPath(r, pm.toImage(), 1, 1, offset); else { const qreal sx = pm.width() / qreal(scaled.width()); const qreal sy = pm.height() / qreal(scaled.height()); - d->drawTiledImageAsPath(r, scaled, sx, sy); + d->drawTiledImageAsPath(r, scaled, sx, sy, offset); } } else { d->flushDrawQueue(); @@ -4359,8 +4361,12 @@ void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con q_vertexType vertexArray[4*2]; q_vertexType texCoordArray[4*2]; + double offset_x = offset.x() / pm.width(); + double offset_y = offset.y() / pm.height(); + qt_add_rect_to_array(r, vertexArray); - qt_add_texcoords_to_array(0, 0, tc_w, tc_h, texCoordArray); + qt_add_texcoords_to_array(offset_x, offset_y, + tc_w + offset_x, tc_h + offset_y, texCoordArray); glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray); diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro new file mode 100644 index 0000000..4d499ef --- /dev/null +++ b/src/openvg/openvg.pro @@ -0,0 +1,48 @@ +TARGET = QtOpenVG +QT += core \ + gui + +DEFINES+=QT_BUILD_OPENVG_LIB + +contains(QT_CONFIG, shivavg) { + DEFINES += QVG_NO_DRAW_GLYPHS + DEFINES += QVG_NO_RENDER_TO_MASK + DEFINES += QVG_SCISSOR_CLIP +} + +HEADERS += \ + qvg.h \ + qvg_p.h \ + qpaintengine_vg_p.h \ + qpixmapdata_vg_p.h \ + qpixmapfilter_vg_p.h \ + qvgcompositionhelper_p.h +SOURCES += \ + qpaintengine_vg.cpp \ + qpixmapdata_vg.cpp \ + qpixmapfilter_vg.cpp + +contains(QT_CONFIG, egl) { + HEADERS += \ + qwindowsurface_vgegl_p.h \ + qwindowsurface_vg_p.h + SOURCES += \ + qwindowsurface_vg.cpp \ + qwindowsurface_vgegl.cpp +} + +include(../qbase.pri) + +unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui + +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG + +contains(QT_CONFIG, egl) { + !isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL + !isEmpty(QMAKE_LIBDIR_EGL): LIBS += -L$$QMAKE_LIBDIR_EGL + !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL +} + +INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp new file mode 100644 index 0000000..37945bf --- /dev/null +++ b/src/openvg/qpaintengine_vg.cpp @@ -0,0 +1,3231 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpaintengine_vg_p.h" +#include "qpixmapdata_vg_p.h" +#include "qpixmapfilter_vg_p.h" +#include "qvgcompositionhelper_p.h" +#if !defined(QT_NO_EGL) +#include <QtGui/private/qegl_p.h> +#include "qwindowsurface_vgegl_p.h" +#endif +#include <QtCore/qvarlengtharray.h> +#include <QtGui/private/qdrawhelper_p.h> +#include <QtGui/private/qtextureglyphcache_p.h> +#include <QtGui/private/qtextengine_p.h> +#include <QtGui/private/qfontengine_p.h> +#include <QDebug> +#include <QSet> + +QT_BEGIN_NAMESPACE + +// vgDrawGlyphs() only exists in OpenVG 1.1 and higher. +#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_DRAW_GLYPHS) +#define QVG_NO_DRAW_GLYPHS 1 +#endif + +// vgRenderToMask() only exists in OpenVG 1.1 and higher. +// Also, disable masking completely if we are using the scissor to clip. +#if !defined(OPENVG_VERSION_1_1) && !defined(QVG_NO_RENDER_TO_MASK) +#define QVG_NO_RENDER_TO_MASK 1 +#endif +#if defined(QVG_SCISSOR_CLIP) && !defined(QVG_NO_RENDER_TO_MASK) +#define QVG_NO_RENDER_TO_MASK 1 +#endif + +#if !defined(QVG_NO_DRAW_GLYPHS) + +extern int qt_defaultDpiX(); +extern int qt_defaultDpiY(); + +class QVGPaintEnginePrivate; + +class QVGFontGlyphCache +{ +public: + QVGFontGlyphCache(); + ~QVGFontGlyphCache(); + + void cacheGlyphs(QVGPaintEnginePrivate *d, + const QTextItemInt &ti, + const QVarLengthArray<glyph_t> &glyphs); + void setScaleFromText(const QTextItemInt &ti); + + VGFont font; + VGfloat scaleX; + VGfloat scaleY; + + uint cachedGlyphsMask[256 / 32]; + QSet<glyph_t> cachedGlyphs; +}; + +typedef QHash<QFontEngine*, QVGFontGlyphCache*> QVGFontCache; + +#endif + +class QVGFontEngineCleaner : public QObject +{ + Q_OBJECT +public: + QVGFontEngineCleaner(QVGPaintEnginePrivate *d); + ~QVGFontEngineCleaner(); + +public slots: + void fontEngineDestroyed(); + +private: + QVGPaintEnginePrivate *d_ptr; +}; + +class QVGPaintEnginePrivate : public QPaintEngineExPrivate +{ +public: + QVGPaintEnginePrivate(); + ~QVGPaintEnginePrivate(); + + void init(); + void initObjects(); + void destroy(); + void setTransform(VGMatrixMode mode, const QTransform& transform); + void updateTransform(QPaintDevice *pdev); + void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD); + void stroke(VGPath path, const QPen& pen); + void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD); + VGPath vectorPathToVGPath(const QVectorPath& path); + VGPath painterPathToVGPath(const QPainterPath& path); + VGPaintType setBrush + (VGPaint paint, const QBrush& brush, VGMatrixMode mode, + VGPaintType prevPaintType); + void setPenParams(const QPen& pen); + void setBrushTransform(const QBrush& brush, VGMatrixMode mode); + void setupColorRamp(const QGradient *grad, VGPaint paint); + void setImageOptions(); +#if !defined(QVG_SCISSOR_CLIP) + void ensureMask(QVGPaintEngine *engine, int width, int height); + void modifyMask + (QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region); +#endif + + VGint maxScissorRects; // Maximum scissor rectangles for clipping. + + VGPaint penPaint; // Paint for currently active pen. + VGPaint brushPaint; // Paint for currently active brush. + VGPaint opacityPaint; // Paint for drawing images with opacity. + VGPaint fillPaint; // Current fill paint that is active. + + QPen currentPen; // Current pen set in "penPaint". + QBrush currentBrush; // Current brush set in "brushPaint". + + bool forcePenChange; // Force a pen change, even if the same. + bool forceBrushChange; // Force a brush change, even if the same. + + VGPaintType penType; // Type of the last pen that was set. + VGPaintType brushType; // Type of the last brush that was set. + + QPointF brushOrigin; // Current brush origin. + + VGint fillRule; // Last fill rule that was set. + + qreal opacity; // Current drawing opacity. + qreal paintOpacity; // Opacity in opacityPaint. + +#if !defined(QVG_NO_MODIFY_PATH) + VGPath rectPath; // Cached path for quick drawing of rectangles. + VGPath linePath; // Cached path for quick drawing of lines. +#endif + + QTransform transform; // Currently active transform. + bool simpleTransform; // True if the transform is simple (non-projective). + qreal penScale; // Pen scaling factor from "transform". + + QTransform pathTransform; // Calculated VG path transformation. + QTransform imageTransform; // Calculated VG image transformation. + bool pathTransformSet; // True if path transform set in the VG context. + + bool maskValid; // True if vgMask() contains valid data. + bool maskIsSet; // True if mask would be fully set if it was valid. + bool rawVG; // True if processing a raw VG escape. + + QRect maskRect; // Rectangle version of mask if it is simple. + + QTransform penTransform; // Transform for the pen. + QTransform brushTransform; // Transform for the brush. + + VGMatrixMode matrixMode; // Last matrix mode that was set. + VGImageMode imageMode; // Last image mode that was set. + + QRegion scissorRegion; // Currently active scissor region. + bool scissorActive; // True if scissor region is active. + + QPaintEngine::DirtyFlags dirty; + + QColor clearColor; // Last clear color that was set. + VGfloat clearOpacity; // Opacity during the last clear. + + VGBlendMode blendMode; // Active blend mode. + VGRenderingQuality renderingQuality; // Active rendering quality. + VGImageQuality imageQuality; // Active image quality. + +#if !defined(QVG_NO_DRAW_GLYPHS) + QVGFontCache fontCache; + QVGFontEngineCleaner *fontEngineCleaner; +#endif + + // Ensure that the path transform is properly set in the VG context + // before we perform a vgDrawPath() operation. + inline void ensurePathTransform() + { + if (!pathTransformSet) { + setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, pathTransform); + pathTransformSet = true; + } + } + + // Ensure that a specific pen has been set into penPaint. + inline void ensurePen(const QPen& pen) { + if (forcePenChange || pen != currentPen) { + currentPen = pen; + forcePenChange = false; + penType = setBrush + (penPaint, pen.brush(), + VG_MATRIX_STROKE_PAINT_TO_USER, penType); + setPenParams(pen); + } + } + + // Ensure that a specific brush has been set into brushPaint. + inline void ensureBrush(const QBrush& brush) { + if (forceBrushChange || brush != currentBrush) { + currentBrush = brush; + forceBrushChange = false; + brushType = setBrush + (brushPaint, brush, VG_MATRIX_FILL_PAINT_TO_USER, brushType); + } + if (fillPaint != brushPaint) { + vgSetPaint(brushPaint, VG_FILL_PATH); + fillPaint = brushPaint; + } + } + + // Set various modes, but only if different. + inline void setImageMode(VGImageMode mode); + inline void setRenderingQuality(VGRenderingQuality mode); + inline void setImageQuality(VGImageQuality mode); + inline void setBlendMode(VGBlendMode mode); + inline void setFillRule(VGint mode); + + // Clear all lazily-set modes. + void clearModes(); +}; + +inline void QVGPaintEnginePrivate::setImageMode(VGImageMode mode) +{ + if (imageMode != mode) { + imageMode = mode; + vgSeti(VG_IMAGE_MODE, mode); + } +} + +inline void QVGPaintEnginePrivate::setRenderingQuality(VGRenderingQuality mode) +{ + if (renderingQuality != mode) { + vgSeti(VG_RENDERING_QUALITY, mode); + renderingQuality = mode; + } +} + +inline void QVGPaintEnginePrivate::setImageQuality(VGImageQuality mode) +{ + if (imageQuality != mode) { + vgSeti(VG_IMAGE_QUALITY, mode); + imageQuality = mode; + } +} + +inline void QVGPaintEnginePrivate::setBlendMode(VGBlendMode mode) +{ + if (blendMode != mode) { + vgSeti(VG_BLEND_MODE, mode); + blendMode = mode; + } +} + +inline void QVGPaintEnginePrivate::setFillRule(VGint mode) +{ + if (fillRule != mode) { + fillRule = mode; + vgSeti(VG_FILL_RULE, mode); + } +} + +void QVGPaintEnginePrivate::clearModes() +{ + matrixMode = (VGMatrixMode)0; + imageMode = (VGImageMode)0; + blendMode = (VGBlendMode)0; + renderingQuality = (VGRenderingQuality)0; + imageQuality = (VGImageQuality)0; +} + +QVGPaintEnginePrivate::QVGPaintEnginePrivate() +{ + init(); +} + +void QVGPaintEnginePrivate::init() +{ + maxScissorRects = 0; + + penPaint = 0; + brushPaint = 0; + opacityPaint = 0; + fillPaint = 0; + + forcePenChange = true; + forceBrushChange = true; + penType = (VGPaintType)0; + brushType = (VGPaintType)0; + + brushOrigin = QPointF(0.0f, 0.0f); + + fillRule = 0; + + opacity = 1.0; + paintOpacity = 1.0f; + +#if !defined(QVG_NO_MODIFY_PATH) + rectPath = 0; + linePath = 0; +#endif + + simpleTransform = true; + pathTransformSet = false; + penScale = 1.0; + + maskValid = false; + maskIsSet = false; + rawVG = false; + + scissorActive = false; + + dirty = 0; + + clearOpacity = 1.0f; + +#if !defined(QVG_NO_DRAW_GLYPHS) + fontEngineCleaner = 0; +#endif + + clearModes(); +} + +QVGPaintEnginePrivate::~QVGPaintEnginePrivate() +{ + destroy(); +} + +void QVGPaintEnginePrivate::initObjects() +{ + maxScissorRects = vgGeti(VG_MAX_SCISSOR_RECTS); + + penPaint = vgCreatePaint(); + vgSetParameteri(penPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetPaint(penPaint, VG_STROKE_PATH); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER); + vgLoadIdentity(); + + brushPaint = vgCreatePaint(); + vgSetParameteri(brushPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetPaint(brushPaint, VG_FILL_PATH); + fillPaint = brushPaint; + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER); + vgLoadIdentity(); + matrixMode = VG_MATRIX_FILL_PAINT_TO_USER; + + opacityPaint = vgCreatePaint(); + vgSetParameteri(opacityPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + VGfloat values[4]; + values[0] = 1.0f; + values[1] = 1.0f; + values[2] = 1.0f; + values[3] = paintOpacity; + vgSetParameterfv(opacityPaint, VG_PAINT_COLOR, 4, values); + +#if !defined(QVG_NO_MODIFY_PATH) + // Create a dummy path for rectangle drawing, which we can + // modify later with vgModifyPathCoords(). This should be + // faster than constantly creating and destroying paths. + rectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 5, // segmentCapacityHint + 8, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + static VGubyte const segments[5] = { + VG_MOVE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_CLOSE_PATH + }; + VGfloat coords[8]; + coords[0] = 0.0f; + coords[1] = 0.0f; + coords[2] = 100.0f; + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = 100.0f; + coords[6] = coords[0]; + coords[7] = coords[5]; + vgAppendPathData(rectPath, 5, segments, coords); + + // Create a dummy line drawing path as well. + linePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 2, // segmentCapacityHint + 4, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + vgAppendPathData(linePath, 2, segments, coords); +#endif +} + +void QVGPaintEnginePrivate::destroy() +{ + if (penPaint) + vgDestroyPaint(penPaint); + if (brushPaint) + vgDestroyPaint(brushPaint); + if (opacityPaint) + vgDestroyPaint(opacityPaint); + +#if !defined(QVG_NO_MODIFY_PATH) + if (rectPath) + vgDestroyPath(rectPath); + if (linePath) + vgDestroyPath(linePath); +#endif + +#if !defined(QVG_NO_DRAW_GLYPHS) + QVGFontCache::Iterator it; + for (it = fontCache.begin(); it != fontCache.end(); ++it) + delete it.value(); + fontCache.clear(); + delete fontEngineCleaner; +#endif +} + +// Set a specific VG transformation matrix in the current VG context. +void QVGPaintEnginePrivate::setTransform + (VGMatrixMode mode, const QTransform& transform) +{ + VGfloat mat[9]; + if (mode != matrixMode) { + vgSeti(VG_MATRIX_MODE, mode); + matrixMode = mode; + } + mat[0] = transform.m11(); + mat[1] = transform.m12(); + mat[2] = transform.m13(); + mat[3] = transform.m21(); + mat[4] = transform.m22(); + mat[5] = transform.m23(); + mat[6] = transform.m31(); + mat[7] = transform.m32(); + mat[8] = transform.m33(); + vgLoadMatrix(mat); +} + +extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); + +void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) +{ + VGfloat devh = pdev->height() - 1; + + // Construct the VG transform by combining the Qt transform with + // the following viewport transformation: + // | 1 0 0 | | 1 0 0.5 | | 1 0 0.5 | + // | 0 -1 devh | * | 0 1 -0.5 | = | 0 -1 (0.5 + devh) | + // | 0 0 1 | | 0 0 1 | | 0 0 1 | + // The full VG transform is effectively: + // 1. Apply the user's transformation matrix. + // 2. Translate by (0.5, -0.5) to correct for Qt and VG putting + // the centre of the pixel at different positions. + // 3. Flip the co-ordinate system upside down. + QTransform viewport(1.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.5f, devh + 0.5f, 1.0f); + + // The image transform is always the full transformation, + // because it can be projective. + imageTransform = transform * viewport; + + // Determine if the transformation is projective. + bool projective = (imageTransform.m13() != 0.0f || + imageTransform.m23() != 0.0f || + imageTransform.m33() != 1.0f); + if (projective) { + // The engine cannot do projective path transforms for us, + // so we will have to convert the co-ordinates ourselves. + // Change the matrix to just the viewport transformation. + pathTransform = viewport; + simpleTransform = false; + } else { + pathTransform = imageTransform; + simpleTransform = true; + } + pathTransformSet = false; + + // Calculate the scaling factor to use for turning cosmetic pens + // into ordinary non-cosmetic pens. + qt_scaleForTransform(transform, &penScale); +} + +VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) +{ + int count = path.elementCount(); + const qreal *points = path.points(); + const QPainterPath::ElementType *elements = path.elements(); + + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + + // Size is sufficient segments for drawRoundedRect() paths. + QVarLengthArray<VGubyte, 20> segments; + + if (sizeof(qreal) == sizeof(VGfloat) && elements && simpleTransform) { + // If Qt was compiled with qreal the same size as VGfloat, + // then convert the segment types and use the incoming + // points array directly. + for (int i = 0; i < count; ++i) { + switch (elements[i]) { + + case QPainterPath::MoveToElement: + segments.append(VG_MOVE_TO_ABS); break; + + case QPainterPath::LineToElement: + segments.append(VG_LINE_TO_ABS); break; + + case QPainterPath::CurveToElement: break; + + case QPainterPath::CurveToDataElement: + segments.append(VG_CUBIC_TO_ABS); break; + + } + } + if (path.hasImplicitClose()) + segments.append(VG_CLOSE_PATH); + + vgAppendPathData(vgpath, segments.count(), segments.constData(), + reinterpret_cast<const VGfloat *>(points)); + + return vgpath; + } + + // Sizes chosen so that drawRoundedRect() paths fit in these arrays. + QVarLengthArray<VGfloat, 48> coords; + + int curvePos = 0; + QPointF temp; + + if (elements && simpleTransform) { + // Convert the members of the element array. + for (int i = 0; i < count; ++i) { + switch (elements[i]) { + + case QPainterPath::MoveToElement: + { + coords.append(points[0]); + coords.append(points[1]); + segments.append(VG_MOVE_TO_ABS); + } + break; + + case QPainterPath::LineToElement: + { + coords.append(points[0]); + coords.append(points[1]); + segments.append(VG_LINE_TO_ABS); + } + break; + + case QPainterPath::CurveToElement: + { + coords.append(points[0]); + coords.append(points[1]); + curvePos = 2; + } + break; + + case QPainterPath::CurveToDataElement: + { + coords.append(points[0]); + coords.append(points[1]); + curvePos += 2; + if (curvePos == 6) { + curvePos = 0; + segments.append(VG_CUBIC_TO_ABS); + } + } + break; + + } + points += 2; + } + } else if (elements && !simpleTransform) { + // Convert the members of the element array after applying the + // current transform to the path locally. + for (int i = 0; i < count; ++i) { + switch (elements[i]) { + + case QPainterPath::MoveToElement: + { + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + segments.append(VG_MOVE_TO_ABS); + } + break; + + case QPainterPath::LineToElement: + { + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + segments.append(VG_LINE_TO_ABS); + } + break; + + case QPainterPath::CurveToElement: + { + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + curvePos = 2; + } + break; + + case QPainterPath::CurveToDataElement: + { + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + curvePos += 2; + if (curvePos == 6) { + curvePos = 0; + segments.append(VG_CUBIC_TO_ABS); + } + } + break; + + } + points += 2; + } + } else if (count > 0 && simpleTransform) { + // If there is no element array, then the path is assumed + // to be a MoveTo followed by several LineTo's. + coords.append(points[0]); + coords.append(points[1]); + segments.append(VG_MOVE_TO_ABS); + while (count > 1) { + points += 2; + coords.append(points[0]); + coords.append(points[1]); + segments.append(VG_LINE_TO_ABS); + --count; + } + } else if (count > 0 && !simpleTransform) { + // Convert a simple path, and apply the transform locally. + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + segments.append(VG_MOVE_TO_ABS); + while (count > 1) { + points += 2; + temp = transform.map(QPointF(points[0], points[1])); + coords.append(temp.x()); + coords.append(temp.y()); + segments.append(VG_LINE_TO_ABS); + --count; + } + } + + // Close the path if specified. + if (path.hasImplicitClose()) + segments.append(VG_CLOSE_PATH); + + vgAppendPathData(vgpath, segments.count(), + segments.constData(), coords.constData()); + + return vgpath; +} + +VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path) +{ + int count = path.elementCount(); + + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + + if (count == 0) + return vgpath; + + const QPainterPath::Element *elements = &(path.elementAt(0)); + + // Sizes chosen so that drawRoundedRect() paths fit in these arrays. + QVarLengthArray<VGfloat, 48> coords; + QVarLengthArray<VGubyte, 20> segments; + + int curvePos = 0; + QPointF temp; + + // Keep track of the start and end of each sub-path. QPainterPath + // does not have an "implicit close" flag like QVectorPath does. + // We therefore have to detect closed paths by looking for a LineTo + // element that connects back to the initial MoveTo element. + qreal startx = 0.0; + qreal starty = 0.0; + qreal endx = 0.0; + qreal endy = 0.0; + bool haveStart = false; + bool haveEnd = false; + + if (simpleTransform) { + // Convert the members of the element array. + for (int i = 0; i < count; ++i) { + switch (elements[i].type) { + + case QPainterPath::MoveToElement: + { + if (haveStart && haveEnd && startx == endx && starty == endy) { + // Implicitly close the previous sub-path. + segments.append(VG_CLOSE_PATH); + } + startx = elements[i].x; + starty = elements[i].y; + coords.append(startx); + coords.append(starty); + haveStart = true; + haveEnd = false; + segments.append(VG_MOVE_TO_ABS); + } + break; + + case QPainterPath::LineToElement: + { + endx = elements[i].x; + endy = elements[i].y; + coords.append(endx); + coords.append(endy); + haveEnd = true; + segments.append(VG_LINE_TO_ABS); + } + break; + + case QPainterPath::CurveToElement: + { + coords.append(elements[i].x); + coords.append(elements[i].y); + haveEnd = false; + curvePos = 2; + } + break; + + case QPainterPath::CurveToDataElement: + { + coords.append(elements[i].x); + coords.append(elements[i].y); + haveEnd = false; + curvePos += 2; + if (curvePos == 6) { + curvePos = 0; + segments.append(VG_CUBIC_TO_ABS); + } + } + break; + + } + } + } else { + // Convert the members of the element array after applying the + // current transform to the path locally. + for (int i = 0; i < count; ++i) { + switch (elements[i].type) { + + case QPainterPath::MoveToElement: + { + if (haveStart && haveEnd && startx == endx && starty == endy) { + // Implicitly close the previous sub-path. + segments.append(VG_CLOSE_PATH); + } + temp = transform.map(QPointF(elements[i].x, elements[i].y)); + startx = temp.x(); + starty = temp.y(); + coords.append(startx); + coords.append(starty); + haveStart = true; + haveEnd = false; + segments.append(VG_MOVE_TO_ABS); + } + break; + + case QPainterPath::LineToElement: + { + temp = transform.map(QPointF(elements[i].x, elements[i].y)); + endx = temp.x(); + endy = temp.y(); + coords.append(endx); + coords.append(endy); + haveEnd = true; + segments.append(VG_LINE_TO_ABS); + } + break; + + case QPainterPath::CurveToElement: + { + temp = transform.map(QPointF(elements[i].x, elements[i].y)); + coords.append(temp.x()); + coords.append(temp.y()); + haveEnd = false; + curvePos = 2; + } + break; + + case QPainterPath::CurveToDataElement: + { + temp = transform.map(QPointF(elements[i].x, elements[i].y)); + coords.append(temp.x()); + coords.append(temp.y()); + haveEnd = false; + curvePos += 2; + if (curvePos == 6) { + curvePos = 0; + segments.append(VG_CUBIC_TO_ABS); + } + } + break; + + } + } + } + + if (haveStart && haveEnd && startx == endx && starty == endy) { + // Implicitly close the last sub-path. + segments.append(VG_CLOSE_PATH); + } + + vgAppendPathData(vgpath, segments.count(), + segments.constData(), coords.constData()); + + return vgpath; +} + +extern QImage qt_imageForBrush(int style, bool invert); + +static QImage colorizeBitmap(const QImage &image, const QColor &color) +{ + QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB); + QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied); + + QRgb fg = PREMUL(color.rgba()); + QRgb bg = 0; + + int height = sourceImage.height(); + int width = sourceImage.width(); + for (int y=0; y<height; ++y) { + uchar *source = sourceImage.scanLine(y); + QRgb *target = reinterpret_cast<QRgb *>(dest.scanLine(y)); + for (int x=0; x < width; ++x) + target[x] = (source[x>>3] >> (x&7)) & 1 ? fg : bg; + } + return dest; +} + +static VGImage toVGImage + (const QImage & image, Qt::ImageConversionFlags flags = Qt::AutoColor) +{ + QImage img(image); + + VGImageFormat format; + switch (img.format()) { + case QImage::Format_Mono: + img = image.convertToFormat(QImage::Format_MonoLSB, flags); + format = VG_BW_1; + break; + case QImage::Format_MonoLSB: + format = VG_BW_1; + break; + case QImage::Format_RGB32: + format = VG_sXRGB_8888; + break; + case QImage::Format_ARGB32: + format = VG_sARGB_8888; + break; + case QImage::Format_ARGB32_Premultiplied: + format = VG_sARGB_8888_PRE; + break; + case QImage::Format_RGB16: + format = VG_sRGB_565; + break; + default: + // Convert everything else into ARGB32_Premultiplied. + img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags); + format = VG_sARGB_8888_PRE; + break; + } + + const uchar *pixels = img.bits(); + + VGImage vgImg = vgCreateImage + (format, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData + (vgImg, pixels, img.bytesPerLine(), format, 0, 0, + img.width(), img.height()); + + return vgImg; +} + +static VGImage toVGImageSubRect + (const QImage & image, const QRect& sr, + Qt::ImageConversionFlags flags = Qt::AutoColor) +{ + QImage img(image); + + VGImageFormat format; + int bpp = 4; + + switch (img.format()) { + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + return VG_INVALID_HANDLE; + case QImage::Format_RGB32: + format = VG_sXRGB_8888; + break; + case QImage::Format_ARGB32: + format = VG_sARGB_8888; + break; + case QImage::Format_ARGB32_Premultiplied: + format = VG_sARGB_8888_PRE; + break; + case QImage::Format_RGB16: + format = VG_sRGB_565; + bpp = 2; + break; + default: + // Convert everything else into ARGB32_Premultiplied. + img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied, flags); + format = VG_sARGB_8888_PRE; + break; + } + + const uchar *pixels = img.bits() + bpp * sr.x() + + img.bytesPerLine() * sr.y(); + + VGImage vgImg = vgCreateImage + (format, sr.width(), sr.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData + (vgImg, pixels, img.bytesPerLine(), format, 0, 0, + sr.width(), sr.height()); + + return vgImg; +} + +static VGImage toVGImageWithOpacity(const QImage & image, qreal opacity) +{ + QImage img(image.size(), QImage::Format_ARGB32_Premultiplied); + img.fill(0); + QPainter painter; + painter.begin(&img); + painter.setOpacity(opacity); + painter.drawImage(0, 0, image); + painter.end(); + + const uchar *pixels = img.bits(); + + VGImage vgImg = vgCreateImage + (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData + (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, + img.width(), img.height()); + + return vgImg; +} + +static VGImage toVGImageWithOpacitySubRect + (const QImage & image, qreal opacity, const QRect& sr) +{ + QImage img(sr.size(), QImage::Format_ARGB32_Premultiplied); + img.fill(0); + QPainter painter; + painter.begin(&img); + painter.setOpacity(opacity); + painter.drawImage(QPoint(0, 0), image, sr); + painter.end(); + + const uchar *pixels = img.bits(); + + VGImage vgImg = vgCreateImage + (VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData + (vgImg, pixels, img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, + img.width(), img.height()); + + return vgImg; +} + +VGPaintType QVGPaintEnginePrivate::setBrush + (VGPaint paint, const QBrush& brush, VGMatrixMode mode, + VGPaintType prevType) +{ + VGfloat values[5]; + setBrushTransform(brush, mode); + + // Reset the paint pattern on the brush, which will discard + // the previous VGImage if one was set. + if (prevType == VG_PAINT_TYPE_PATTERN || prevType == (VGPaintType)0) + vgPaintPattern(paint, VG_INVALID_HANDLE); + + switch (brush.style()) { + + case Qt::SolidPattern: { + // The brush is a solid color. + QColor color(brush.color()); + values[0] = color.redF(); + values[1] = color.greenF(); + values[2] = color.blueF(); + values[3] = color.alphaF() * opacity; + if (prevType != VG_PAINT_TYPE_COLOR) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(paint, VG_PAINT_COLOR, 4, values); + return VG_PAINT_TYPE_COLOR; + } + + case Qt::LinearGradientPattern: { + // The brush is a linear gradient. + Q_ASSERT(brush.gradient()->type() == QGradient::LinearGradient); + const QLinearGradient *grad = + static_cast<const QLinearGradient*>(brush.gradient()); + values[0] = grad->start().x(); + values[1] = grad->start().y(); + values[2] = grad->finalStop().x(); + values[3] = grad->finalStop().y(); + if (prevType != VG_PAINT_TYPE_LINEAR_GRADIENT) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT); + vgSetParameterfv(paint, VG_PAINT_LINEAR_GRADIENT, 4, values); + setupColorRamp(grad, paint); + return VG_PAINT_TYPE_LINEAR_GRADIENT; + } + + case Qt::RadialGradientPattern: { + // The brush is a radial gradient. + Q_ASSERT(brush.gradient()->type() == QGradient::RadialGradient); + const QRadialGradient *grad = + static_cast<const QRadialGradient*>(brush.gradient()); + values[0] = grad->center().x(); + values[1] = grad->center().y(); + values[2] = grad->focalPoint().x(); + values[3] = grad->focalPoint().y(); + values[4] = grad->radius(); + if (prevType != VG_PAINT_TYPE_RADIAL_GRADIENT) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT); + vgSetParameterfv(paint, VG_PAINT_RADIAL_GRADIENT, 5, values); + setupColorRamp(grad, paint); + return VG_PAINT_TYPE_RADIAL_GRADIENT; + } + + case Qt::TexturePattern: { + // The brush is a texture specified by a QPixmap/QImage. + QPixmapData *pd = brush.texture().pixmapData(); + VGImage vgImg; + if (pd->pixelType() == QPixmapData::BitmapType) { + // Colorize bitmaps using the brush color and opacity. + QColor color = brush.color(); + if (opacity != 1.0) + color.setAlphaF(color.alphaF() * opacity); + QImage image = colorizeBitmap(*(pd->buffer()), color); + vgImg = toVGImage(image); + } else if (opacity == 1.0) { + if (pd->classId() == QPixmapData::OpenVGClass) { + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd); + vgImg = vgpd->toVGImage(); + } else { + vgImg = toVGImage(*(pd->buffer())); + } + } else { + vgImg = toVGImageWithOpacity(*(pd->buffer()), opacity); + } + if (vgImg == VG_INVALID_HANDLE) + break; + if (prevType != VG_PAINT_TYPE_PATTERN) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN); + vgSetParameteri(paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT); + vgPaintPattern(paint, vgImg); + vgDestroyImage(vgImg); // Will stay valid until pattern is destroyed. + return VG_PAINT_TYPE_PATTERN; + } + + case Qt::ConicalGradientPattern: { + // Convert conical gradients into the first stop color. + qWarning() << "QVGPaintEnginePrivate::setBrush: conical gradients are not supported by OpenVG"; + Q_ASSERT(brush.gradient()->type() == QGradient::ConicalGradient); + const QConicalGradient *grad = + static_cast<const QConicalGradient*>(brush.gradient()); + const QGradientStops stops = grad->stops(); + QColor color; + if (stops.size() > 0) + color = stops[0].second; + values[0] = color.redF(); + values[1] = color.greenF(); + values[2] = color.blueF(); + values[3] = color.alphaF() * opacity; + if (prevType != VG_PAINT_TYPE_COLOR) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(paint, VG_PAINT_COLOR, 4, values); + return VG_PAINT_TYPE_COLOR; + } + + case Qt::Dense1Pattern: + case Qt::Dense2Pattern: + case Qt::Dense3Pattern: + case Qt::Dense4Pattern: + case Qt::Dense5Pattern: + case Qt::Dense6Pattern: + case Qt::Dense7Pattern: + case Qt::HorPattern: + case Qt::VerPattern: + case Qt::CrossPattern: + case Qt::BDiagPattern: + case Qt::FDiagPattern: + case Qt::DiagCrossPattern: { + // The brush is a traditional dotted or cross-hatched pattern brush. + QColor color = brush.color(); + if (opacity != 1.0) + color.setAlphaF(color.alphaF() * opacity); + QImage image = colorizeBitmap + (qt_imageForBrush(brush.style(), true), color); + VGImage vgImg = toVGImage(image); + if (prevType != VG_PAINT_TYPE_PATTERN) + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN); + vgSetParameteri(paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT); + vgPaintPattern(paint, vgImg); + vgDestroyImage(vgImg); // Will stay valid until pattern is destroyed. + return VG_PAINT_TYPE_PATTERN; + } + + default: break; + } + return (VGPaintType)0; +} + +void QVGPaintEnginePrivate::setPenParams(const QPen& pen) +{ + // Note: OpenVG does not support zero-width or cosmetic pens, + // so we have to simulate cosmetic pens by reversing the scale. + VGfloat width = pen.widthF(); + if (width <= 0.0f) + width = 1.0f; + if (pen.isCosmetic()) { + if (penScale != 1.0 && penScale != 0.0) + width /= penScale; + } + vgSetf(VG_STROKE_LINE_WIDTH, width); + + if (pen.capStyle() == Qt::FlatCap) + vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); + else if (pen.capStyle() == Qt::SquareCap) + vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_SQUARE); + else + vgSetf(VG_STROKE_CAP_STYLE, VG_CAP_ROUND); + + if (pen.joinStyle() == Qt::MiterJoin) { + vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); + vgSetf(VG_STROKE_MITER_LIMIT, pen.miterLimit()); + } else if (pen.joinStyle() == Qt::BevelJoin) { + vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL); + } else { + vgSetf(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND); + } + + if (pen.style() == Qt::SolidLine) { + vgSetfv(VG_STROKE_DASH_PATTERN, 0, NULL); + } else { + const QVector<qreal> dashPattern = pen.dashPattern(); + QVector<VGfloat> currentDashPattern(dashPattern.count()); + for (int i = 0; i < dashPattern.count(); ++i) + currentDashPattern[i] = dashPattern[i] * width; + vgSetfv(VG_STROKE_DASH_PATTERN, currentDashPattern.count(), currentDashPattern.data()); + vgSetf(VG_STROKE_DASH_PHASE, pen.dashOffset()); + vgSetf(VG_STROKE_DASH_PHASE_RESET, VG_FALSE); + } +} + +void QVGPaintEnginePrivate::setBrushTransform + (const QBrush& brush, VGMatrixMode mode) +{ + // Compute the new brush transformation matrix. + QTransform transform(brush.transform()); + if (brushOrigin.x() != 0.0f || brushOrigin.y() != 0.0f) + transform.translate(brushOrigin.x(), brushOrigin.y()); + + // Bail out if the matrix is the same as last time, to avoid + // updating the VG context state unless absolutely necessary. + // Most applications won't have a brush transformation set, + // which will leave the VG setting at its default of identity. + // Always change the transform if coming out of raw VG mode. + if (mode == VG_MATRIX_FILL_PAINT_TO_USER) { + if (!rawVG && transform == brushTransform) + return; + brushTransform = transform; + } else { + if (!rawVG && transform == penTransform) + return; + penTransform = transform; + } + + // Set the brush transformation matrix. + if (mode != matrixMode) { + vgSeti(VG_MATRIX_MODE, mode); + matrixMode = mode; + } + if (transform.isIdentity()) { + vgLoadIdentity(); + } else { + VGfloat mat[9]; + mat[0] = transform.m11(); + mat[1] = transform.m12(); + mat[2] = transform.m13(); + mat[3] = transform.m21(); + mat[4] = transform.m22(); + mat[5] = transform.m23(); + mat[6] = transform.m31(); + mat[7] = transform.m32(); + mat[8] = transform.m33(); + vgLoadMatrix(mat); + } +} + +void QVGPaintEnginePrivate::setupColorRamp(const QGradient *grad, VGPaint paint) +{ + QGradient::Spread spread = grad->spread(); + VGColorRampSpreadMode spreadMode; + if (spread == QGradient::ReflectSpread) + spreadMode = VG_COLOR_RAMP_SPREAD_REFLECT; + else if (spread == QGradient::RepeatSpread) + spreadMode = VG_COLOR_RAMP_SPREAD_REPEAT; + else + spreadMode = VG_COLOR_RAMP_SPREAD_PAD; + + const QGradientStops stops = grad->stops(); + int n = 5*stops.size(); + QVector<VGfloat> fill_stops(n); + + for (int i = 0; i < stops.size(); ++i ) { + QColor col = stops[i].second; + fill_stops[i*5] = stops[i].first; + fill_stops[i*5 + 1] = col.redF(); + fill_stops[i*5 + 2] = col.greenF(); + fill_stops[i*5 + 3] = col.blueF(); + fill_stops[i*5 + 4] = col.alphaF() * opacity; + } + + vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, spreadMode); + vgSetParameteri(paint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, VG_FALSE); + vgSetParameterfv(paint, VG_PAINT_COLOR_RAMP_STOPS, n, fill_stops.data()); +} + +QVGPainterState::QVGPainterState(QVGPainterState& other) + : QPainterState(other), + isNew(true), clipRegion(other.clipRegion), + savedDirty(0) +{ +} + +QVGPainterState::QVGPainterState() + : isNew(true), savedDirty(0) +{ +} + +QVGPainterState::~QVGPainterState() +{ +} + +QVGPaintEngine::QVGPaintEngine() + : QPaintEngineEx(*new QVGPaintEnginePrivate) +{ +} + +QVGPaintEngine::QVGPaintEngine(QVGPaintEnginePrivate &data) + : QPaintEngineEx(data) +{ +} + +QVGPaintEngine::~QVGPaintEngine() +{ +} + +QPainterState *QVGPaintEngine::createState(QPainterState *orig) const +{ + if (!orig) { + return new QVGPainterState(); + } else { + QVGPaintEnginePrivate *d = + static_cast<QVGPaintEnginePrivate *>(d_ptr); + QVGPainterState *origState = static_cast<QVGPainterState *>(orig); + origState->savedDirty = d->dirty; + d->dirty = 0; + return new QVGPainterState(*origState); + } +} + +void QVGPaintEnginePrivate::draw + (VGPath path, const QPen& pen, const QBrush& brush, VGint rule) +{ + VGbitfield mode = 0; + if (pen.style() != Qt::NoPen) { + ensurePen(pen); + mode |= VG_STROKE_PATH; + } + if (brush.style() != Qt::NoBrush) { + ensureBrush(brush); + setFillRule(rule); + mode |= VG_FILL_PATH; + } + if (mode != 0) { + ensurePathTransform(); + vgDrawPath(path, mode); + } +} + +void QVGPaintEnginePrivate::stroke(VGPath path, const QPen& pen) +{ + if (pen.style() == Qt::NoPen) + return; + ensurePen(pen); + ensurePathTransform(); + vgDrawPath(path, VG_STROKE_PATH); +} + +void QVGPaintEnginePrivate::fill(VGPath path, const QBrush& brush, VGint rule) +{ + if (brush.style() == Qt::NoBrush) + return; + ensureBrush(brush); + setFillRule(rule); + ensurePathTransform(); + vgDrawPath(path, VG_FILL_PATH); +} + +bool QVGPaintEngine::begin(QPaintDevice *pdev) +{ + Q_UNUSED(pdev); + Q_D(QVGPaintEngine); + + // Initialize the VG painting objects if we haven't done it yet. + if (!d->penPaint) + d->initObjects(); + + // The initial clip region is the entire device area. + QVGPainterState *s = state(); + s->clipRegion = defaultClipRegion(); + + // Initialize the VG state for this paint operation. + restoreState(QPaintEngine::AllDirty); + d->dirty = 0; + d->rawVG = false; + return true; +} + +bool QVGPaintEngine::end() +{ + return true; +} + +void QVGPaintEngine::draw(const QVectorPath &path) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + VGPath vgpath = d->vectorPathToVGPath(path); + if (!path.hasWindingFill()) + d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); + else + d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); + vgDestroyPath(vgpath); +} + +void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) +{ + Q_D(QVGPaintEngine); + VGPath vgpath = d->vectorPathToVGPath(path); + if (!path.hasWindingFill()) + d->fill(vgpath, brush, VG_EVEN_ODD); + else + d->fill(vgpath, brush, VG_NON_ZERO); + vgDestroyPath(vgpath); +} + +void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) +{ + Q_D(QVGPaintEngine); + VGPath vgpath = d->vectorPathToVGPath(path); + d->stroke(vgpath, pen); + vgDestroyPath(vgpath); +} + +// Determine if a co-ordinate transform is simple enough to allow +// rectangle-based clipping with vgMask(). Simple transforms most +// often result from origin translations. +static inline bool clipTransformIsSimple(const QTransform& transform) +{ + QTransform::TransformationType type = transform.type(); + return (type == QTransform::TxNone || type == QTransform::TxTranslate); +} + +#if defined(QVG_SCISSOR_CLIP) + +void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + if (op == Qt::NoClip) { + s->clipRegion = defaultClipRegion(); + updateScissor(); + return; + } + + // We aren't using masking, so handle simple QRectF's only. + if (path.shape() == QVectorPath::RectangleHint && + path.elementCount() == 4 && clipTransformIsSimple(d->transform)) { + // Clipping region that resulted from QPainter::setClipRect(QRectF). + // Convert it into a QRect and apply. + const qreal *points = path.points(); + QRectF rect(points[0], points[1], points[2] - points[0], + points[5] - points[1]); + clip(rect.toRect(), op); + } +} + +void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + // If we have a non-simple transform, then use path-based clipping. + if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) { + QPaintEngineEx::clip(rect, op); + return; + } + + switch (op) { + case Qt::NoClip: + { + s->clipRegion = defaultClipRegion(); + } + break; + + case Qt::ReplaceClip: + { + s->clipRegion = d->transform.map(QRegion(rect)); + } + break; + + case Qt::IntersectClip: + { + s->clipRegion = s->clipRegion.intersect(d->transform.map(QRegion(rect))); + } + break; + + case Qt::UniteClip: + { + s->clipRegion = s->clipRegion.unite(d->transform.map(QRegion(rect))); + } + break; + } + + updateScissor(); +} + +void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + // If we have a non-simple transform, then use path-based clipping. + if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) { + QPaintEngineEx::clip(region, op); + return; + } + + switch (op) { + case Qt::NoClip: + { + s->clipRegion = defaultClipRegion(); + } + break; + + case Qt::ReplaceClip: + { + s->clipRegion = d->transform.map(region); + } + break; + + case Qt::IntersectClip: + { + s->clipRegion = s->clipRegion.intersect(d->transform.map(region)); + } + break; + + case Qt::UniteClip: + { + s->clipRegion = s->clipRegion.unite(d->transform.map(region)); + } + break; + } + + updateScissor(); +} + +void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) +{ + QPaintEngineEx::clip(path, op); +} + +#else // !QVG_SCISSOR_CLIP + +void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) +{ + Q_D(QVGPaintEngine); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + if (op == Qt::NoClip) { + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + vgSeti(VG_MASKING, VG_FALSE); + return; + } + +#if defined(QVG_NO_RENDER_TO_MASK) + // We don't have vgRenderToMask(), so handle simple QRectF's only. + if (path.shape() == QVectorPath::RectangleHint && + path.elementCount() == 4 && clipTransformIsSimple(d->transform)) { + // Clipping region that resulted from QPainter::setClipRect(QRectF). + // Convert it into a QRect and apply. + const qreal *points = path.points(); + QRectF rect(points[0], points[1], points[2] - points[0], + points[5] - points[1]); + clip(rect.toRect(), op); + } +#else + QPaintDevice *pdev = paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + if (op == Qt::ReplaceClip) { + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height); + d->maskRect = QRect(); + } else if (!d->maskValid) { + d->ensureMask(this, width, height); + } + + d->ensurePathTransform(); + VGPath vgpath = d->vectorPathToVGPath(path); + switch (op) { + case Qt::ReplaceClip: + case Qt::UniteClip: + vgRenderToMask(vgpath, VG_FILL_PATH, VG_UNION_MASK); + break; + + case Qt::IntersectClip: + vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK); + break; + + default: break; + } + vgDestroyPath(vgpath); + + vgSeti(VG_MASKING, VG_TRUE); + d->maskValid = true; + d->maskIsSet = false; +#endif +} + +void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) +{ + clip(QRegion(rect), op); +} + +void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) +{ + Q_D(QVGPaintEngine); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + // If we have a non-simple transform, then use path-based clipping. + if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) { + QPaintEngineEx::clip(region, op); + return; + } + + switch (op) { + case Qt::NoClip: + { + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + vgSeti(VG_MASKING, VG_FALSE); + } + break; + + case Qt::ReplaceClip: + { + QRegion r = d->transform.map(region); + if (isDefaultClipRegion(r)) { + // Replacing the clip with a full-window region is the + // same as turning off clipping. + if (d->maskValid) + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + } else { + // Special case: if the intersection of the system + // clip and the region is a single rectangle, then + // use the scissor for clipping. + QRegion clip = d->systemClip; + if (clip.isEmpty()) + clip = r; + else + clip = clip.intersect(r); + if (r.numRects() == 1) { + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = r.boundingRect(); + vgSeti(VG_MASKING, VG_FALSE); + updateScissor(); + } else { + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = QRect(); + d->modifyMask(this, VG_FILL_MASK, r); + } + } + } + break; + + case Qt::IntersectClip: + { + if (region.numRects() != 1) { + // If there is more than one rectangle, then intersecting + // the rectangles one by one in modifyMask() will not give + // the desired result. So fall back to path-based clipping. + QPaintEngineEx::clip(region, op); + return; + } + QRegion r = d->transform.map(region); + if (d->maskIsSet && isDefaultClipRegion(r)) { + // Intersecting a full-window clip with a full-window + // region is the same as turning off clipping. + if (d->maskValid) + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + } else { + d->modifyMask(this, VG_INTERSECT_MASK, r); + } + } + break; + + case Qt::UniteClip: + { + // If we already have a full-window clip, then uniting a + // region with it will do nothing. Otherwise union. + if (!(d->maskIsSet)) + d->modifyMask(this, VG_UNION_MASK, d->transform.map(region)); + } + break; + } +} + +void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) +{ +#if !defined(QVG_NO_RENDER_TO_MASK) + Q_D(QVGPaintEngine); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + if (op == Qt::NoClip) { + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + vgSeti(VG_MASKING, VG_FALSE); + return; + } + + QPaintDevice *pdev = paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + if (op == Qt::ReplaceClip) { + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height); + d->maskRect = QRect(); + } else if (!d->maskValid) { + d->ensureMask(this, width, height); + } + + d->ensurePathTransform(); + VGPath vgpath = d->painterPathToVGPath(path); + switch (op) { + case Qt::ReplaceClip: + case Qt::UniteClip: + vgRenderToMask(vgpath, VG_FILL_PATH, VG_UNION_MASK); + break; + + case Qt::IntersectClip: + vgRenderToMask(vgpath, VG_FILL_PATH, VG_INTERSECT_MASK); + break; + + default: break; + } + vgDestroyPath(vgpath); + + vgSeti(VG_MASKING, VG_TRUE); + d->maskValid = true; + d->maskIsSet = false; +#else + QPaintEngineEx::clip(path, op); +#endif +} + +void QVGPaintEnginePrivate::ensureMask + (QVGPaintEngine *engine, int width, int height) +{ + if (maskIsSet) { + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height); + maskRect = QRect(); + } else { + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height); + if (!maskRect.isNull()) { + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, + maskRect.x(), height - maskRect.y() - maskRect.height(), + maskRect.width(), maskRect.height()); + maskRect = QRect(); + engine->updateScissor(); + } + } +} + +void QVGPaintEnginePrivate::modifyMask + (QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region) +{ + QPaintDevice *pdev = engine->paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + if (!maskValid) + ensureMask(engine, width, height); + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); ++i) { + vgMask(VG_INVALID_HANDLE, op, + rects[i].x(), height - rects[i].y() - rects[i].height(), + rects[i].width(), rects[i].height()); + } + + vgSeti(VG_MASKING, VG_TRUE); + maskValid = true; + maskIsSet = false; +} + +#endif // !QVG_SCISSOR_CLIP + +void QVGPaintEngine::updateScissor() +{ + Q_D(QVGPaintEngine); + + QRegion region = d->systemClip; + +#if defined(QVG_SCISSOR_CLIP) + // Using the scissor to do clipping, so combine the systemClip + // with the current painting clipRegion. + QVGPainterState *s = state(); + if (s->clipEnabled) { + if (region.isEmpty()) + region = s->clipRegion; + else + region = region.intersect(s->clipRegion); + if (isDefaultClipRegion(region)) { + // The scissor region is the entire drawing surface, + // so there is no point doing any scissoring. + vgSeti(VG_SCISSORING, VG_FALSE); + d->scissorActive = false; + return; + } + } else +#endif + { +#if !defined(QVG_SCISSOR_CLIP) + // Combine the system clip with the simple mask rectangle. + if (!d->maskRect.isNull()) { + if (region.isEmpty()) + region = d->maskRect; + else + region.intersect(d->maskRect); + if (isDefaultClipRegion(region)) { + // The scissor region is the entire drawing surface, + // so there is no point doing any scissoring. + vgSeti(VG_SCISSORING, VG_FALSE); + d->scissorActive = false; + return; + } + } else +#endif + + // Disable the scissor completely if the system clip is empty. + if (region.isEmpty()) { + vgSeti(VG_SCISSORING, VG_FALSE); + d->scissorActive = false; + return; + } + } + + if (d->scissorActive && region == d->scissorRegion) + return; + + QVector<QRect> rects = region.rects(); + int count = rects.count(); + if (count > d->maxScissorRects) + count = d->maxScissorRects; + QVarLengthArray<VGint> params(count * 4); + int height = paintDevice()->height(); + for (int i = 0; i < count; ++i) { + params[i * 4 + 0] = rects[i].x(); + params[i * 4 + 1] = height - rects[i].y() - rects[i].height(); + params[i * 4 + 2] = rects[i].width(); + params[i * 4 + 3] = rects[i].height(); + } + + vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data()); + vgSeti(VG_SCISSORING, VG_TRUE); + d->scissorActive = true; + d->scissorRegion = region; +} + +QRegion QVGPaintEngine::defaultClipRegion() +{ + // The default clip region for a paint device is the whole drawing area. + QPaintDevice *pdev = paintDevice(); + return QRegion(0, 0, pdev->width(), pdev->height()); +} + +bool QVGPaintEngine::isDefaultClipRegion(const QRegion& region) +{ + if (region.numRects() != 1) + return false; + + QPaintDevice *pdev = paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + QRect rect = region.boundingRect(); + return (rect.x() == 0 && rect.y() == 0 && + rect.width() == width && rect.height() == height); +} + +void QVGPaintEngine::clipEnabledChanged() +{ +#if defined(QVG_SCISSOR_CLIP) + updateScissor(); +#else + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + d->dirty |= QPaintEngine::DirtyClipEnabled; + if (s->clipEnabled && s->clipOperation != Qt::NoClip) { + // Replay the entire clip stack to put the mask into the right state. + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + s->clipRegion = defaultClipRegion(); + d->replayClipOperations(); + d->transform = s->transform(); + d->updateTransform(paintDevice()); + } else { + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = QRect(); + } +#endif +} + +void QVGPaintEngine::penChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyPen; +} + +void QVGPaintEngine::brushChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyBrush; +} + +void QVGPaintEngine::brushOriginChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyBrushOrigin; + d->brushOrigin = state()->brushOrigin; + d->forcePenChange = true; + d->forceBrushChange = true; +} + +void QVGPaintEngine::opacityChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyOpacity; + d->opacity = state()->opacity; + d->forcePenChange = true; + d->forceBrushChange = true; +} + +void QVGPaintEngine::compositionModeChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyCompositionMode; + + VGBlendMode vgMode = VG_BLEND_SRC_OVER; + + switch (state()->composition_mode) { + case QPainter::CompositionMode_SourceOver: + vgMode = VG_BLEND_SRC_OVER; + break; + case QPainter::CompositionMode_DestinationOver: + vgMode = VG_BLEND_DST_OVER; + break; + case QPainter::CompositionMode_Source: + vgMode = VG_BLEND_SRC; + break; + case QPainter::CompositionMode_SourceIn: + vgMode = VG_BLEND_SRC_IN; + break; + case QPainter::CompositionMode_DestinationIn: + vgMode = VG_BLEND_DST_IN; + break; + case QPainter::CompositionMode_Plus: + vgMode = VG_BLEND_ADDITIVE; + break; + case QPainter::CompositionMode_Multiply: + vgMode = VG_BLEND_MULTIPLY; + break; + case QPainter::CompositionMode_Screen: + vgMode = VG_BLEND_SCREEN; + break; + case QPainter::CompositionMode_Darken: + vgMode = VG_BLEND_DARKEN; + break; + case QPainter::CompositionMode_Lighten: + vgMode = VG_BLEND_LIGHTEN; + break; + default: + qWarning() << "QVGPaintEngine::compositionModeChanged unsupported mode" << state()->composition_mode; + break; // Fall back to VG_BLEND_SRC_OVER. + } + + d->setBlendMode(vgMode); +} + +void QVGPaintEngine::renderHintsChanged() +{ + Q_D(QVGPaintEngine); + d->dirty |= QPaintEngine::DirtyHints; + + QPainter::RenderHints hints = state()->renderHints; + + VGRenderingQuality rq = + (hints & QPainter::Antialiasing) + ? VG_RENDERING_QUALITY_BETTER + : VG_RENDERING_QUALITY_NONANTIALIASED; + VGImageQuality iq = + (hints & QPainter::SmoothPixmapTransform) + ? VG_IMAGE_QUALITY_BETTER + : VG_IMAGE_QUALITY_NONANTIALIASED; + + d->setRenderingQuality(rq); + d->setImageQuality(iq); +} + +void QVGPaintEngine::transformChanged() +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + d->dirty |= QPaintEngine::DirtyTransform; + d->transform = s->transform(); + qreal oldPenScale = d->penScale; + d->updateTransform(paintDevice()); + if (d->penScale != oldPenScale) + d->forcePenChange = true; +} + +bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + if (!s->clipEnabled || s->clipOperation == Qt::NoClip) { + // The transform will either be identity or a simple translation, + // so do a simpler version of "r = d->transform.map(rect).toRect()". + QRect r = QRect(qRound(rect.x() + d->transform.dx()), + qRound(rect.y() + d->transform.dy()), + qRound(rect.width()), + qRound(rect.height())); + int height = paintDevice()->height(); + if (d->clearColor != color || d->clearOpacity != s->opacity) { + VGfloat values[4]; + values[0] = color.redF(); + values[1] = color.greenF(); + values[2] = color.blueF(); + values[3] = color.alphaF() * s->opacity; + vgSetfv(VG_CLEAR_COLOR, 4, values); + d->clearColor = color; + d->clearOpacity = s->opacity; + } + vgClear(r.x(), height - r.y() - r.height(), + r.width(), r.height()); + return true; + } + return false; +} + +void QVGPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) +{ + Q_D(QVGPaintEngine); + + if (brush.style() == Qt::NoBrush) + return; + + // Check to see if we can use vgClear() for faster filling. + if (brush.style() == Qt::SolidPattern && + clipTransformIsSimple(d->transform) && d->opacity == 1.0f && + clearRect(rect, brush.color())) { + return; + } + +#if !defined(QVG_NO_MODIFY_PATH) + VGfloat coords[8]; + if (d->simpleTransform) { + coords[0] = rect.x(); + coords[1] = rect.y(); + coords[2] = rect.x() + rect.width(); + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = rect.y() + rect.height(); + coords[6] = coords[0]; + coords[7] = coords[5]; + } else { + QPointF tl = d->transform.map(rect.topLeft()); + QPointF tr = d->transform.map(rect.topRight()); + QPointF bl = d->transform.map(rect.bottomLeft()); + QPointF br = d->transform.map(rect.bottomRight()); + coords[0] = tl.x(); + coords[1] = tl.y(); + coords[2] = tr.x(); + coords[3] = tr.y(); + coords[4] = br.x(); + coords[5] = br.y(); + coords[6] = bl.x(); + coords[7] = bl.y(); + } + vgModifyPathCoords(d->rectPath, 0, 4, coords); + d->fill(d->rectPath, brush); +#else + QPaintEngineEx::fillRect(rect, brush); +#endif +} + +void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color) +{ + Q_D(QVGPaintEngine); + + // Check to see if we can use vgClear() for faster filling. + if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f && + clearRect(rect, color)) { + return; + } + +#if !defined(QVG_NO_MODIFY_PATH) + VGfloat coords[8]; + if (d->simpleTransform) { + coords[0] = rect.x(); + coords[1] = rect.y(); + coords[2] = rect.x() + rect.width(); + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = rect.y() + rect.height(); + coords[6] = coords[0]; + coords[7] = coords[5]; + } else { + QPointF tl = d->transform.map(rect.topLeft()); + QPointF tr = d->transform.map(rect.topRight()); + QPointF bl = d->transform.map(rect.bottomLeft()); + QPointF br = d->transform.map(rect.bottomRight()); + coords[0] = tl.x(); + coords[1] = tl.y(); + coords[2] = tr.x(); + coords[3] = tr.y(); + coords[4] = br.x(); + coords[5] = br.y(); + coords[6] = bl.x(); + coords[7] = bl.y(); + } + vgModifyPathCoords(d->rectPath, 0, 4, coords); + d->fill(d->rectPath, QBrush(color)); +#else + QPaintEngineEx::fillRect(rect, QBrush(color)); +#endif +} + +void QVGPaintEngine::drawRects(const QRect *rects, int rectCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + for (int i = 0; i < rectCount; ++i, ++rects) { + VGfloat coords[8]; + if (d->simpleTransform) { + coords[0] = rects->x(); + coords[1] = rects->y(); + coords[2] = rects->x() + rects->width(); + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = rects->y() + rects->height(); + coords[6] = coords[0]; + coords[7] = coords[5]; + } else { + QPointF tl = d->transform.map(QPointF(rects->x(), rects->y())); + QPointF tr = d->transform.map(QPointF(rects->x() + rects->width(), + rects->y())); + QPointF bl = d->transform.map(QPointF(rects->x(), + rects->y() + rects->height())); + QPointF br = d->transform.map(QPointF(rects->x() + rects->width(), + rects->y() + rects->height())); + coords[0] = tl.x(); + coords[1] = tl.y(); + coords[2] = tr.x(); + coords[3] = tr.y(); + coords[4] = br.x(); + coords[5] = br.y(); + coords[6] = bl.x(); + coords[7] = bl.y(); + } + vgModifyPathCoords(d->rectPath, 0, 4, coords); + d->draw(d->rectPath, s->pen, s->brush); + } +#else + QPaintEngineEx::drawRects(rects, rectCount); +#endif +} + +void QVGPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + for (int i = 0; i < rectCount; ++i, ++rects) { + VGfloat coords[8]; + if (d->simpleTransform) { + coords[0] = rects->x(); + coords[1] = rects->y(); + coords[2] = rects->x() + rects->width(); + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = rects->y() + rects->height(); + coords[6] = coords[0]; + coords[7] = coords[5]; + } else { + QPointF tl = d->transform.map(rects->topLeft()); + QPointF tr = d->transform.map(rects->topRight()); + QPointF bl = d->transform.map(rects->bottomLeft()); + QPointF br = d->transform.map(rects->bottomRight()); + coords[0] = tl.x(); + coords[1] = tl.y(); + coords[2] = tr.x(); + coords[3] = tr.y(); + coords[4] = br.x(); + coords[5] = br.y(); + coords[6] = bl.x(); + coords[7] = bl.y(); + } + vgModifyPathCoords(d->rectPath, 0, 4, coords); + d->draw(d->rectPath, s->pen, s->brush); + } +#else + QPaintEngineEx::drawRects(rects, rectCount); +#endif +} + +void QVGPaintEngine::drawLines(const QLine *lines, int lineCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + for (int i = 0; i < lineCount; ++i, ++lines) { + VGfloat coords[4]; + if (d->simpleTransform) { + coords[0] = lines->x1(); + coords[1] = lines->y1(); + coords[2] = lines->x2(); + coords[3] = lines->y2(); + } else { + QPointF p1 = d->transform.map(QPointF(lines->x1(), lines->y1())); + QPointF p2 = d->transform.map(QPointF(lines->x2(), lines->y2())); + coords[0] = p1.x(); + coords[1] = p1.y(); + coords[2] = p2.x(); + coords[3] = p2.y(); + } + vgModifyPathCoords(d->linePath, 0, 2, coords); + d->stroke(d->linePath, s->pen); + } +#else + QPaintEngineEx::drawLines(lines, lineCount); +#endif +} + +void QVGPaintEngine::drawLines(const QLineF *lines, int lineCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + for (int i = 0; i < lineCount; ++i, ++lines) { + VGfloat coords[4]; + if (d->simpleTransform) { + coords[0] = lines->x1(); + coords[1] = lines->y1(); + coords[2] = lines->x2(); + coords[3] = lines->y2(); + } else { + QPointF p1 = d->transform.map(lines->p1()); + QPointF p2 = d->transform.map(lines->p2()); + coords[0] = p1.x(); + coords[1] = p1.y(); + coords[2] = p2.x(); + coords[3] = p2.y(); + } + vgModifyPathCoords(d->linePath, 0, 2, coords); + d->stroke(d->linePath, s->pen); + } +#else + QPaintEngineEx::drawLines(lines, lineCount); +#endif +} + +void QVGPaintEngine::drawEllipse(const QRectF &r) +{ + // Based on the description of vguEllipse() in the OpenVG specification. + // We don't use vguEllipse(), to avoid unnecessary library dependencies. + Q_D(QVGPaintEngine); + if (d->simpleTransform) { + QVGPainterState *s = state(); + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 4, // segmentCapacityHint + 12, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + static VGubyte segments[4] = { + VG_MOVE_TO_ABS, + VG_SCCWARC_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + VGfloat coords[12]; + VGfloat halfwid = r.width() / 2; + VGfloat halfht = r.height() / 2; + coords[0] = r.x() + r.width(); + coords[1] = r.y() + halfht; + coords[2] = halfwid; + coords[3] = halfht; + coords[4] = 0.0f; + coords[5] = -r.width(); + coords[6] = 0.0f; + coords[7] = halfwid; + coords[8] = halfht; + coords[9] = 0.0f; + coords[10] = r.width(); + coords[11] = 0.0f; + vgAppendPathData(path, 4, segments, coords); + d->draw(path, s->pen, s->brush); + vgDestroyPath(path); + } else { + // The projective transform version of an ellipse is difficult. + // Generate a QVectorPath containing cubic curves and transform that. + QPaintEngineEx::drawEllipse(r); + } +} + +void QVGPaintEngine::drawEllipse(const QRect &r) +{ + drawEllipse(QRectF(r)); +} + +void QVGPaintEngine::drawPath(const QPainterPath &path) +{ + // Shortcut past the QPainterPath -> QVectorPath conversion, + // converting the QPainterPath directly into a VGPath. + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + VGPath vgpath = d->painterPathToVGPath(path); + if (path.fillRule() == Qt::OddEvenFill) + d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); + else + d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); + vgDestroyPath(vgpath); +} + +void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + + // Set up a new pen if necessary. + QPen pen = state()->pen; + if (pen.style() == Qt::NoPen) + return; + if (pen.capStyle() == Qt::FlatCap) + pen.setCapStyle(Qt::SquareCap); + + for (int i = 0; i < pointCount; ++i, ++points) { + VGfloat coords[4]; + if (d->simpleTransform) { + coords[0] = points->x(); + coords[1] = points->y(); + coords[2] = coords[0]; + coords[3] = coords[1]; + } else { + QPointF p = d->transform.map(*points); + coords[0] = p.x(); + coords[1] = p.y(); + coords[2] = coords[0]; + coords[3] = coords[1]; + } + vgModifyPathCoords(d->linePath, 0, 2, coords); + d->stroke(d->linePath, pen); + } +#else + QPaintEngineEx::drawPoints(points, pointCount); +#endif +} + +void QVGPaintEngine::drawPoints(const QPoint *points, int pointCount) +{ +#if !defined(QVG_NO_MODIFY_PATH) + Q_D(QVGPaintEngine); + + // Set up a new pen if necessary. + QPen pen = state()->pen; + if (pen.style() == Qt::NoPen) + return; + if (pen.capStyle() == Qt::FlatCap) + pen.setCapStyle(Qt::SquareCap); + + for (int i = 0; i < pointCount; ++i, ++points) { + VGfloat coords[4]; + if (d->simpleTransform) { + coords[0] = points->x(); + coords[1] = points->y(); + coords[2] = coords[0]; + coords[3] = coords[1]; + } else { + QPointF p = d->transform.map(QPointF(*points)); + coords[0] = p.x(); + coords[1] = p.y(); + coords[2] = coords[0]; + coords[3] = coords[1]; + } + vgModifyPathCoords(d->linePath, 0, 2, coords); + d->stroke(d->linePath, pen); + } +#else + QPaintEngineEx::drawPoints(points, pointCount); +#endif +} + +void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + pointCount + 1, // segmentCapacityHint + pointCount * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + QVarLengthArray<VGfloat, 16> coords; + QVarLengthArray<VGubyte, 10> segments; + for (int i = 0; i < pointCount; ++i, ++points) { + if (d->simpleTransform) { + coords.append(points->x()); + coords.append(points->y()); + } else { + QPointF temp = d->transform.map(*points); + coords.append(temp.x()); + coords.append(temp.y()); + } + if (i == 0) + segments.append(VG_MOVE_TO_ABS); + else + segments.append(VG_LINE_TO_ABS); + } + if (mode != QPaintEngine::PolylineMode) + segments.append(VG_CLOSE_PATH); + vgAppendPathData(path, segments.count(), + segments.constData(), coords.constData()); + switch (mode) { + case QPaintEngine::WindingMode: + d->draw(path, s->pen, s->brush, VG_NON_ZERO); + break; + + case QPaintEngine::PolylineMode: + d->stroke(path, s->pen); + break; + + default: + d->draw(path, s->pen, s->brush, VG_EVEN_ODD); + break; + } + vgDestroyPath(path); +} + +void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QVGPaintEngine); + QVGPainterState *s = state(); + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + pointCount + 1, // segmentCapacityHint + pointCount * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + QVarLengthArray<VGfloat, 16> coords; + QVarLengthArray<VGubyte, 10> segments; + for (int i = 0; i < pointCount; ++i, ++points) { + if (d->simpleTransform) { + coords.append(points->x()); + coords.append(points->y()); + } else { + QPointF temp = d->transform.map(QPointF(*points)); + coords.append(temp.x()); + coords.append(temp.y()); + } + if (i == 0) + segments.append(VG_MOVE_TO_ABS); + else + segments.append(VG_LINE_TO_ABS); + } + if (mode != QPaintEngine::PolylineMode) + segments.append(VG_CLOSE_PATH); + vgAppendPathData(path, segments.count(), + segments.constData(), coords.constData()); + switch (mode) { + case QPaintEngine::WindingMode: + d->draw(path, s->pen, s->brush, VG_NON_ZERO); + break; + + case QPaintEngine::PolylineMode: + d->stroke(path, s->pen); + break; + + default: + d->draw(path, s->pen, s->brush, VG_EVEN_ODD); + break; + } + vgDestroyPath(path); +} + +void QVGPaintEnginePrivate::setImageOptions() +{ + if (opacity != 1.0f && simpleTransform) { + if (opacity != paintOpacity) { + VGfloat values[4]; + values[0] = 1.0f; + values[1] = 1.0f; + values[2] = 1.0f; + values[3] = opacity; + vgSetParameterfv(opacityPaint, VG_PAINT_COLOR, 4, values); + paintOpacity = opacity; + } + if (fillPaint != opacityPaint) { + vgSetPaint(opacityPaint, VG_FILL_PATH); + fillPaint = opacityPaint; + } + setImageMode(VG_DRAW_IMAGE_MULTIPLY); + } else { + setImageMode(VG_DRAW_IMAGE_NORMAL); + } +} + +static void drawVGImage(QVGPaintEnginePrivate *d, + const QRectF& r, VGImage vgImg, + const QSize& imageSize, const QRectF& sr) +{ + if (vgImg == VG_INVALID_HANDLE) + return; + VGImage child = VG_INVALID_HANDLE; + + if (sr.topLeft().isNull() && sr.size() == imageSize) { + child = vgImg; + } else { + QRect src = sr.toRect(); +#if !defined(QT_SHIVAVG) + child = vgChildImage(vgImg, src.x(), src.y(), src.width(), src.height()); +#else + child = vgImg; // XXX: ShivaVG doesn't have vgChildImage(). +#endif + } + + QTransform transform(d->imageTransform); + VGfloat scaleX = sr.width() == 0.0f ? 0.0f : r.width() / sr.width(); + VGfloat scaleY = sr.height() == 0.0f ? 0.0f : r.height() / sr.height(); + transform.translate(r.x(), r.y()); + transform.scale(scaleX, scaleY); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + d->setImageOptions(); + vgDrawImage(child); + + if(child != vgImg) + vgDestroyImage(child); +} + +static void drawVGImage(QVGPaintEnginePrivate *d, + const QPointF& pos, VGImage vgImg) +{ + if (vgImg == VG_INVALID_HANDLE) + return; + + QTransform transform(d->imageTransform); + transform.translate(pos.x(), pos.y()); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + d->setImageOptions(); + vgDrawImage(vgImg); +} + +// Used by qpixmapfilter_vg.cpp to draw filtered VGImage's. +void qt_vg_drawVGImage(QPainter *painter, const QPointF& pos, VGImage vgImg) +{ + QVGPaintEngine *engine = + static_cast<QVGPaintEngine *>(painter->paintEngine()); + drawVGImage(engine->vgPrivate(), pos, vgImg); +} + +void QVGPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + QPixmapData *pd = pm.pixmapData(); + if (pd->classId() == QPixmapData::OpenVGClass) { + Q_D(QVGPaintEngine); + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd); + if (!vgpd->isValid()) + return; + if (d->simpleTransform) + drawVGImage(d, r, vgpd->toVGImage(), vgpd->size(), sr); + else + drawVGImage(d, r, vgpd->toVGImage(d->opacity), vgpd->size(), sr); + } else { + drawImage(r, *(pd->buffer()), sr, Qt::AutoColor); + } +} + +void QVGPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) +{ + QPixmapData *pd = pm.pixmapData(); + if (pd->classId() == QPixmapData::OpenVGClass) { + Q_D(QVGPaintEngine); + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd); + if (!vgpd->isValid()) + return; + if (d->simpleTransform) + drawVGImage(d, pos, vgpd->toVGImage()); + else + drawVGImage(d, pos, vgpd->toVGImage(d->opacity)); + } else { + drawImage(pos, *(pd->buffer())); + } +} + +void QVGPaintEngine::drawImage + (const QRectF &r, const QImage &image, const QRectF &sr, + Qt::ImageConversionFlags flags) +{ + Q_D(QVGPaintEngine); + VGImage vgImg; + if (d->simpleTransform || d->opacity == 1.0f) + vgImg = toVGImageSubRect(image, sr.toRect(), flags); + else + vgImg = toVGImageWithOpacitySubRect(image, d->opacity, sr.toRect()); + if (vgImg != VG_INVALID_HANDLE) { + if (r.size() == sr.size()) { + drawVGImage(d, r.topLeft(), vgImg); + } else { + drawVGImage(d, r, vgImg, sr.size().toSize(), + QRectF(QPointF(0, 0), sr.size())); + } + } else { + // Monochrome images need to use the vgChildImage() path. + vgImg = toVGImage(image, flags); + drawVGImage(d, r, vgImg, image.size(), sr); + } + vgDestroyImage(vgImg); +} + +void QVGPaintEngine::drawImage(const QPointF &pos, const QImage &image) +{ + Q_D(QVGPaintEngine); + VGImage vgImg; + if (d->simpleTransform || d->opacity == 1.0f) + vgImg = toVGImage(image); + else + vgImg = toVGImageWithOpacity(image, d->opacity); + drawVGImage(d, pos, vgImg); + vgDestroyImage(vgImg); +} + +void QVGPaintEngine::drawTiledPixmap + (const QRectF &r, const QPixmap &pixmap, const QPointF &s) +{ + QBrush brush(state()->pen.color(), pixmap); + QTransform xform; + xform.translate(-s.x(), -s.y()); + brush.setTransform(xform); + fillRect(r, brush); +} + +QVGFontEngineCleaner::QVGFontEngineCleaner(QVGPaintEnginePrivate *d) + : QObject(), d_ptr(d) +{ +} + +QVGFontEngineCleaner::~QVGFontEngineCleaner() +{ +} + +void QVGFontEngineCleaner::fontEngineDestroyed() +{ +#if !defined(QVG_NO_DRAW_GLYPHS) + QFontEngine *engine = static_cast<QFontEngine *>(sender()); + QVGFontCache::Iterator it = d_ptr->fontCache.find(engine); + if (it != d_ptr->fontCache.end()) { + delete it.value(); + d_ptr->fontCache.erase(it); + } +#endif +} + +#if !defined(QVG_NO_DRAW_GLYPHS) + +QVGFontGlyphCache::QVGFontGlyphCache() +{ + font = vgCreateFont(0); + scaleX = scaleY = 0.0; + memset(cachedGlyphsMask, 0, sizeof(cachedGlyphsMask)); +} + +QVGFontGlyphCache::~QVGFontGlyphCache() +{ + if (font != VG_INVALID_HANDLE) + vgDestroyFont(font); +} + +void QVGFontGlyphCache::setScaleFromText(const QTextItemInt &ti) +{ + QFontInfo fi(ti.font()); + qreal pixelSize = fi.pixelSize(); + qreal emSquare = ti.fontEngine->properties().emSquare.toReal(); + scaleX = scaleY = static_cast<VGfloat>(pixelSize / emSquare); +} + +void QVGFontGlyphCache::cacheGlyphs + (QVGPaintEnginePrivate *d, const QTextItemInt &ti, + const QVarLengthArray<glyph_t> &glyphs) +{ + VGfloat origin[2]; + VGfloat escapement[2]; + const glyph_t *g = glyphs.constData(); + int count = glyphs.size(); + glyph_metrics_t metrics; + // Some Qt font engines don't set yoff in getUnscaledGlyph(). + // Zero the metric structure so that everything has a default value. + memset(&metrics, 0, sizeof(metrics)); + while (count-- > 0) { + // Skip this glyph if we have already cached it before. + glyph_t glyph = *g++; + if (glyph < 256) { + if ((cachedGlyphsMask[glyph / 32] & (1 << (glyph % 32))) != 0) + continue; + cachedGlyphsMask[glyph / 32] |= (1 << (glyph % 32)); + } else if (cachedGlyphs.contains(glyph)) { + continue; + } else { + cachedGlyphs.insert(glyph); + } +#if !defined(QVG_NO_IMAGE_GLYPHS) + Q_UNUSED(d); + QImage scaledImage = ti.fontEngine->alphaMapForGlyph(glyph); + VGImage vgImage = VG_INVALID_HANDLE; + metrics = ti.fontEngine->boundingBox(glyph); + if (!scaledImage.isNull()) { // Not a space character + // The QPF implementation of alphaMapForGlyph() uses the color + // RGBA = (value, value, value, 255) instead of the color + // RGBA = (0, 0, 0, value) that the other font engines use. + // We modify the image colors to rectify this situation. + QFontEngine::Type type = ti.fontEngine->type(); + if (type == QFontEngine::QPF1 || type == QFontEngine::QPF2) { + if (scaledImage.format() == QImage::Format_Indexed8) { + for (int i = 0; i < 256; ++i) + scaledImage.setColor(i, qRgba(0, 0, 0, i)); + } else if (scaledImage.format() == QImage::Format_Mono) { + scaledImage.setColor(0, qRgba(0, 0, 0, 0)); + scaledImage.setColor(1, qRgba(0, 0, 0, 255)); + } + } + if (scaledImage.format() == QImage::Format_Indexed8) { + vgImage = vgCreateImage(VG_A_8, scaledImage.width(), scaledImage.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData(vgImage, scaledImage.bits(), scaledImage.bytesPerLine(), VG_A_8, 0, 0, scaledImage.width(), scaledImage.height()); + } else if (scaledImage.format() == QImage::Format_Mono) { + QImage img = scaledImage.convertToFormat(QImage::Format_Indexed8); + vgImage = vgCreateImage(VG_A_8, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_A_8, 0, 0, img.width(), img.height()); + } else { + QImage img = scaledImage.convertToFormat(QImage::Format_ARGB32_Premultiplied); + vgImage = vgCreateImage(VG_sARGB_8888_PRE, img.width(), img.height(), VG_IMAGE_QUALITY_FASTER); + vgImageSubData(vgImage, img.bits(), img.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, img.width(), img.height()); + } + } + origin[0] = -metrics.x.toReal() + 0.5f; + origin[1] = -metrics.y.toReal() + 0.5f; + escapement[0] = metrics.xoff.toReal(); + escapement[1] = metrics.yoff.toReal(); + vgSetGlyphToImage(font, glyph, vgImage, origin, escapement); + vgDestroyImage(vgImage); // Reduce reference count. +#else + // Calculate the path for the glyph and cache it. + QPainterPath path; + ti.fontEngine->getUnscaledGlyph(glyph, &path, &metrics); + VGPath vgPath; + if (!path.isEmpty()) { + vgPath = d->painterPathToVGPath(path); + } else { + // Probably a "space" character with no visible outline. + vgPath = VG_INVALID_HANDLE; + } + origin[0] = 0; + origin[1] = 0; + escapement[0] = metrics.xoff.toReal(); + escapement[1] = metrics.yoff.toReal(); + vgSetGlyphToPath(font, glyph, vgPath, VG_FALSE, origin, escapement); + vgDestroyPath(vgPath); // Reduce reference count. +#endif // !defined(QVG_NO_IMAGE_GLYPHS) + } +} + +#endif // !defined(QVG_NO_DRAW_GLYPHS) + +void QVGPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +{ +#if !defined(QVG_NO_DRAW_GLYPHS) + Q_D(QVGPaintEngine); + const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); + + // If we are not using a simple transform, then fall back + // to the default Qt path stroking algorithm. + if (!d->simpleTransform) { + QPaintEngineEx::drawTextItem(p, textItem); + return; + } + + // Get the glyphs and positions associated with the text item. + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = d->transform; + matrix.translate(p.x(), p.y()); + ti.fontEngine->getGlyphPositions + (ti.glyphs, matrix, ti.flags, glyphs, positions); + + // Find the glyph cache for this font. + QVGFontCache::ConstIterator it = d->fontCache.constFind(ti.fontEngine); + QVGFontGlyphCache *glyphCache; + if (it != d->fontCache.constEnd()) { + glyphCache = it.value(); + } else { + glyphCache = new QVGFontGlyphCache(); + if (glyphCache->font == VG_INVALID_HANDLE) { + qWarning("QVGPaintEngine::drawTextItem: OpenVG fonts are not supported by the OpenVG engine"); + delete glyphCache; + QPaintEngineEx::drawTextItem(p, textItem); + return; + } + glyphCache->setScaleFromText(ti); + d->fontCache.insert(ti.fontEngine, glyphCache); + if (!d->fontEngineCleaner) + d->fontEngineCleaner = new QVGFontEngineCleaner(d); + QObject::connect(ti.fontEngine, SIGNAL(destroyed()), + d->fontEngineCleaner, SLOT(fontEngineDestroyed())); + } + + // Set the transformation to use for drawing the current glyphs. + QTransform glyphTransform(d->pathTransform); + glyphTransform.translate(p.x(), p.y()); +#if defined(QVG_NO_IMAGE_GLYPHS) + glyphTransform.scale(glyphCache->scaleX, glyphCache->scaleY); +#endif + d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, glyphTransform); + + // Add the glyphs from the text item into the glyph cache. + glyphCache->cacheGlyphs(d, ti, glyphs); + + // Set the glyph drawing origin. + VGfloat origin[2]; + origin[0] = 0; + origin[1] = 0; + vgSetfv(VG_GLYPH_ORIGIN, 2, origin); + + // Fast anti-aliasing for paths, better for images. +#if !defined(QVG_NO_IMAGE_GLYPHS) + d->setImageQuality(VG_IMAGE_QUALITY_BETTER); + d->setImageMode(VG_DRAW_IMAGE_STENCIL); +#else + d->setRenderingQuality(VG_RENDERING_QUALITY_FASTER); +#endif + + // Draw the glyphs. We need to fill with the brush associated with + // the Qt pen, not the Qt brush. + d->ensureBrush(state()->pen.brush()); + vgDrawGlyphs(glyphCache->font, glyphs.size(), (VGuint*)glyphs.data(), + NULL, NULL, VG_FILL_PATH, VG_TRUE); +#else + // OpenGL 1.0 does not have support for VGFont and glyphs, + // so fall back to the default Qt path stroking algorithm. + QPaintEngineEx::drawTextItem(p, textItem); +#endif +} + +void QVGPaintEngine::setState(QPainterState *s) +{ + Q_D(QVGPaintEngine); + QPaintEngineEx::setState(s); + QVGPainterState *ps = static_cast<QVGPainterState *>(s); + if (ps->isNew) { + // Newly created state object. The call to setState() + // will either be followed by a call to begin(), or we are + // setting the state as part of a save(). + ps->isNew = false; + } else { + // This state object was set as part of a restore(). + restoreState(d->dirty); + d->dirty = ps->savedDirty; + } +} + +// Called from QPaintEngine::syncState() to force a state flush. +// This should be called before and after raw VG operations. +void QVGPaintEngine::updateState(const QPaintEngineState &state) +{ + Q_UNUSED(state); + Q_D(QVGPaintEngine); + + if (!(d->rawVG)) { + // About to enter raw VG mode: flush pending changes and make + // sure that all matrices are set to the current transformation. + QVGPainterState *s = this->state(); + d->ensurePen(s->pen); + d->ensureBrush(s->brush); + d->ensurePathTransform(); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, d->imageTransform); +#if !defined(QVG_NO_DRAW_GLYPHS) + d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, d->pathTransform); +#endif + d->rawVG = true; + } else { + // Exiting raw VG mode: force all state values to be + // explicitly set on the VG engine to undo any changes + // that were made by the raw VG function calls. + QPaintEngine::DirtyFlags dirty = d->dirty; + d->clearModes(); + d->forcePenChange = true; + d->forceBrushChange = true; + d->penType = (VGPaintType)0; + d->brushType = (VGPaintType)0; + d->clearColor = QColor(); + d->fillPaint = d->brushPaint; + restoreState(QPaintEngine::AllDirty); + d->dirty = dirty; + d->rawVG = false; + vgSetPaint(d->penPaint, VG_STROKE_PATH); + vgSetPaint(d->brushPaint, VG_FILL_PATH); + } +} + +QPixmapFilter *QVGPaintEngine::createPixmapFilter(int type) const +{ +#if !defined(QT_SHIVAVG) + if (type == QPixmapFilter::ConvolutionFilter) + return new QVGPixmapConvolutionFilter; + else if (type == QPixmapFilter::ColorizeFilter) + return new QVGPixmapColorizeFilter; + else if (type == QPixmapFilter::DropShadowFilter) + return new QVGPixmapDropShadowFilter; + else +#endif + return QPaintEngineEx::createPixmapFilter(type); +} + +void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty) +{ + Q_D(QVGPaintEngine); + + // Restore the pen, brush, and other settings. + if ((dirty & QPaintEngine::DirtyBrushOrigin) != 0) + brushOriginChanged(); + d->fillRule = 0; + if ((dirty & QPaintEngine::DirtyOpacity) != 0) + opacityChanged(); + if ((dirty & QPaintEngine::DirtyTransform) != 0) + transformChanged(); + if ((dirty & QPaintEngine::DirtyCompositionMode) != 0) + compositionModeChanged(); + if ((dirty & QPaintEngine::DirtyHints) != 0) + renderHintsChanged(); + if ((dirty & (QPaintEngine::DirtyClipRegion | + QPaintEngine::DirtyClipPath | + QPaintEngine::DirtyClipEnabled)) != 0) { + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = QRect(); + clipEnabledChanged(); + } + +#if defined(QVG_SCISSOR_CLIP) + if ((dirty & (QPaintEngine::DirtyClipRegion | + QPaintEngine::DirtyClipPath | + QPaintEngine::DirtyClipEnabled)) == 0) { + updateScissor(); + } +#else + updateScissor(); +#endif +} + +#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QT_NO_EGL) + +QVGCompositionHelper::QVGCompositionHelper() +{ + d = qt_vg_create_paint_engine()->vgPrivate(); +} + +QVGCompositionHelper::~QVGCompositionHelper() +{ +} + +void QVGCompositionHelper::startCompositing(const QSize& screenSize) +{ + this->screenSize = screenSize; + clearScissor(); + d->setBlendMode(VG_BLEND_SRC_OVER); +} + +void QVGCompositionHelper::endCompositing() +{ + clearScissor(); +} + +void QVGCompositionHelper::blitWindow + (QVGEGLWindowSurfacePrivate *surface, const QRect& rect, + const QPoint& topLeft, int opacity) +{ + // Get the VGImage that is acting as a back buffer for the window. + VGImage image = surface->surfaceImage(); + if (image == VG_INVALID_HANDLE) + return; + QSize imageSize = surface->surfaceSize(); + + // Determine which sub rectangle of the window to draw. + QRect sr = rect.translated(-topLeft); + + if (opacity >= 255) { + // Fully opaque: use vgSetPixels() to directly copy the sub-region. + int y = screenSize.height() - (rect.bottom() + 1); + vgSetPixels(rect.x(), y, image, sr.x(), + imageSize.height() - (sr.y() + sr.height()), + sr.width(), sr.height()); + } else { + // Extract the child image that we want to draw. + VGImage child; + if (sr.topLeft().isNull() && sr.size() == imageSize) + child = image; + else { + child = vgChildImage + (image, sr.x(), imageSize.height() - (sr.y() + sr.height()), + sr.width(), sr.height()); + } + + // Set the image transform. + QTransform transform; + int y = screenSize.height() - (rect.bottom() + 1); + transform.translate(rect.x() + 0.5f, y + 0.5f); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + // Enable opacity for image drawing if necessary. + if (opacity < 255) { + if (opacity != d->paintOpacity) { + VGfloat values[4]; + values[0] = 1.0f; + values[1] = 1.0f; + values[2] = 1.0f; + values[3] = ((VGfloat)opacity) / 255.0f; + vgSetParameterfv(d->opacityPaint, VG_PAINT_COLOR, 4, values); + d->paintOpacity = values[3]; + } + if (d->fillPaint != d->opacityPaint) { + vgSetPaint(d->opacityPaint, VG_FILL_PATH); + d->fillPaint = d->opacityPaint; + } + d->setImageMode(VG_DRAW_IMAGE_MULTIPLY); + } else { + d->setImageMode(VG_DRAW_IMAGE_NORMAL); + } + + // Draw the child image. + vgDrawImage(child); + + // Destroy the child image. + if(child != image) + vgDestroyImage(child); + } +} + +static void fillBackgroundRect(const QRect& rect, QVGPaintEnginePrivate *d) +{ + VGfloat coords[8]; + coords[0] = rect.x(); + coords[1] = rect.y(); + coords[2] = rect.x() + rect.width(); + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = rect.y() + rect.height(); + coords[6] = coords[0]; + coords[7] = coords[5]; +#if !defined(QVG_NO_MODIFY_PATH) + vgModifyPathCoords(d->rectPath, 0, 4, coords); + vgDrawPath(d->rectPath, VG_FILL_PATH); +#else + Q_UNUSED(d); + VGPath rectPath = vgCreatePath + (VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 5, // segmentCapacityHint + 8, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + static VGubyte const segments[5] = { + VG_MOVE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_LINE_TO_ABS, + VG_CLOSE_PATH + }; + vgAppendPathData(rectPath, 5, segments, coords); + vgDrawPath(rectPath, VG_FILL_PATH); + vgDestroyPath(rectPath); +#endif +} + +void QVGCompositionHelper::fillBackground + (const QRegion& region, const QBrush& brush) +{ + // Set the path transform to the default viewport transformation. + VGfloat devh = screenSize.height() - 1; + QTransform viewport(1.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.5f, devh + 0.5f, 1.0f); + d->setTransform(VG_MATRIX_PATH_USER_TO_SURFACE, viewport); + + // Set the brush to use to fill the background. + d->ensureBrush(brush); + d->setFillRule(VG_EVEN_ODD); + + if (region.numRects() == 1) { + fillBackgroundRect(region.boundingRect(), d); + } else { + const QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); ++i) + fillBackgroundRect(rects.at(i), d); + } + + // We will need to reset the path transform during the next paint. + d->pathTransformSet = false; +} + +void QVGCompositionHelper::drawCursorImage + (const QImage& image, const QPoint& offset) +{ + QImage img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + VGImage vgImg = vgCreateImage + (VG_sARGB_8888_PRE, img.width(), img.height(), + VG_IMAGE_QUALITY_FASTER); + vgImageSubData + (vgImg, img.bits() + img.bytesPerLine() * (img.height() - 1), + -(img.bytesPerLine()), VG_sARGB_8888_PRE, 0, 0, + img.width(), img.height()); + + QTransform transform; + int y = screenSize.height() - (offset.y() + img.height()); + transform.translate(offset.x() + 0.5f, y + 0.5f); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + d->setImageMode(VG_DRAW_IMAGE_NORMAL); + vgDrawImage(vgImg); + + vgDestroyImage(vgImg); +} + +void QVGCompositionHelper::drawCursorPixmap + (const QPixmap& pixmap, const QPoint& offset) +{ + QPixmapData *pd = pixmap.pixmapData(); + if (pd->classId() == QPixmapData::OpenVGClass) { + QVGPixmapData *vgpd = static_cast<QVGPixmapData *>(pd); + if (vgpd->isValid()) { + VGfloat devh = screenSize.height() - 1; + QTransform transform(1.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.5f, devh + 0.5f, 1.0f); + transform.translate(offset.x(), offset.y()); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, transform); + + d->setImageMode(VG_DRAW_IMAGE_NORMAL); + vgDrawImage(vgpd->toVGImage()); + return; + } + } + + drawCursorImage(pixmap.toImage(), offset); +} + +void QVGCompositionHelper::setScissor(const QRegion& region) +{ + QVector<QRect> rects = region.rects(); + int count = rects.count(); + if (count > d->maxScissorRects) + count = d->maxScissorRects; + QVarLengthArray<VGint> params(count * 4); + int height = screenSize.height(); + for (int i = 0; i < count; ++i) { + params[i * 4 + 0] = rects[i].x(); + params[i * 4 + 1] = height - rects[i].y() - rects[i].height(); + params[i * 4 + 2] = rects[i].width(); + params[i * 4 + 3] = rects[i].height(); + } + + vgSetiv(VG_SCISSOR_RECTS, count * 4, params.data()); + vgSeti(VG_SCISSORING, VG_TRUE); + d->scissorActive = true; + d->scissorRegion = region; +} + +void QVGCompositionHelper::clearScissor() +{ + if (d->scissorActive) { + vgSeti(VG_SCISSORING, VG_FALSE); + d->scissorActive = false; + } +} + +#endif // !QVG_NO_SINGLE_CONTEXT && !QT_NO_EGL + +VGImageFormat qt_vg_image_to_vg_format(QImage::Format format) +{ + switch (format) { + case QImage::Format_MonoLSB: + return VG_BW_1; + case QImage::Format_ARGB32_Premultiplied: + return VG_sARGB_8888_PRE; + case QImage::Format_RGB32: + return VG_sXRGB_8888; + case QImage::Format_ARGB32: + return VG_sARGB_8888; + case QImage::Format_RGB16: + return VG_sRGB_565; + case QImage::Format_ARGB4444_Premultiplied: + return VG_sARGB_4444; + default: break; + } + return VG_sARGB_8888; // XXX +} + +QT_END_NAMESPACE + +#include "qpaintengine_vg.moc" diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h new file mode 100644 index 0000000..a390c80 --- /dev/null +++ b/src/openvg/qpaintengine_vg_p.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAINTENGINE_VG_P_H +#define QPAINTENGINE_VG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qpaintengineex_p.h> + +QT_BEGIN_NAMESPACE + +class QVGPaintEnginePrivate; +class QPixmapData; +class QVGEGLWindowSurfacePrivate; + +class Q_OPENVG_EXPORT QVGPainterState : public QPainterState +{ +public: + QVGPainterState(QVGPainterState& other); + QVGPainterState(); + ~QVGPainterState(); + + bool isNew; + QRegion clipRegion; + QPaintEngine::DirtyFlags savedDirty; +}; + +class Q_OPENVG_EXPORT QVGPaintEngine : public QPaintEngineEx +{ + Q_DECLARE_PRIVATE(QVGPaintEngine) +public: + QVGPaintEngine(); + ~QVGPaintEngine(); + + Type type() const { return OpenVG; } + + QPainterState *createState(QPainterState *orig) const; + + bool begin(QPaintDevice *pdev); + bool end(); + + void draw(const QVectorPath &path); + void fill(const QVectorPath &path, const QBrush &brush); + void stroke(const QVectorPath &path, const QPen &pen); + + void clip(const QVectorPath &path, Qt::ClipOperation op); + void clip(const QRect &rect, Qt::ClipOperation op); + void clip(const QRegion ®ion, Qt::ClipOperation op); + void clip(const QPainterPath &path, Qt::ClipOperation op); + + void clipEnabledChanged(); + void penChanged(); + void brushChanged(); + void brushOriginChanged(); + void opacityChanged(); + void compositionModeChanged(); + void renderHintsChanged(); + void transformChanged(); + + void fillRect(const QRectF &rect, const QBrush &brush); + void fillRect(const QRectF &rect, const QColor &color); + + void drawRects(const QRect *rects, int rectCount); + void drawRects(const QRectF *rects, int rectCount); + + void drawLines(const QLine *lines, int lineCount); + void drawLines(const QLineF *lines, int lineCount); + + void drawEllipse(const QRectF &r); + void drawEllipse(const QRect &r); + + void drawPath(const QPainterPath &path); + + void drawPoints(const QPointF *points, int pointCount); + void drawPoints(const QPoint *points, int pointCount); + + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); + + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + void drawPixmap(const QPointF &pos, const QPixmap &pm); + + void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, + Qt::ImageConversionFlags flags = Qt::AutoColor); + void drawImage(const QPointF &pos, const QImage &image); + + void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); + + void drawTextItem(const QPointF &p, const QTextItem &textItem); + + void setState(QPainterState *s); + QVGPainterState *state() { return static_cast<QVGPainterState *>(QPaintEngineEx::state()); } + const QVGPainterState *state() const { return static_cast<const QVGPainterState *>(QPaintEngineEx::state()); } + + void updateState(const QPaintEngineState &state); + + QPixmapFilter *createPixmapFilter(int type) const; + + QVGPaintEnginePrivate *vgPrivate() { Q_D(QVGPaintEngine); return d; } + +protected: + QVGPaintEngine(QVGPaintEnginePrivate &data); + +private: + void restoreState(QPaintEngine::DirtyFlags dirty); + void updateScissor(); + QRegion defaultClipRegion(); + bool isDefaultClipRegion(const QRegion& region); + bool clearRect(const QRectF &rect, const QColor &color); +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp new file mode 100644 index 0000000..90fd9a5 --- /dev/null +++ b/src/openvg/qpixmapdata_vg.cpp @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpixmapdata_vg_p.h" +#include "qpaintengine_vg_p.h" +#include <QtGui/private/qdrawhelper_p.h> +#include "qvg_p.h" + +QT_BEGIN_NAMESPACE + +static int qt_vg_pixmap_serial = 0; + +QVGPixmapData::QVGPixmapData(PixelType type) + : QPixmapData(type, OpenVGClass) +{ + Q_ASSERT(type == QPixmapData::PixmapType); + vgImage = VG_INVALID_HANDLE; + vgImageOpacity = VG_INVALID_HANDLE; + cachedOpacity = 1.0f; + recreate = true; +#if !defined(QT_NO_EGL) + context = 0; +#endif + setSerialNumber(++qt_vg_pixmap_serial); +} + +QVGPixmapData::~QVGPixmapData() +{ + if (vgImage != VG_INVALID_HANDLE) { + // We need to have a context current to destroy the image. +#if !defined(QT_NO_EGL) + if (context->isCurrent()) { + vgDestroyImage(vgImage); + if (vgImageOpacity != VG_INVALID_HANDLE) + vgDestroyImage(vgImageOpacity); + } else { + // We don't currently have a widget surface active, but we + // need a surface to make the context current. So use the + // shared pbuffer surface instead. + qt_vg_make_current(context, qt_vg_shared_surface()); + vgDestroyImage(vgImage); + if (vgImageOpacity != VG_INVALID_HANDLE) + vgDestroyImage(vgImageOpacity); + qt_vg_done_current(context); + context->setSurface(EGL_NO_SURFACE); + } +#else + vgDestroyImage(vgImage); + if (vgImageOpacity != VG_INVALID_HANDLE) + vgDestroyImage(vgImageOpacity); + } else { +#endif + } +#if !defined(QT_NO_EGL) + if (context) + qt_vg_destroy_context(context); +#endif +} + +bool QVGPixmapData::isValid() const +{ + return (w > 0 && h > 0); +} + +void QVGPixmapData::resize(int wid, int ht) +{ + if (w == wid && h == ht) + return; + + w = wid; + h = ht; + d = 32; // We always use ARGB_Premultiplied for VG pixmaps. + is_null = (w <= 0 || h <= 0); + source = QImage(); + recreate = true; + + setSerialNumber(++qt_vg_pixmap_serial); +} + +void QVGPixmapData::fromImage + (const QImage &image, Qt::ImageConversionFlags flags) +{ + if (image.size() == QSize(w, h)) + setSerialNumber(++qt_vg_pixmap_serial); + else + resize(image.width(), image.height()); + source = image.convertToFormat(sourceFormat(), flags); + recreate = true; +} + +void QVGPixmapData::fill(const QColor &color) +{ + if (!isValid()) + return; + + if (source.isNull()) + source = QImage(w, h, sourceFormat()); + + if (source.depth() == 1) { + // Pick the best approximate color in the image's colortable. + int gray = qGray(color.rgba()); + if (qAbs(qGray(source.color(0)) - gray) < qAbs(qGray(source.color(1)) - gray)) + source.fill(0); + else + source.fill(1); + } else { + source.fill(PREMUL(color.rgba())); + } + + // Re-upload the image to VG the next time toVGImage() is called. + recreate = true; +} + +bool QVGPixmapData::hasAlphaChannel() const +{ + if (!source.isNull()) + return source.hasAlphaChannel(); + else + return isValid(); +} + +void QVGPixmapData::setAlphaChannel(const QPixmap &alphaChannel) +{ + forceToImage(); + source.setAlphaChannel(alphaChannel.toImage()); +} + +QImage QVGPixmapData::toImage() const +{ + if (!isValid()) + return QImage(); + + if (source.isNull()) { + source = QImage(w, h, sourceFormat()); + recreate = true; + } + + return source; +} + +QImage *QVGPixmapData::buffer() +{ + forceToImage(); + return &source; +} + +QPaintEngine* QVGPixmapData::paintEngine() const +{ + // If the application wants to paint into the QPixmap, we first + // force it to QImage format and then paint into that. + // This is simpler than juggling multiple VG contexts. + const_cast<QVGPixmapData *>(this)->forceToImage(); + return source.paintEngine(); +} + +VGImage QVGPixmapData::toVGImage() +{ + if (!isValid()) + return VG_INVALID_HANDLE; + +#if !defined(QT_NO_EGL) + // Increase the reference count on the shared context. + if (!context) + context = qt_vg_create_context(0); +#endif + + if (recreate) { + if (vgImage != VG_INVALID_HANDLE) { + vgDestroyImage(vgImage); + vgImage = VG_INVALID_HANDLE; + } + if (vgImageOpacity != VG_INVALID_HANDLE) { + vgDestroyImage(vgImageOpacity); + vgImageOpacity = VG_INVALID_HANDLE; + } + } + + if (vgImage == VG_INVALID_HANDLE) { + vgImage = vgCreateImage + (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); + } + + if (!source.isNull() && recreate) { + vgImageSubData + (vgImage, + source.bits(), source.bytesPerLine(), + VG_sARGB_8888_PRE, 0, 0, w, h); + } + + recreate = false; + + return vgImage; +} + +VGImage QVGPixmapData::toVGImage(qreal opacity) +{ +#if !defined(QT_SHIVAVG) + if (!isValid()) + return VG_INVALID_HANDLE; + +#if !defined(QT_NO_EGL) + // Increase the reference count on the shared context. + if (!context) + context = qt_vg_create_context(0); +#endif + + if (recreate) { + if (vgImage != VG_INVALID_HANDLE) { + vgDestroyImage(vgImage); + vgImage = VG_INVALID_HANDLE; + } + if (vgImageOpacity != VG_INVALID_HANDLE) { + vgDestroyImage(vgImageOpacity); + vgImageOpacity = VG_INVALID_HANDLE; + } + } + + if (vgImage == VG_INVALID_HANDLE) { + vgImage = vgCreateImage + (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); + } + + if (!source.isNull() && recreate) { + vgImageSubData + (vgImage, + source.bits(), source.bytesPerLine(), + VG_sARGB_8888_PRE, 0, 0, w, h); + } + + recreate = false; + + if (opacity == 1.0f) + return vgImage; + + if (vgImageOpacity == VG_INVALID_HANDLE || cachedOpacity != opacity) { + if (vgImageOpacity == VG_INVALID_HANDLE) { + vgImageOpacity = vgCreateImage + (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER); + } + VGfloat matrix[20] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, opacity, + 0.0f, 0.0f, 0.0f, 0.0f + }; + vgColorMatrix(vgImageOpacity, vgImage, matrix); + cachedOpacity = opacity; + } + + return vgImageOpacity; +#else + // vgColorMatrix() doesn't work with ShivaVG, so ignore the opacity. + Q_UNUSED(opacity); + return toVGImage(); +#endif +} + +extern int qt_defaultDpiX(); +extern int qt_defaultDpiY(); + +int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const +{ + switch (metric) { + case QPaintDevice::PdmWidth: + return w; + case QPaintDevice::PdmHeight: + return h; + case QPaintDevice::PdmNumColors: + return 0; + case QPaintDevice::PdmDepth: + return d; + case QPaintDevice::PdmWidthMM: + return qRound(w * 25.4 / qt_defaultDpiX()); + case QPaintDevice::PdmHeightMM: + return qRound(h * 25.4 / qt_defaultDpiY()); + case QPaintDevice::PdmDpiX: + case QPaintDevice::PdmPhysicalDpiX: + return qt_defaultDpiX(); + case QPaintDevice::PdmDpiY: + case QPaintDevice::PdmPhysicalDpiY: + return qt_defaultDpiY(); + default: + qWarning("QVGPixmapData::metric(): Invalid metric"); + return 0; + } +} + +// Force the pixmap data to be in QImage format. +void QVGPixmapData::forceToImage() +{ + if (!isValid()) + return; + + if (source.isNull()) + source = QImage(w, h, sourceFormat()); + + recreate = true; +} + +QImage::Format QVGPixmapData::sourceFormat() const +{ + return QImage::Format_ARGB32_Premultiplied; +} + +QT_END_NAMESPACE diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h new file mode 100644 index 0000000..bb019be --- /dev/null +++ b/src/openvg/qpixmapdata_vg_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPIXMAPDATA_VG_P_H +#define QPIXMAPDATA_VG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qpixmap_raster_p.h> +#include "qvg_p.h" +#if !defined(QT_NO_EGL) +#include <QtGui/private/qegl_p.h> +#endif + +QT_BEGIN_NAMESPACE + +class QEglContext; + +class Q_OPENVG_EXPORT QVGPixmapData : public QPixmapData +{ +public: + QVGPixmapData(PixelType type); + ~QVGPixmapData(); + + // Is this pixmap valid (i.e. non-zero in size)? + bool isValid() const; + + void resize(int width, int height); + void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + + void fill(const QColor &color); + bool hasAlphaChannel() const; + void setAlphaChannel(const QPixmap &alphaChannel); + QImage toImage() const; + QImage *buffer(); + QPaintEngine* paintEngine() const; + + // Return the VGImage form of this pixmap, creating it if necessary. + // This assumes that there is a VG context current. + VGImage toVGImage(); + + // Return the VGImage form for a specific opacity setting. + VGImage toVGImage(qreal opacity); + + QSize size() const { return QSize(w, h); } + +protected: + int metric(QPaintDevice::PaintDeviceMetric metric) const; + +private: + VGImage vgImage; + VGImage vgImageOpacity; + qreal cachedOpacity; + mutable QImage source; + mutable bool recreate; +#if !defined(QT_NO_EGL) + mutable QEglContext *context; +#endif + + void forceToImage(); + QImage::Format sourceFormat() const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qpixmapfilter_vg.cpp b/src/openvg/qpixmapfilter_vg.cpp new file mode 100644 index 0000000..ff8604b --- /dev/null +++ b/src/openvg/qpixmapfilter_vg.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpixmapfilter_vg_p.h" +#include <QtCore/qvarlengtharray.h> +#include <QtGui/qpainter.h> + +QT_BEGIN_NAMESPACE + +#if !defined(QT_SHIVAVG) + +QVGPixmapConvolutionFilter::QVGPixmapConvolutionFilter() + : QPixmapConvolutionFilter() +{ +} + +QVGPixmapConvolutionFilter::~QVGPixmapConvolutionFilter() +{ +} + +extern void qt_vg_drawVGImage + (QPainter *painter, const QPointF& pos, VGImage vgImg); + +void QVGPixmapConvolutionFilter::draw + (QPainter *painter, const QPointF &dest, + const QPixmap &src, const QRectF &srcRect) const +{ + if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { + // The pixmap data is not an instance of QVGPixmapData, so fall + // back to the default convolution filter implementation. + QPixmapConvolutionFilter::draw(painter, dest, src, srcRect); + return; + } + + QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); + + VGImage srcImage = pd->toVGImage(); + if (srcImage == VG_INVALID_HANDLE) + return; + + QSize size = pd->size(); + VGImage dstImage = vgCreateImage + (VG_sARGB_8888_PRE, size.width(), size.height(), + VG_IMAGE_QUALITY_FASTER); + if (dstImage == VG_INVALID_HANDLE) + return; + + int kernelWidth = rows(); + int kernelHeight = columns(); + const qreal *kern = convolutionKernel(); + QVarLengthArray<VGshort> kernel; + for (int i = 0; i < kernelWidth; ++i) { + for (int j = 0; j < kernelHeight; ++j) { + kernel.append((VGshort)(kern[j * kernelWidth + i] * 1024.0f)); + } + } + + VGfloat values[4]; + values[0] = 0.0f; + values[1] = 0.0f; + values[2] = 0.0f; + values[3] = 0.0f; + vgSetfv(VG_TILE_FILL_COLOR, 4, values); + + vgConvolve(dstImage, srcImage, + kernelWidth, kernelHeight, 0, 0, + kernel.constData(), 1.0f / 1024.0f, 0.0f, + VG_TILE_FILL); + + VGImage child = VG_INVALID_HANDLE; + + if (srcRect.isNull() || + (srcRect.topLeft().isNull() && srcRect.size() == size)) { + child = dstImage; + } else { + QRect src = srcRect.toRect(); + child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); + } + + qt_vg_drawVGImage(painter, dest, child); + + if(child != dstImage) + vgDestroyImage(child); + vgDestroyImage(dstImage); +} + +QVGPixmapColorizeFilter::QVGPixmapColorizeFilter() + : QPixmapColorizeFilter(), + firstTime(true) +{ +} + +QVGPixmapColorizeFilter::~QVGPixmapColorizeFilter() +{ +} + +void QVGPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const +{ + if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { + // The pixmap data is not an instance of QVGPixmapData, so fall + // back to the default convolution filter implementation. + QPixmapColorizeFilter::draw(painter, dest, src, srcRect); + return; + } + + QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); + + VGImage srcImage = pd->toVGImage(); + if (srcImage == VG_INVALID_HANDLE) + return; + + QSize size = pd->size(); + VGImage dstImage = vgCreateImage + (VG_sARGB_8888_PRE, size.width(), size.height(), + VG_IMAGE_QUALITY_FASTER); + if (dstImage == VG_INVALID_HANDLE) + return; + + // Recompute the color matrix if the color has changed. + QColor c = color(); + if (c != prevColor || firstTime) { + prevColor = c; + + // Determine the weights for the matrix from the color. + VGfloat weights[3]; + VGfloat invweights[3]; + VGfloat alpha = c.alphaF(); + weights[0] = c.redF() * alpha; + weights[1] = c.greenF() * alpha; + weights[2] = c.blueF() * alpha; + invweights[0] = 1.0f - weights[0]; + invweights[1] = 1.0f - weights[1]; + invweights[2] = 1.0f - weights[2]; + + // Grayscale weights. + static const VGfloat redGray = 11.0f / 32.0f; + static const VGfloat greenGray = 16.0f / 32.0f; + static const VGfloat blueGray = 1.0f - (redGray + greenGray); + + matrix[0][0] = redGray * invweights[0]; + matrix[0][1] = redGray * invweights[1]; + matrix[0][2] = redGray * invweights[2]; + matrix[0][3] = 0.0f; + matrix[1][0] = greenGray * invweights[0]; + matrix[1][1] = greenGray * invweights[1]; + matrix[1][2] = greenGray * invweights[2]; + matrix[1][3] = 0.0f; + matrix[2][0] = blueGray * invweights[0]; + matrix[2][1] = blueGray * invweights[1]; + matrix[2][2] = blueGray * invweights[2]; + matrix[2][3] = 0.0f; + matrix[3][0] = 0.0f; + matrix[3][1] = 0.0f; + matrix[3][2] = 0.0f; + matrix[3][3] = 1.0f; + matrix[4][0] = weights[0]; + matrix[4][1] = weights[1]; + matrix[4][2] = weights[2]; + matrix[4][3] = 0.0f; + } + + firstTime = false; + + vgColorMatrix(dstImage, srcImage, matrix[0]); + + VGImage child = VG_INVALID_HANDLE; + + if (srcRect.isNull() || + (srcRect.topLeft().isNull() && srcRect.size() == size)) { + child = dstImage; + } else { + QRect src = srcRect.toRect(); + child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); + } + + qt_vg_drawVGImage(painter, dest, child); + + if(child != dstImage) + vgDestroyImage(child); + vgDestroyImage(dstImage); +} + +QVGPixmapDropShadowFilter::QVGPixmapDropShadowFilter() + : QPixmapDropShadowFilter(), + prevRadius(0.0f), + kernelSize(0), + firstTime(true) +{ +} + +QVGPixmapDropShadowFilter::~QVGPixmapDropShadowFilter() +{ +} + +void QVGPixmapDropShadowFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const +{ + if (src.pixmapData()->classId() != QPixmapData::OpenVGClass) { + // The pixmap data is not an instance of QVGPixmapData, so fall + // back to the default drop shadow filter implementation. + QPixmapDropShadowFilter::draw(painter, dest, src, srcRect); + return; + } + + QVGPixmapData *pd = static_cast<QVGPixmapData *>(src.pixmapData()); + + VGImage srcImage = pd->toVGImage(); + if (srcImage == VG_INVALID_HANDLE) + return; + + QSize size = pd->size(); + VGImage tmpImage = vgCreateImage + (VG_sARGB_8888_PRE, size.width(), size.height(), + VG_IMAGE_QUALITY_FASTER); + if (tmpImage == VG_INVALID_HANDLE) + return; + + VGImage dstImage = vgCreateImage + (VG_sARGB_8888_PRE, size.width(), size.height(), + VG_IMAGE_QUALITY_FASTER); + if (dstImage == VG_INVALID_HANDLE) { + vgDestroyImage(tmpImage); + return; + } + + // Recompute the color matrix if the color has changed. + QColor c = color(); + if (c != prevColor || firstTime) { + prevColor = c; + + matrix[0][0] = 0.0f; + matrix[0][1] = 0.0f; + matrix[0][2] = 0.0f; + matrix[0][3] = 0.0f; + matrix[1][0] = 0.0f; + matrix[1][1] = 0.0f; + matrix[1][2] = 0.0f; + matrix[1][3] = 0.0f; + matrix[2][0] = 0.0f; + matrix[2][1] = 0.0f; + matrix[2][2] = 0.0f; + matrix[2][3] = 0.0f; + matrix[3][0] = c.redF(); + matrix[3][1] = c.greenF(); + matrix[3][2] = c.blueF(); + matrix[3][3] = c.alphaF(); + matrix[4][0] = 0.0f; + matrix[4][1] = 0.0f; + matrix[4][2] = 0.0f; + matrix[4][3] = 0.0f; + } + + // Blacken the source image. + vgColorMatrix(tmpImage, srcImage, matrix[0]); + + // Recompute the convolution kernel if the blur radius has changed. + qreal radius = blurRadius(); + if (radius != prevRadius || firstTime) { + prevRadius = radius; + int dim = 2 * qRound(radius) + 1; + int size = dim * dim; + VGshort f = VGshort(1024.0f / size); + kernel.resize(size); + for (int i = 0; i < size; ++i) + kernel[i] = f; + kernelSize = dim; + } + + // Apply the convolution filter using the kernel. + VGfloat values[4]; + values[0] = 0.0f; + values[1] = 0.0f; + values[2] = 0.0f; + values[3] = 0.0f; + vgSetfv(VG_TILE_FILL_COLOR, 4, values); + vgConvolve(dstImage, tmpImage, + kernelSize, kernelSize, 0, 0, + kernel.constData(), 1.0f / 1024.0f, 0.0f, + VG_TILE_FILL); + + firstTime = false; + + VGImage child = VG_INVALID_HANDLE; + + if (srcRect.isNull() || + (srcRect.topLeft().isNull() && srcRect.size() == size)) { + child = dstImage; + } else { + QRect src = srcRect.toRect(); + child = vgChildImage(dstImage, src.x(), src.y(), src.width(), src.height()); + } + + qt_vg_drawVGImage(painter, dest + offset(), child); + + if(child != dstImage) + vgDestroyImage(child); + vgDestroyImage(tmpImage); + vgDestroyImage(dstImage); +} + +#endif + +QT_END_NAMESPACE diff --git a/src/openvg/qpixmapfilter_vg_p.h b/src/openvg/qpixmapfilter_vg_p.h new file mode 100644 index 0000000..412fb55 --- /dev/null +++ b/src/openvg/qpixmapfilter_vg_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPIXMAPFILTER_VG_P_H +#define QPIXMAPFILTER_VG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpixmapdata_vg_p.h" +#include <QtGui/private/qpixmapfilter_p.h> +#include <QtCore/qvarlengtharray.h> + +QT_BEGIN_NAMESPACE + +#if !defined(QT_SHIVAVG) + +class Q_OPENVG_EXPORT QVGPixmapConvolutionFilter : public QPixmapConvolutionFilter +{ +public: + QVGPixmapConvolutionFilter(); + ~QVGPixmapConvolutionFilter(); + + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const; +}; + +class Q_OPENVG_EXPORT QVGPixmapColorizeFilter : public QPixmapColorizeFilter +{ +public: + QVGPixmapColorizeFilter(); + ~QVGPixmapColorizeFilter(); + + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const; + +private: + mutable VGfloat matrix[5][4]; + mutable QColor prevColor; + mutable bool firstTime; +}; + +class Q_OPENVG_EXPORT QVGPixmapDropShadowFilter : public QPixmapDropShadowFilter +{ +public: + QVGPixmapDropShadowFilter(); + ~QVGPixmapDropShadowFilter(); + + void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src) const; + +private: + mutable VGfloat matrix[5][4]; + mutable QColor prevColor; + mutable qreal prevRadius; + mutable int kernelSize; + mutable bool firstTime; + mutable QVarLengthArray<VGshort, 16> kernel; +}; + +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qvg.h b/src/openvg/qvg.h new file mode 100644 index 0000000..8da6159 --- /dev/null +++ b/src/openvg/qvg.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVG_H +#define QVG_H + +#include <QtCore/qglobal.h> + +// Include the OpenVG headers for use in applications that +// issue raw OpenVG function calls. +#if defined(QT_LOWER_CASE_VG_INCLUDES) +#include <vg/openvg.h> +#else +#include <VG/openvg.h> +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenVG) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/openvg/qvg_p.h b/src/openvg/qvg_p.h new file mode 100644 index 0000000..7ac2430 --- /dev/null +++ b/src/openvg/qvg_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVG_P_H +#define QVG_P_H + +#include "qvg.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qimage.h> + +#if !defined(QT_NO_EGL) +#include <QtGui/private/qegl_p.h> +#endif + +QT_BEGIN_NAMESPACE + +class QVGPaintEngine; + +#if !defined(QT_NO_EGL) + +class QEglContext; + +// Create an EGL context, but don't bind it to a surface. If single-context +// mode is enabled, this will return the previously-created context. +Q_OPENVG_EXPORT QEglContext *qt_vg_create_context(QPaintDevice *device); + +// Destroy an EGL context that was created by qt_vg_create_context(). +// If single-context mode is enabled, this will decrease the reference count. +Q_OPENVG_EXPORT void qt_vg_destroy_context(QEglContext *context); + +// Return the shared pbuffer surface that can be made current to +// destroy VGImage objects when there is no other surface available. +Q_OPENVG_EXPORT EGLSurface qt_vg_shared_surface(void); + +// Make a context current with a specific surface. +Q_OPENVG_EXPORT void qt_vg_make_current(QEglContext *context, EGLSurface surface); + +// Make a context uncurrent. +Q_OPENVG_EXPORT void qt_vg_done_current(QEglContext *context, bool force = false); + +// Destroy a surface that was previously associated with a context. +Q_OPENVG_EXPORT void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface); + +// Convert the configuration format in a context to a VG or QImage format. +Q_OPENVG_EXPORT VGImageFormat qt_vg_config_to_vg_format(QEglContext *context); +Q_OPENVG_EXPORT QImage::Format qt_vg_config_to_image_format(QEglContext *context); + +#endif + +// Create a paint engine. Returns the common engine in single-context mode. +Q_OPENVG_EXPORT QVGPaintEngine *qt_vg_create_paint_engine(void); + +// Destroy a paint engine. Does nothing in single-context mode. +Q_OPENVG_EXPORT void qt_vg_destroy_paint_engine(QVGPaintEngine *engine); + +// Convert between QImage and VGImage format values. +Q_OPENVG_EXPORT VGImageFormat qt_vg_image_to_vg_format(QImage::Format format); + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qvgcompositionhelper_p.h b/src/openvg/qvgcompositionhelper_p.h new file mode 100644 index 0000000..cdf1be9 --- /dev/null +++ b/src/openvg/qvgcompositionhelper_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVGCOMPOSITIONHELPER_H +#define QVGCOMPOSITIONHELPER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qwindowsurface_vgegl_p.h" + +QT_BEGIN_NAMESPACE + +#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QT_NO_EGL) + +class QVGPaintEnginePrivate; +class QVGEGLWindowSurfacePrivate; + +class Q_OPENVG_EXPORT QVGCompositionHelper +{ +public: + QVGCompositionHelper(); + virtual ~QVGCompositionHelper(); + + void startCompositing(const QSize& screenSize); + void endCompositing(); + + void blitWindow(QVGEGLWindowSurfacePrivate *surface, const QRect& rect, + const QPoint& topLeft, int opacity); + void fillBackground(const QRegion& region, const QBrush& brush); + void drawCursorImage(const QImage& image, const QPoint& offset); + void drawCursorPixmap(const QPixmap& pixmap, const QPoint& offset); + void setScissor(const QRegion& region); + void clearScissor(); + +private: + QVGPaintEnginePrivate *d; + QSize screenSize; +}; + +#endif + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qwindowsurface_vg.cpp b/src/openvg/qwindowsurface_vg.cpp new file mode 100644 index 0000000..c77aa93 --- /dev/null +++ b/src/openvg/qwindowsurface_vg.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsurface_vg_p.h" +#include "qwindowsurface_vgegl_p.h" +#include "qpaintengine_vg_p.h" +#include "qpixmapdata_vg_p.h" +#include "qvg_p.h" + +#if !defined(QT_NO_EGL) + +#include <QtGui/private/qegl_p.h> + +QT_BEGIN_NAMESPACE + +QVGWindowSurface::QVGWindowSurface(QWidget *window) + : QWindowSurface(window) +{ + d_ptr = QVGEGLWindowSurfacePrivate::create + (QVGEGLWindowSurfacePrivate::WindowSurface, this); +} + +QVGWindowSurface::QVGWindowSurface + (QWidget *window, QVGEGLWindowSurfacePrivate *d) + : QWindowSurface(window), d_ptr(d) +{ +} + +QVGWindowSurface::~QVGWindowSurface() +{ + delete d_ptr; +} + +QPaintDevice *QVGWindowSurface::paintDevice() +{ + d_ptr->beginPaint(window()); + return this; +} + +void QVGWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset); + QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); + d_ptr->endPaint(parent, region); +} + +void QVGWindowSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); + d_ptr->ensureContext(window()); +} + +bool QVGWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QVGWindowSurface::beginPaint(const QRegion ®ion) +{ + // Nothing to do here. + Q_UNUSED(region); +} + +void QVGWindowSurface::endPaint(const QRegion ®ion) +{ + // Nothing to do here. + Q_UNUSED(region); +} + +QPaintEngine *QVGWindowSurface::paintEngine() const +{ + return d_ptr->paintEngine(); +} + +int QVGWindowSurface::metric(PaintDeviceMetric met) const +{ + return window()->metric(met); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qwindowsurface_vg_p.h b/src/openvg/qwindowsurface_vg_p.h new file mode 100644 index 0000000..e2ee583 --- /dev/null +++ b/src/openvg/qwindowsurface_vg_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_VG_P_H +#define QWINDOWSURFACE_VG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_EGL) + +class QVGEGLWindowSurfacePrivate; + +class Q_OPENVG_EXPORT QVGWindowSurface : public QWindowSurface, public QPaintDevice +{ +public: + QVGWindowSurface(QWidget *window); + QVGWindowSurface(QWidget *window, QVGEGLWindowSurfacePrivate *d); + ~QVGWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + QPaintEngine *paintEngine() const; + +protected: + int metric(PaintDeviceMetric metric) const; + +private: + QVGEGLWindowSurfacePrivate *d_ptr; +}; + +#endif + +QT_END_NAMESPACE + +#endif // QWINDOWSURFACE_VG_P_H diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp new file mode 100644 index 0000000..11c7021 --- /dev/null +++ b/src/openvg/qwindowsurface_vgegl.cpp @@ -0,0 +1,751 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsurface_vgegl_p.h" +#include "qpaintengine_vg_p.h" +#include "qpixmapdata_vg_p.h" +#include "qvg_p.h" + +#if !defined(QT_NO_EGL) + +QT_BEGIN_NAMESPACE + +// Turn off "direct to window" rendering if EGL cannot support it. +#if !defined(EGL_RENDER_BUFFER) || !defined(EGL_SINGLE_BUFFER) +#if defined(QVG_DIRECT_TO_WINDOW) +#undef QVG_DIRECT_TO_WINDOW +#endif +#endif + +// Determine if preserved window contents should be used. +#if !defined(EGL_SWAP_BEHAVIOR) || !defined(EGL_BUFFER_PRESERVED) +#if !defined(QVG_NO_PRESERVED_SWAP) +#define QVG_NO_PRESERVED_SWAP 1 +#endif +#endif + +VGImageFormat qt_vg_config_to_vg_format(QEglContext *context) +{ + return qt_vg_image_to_vg_format + (qt_vg_config_to_image_format(context)); +} + +QImage::Format qt_vg_config_to_image_format(QEglContext *context) +{ + EGLint red = 0; + EGLint green = 0; + EGLint blue = 0; + EGLint alpha = 0; + context->configAttrib(EGL_RED_SIZE, &red); + context->configAttrib(EGL_GREEN_SIZE, &green); + context->configAttrib(EGL_BLUE_SIZE, &blue); + context->configAttrib(EGL_ALPHA_SIZE, &alpha); + QImage::Format argbFormat; +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + EGLint type = 0; + context->configAttrib(EGL_SURFACE_TYPE, &type); + if ((type & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0) + argbFormat = QImage::Format_ARGB32_Premultiplied; + else + argbFormat = QImage::Format_ARGB32; +#else + argbFormat = QImage::Format_ARGB32; +#endif + if (red == 8 && green == 8 && blue == 8 && alpha == 8) + return argbFormat; + else if (red == 8 && green == 8 && blue == 8 && alpha == 0) + return QImage::Format_RGB32; + else if (red == 5 && green == 6 && blue == 5 && alpha == 0) + return QImage::Format_RGB16; + else if (red == 4 && green == 4 && blue == 4 && alpha == 4) + return QImage::Format_ARGB4444_Premultiplied; + else + return argbFormat; // XXX +} + +static void copySubImage(QImage *image, VGImage vgImage, const QRect& rect) +{ + vgGetImageSubData + (vgImage, + image->bits() + rect.bottom() * image->bytesPerLine() + + rect.x() * (image->depth() / 8), + -(image->bytesPerLine()), + qt_vg_image_to_vg_format(image->format()), + rect.x(), (image->height() - 1) - rect.bottom(), + rect.width(), rect.height()); +} + +#if !defined(QVG_NO_SINGLE_CONTEXT) + +class QVGSharedContext +{ +public: + QVGSharedContext(); + ~QVGSharedContext(); + + QEglContext *context; + int refCount; + QVGPaintEngine *engine; + EGLSurface surface; + EGLSurface lastSurface; +}; + +QVGSharedContext::QVGSharedContext() + : context(0) + , refCount(0) + , engine(0) + , surface(EGL_NO_SURFACE) + , lastSurface(EGL_NO_SURFACE) +{ +} + +QVGSharedContext::~QVGSharedContext() +{ + if (context) + qt_vg_make_current(context, qt_vg_shared_surface()); + delete engine; + if (context) + qt_vg_done_current(context, true); + if (surface != EGL_NO_SURFACE) + qt_vg_destroy_surface(context, surface); + delete context; +} + +Q_GLOBAL_STATIC(QVGSharedContext, sharedContext); + +QVGPaintEngine *qt_vg_create_paint_engine(void) +{ + QVGSharedContext *shared = sharedContext(); + if (!shared->engine) + shared->engine = new QVGPaintEngine(); + return shared->engine; +} + +void qt_vg_destroy_paint_engine(QVGPaintEngine *engine) +{ + Q_UNUSED(engine); +} + +#else + +QVGPaintEngine *qt_vg_create_paint_engine(void) +{ + return new QVGPaintEngine(); +} + +void qt_vg_destroy_paint_engine(QVGPaintEngine *engine) +{ + delete engine; +} + +#endif + +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + +static bool isPremultipliedContext(const QEglContext *context) +{ + EGLint value = 0; + if (context->configAttrib(EGL_SURFACE_TYPE, &value)) + return (value & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0; + else + return false; +} + +#endif + +static QEglContext *createContext(QPaintDevice *device) +{ + QEglContext *context; + + // Create the context object and open the display. + context = new QEglContext(); + context->setApi(QEgl::OpenVG); + if (!context->openDisplay(device)) { + delete context; + return 0; + } + + // Choose an appropriate configuration for rendering into the device. + QEglProperties configProps; + configProps.setPaintDeviceFormat(device); + int redSize = configProps.value(EGL_RED_SIZE); + if (redSize == EGL_DONT_CARE || redSize == 0) + configProps.setPixelFormat(QImage::Format_ARGB32); // XXX +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT | + EGL_VG_ALPHA_FORMAT_PRE_BIT); + configProps.setRenderableType(QEgl::OpenVG); + if (!context->chooseConfig(configProps)) { + // Try again without the "pre" bit. + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); + if (!context->chooseConfig(configProps)) { + delete context; + return 0; + } + } +#else + configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT); + configProps.setRenderableType(QEgl::OpenVG); + if (!context->chooseConfig(configProps)) { + delete context; + return 0; + } +#endif + + // Construct a new EGL context for the selected configuration. + if (!context->createContext()) { + delete context; + return 0; + } + + return context; +} + +#if !defined(QVG_NO_SINGLE_CONTEXT) + +QEglContext *qt_vg_create_context(QPaintDevice *device) +{ + QVGSharedContext *shared = sharedContext(); + if (shared->context) { + ++(shared->refCount); + return shared->context; + } else { + shared->context = createContext(device); + shared->refCount = 1; + return shared->context; + } +} + +void qt_vg_destroy_context(QEglContext *context) +{ + QVGSharedContext *shared = sharedContext(); + if (shared->context != context) { + // This is not the shared context. Shouldn't happen! + delete context; + } else if (--(shared->refCount) <= 0) { + qt_vg_make_current(shared->context, qt_vg_shared_surface()); + delete shared->engine; + shared->engine = 0; + qt_vg_done_current(shared->context, true); + if (shared->surface != EGL_NO_SURFACE) { + qt_vg_destroy_surface(shared->context, shared->surface); + shared->surface = EGL_NO_SURFACE; + } + delete shared->context; + shared->context = 0; + } +} + +EGLSurface qt_vg_shared_surface(void) +{ + QVGSharedContext *shared = sharedContext(); + if (shared->surface == EGL_NO_SURFACE) { + EGLint attribs[7]; + attribs[0] = EGL_WIDTH; + attribs[1] = 16; + attribs[2] = EGL_HEIGHT; + attribs[3] = 16; +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + if (isPremultipliedContext(shared->context)) { + attribs[4] = EGL_VG_ALPHA_FORMAT; + attribs[5] = EGL_VG_ALPHA_FORMAT_PRE; + attribs[6] = EGL_NONE; + } else +#endif + { + attribs[4] = EGL_NONE; + } + shared->surface = eglCreatePbufferSurface + (shared->context->display(), shared->context->config(), attribs); + } + return shared->surface; +} + +void qt_vg_make_current(QEglContext *context, EGLSurface surface) +{ + // Bail out if the context and surface are already current. + if (context->isCurrent() && context->surface() == surface) + return; + + // Are we setting the surface to the same as the last elided doneCurrent()? + QVGSharedContext *shared = sharedContext(); + if (context->isCurrent() && shared->lastSurface == surface) { + shared->lastSurface = EGL_NO_SURFACE; + context->setSurface(surface); + return; + } + + // Switch to the new context and surface. + shared->lastSurface = EGL_NO_SURFACE; + context->setSurface(surface); + context->makeCurrent(); +} + +void qt_vg_done_current(QEglContext *context, bool force) +{ + QVGSharedContext *shared = sharedContext(); + if (force) { + context->doneCurrent(); + shared->lastSurface = EGL_NO_SURFACE; + } else { + // Keep the context current for now just in case we immediately + // reuse the same surface for the next frame. + shared->lastSurface = context->surface(); + } +} + +void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface) +{ + QVGSharedContext *shared = sharedContext(); + if (shared->lastSurface == surface) { + shared->lastSurface = EGL_NO_SURFACE; + context->doneCurrent(); + } + context->setSurface(surface); + context->destroySurface(); +} + +#else + +QEglContext *qt_vg_create_context(QPaintDevice *device) +{ + return createContext(device); +} + +void qt_vg_destroy_context(QEglContext *context) +{ + delete context; +} + +EGLSurface qt_vg_shared_surface(void) +{ + return EGL_NO_SURFACE; +} + +void qt_vg_make_current(QEglContext *context, EGLSurface surface) +{ + context->setSurface(surface); + context->makeCurrent(); +} + +void qt_vg_done_current(QEglContext *context, bool force) +{ + Q_UNUSED(force); + context->doneCurrent(); +} + +void qt_vg_destroy_surface(QEglContext *context, EGLSurface surface) +{ + context->setSurface(surface); + context->destroySurface(); +} + +#endif + +QVGEGLWindowSurfacePrivate::QVGEGLWindowSurfacePrivate(QWindowSurface *win) +{ + winSurface = win; + engine = 0; +} + +QVGEGLWindowSurfacePrivate::~QVGEGLWindowSurfacePrivate() +{ + // Destroy the paint engine if it hasn't been destroyed already. + destroyPaintEngine(); +} + +QVGEGLWindowSurfacePrivate *QVGEGLWindowSurfacePrivate::create + (SurfaceType type, QWindowSurface *win) +{ +#if defined(QVG_VGIMAGE_BACKBUFFERS) + if (type == VGImageSurface) + return new QVGEGLWindowSurfaceVGImage(win); + else if (type == QImageSurface) + return new QVGEGLWindowSurfaceQImage(win); +#endif + if (type == WindowSurface) + return new QVGEGLWindowSurfaceDirect(win); + return 0; +} + +QVGPaintEngine *QVGEGLWindowSurfacePrivate::paintEngine() +{ + if (!engine) + engine = qt_vg_create_paint_engine(); + return engine; +} + +VGImage QVGEGLWindowSurfacePrivate::surfaceImage() const +{ + return VG_INVALID_HANDLE; +} + +void QVGEGLWindowSurfacePrivate::destroyPaintEngine() +{ + if (engine) { + qt_vg_destroy_paint_engine(engine); + engine = 0; + } +} + +QSize QVGEGLWindowSurfacePrivate::windowSurfaceSize(QWidget *widget) const +{ + Q_UNUSED(widget); + + QRect rect = winSurface->geometry(); + QSize newSize = rect.size(); + +#if defined(Q_WS_QWS) + // Account for the widget mask, if any. + if (widget && !widget->mask().isEmpty()) { + const QRegion region = widget->mask() + & rect.translated(-widget->geometry().topLeft()); + newSize = region.boundingRect().size(); + } +#endif + + return newSize; +} + +#if defined(QVG_VGIMAGE_BACKBUFFERS) + +QVGEGLWindowSurfaceVGImage::QVGEGLWindowSurfaceVGImage(QWindowSurface *win) + : QVGEGLWindowSurfacePrivate(win) + , context(0) + , backBuffer(VG_INVALID_HANDLE) + , backBufferSurface(EGL_NO_SURFACE) + , recreateBackBuffer(false) + , isPaintingActive(false) + , windowSurface(EGL_NO_SURFACE) +{ +} + +QVGEGLWindowSurfaceVGImage::~QVGEGLWindowSurfaceVGImage() +{ + destroyPaintEngine(); + if (context) { + if (backBufferSurface != EGL_NO_SURFACE) { + // We need a current context to be able to destroy the image. + // We use the shared surface because the native window handle + // associated with "windowSurface" may have been destroyed already. + qt_vg_make_current(context, qt_vg_shared_surface()); + qt_vg_destroy_surface(context, backBufferSurface); + vgDestroyImage(backBuffer); + qt_vg_done_current(context, true); + } + if (windowSurface != EGL_NO_SURFACE) + qt_vg_destroy_surface(context, windowSurface); + qt_vg_destroy_context(context); + } +} + +QEglContext *QVGEGLWindowSurfaceVGImage::ensureContext(QWidget *widget) +{ + QSize newSize = windowSurfaceSize(widget); + if (context && size != newSize) { + // The surface size has changed, so we need to recreate + // the back buffer. Keep the same context and paint engine. + size = newSize; + if (isPaintingActive) + qt_vg_done_current(context, true); + isPaintingActive = false; + recreateBackBuffer = true; + } + if (!context) { + // Create a new EGL context. We create the surface in beginPaint(). + size = newSize; + context = qt_vg_create_context(widget); + if (!context) + return 0; + isPaintingActive = false; + } + return context; +} + +void QVGEGLWindowSurfaceVGImage::beginPaint(QWidget *widget) +{ + QEglContext *context = ensureContext(widget); + if (context) { + if (recreateBackBuffer || backBufferSurface == EGL_NO_SURFACE) { + // Create a VGImage object to act as the back buffer + // for this window. We have to create the VGImage with a + // current context, so activate the main surface for the window. + qt_vg_make_current(context, mainSurface()); + recreateBackBuffer = false; + if (backBufferSurface != EGL_NO_SURFACE) { + eglDestroySurface(context->display(), backBufferSurface); + backBufferSurface = EGL_NO_SURFACE; + } + if (backBuffer != VG_INVALID_HANDLE) { + vgDestroyImage(backBuffer); + } + VGImageFormat format = qt_vg_config_to_vg_format(context); + backBuffer = vgCreateImage + (format, size.width(), size.height(), + VG_IMAGE_QUALITY_FASTER); + if (backBuffer != VG_INVALID_HANDLE) { + // Create an EGL surface for rendering into the VGImage. + backBufferSurface = eglCreatePbufferFromClientBuffer + (context->display(), EGL_OPENVG_IMAGE, + (EGLClientBuffer)(backBuffer), + context->config(), NULL); + if (backBufferSurface == EGL_NO_SURFACE) { + vgDestroyImage(backBuffer); + backBuffer = VG_INVALID_HANDLE; + } + } + } + if (backBufferSurface != EGL_NO_SURFACE) + qt_vg_make_current(context, backBufferSurface); + else + qt_vg_make_current(context, mainSurface()); + isPaintingActive = true; + } +} + +void QVGEGLWindowSurfaceVGImage::endPaint + (QWidget *widget, const QRegion& region, QImage *image) +{ + Q_UNUSED(region); + Q_UNUSED(image); + QEglContext *context = ensureContext(widget); + if (context) { + if (backBufferSurface != EGL_NO_SURFACE) { + if (isPaintingActive) + vgFlush(); + qt_vg_done_current(context); + } + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +VGImage QVGEGLWindowSurfaceVGImage::surfaceImage() const +{ + return backBuffer; +} + +EGLSurface QVGEGLWindowSurfaceVGImage::mainSurface() const +{ + if (windowSurface != EGL_NO_SURFACE) + return windowSurface; + else + return qt_vg_shared_surface(); +} + +QVGEGLWindowSurfaceQImage::QVGEGLWindowSurfaceQImage(QWindowSurface *win) + : QVGEGLWindowSurfaceVGImage(win) +{ +} + +QVGEGLWindowSurfaceQImage::~QVGEGLWindowSurfaceQImage() +{ +} + +void QVGEGLWindowSurfaceQImage::endPaint + (QWidget *widget, const QRegion& region, QImage *image) +{ + QEglContext *context = ensureContext(widget); + if (context) { + if (backBufferSurface != EGL_NO_SURFACE) { + if (isPaintingActive) + vgFlush(); + qt_vg_make_current(context, mainSurface()); + QRegion rgn = region.intersected + (QRect(0, 0, image->width(), image->height())); + if (rgn.numRects() == 1) { + copySubImage(image, backBuffer, rgn.boundingRect()); + } else { + QVector<QRect> rects = rgn.rects(); + for (int index = 0; index < rects.size(); ++index) + copySubImage(image, backBuffer, rects[index]); + } + qt_vg_done_current(context); + } + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +#endif // QVG_VGIMAGE_BACKBUFFERS + +QVGEGLWindowSurfaceDirect::QVGEGLWindowSurfaceDirect(QWindowSurface *win) + : QVGEGLWindowSurfacePrivate(win) + , context(0) + , isPaintingActive(false) + , needToSwap(false) + , windowSurface(EGL_NO_SURFACE) +{ +} + +QVGEGLWindowSurfaceDirect::~QVGEGLWindowSurfaceDirect() +{ +} + +QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget) +{ + QSize newSize = windowSurfaceSize(widget); + QEglProperties surfaceProps; + +#if defined(QVG_RECREATE_ON_SIZE_CHANGE) +#if !defined(QVG_NO_SINGLE_CONTEXT) + if (context && size != newSize) { + // The surface size has changed, so we need to recreate it. + // We can keep the same context and paint engine. + size = newSize; + if (isPaintingActive) + qt_vg_done_current(context, true); + context->setSurface(windowSurface); + context->destroySurface(); +#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT) + if (isPremultipliedContext(context)) { + surfaceProps.setValue + (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); + } else { + surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT); + } +#endif + context->createSurface(widget, &surfaceProps); + windowSurface = context->surface(); + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +#else + if (context && size != newSize) { + // The surface size has changed, so we need to recreate + // the EGL context for the widget. We also need to recreate + // the surface's paint engine if context sharing is not + // enabled because we cannot reuse the existing paint objects + // in the new context. + qt_vg_destroy_paint_engine(engine); + engine = 0; + context->setSurface(windowSurface); + context->destroySurface(); + qt_vg_destroy_context(context); + context = 0; + windowSurface = EGL_NO_SURFACE; + } +#endif +#endif + if (!context) { + // Create a new EGL context and bind it to the widget surface. + size = newSize; + context = qt_vg_create_context(widget); + if (!context) + return 0; + // We want a direct to window rendering surface if possible. +#if defined(QVG_DIRECT_TO_WINDOW) + surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); +#endif +#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT) + if (isPremultipliedContext(context)) { + surfaceProps.setValue + (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); + } else { + surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT); + } +#endif + if (!context->createSurface(widget, &surfaceProps)) { + qt_vg_destroy_context(context); + context = 0; + return 0; + } + needToSwap = true; +#if defined(QVG_DIRECT_TO_WINDOW) + // Did we get a direct to window rendering surface? + EGLint buffer = 0; + if (eglQueryContext(context->display(), context->context(), + EGL_RENDER_BUFFER, &buffer) && + buffer == EGL_SINGLE_BUFFER) { + needToSwap = false; + } +#endif +#if !defined(QVG_NO_PRESERVED_SWAP) + // Try to force the surface back buffer to preserve its contents. + if (needToSwap) { + eglGetError(); // Clear error state first. + eglSurfaceAttrib(context->display(), context->surface(), + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + if (eglGetError() != EGL_SUCCESS) { + qWarning("QVG: could not enable preserved swap"); + } + } +#endif + windowSurface = context->surface(); + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } + return context; +} + +void QVGEGLWindowSurfaceDirect::beginPaint(QWidget *widget) +{ + QEglContext *context = ensureContext(widget); + if (context) { + qt_vg_make_current(context, windowSurface); + isPaintingActive = true; + } +} + +void QVGEGLWindowSurfaceDirect::endPaint + (QWidget *widget, const QRegion& region, QImage *image) +{ + Q_UNUSED(region); + Q_UNUSED(image); + QEglContext *context = ensureContext(widget); + if (context) { + if (needToSwap) { + if (!isPaintingActive) + qt_vg_make_current(context, windowSurface); + context->swapBuffers(); + qt_vg_done_current(context); + } else if (isPaintingActive) { + vgFlush(); + qt_vg_done_current(context); + } + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +QT_END_NAMESPACE + +#endif diff --git a/src/openvg/qwindowsurface_vgegl_p.h b/src/openvg/qwindowsurface_vgegl_p.h new file mode 100644 index 0000000..aa23772 --- /dev/null +++ b/src/openvg/qwindowsurface_vgegl_p.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_VGEGL_P_H +#define QWINDOWSURFACE_VGEGL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qwindowsurface_p.h> +#include "qvg_p.h" + +#if !defined(QT_NO_EGL) + +#include <QtGui/private/qegl_p.h> + +QT_BEGIN_NAMESPACE + +class QWindowSurface; + +class Q_OPENVG_EXPORT QVGEGLWindowSurfacePrivate +{ +public: + QVGEGLWindowSurfacePrivate(QWindowSurface *win); + virtual ~QVGEGLWindowSurfacePrivate(); + + enum SurfaceType + { + WindowSurface, + VGImageSurface, + QImageSurface + }; + + static QVGEGLWindowSurfacePrivate *create + (SurfaceType type, QWindowSurface *win); + + QVGPaintEngine *paintEngine(); + virtual QEglContext *ensureContext(QWidget *widget) = 0; + virtual void beginPaint(QWidget *widget) = 0; + virtual void endPaint + (QWidget *widget, const QRegion& region, QImage *image = 0) = 0; + virtual VGImage surfaceImage() const; + virtual QSize surfaceSize() const = 0; + +private: + QVGPaintEngine *engine; + +protected: + QWindowSurface *winSurface; + + void destroyPaintEngine(); + QSize windowSurfaceSize(QWidget *widget) const; +}; + +#if defined(EGL_OPENVG_IMAGE) && !defined(QVG_NO_SINGLE_CONTEXT) + +#define QVG_VGIMAGE_BACKBUFFERS 1 + +class Q_OPENVG_EXPORT QVGEGLWindowSurfaceVGImage : public QVGEGLWindowSurfacePrivate +{ +public: + QVGEGLWindowSurfaceVGImage(QWindowSurface *win); + virtual ~QVGEGLWindowSurfaceVGImage(); + + QEglContext *ensureContext(QWidget *widget); + void beginPaint(QWidget *widget); + void endPaint(QWidget *widget, const QRegion& region, QImage *image); + VGImage surfaceImage() const; + QSize surfaceSize() const { return size; } + +protected: + QEglContext *context; + VGImage backBuffer; + EGLSurface backBufferSurface; + bool recreateBackBuffer; + bool isPaintingActive; + QSize size; + EGLSurface windowSurface; + + EGLSurface mainSurface() const; +}; + +class Q_OPENVG_EXPORT QVGEGLWindowSurfaceQImage : public QVGEGLWindowSurfaceVGImage +{ +public: + QVGEGLWindowSurfaceQImage(QWindowSurface *win); + virtual ~QVGEGLWindowSurfaceQImage(); + + void endPaint(QWidget *widget, const QRegion& region, QImage *image); +}; + +#endif // EGL_OPENVG_IMAGE + +class Q_OPENVG_EXPORT QVGEGLWindowSurfaceDirect : public QVGEGLWindowSurfacePrivate +{ +public: + QVGEGLWindowSurfaceDirect(QWindowSurface *win); + virtual ~QVGEGLWindowSurfaceDirect(); + + QEglContext *ensureContext(QWidget *widget); + void beginPaint(QWidget *widget); + void endPaint(QWidget *widget, const QRegion& region, QImage *image); + QSize surfaceSize() const { return size; } + +protected: + QEglContext *context; + QSize size; + bool isPaintingActive; + bool needToSwap; + EGLSurface windowSurface; +}; + +QT_END_NAMESPACE + +#endif // !QT_NO_EGL + +#endif // QWINDOWSURFACE_VGEGL_P_H diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 2e18b48..1b499b6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -686,8 +686,11 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) if (!d->unsupportedCompositionMode && d->dfbCanHandleClip(rect) && !d->matrixRotShear) { switch (brush.style()) { case Qt::SolidPattern: { + const QColor color = brush.color(); + if (!color.isValid()) + return; d->unlock(); - d->setDFBColor(brush.color()); + d->setDFBColor(color); const QRect r = d->transform.mapRect(rect).toRect(); d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()); @@ -711,6 +714,8 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) { + if (!color.isValid()) + return; Q_D(QDirectFBPaintEngine); d->updateClip(); if (d->unsupportedCompositionMode || !d->dfbCanHandleClip() || d->matrixRotShear) { @@ -892,7 +897,6 @@ void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) setCompositionMode(q->state()->compositionMode()); dirtyClip = true; setPen(q->state()->pen); - setDFBColor(pen.color()); } void QDirectFBPaintEnginePrivate::end() diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 62fef5b..76064ad 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -725,7 +725,7 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','), QString::SkipEmptyParts); flipFlags = DSFLIP_NONE; - foreach (QString flip, flips) { + foreach(const QString &flip, flips) { if (flip == QLatin1String("wait")) flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_WAIT); else if (flip == QLatin1String("blit")) diff --git a/src/plugins/graphicssystems/graphicssystems.pro b/src/plugins/graphicssystems/graphicssystems.pro index b8216ff..bfdec6a 100644 --- a/src/plugins/graphicssystems/graphicssystems.pro +++ b/src/plugins/graphicssystems/graphicssystems.pro @@ -1,2 +1,8 @@ TEMPLATE = subdirs contains(QT_CONFIG, opengl):SUBDIRS += opengl +contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg + +contains(QT_CONFIG, shivavg) { + # Only works under X11 at present + !win32:!embedded:!mac:SUBDIRS += shivavg +} diff --git a/src/plugins/graphicssystems/openvg/main.cpp b/src/plugins/graphicssystems/openvg/main.cpp new file mode 100644 index 0000000..265ccd3 --- /dev/null +++ b/src/plugins/graphicssystems/openvg/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_vg_p.h" + +QT_BEGIN_NAMESPACE + +class QVGGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QVGGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "OpenVG"; + return list; +} + +QGraphicsSystem* QVGGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "openvg") + return new QVGGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(openvg, QVGGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/openvg/openvg.pro b/src/plugins/graphicssystems/openvg/openvg.pro new file mode 100644 index 0000000..0abbfbd --- /dev/null +++ b/src/plugins/graphicssystems/openvg/openvg.pro @@ -0,0 +1,20 @@ +TARGET = qvggraphicssystem +include(../../qpluginbase.pri) + +QT += openvg + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_vg.cpp +HEADERS = qgraphicssystem_vg_p.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target + +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG + +!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL +!isEmpty(QMAKE_LIBDIR_EGL): LIBS += -L$$QMAKE_LIBDIR_EGL +!isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp new file mode 100644 index 0000000..d975ad7 --- /dev/null +++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicssystem_vg_p.h" +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#include <QtOpenVG/private/qwindowsurface_vg_p.h> + +QT_BEGIN_NAMESPACE + +QVGGraphicsSystem::QVGGraphicsSystem() +{ +} + +QPixmapData *QVGGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ +#if !defined(QVG_NO_SINGLE_CONTEXT) && !defined(QVG_NO_PIXMAP_DATA) + // Pixmaps can use QVGPixmapData; bitmaps must use raster. + if (type == QPixmapData::PixmapType) + return new QVGPixmapData(type); + else + return new QRasterPixmapData(type); +#else + return new QRasterPixmapData(type); +#endif +} + +QWindowSurface *QVGGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + return new QVGWindowSurface(widget); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h new file mode 100644 index 0000000..368f48d --- /dev/null +++ b/src/plugins/graphicssystems/openvg/qgraphicssystem_vg_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_VG_P_H +#define QGRAPHICSSYSTEM_VG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class QVGGraphicsSystem : public QGraphicsSystem +{ +public: + QVGGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/shivavg/README b/src/plugins/graphicssystems/shivavg/README new file mode 100644 index 0000000..15ee710 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/README @@ -0,0 +1,8 @@ + +This graphics system uses ShivaVG (http://sourceforge.net/projects/shivavg) +to perform OpenVG rendering on X11 systems. The graphics system name for +the "-graphicssystem" command-line option is "ShivaVG". + +ShivaVG support is experimental, mostly to demonstrate how to integrate +non-EGL OpenVG engines into the system. It will probably not produce +good output. diff --git a/src/plugins/graphicssystems/shivavg/main.cpp b/src/plugins/graphicssystems/shivavg/main.cpp new file mode 100644 index 0000000..037bfb2 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qgraphicssystemplugin_p.h> +#include "shivavggraphicssystem.h" + +QT_BEGIN_NAMESPACE + +class ShivaVGGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList ShivaVGGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "ShivaVG"; + return list; +} + +QGraphicsSystem* ShivaVGGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "shivavg") + return new ShivaVGGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(shivavg, ShivaVGGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/shivavg/shivavg.pro b/src/plugins/graphicssystems/shivavg/shivavg.pro new file mode 100644 index 0000000..68345af --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/shivavg.pro @@ -0,0 +1,16 @@ +TARGET = qshivavggraphicssystem +include(../../qpluginbase.pri) + +QT += openvg + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp shivavggraphicssystem.cpp shivavgwindowsurface.cpp +HEADERS = shivavggraphicssystem.h shivavgwindowsurface.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target + +!isEmpty(QMAKE_INCDIR_OPENVG): INCLUDEPATH += $$QMAKE_INCDIR_OPENVG +!isEmpty(QMAKE_LIBDIR_OPENVG): LIBS += -L$$QMAKE_LIBDIR_OPENVG +!isEmpty(QMAKE_LIBS_OPENVG): LIBS += $$QMAKE_LIBS_OPENVG diff --git a/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp new file mode 100644 index 0000000..fb60a42 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "shivavggraphicssystem.h" +#include "shivavgwindowsurface.h" +#include <QtGui/private/qpixmap_raster_p.h> + +QT_BEGIN_NAMESPACE + +ShivaVGGraphicsSystem::ShivaVGGraphicsSystem() +{ +} + +QPixmapData *ShivaVGGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *ShivaVGGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + return new ShivaVGWindowSurface(widget); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h new file mode 100644 index 0000000..1c9ec70 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/shivavggraphicssystem.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIVAVGGRAPHICSSYSTEM_H +#define SHIVAVGGRAPHICSSYSTEM_H + +#include <QtGui/private/qgraphicssystem_p.h> + +QT_BEGIN_NAMESPACE + +class ShivaVGGraphicsSystem : public QGraphicsSystem +{ +public: + ShivaVGGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp new file mode 100644 index 0000000..bf1f942 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.cpp @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define GL_GLEXT_PROTOTYPES +#include "shivavgwindowsurface.h" +#include <QtOpenVG/private/qpaintengine_vg_p.h> +#if defined(Q_WS_X11) +#include "private/qt_x11_p.h" +#include "qx11info_x11.h" +#include <GL/glx.h> + +extern QX11Info *qt_x11Info(const QPaintDevice *pd); +#endif + +// Define this to use framebuffer objects. +//#define QVG_USE_FBO 1 + +#include <vg/openvg.h> + +QT_BEGIN_NAMESPACE + +class QShivaContext +{ +public: + QShivaContext(); + ~QShivaContext(); + + bool makeCurrent(ShivaVGWindowSurfacePrivate *surface); + void doneCurrent(); + + bool initialized; + QSize currentSize; + ShivaVGWindowSurfacePrivate *currentSurface; +}; + +Q_GLOBAL_STATIC(QShivaContext, shivaContext); + +class ShivaVGWindowSurfacePrivate +{ +public: + ShivaVGWindowSurfacePrivate() + : isCurrent(false) + , needsResize(true) + , engine(0) +#if defined(QVG_USE_FBO) + , fbo(0) + , texture(0) +#endif +#if defined(Q_WS_X11) + , drawable(0) + , context(0) +#endif + { + } + ~ShivaVGWindowSurfacePrivate(); + + void ensureContext(QWidget *widget); + + QSize size; + bool isCurrent; + bool needsResize; + QVGPaintEngine *engine; +#if defined(QVG_USE_FBO) + GLuint fbo; + GLuint texture; +#endif +#if defined(Q_WS_X11) + GLXDrawable drawable; + GLXContext context; +#endif +}; + +QShivaContext::QShivaContext() + : initialized(false) + , currentSurface(0) +{ +} + +QShivaContext::~QShivaContext() +{ + if (initialized) + vgDestroyContextSH(); +} + +bool QShivaContext::makeCurrent(ShivaVGWindowSurfacePrivate *surface) +{ + if (currentSurface) + currentSurface->isCurrent = false; + surface->isCurrent = true; + currentSurface = surface; + currentSize = surface->size; +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, surface->drawable, surface->context); +#endif + if (!initialized) { + if (!vgCreateContextSH(currentSize.width(), currentSize.height())) { + qWarning("vgCreateContextSH(%d, %d): could not create context", currentSize.width(), currentSize.height()); + return false; + } + initialized = true; + } else { + vgResizeSurfaceSH(currentSize.width(), currentSize.height()); + } +#if defined(QVG_USE_FBO) + if (surface->fbo) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface->fbo); + else + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#endif + return true; +} + +void QShivaContext::doneCurrent() +{ + if (currentSurface) { + currentSurface->isCurrent = false; + currentSurface = 0; + } +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, 0, 0); +#endif +} + +ShivaVGWindowSurfacePrivate::~ShivaVGWindowSurfacePrivate() +{ +#if defined(QVG_USE_FBO) + if (fbo) { + glDeleteTextures(1, &texture); + glDeleteFramebuffersEXT(1, &fbo); + } +#endif +} + +void ShivaVGWindowSurfacePrivate::ensureContext(QWidget *widget) +{ +#if defined(Q_WS_X11) + Window win = widget->winId(); + if (win != drawable) { + if (context) + glXDestroyContext(X11->display, context); + drawable = win; + } + if (context == 0) { + const QX11Info *xinfo = qt_x11Info(widget); + int spec[64]; + int i = 0; + spec[i++] = GLX_DOUBLEBUFFER; + spec[i++] = GLX_DEPTH_SIZE; + spec[i++] = 1; + spec[i++] = GLX_STENCIL_SIZE; + spec[i++] = 1; + spec[i++] = GLX_RGBA; + spec[i++] = GLX_RED_SIZE; + spec[i++] = 1; + spec[i++] = GLX_GREEN_SIZE; + spec[i++] = 1; + spec[i++] = GLX_BLUE_SIZE; + spec[i++] = 1; + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = 4; + spec[i] = XNone; + XVisualInfo *visual = glXChooseVisual + (xinfo->display(), xinfo->screen(), spec); + context = glXCreateContext(X11->display, visual, 0, True); + if (!context) + qWarning("glXCreateContext: could not create GL context for VG rendering"); + } +#else + Q_UNUSED(widget); +#endif +#if defined(QVG_USE_FBO) + if (needsResize && fbo) { +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, drawable, context); +#endif + glDeleteTextures(1, &texture); + glDeleteFramebuffersEXT(1, &fbo); +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, 0, 0); +#endif + fbo = 0; + texture = 0; + } + if (!fbo) { +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, drawable, context); +#endif + glGenFramebuffersEXT(1, &fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size.width(), size.height(), 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glFramebufferTexture2DEXT + (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, + texture, 0); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +#if defined(Q_WS_X11) + glXMakeCurrent(X11->display, 0, 0); +#endif + } +#endif + needsResize = false; +} + +ShivaVGWindowSurface::ShivaVGWindowSurface(QWidget *window) + : QWindowSurface(window), d_ptr(new ShivaVGWindowSurfacePrivate) +{ +} + +ShivaVGWindowSurface::~ShivaVGWindowSurface() +{ + if (d_ptr->isCurrent) { + shivaContext()->doneCurrent(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } +#if defined(Q_WS_X11) + if (d_ptr->context) + glXDestroyContext(X11->display, d_ptr->context); +#endif + delete d_ptr; +} + +QPaintDevice *ShivaVGWindowSurface::paintDevice() +{ + d_ptr->ensureContext(window()); + shivaContext()->makeCurrent(d_ptr); + glClearDepth(0.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + return this; +} + +void ShivaVGWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(region); + Q_UNUSED(offset); + QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); + d_ptr->ensureContext(parent); + QShivaContext *context = shivaContext(); + if (!d_ptr->isCurrent) + context->makeCurrent(d_ptr); +#if defined(QVG_USE_FBO) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + if (d_ptr->fbo) { + static GLfloat const vertices[][2] = { + {-1, -1}, {1, -1}, {1, 1}, {-1, 1} + }; + static GLfloat const texCoords[][2] = { + {0, 0}, {1, 0}, {1, 1}, {0, 1} + }; + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glVertexPointer(2, GL_FLOAT, 0, vertices); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glBindTexture(GL_TEXTURE_2D, d_ptr->texture); + glEnable(GL_TEXTURE_2D); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + } +#endif +#if defined(Q_WS_X11) + glXSwapBuffers(X11->display, d_ptr->drawable); +#endif + context->doneCurrent(); +} + +void ShivaVGWindowSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); + d_ptr->needsResize = true; + d_ptr->size = rect.size(); +} + +bool ShivaVGWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void ShivaVGWindowSurface::beginPaint(const QRegion ®ion) +{ + // Nothing to do here. + Q_UNUSED(region); +} + +void ShivaVGWindowSurface::endPaint(const QRegion ®ion) +{ + // Nothing to do here. + Q_UNUSED(region); +} + +Q_GLOBAL_STATIC(QVGPaintEngine, sharedPaintEngine); + +QPaintEngine *ShivaVGWindowSurface::paintEngine() const +{ + if (!d_ptr->engine) + d_ptr->engine = sharedPaintEngine(); + return d_ptr->engine; +} + +// We need to get access to QWidget::metric() from ShivaVGWindowSurface::metric, +// but it is not a friend of QWidget. To get around this, we create a +// fake QX11PaintEngine class, which is a friend. +class QX11PaintEngine +{ +public: + static int metric(const QWidget *widget, QPaintDevice::PaintDeviceMetric met) + { + return widget->metric(met); + } +}; + +int ShivaVGWindowSurface::metric(PaintDeviceMetric met) const +{ + return QX11PaintEngine::metric(window(), met); +} + +QT_END_NAMESPACE diff --git a/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h new file mode 100644 index 0000000..5211ba4 --- /dev/null +++ b/src/plugins/graphicssystems/shivavg/shivavgwindowsurface.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIVAVGWINDOWSURFACE_H +#define SHIVAVGWINDOWSURFACE_H + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class ShivaVGWindowSurfacePrivate; + +class ShivaVGWindowSurface : public QWindowSurface, public QPaintDevice +{ +public: + ShivaVGWindowSurface(QWidget *window); + virtual ~ShivaVGWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + QPaintEngine *paintEngine() const; + +protected: + int metric(PaintDeviceMetric metric) const; + +private: + ShivaVGWindowSurfacePrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/qt_install.pri b/src/qt_install.pri index 6dd2074..ebeac8d 100644 --- a/src/qt_install.pri +++ b/src/qt_install.pri @@ -15,11 +15,19 @@ qt_install_headers { $$QT_SOURCE_TREE/src/corelib/arch/$$QT_ARCH/arch } - flat_headers.files = $$INSTALL_HEADERS - flat_headers.path = $$[QT_INSTALL_HEADERS]/Qt - INSTALLS += flat_headers + equals(TARGET, phonon) { + class_headers.path = $$[QT_INSTALL_HEADERS]/$$TARGET/Phonon + } else { + flat_headers.files = $$INSTALL_HEADERS + flat_headers.path = $$[QT_INSTALL_HEADERS]/Qt + INSTALLS += flat_headers - targ_headers.files = $$INSTALL_HEADERS $$SYNCQT.HEADER_CLASSES + class_headers.path = $$[QT_INSTALL_HEADERS]/$$TARGET + } + class_headers.files = $$SYNCQT.HEADER_CLASSES + INSTALLS += class_headers + + targ_headers.files = $$INSTALL_HEADERS targ_headers.path = $$[QT_INSTALL_HEADERS]/$$TARGET INSTALLS += targ_headers } diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index b70868d..7bda969 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -91,7 +91,6 @@ public: : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false), isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false) { - sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray; unicode = false; } @@ -100,9 +99,6 @@ public: uint unicode :1; uint useSchema :1; - QVariant::Type sql_char_type; - QVariant::Type sql_varchar_type; - QVariant::Type sql_longvarchar_type; int disconnectCount; bool isMySqlServer; bool isMSSqlServer; @@ -129,7 +125,6 @@ public: QODBCPrivate() : hEnv(0), hDbc(0), hStmt(0), useSchema(false), hasSQLFetchScroll(true) { - sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray; unicode = false; } @@ -142,9 +137,6 @@ public: uint unicode :1; uint useSchema :1; - QVariant::Type sql_char_type; - QVariant::Type sql_varchar_type; - QVariant::Type sql_longvarchar_type; QSqlRecord rInf; QVector<QVariant> fieldCache; @@ -294,14 +286,10 @@ static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, const T* p, bool isSi break; #endif case SQL_CHAR: - type = p->sql_char_type; - break; case SQL_VARCHAR: case SQL_GUID: - type = p->sql_varchar_type; - break; case SQL_LONGVARCHAR: - type = p->sql_longvarchar_type; + type = QVariant::String; break; default: type = QVariant::ByteArray; @@ -818,9 +806,6 @@ QODBCResult::QODBCResult(const QODBCDriver * db, QODBCDriverPrivate* p) d->hDbc = p->hDbc; d->unicode = p->unicode; d->useSchema = p->useSchema; - d->sql_char_type = p->sql_char_type; - d->sql_varchar_type = p->sql_varchar_type; - d->sql_longvarchar_type = p->sql_longvarchar_type; d->disconnectCount = p->disconnectCount; d->hasSQLFetchScroll = p->hasSQLFetchScroll; } @@ -1875,7 +1860,6 @@ void QODBCDriverPrivate::checkUnicode() sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) { - sql_char_type = QVariant::String; unicode = true; } @@ -1885,7 +1869,6 @@ void QODBCDriverPrivate::checkUnicode() sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) { - sql_varchar_type = QVariant::String; unicode = true; } @@ -1895,7 +1878,6 @@ void QODBCDriverPrivate::checkUnicode() sizeof(fFunc), NULL); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) { - sql_longvarchar_type = QVariant::String; unicode = true; } } diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 1ab8214..d197388 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -531,7 +531,7 @@ bool QPSQLResult::prepare(const QString &query) { if (!d->preparedQueriesEnabled) return QSqlResult::prepare(query); - + cleanup(); if (!d->preparedStmtId.isEmpty()) @@ -821,7 +821,20 @@ bool QPSQLDriver::commitTransaction() return false; } PGresult* res = PQexec(d->connection, "COMMIT"); - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { + + bool transaction_failed = false; + + // XXX + // This hack is used to tell if the transaction has succeeded for the protocol versions of + // PostgreSQL below. For 7.x and other protocol versions we are left in the dark. + // This hack can dissapear once there is an API to query this sort of information. + if (d->pro == QPSQLDriver::Version8 || + d->pro == QPSQLDriver::Version81 || + d->pro == QPSQLDriver::Version82) { + transaction_failed = QByteArray(PQcmdStatus(res)) == QByteArray("ROLLBACK")?true:false; + } + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK || transaction_failed) { PQclear(res); setLastError(qMakeError(tr("Could not commit transaction"), QSqlError::TransactionError, d)); @@ -1189,12 +1202,12 @@ bool QPSQLDriver::subscribeToNotificationImplementation(const QString &name) qPrintable(name)); return false; } - + int socket = PQsocket(d->connection); if (socket) { QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName); - if (PQresultStatus(PQexec(d->connection, - d->isUtf8 ? query.toUtf8().constData() + if (PQresultStatus(PQexec(d->connection, + d->isUtf8 ? query.toUtf8().constData() : query.toLocal8Bit().constData()) ) != PGRES_COMMAND_OK) { setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d)); @@ -1225,8 +1238,8 @@ bool QPSQLDriver::unsubscribeFromNotificationImplementation(const QString &name) } QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName); - if (PQresultStatus(PQexec(d->connection, - d->isUtf8 ? query.toUtf8().constData() + if (PQresultStatus(PQexec(d->connection, + d->isUtf8 ? query.toUtf8().constData() : query.toLocal8Bit().constData()) ) != PGRES_COMMAND_OK) { setLastError(qMakeError(tr("Unable to unsubscribe"), QSqlError::StatementError, d)); @@ -1259,7 +1272,7 @@ void QPSQLDriver::_q_handleNotification(int) if (d->seid.contains(name)) emit notification(name); else - qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.", + qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.", qPrintable(name)); qPQfreemem(notify); diff --git a/src/src.pro b/src/src.pro index e35c3f5..47486bb 100644 --- a/src/src.pro +++ b/src/src.pro @@ -19,6 +19,7 @@ win32:{ } contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl +contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg contains(QT_CONFIG, xmlpatterns): SRC_SUBDIRS += src_xmlpatterns contains(QT_CONFIG, phonon): SRC_SUBDIRS += src_phonon contains(QT_CONFIG, svg): SRC_SUBDIRS += src_svg @@ -62,6 +63,8 @@ src_scripttools.subdir = $$QT_SOURCE_TREE/src/scripttools src_scripttools.target = sub-scripttools src_opengl.subdir = $$QT_SOURCE_TREE/src/opengl src_opengl.target = sub-opengl +src_openvg.subdir = $$QT_SOURCE_TREE/src/openvg +src_openvg.target = sub-openvg src_qt3support.subdir = $$QT_SOURCE_TREE/src/qt3support src_qt3support.target = sub-qt3support src_phonon.subdir = $$QT_SOURCE_TREE/src/phonon @@ -99,6 +102,7 @@ src_declarative.target = sub-declarative src_scripttools.depends = src_script src_gui src_network src_network.depends = src_corelib src_opengl.depends = src_gui + src_openvg.depends = src_gui src_sql.depends = src_corelib src_testlib.depends = src_corelib src_qt3support.depends = src_gui src_xml src_network src_sql diff --git a/tests/arthur/common/qengines.cpp b/tests/arthur/common/qengines.cpp index e94e9cc..ce1afe4 100644 --- a/tests/arthur/common/qengines.cpp +++ b/tests/arthur/common/qengines.cpp @@ -49,6 +49,7 @@ #include <QDir> #include <QDebug> #include <QPrintEngine> +#include <QWidget> // For QApplicationPrivate::graphics_system_name #include <private/qapplication_p.h> diff --git a/tests/arthur/data/qps/clipping_state.qps b/tests/arthur/data/qps/clipping_state.qps index fd9a80a..3a66122 100644 --- a/tests/arthur/data/qps/clipping_state.qps +++ b/tests/arthur/data/qps/clipping_state.qps @@ -55,3 +55,18 @@ setClipping true setBrush #6300ff00 drawRect 25 25 50 50 + +# disable clipping followed by setClipRect +translate 150 0 + +setClipRect 0 0 50 50 ReplaceClip + +setClipping false + +setBrush #630000ff +drawRect 0 0 100 100 + +setClipRect 25 25 75 75 IntersectClip + +setBrush #6300ff00 +drawRect 25 25 50 50 diff --git a/tests/arthur/data/qps/clipping_state_qps.png b/tests/arthur/data/qps/clipping_state_qps.png Binary files differindex 9b3dee2..28bee46 100644 --- a/tests/arthur/data/qps/clipping_state_qps.png +++ b/tests/arthur/data/qps/clipping_state_qps.png diff --git a/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro index 114be8e..f4aea32 100644 --- a/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro +++ b/tests/auto/declarative/simplecanvasitem/simplecanvasitem.pro @@ -1,5 +1,6 @@ load(qttest_p4) contains(QT_CONFIG,declarative): QT += declarative +contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl SOURCES += tst_simplecanvasitem.cpp # Define SRCDIR equal to test's source directory diff --git a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp index 74126f8..2d89639 100644 --- a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp +++ b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp @@ -132,6 +132,11 @@ void tst_Q3SqlCursor::createTestTables( QSqlDatabase db ) if ( !db.isValid() ) return; QSqlQuery q( db ); + + if (tst_Databases::isSqlServer(db)) { + QVERIFY_SQL(q, exec("SET ANSI_DEFAULTS ON")); + } + // please never ever change this table; otherwise fix all tests ;) if ( tst_Databases::isMSAccess( db ) ) { QVERIFY_SQL(q, exec( "create table " + qTableName( "qtest" ) + " ( id int not null, t_varchar varchar(40) not null," @@ -301,7 +306,8 @@ void tst_Q3SqlCursor::insert() // check that primeInsert returns a valid QSqlRecord QCOMPARE( (int)irec->count(), 4 ); if ( ( irec->field( 0 ).type() != QVariant::Int ) && - ( irec->field( 0 ).type() != QVariant::String ) ) { + ( irec->field( 0 ).type() != QVariant::String ) && + ( irec->field( 0 ).type() != QVariant::Double ) ) { QFAIL( QString( "Wrong datatype %1 for field 'ID'" " (expected Int or String)" ).arg( QVariant::typeToName( irec->field( 0 ).type() ) ) ); } @@ -533,13 +539,18 @@ void tst_Q3SqlCursor::unicode() cur.del(); if ( res != utf8str ) { - int i; - for ( i = 0; i < (int)res.length(); ++i ) { - if ( res[ i ] != utf8str[ i ] ) - break; - } - QFAIL( QString( "Strings differ at position %1: orig: %2, db: %3" ).arg( i ).arg( utf8str[ i ].unicode(), 0, 16 ).arg( res[ i ].unicode(), 0, 16 ) ); + int i; + for ( i = 0; i < (int)res.length(); ++i ) { + if ( res[ i ] != utf8str[ i ] ) + break; + } + if(db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QDB2")) + qWarning() << "Needs someone with more Unicode knowledge than I have to fix:" << QString( "Strings differ at position %1: orig: %2, db: %3" ).arg( i ).arg( utf8str[ i ].unicode(), 0, 16 ).arg( res[ i ].unicode(), 0, 16 ); + else + QFAIL( QString( "Strings differ at position %1: orig: %2, db: %3" ).arg( i ).arg( utf8str[ i ].unicode(), 0, 16 ).arg( res[ i ].unicode(), 0, 16 ) ); } + if(db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QDB2")) + QEXPECT_FAIL("", "See above message", Continue); QVERIFY( res == utf8str ); } @@ -747,12 +758,12 @@ void tst_Q3SqlCursor::insertFieldNameContainsWS() { QString tableName = qTableName("qtestws"); QSqlQuery q(db); - q.exec(QString("DROP TABLE %1").arg(tableName)); + tst_Databases::safeDropTable(db, tableName); QString query = QString("CREATE TABLE %1 (id int, \"first Name\" varchar(20), " - "lastName varchar(20))"); - QVERIFY_SQL(q, exec(query.arg(tableName))); + "lastName varchar(20))").arg(tableName); + QVERIFY_SQL(q, exec(query)); - Q3SqlCursor cur(QString("%1").arg(tableName), true, db); + Q3SqlCursor cur(tableName, true, db); cur.select(); QSqlRecord *r = cur.primeInsert(); @@ -768,8 +779,8 @@ void tst_Q3SqlCursor::insertFieldNameContainsWS() { QVERIFY(cur.value(0) == 1); QCOMPARE(cur.value(1).toString(), QString("Kong")); QCOMPARE(cur.value(2).toString(), QString("Harald")); - - q.exec(QString("DROP TABLE %1").arg(tableName)); + + tst_Databases::safeDropTable(db, tableName); } diff --git a/tests/auto/q3sqlselectcursor/tst_q3sqlselectcursor.cpp b/tests/auto/q3sqlselectcursor/tst_q3sqlselectcursor.cpp index d026cbf..ec1f805 100644 --- a/tests/auto/q3sqlselectcursor/tst_q3sqlselectcursor.cpp +++ b/tests/auto/q3sqlselectcursor/tst_q3sqlselectcursor.cpp @@ -114,7 +114,7 @@ void tst_Q3SqlSelectCursor::createTestTables( QSqlDatabase db ) void tst_Q3SqlSelectCursor::dropTestTables( QSqlDatabase db ) { - tst_Databases::safeDropTables( db, QStringList() << qTableName( "qtest" ) ); + tst_Databases::safeDropTable( db, qTableName( "qtest" ) ); } void tst_Q3SqlSelectCursor::populateTestTables( QSqlDatabase db ) diff --git a/tests/auto/qbytearray/tst_qbytearray.cpp b/tests/auto/qbytearray/tst_qbytearray.cpp index 0e3df53..78fbf32 100644 --- a/tests/auto/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/qbytearray/tst_qbytearray.cpp @@ -239,10 +239,6 @@ void tst_QByteArray::qUncompress() QTEST(::qUncompress(in), "out"); -#if defined Q_WS_MAC && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4) - QSKIP("Corrupt data causes this test to lock up on Mac OS X Panther", SkipSingle); -#endif - QTEST(::qUncompress(in + "blah"), "out"); } #endif diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 981efeb..7552f18 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -173,6 +173,7 @@ private slots: void sceneBoundingRect(); void childrenBoundingRect(); void childrenBoundingRectTransformed(); + void childrenBoundingRect2(); void group(); void setGroup(); void nestedGroups(); @@ -2995,6 +2996,16 @@ void tst_QGraphicsItem::childrenBoundingRectTransformed() QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250)); } +void tst_QGraphicsItem::childrenBoundingRect2() +{ + QGraphicsItemGroup box; + QGraphicsLineItem l1(0, 0, 100, 0, &box); + QGraphicsLineItem l2(100, 0, 100, 100, &box); + QGraphicsLineItem l3(0, 0, 0, 100, &box); + // Make sure lines (zero with/height) are included in the childrenBoundingRect. + QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100)); +} + void tst_QGraphicsItem::group() { QGraphicsScene scene; diff --git a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro index 0755055..2e41fcd 100644 --- a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro +++ b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro @@ -1,5 +1,5 @@ load(qttest_p4) SOURCES += tst_qhttpnetworkreply.cpp -INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib QT = core network diff --git a/tests/auto/qitemmodel/qitemmodel.pro b/tests/auto/qitemmodel/qitemmodel.pro index c51f4c7..38c615b 100644 --- a/tests/auto/qitemmodel/qitemmodel.pro +++ b/tests/auto/qitemmodel/qitemmodel.pro @@ -1,6 +1,5 @@ -CONFIG += qtestlib +load(qttest_p4) SOURCES += tst_qitemmodel.cpp -TARGET = tst_qitemmodel QT += sql diff --git a/tests/auto/qrect/tst_qrect.cpp b/tests/auto/qrect/tst_qrect.cpp index cdb5560..5a91636 100644 --- a/tests/auto/qrect/tst_qrect.cpp +++ b/tests/auto/qrect/tst_qrect.cpp @@ -4125,6 +4125,7 @@ void tst_QRect::unitedRect_data() QTest::newRow("test 13") << QRect() << QRect(10, 10, 10, 10) << QRect(10, 10, 10, 10); QTest::newRow("test 14") << QRect(10, 10, 10, 10) << QRect() << QRect(10, 10, 10, 10); QTest::newRow("test 15") << QRect() << QRect() << QRect(); + QTest::newRow("test 16") << QRect(0, 0, 100, 0) << QRect(0, 0, 0, 100) << QRect(0, 0, 100, 100); } void tst_QRect::unitedRect() @@ -4160,6 +4161,7 @@ void tst_QRect::unitedRectF_data() QTest::newRow("test 13") << QRectF() << QRectF(10, 10, 10, 10) << QRectF(10, 10, 10, 10); QTest::newRow("test 14") << QRectF(10, 10, 10, 10) << QRectF() << QRectF(10, 10, 10, 10); QTest::newRow("test 15") << QRectF() << QRectF() << QRectF(); + QTest::newRow("test 16") << QRectF(0, 0, 100, 0) << QRectF(0, 0, 0, 100) << QRectF(0, 0, 100, 100); } void tst_QRect::unitedRectF() diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index a490a2f..b81182a 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -238,8 +238,8 @@ public: // addDb( "QIBASE", "/opt/firebird/databases/testdb.fdb", "testuser", "Ee4Gabf6_", "firebird2-nokia.trolltech.com.au" ); // Firebird 2.1.1 // use in-memory database to prevent local files - addDb("QSQLITE", ":memory:"); -// addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") ); +// addDb("QSQLITE", ":memory:"); + addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") ); // addDb( "QSQLITE2", QDir::toNativeSeparators(QDir::tempPath()+"/foo2.db") ); // addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=iceblink.nokia.troll.no\\ICEBLINK", "troll", "trond", "" ); // addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" ); @@ -333,6 +333,11 @@ public: } } + static void safeDropTable( QSqlDatabase db, const QString& tableName ) + { + safeDropTables(db, QStringList() << tableName); + } + static void safeDropViews( QSqlDatabase db, const QStringList &viewNames ) { if ( isMSAccess( db ) ) // Access is sooo stupid. @@ -354,6 +359,11 @@ public: } } + static void safeDropView( QSqlDatabase db, const QString& tableName ) + { + safeDropViews(db, QStringList() << tableName); + } + // returns the type name of the blob datatype for the database db. // blobSize is only used if the db doesn't have a generic blob type static QString blobTypeName( QSqlDatabase db, int blobSize = 10000 ) diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index cce4602..f697488 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -249,7 +249,7 @@ struct FieldDef { // excluding the primary key field static int createFieldTable(const FieldDef fieldDefs[], QSqlDatabase db) { - tst_Databases::safeDropTables(db, QStringList() << qTableName("qtestfields")); + tst_Databases::safeDropTable(db, qTableName("qtestfields")); QSqlQuery q(db); // construct a create table statement consisting of all fieldtypes QString qs = "create table " + qTableName("qtestfields"); @@ -357,6 +357,7 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db) tableNames << (qTableName("qtest") + " test"); tst_Databases::safeDropTables(db, tableNames); + tst_Databases::safeDropView(db, qTableName("qtest_view")); } void tst_QSqlDatabase::populateTestTables(QSqlDatabase db) @@ -540,11 +541,6 @@ void tst_QSqlDatabase::tables() QVERIFY(tables.contains(qTableName("temp_tab"), Qt::CaseInsensitive)); QVERIFY(tables.contains(qTableName("qtest"), Qt::CaseInsensitive)); - if (tst_Databases::isMSAccess(db)) - QSqlQuery("drop table " + qTableName("qtest_view"), db); - else - QSqlQuery("drop view " + qTableName("qtest_view"), db); - if (db.driverName().startsWith("QPSQL")) { QVERIFY(tables.contains(qTableName("qtest") + " test")); } diff --git a/tests/auto/qsqldriver/tst_qsqldriver.cpp b/tests/auto/qsqldriver/tst_qsqldriver.cpp index bbd7483..d8f7747 100644 --- a/tests/auto/qsqldriver/tst_qsqldriver.cpp +++ b/tests/auto/qsqldriver/tst_qsqldriver.cpp @@ -85,9 +85,7 @@ void tst_QSqlDriver::recreateTestTables(QSqlDatabase db) { QSqlQuery q(db); - QStringList tableNames; - tableNames << qTableName( "relTEST1" ); - tst_Databases::safeDropTables( db, tableNames ); + tst_Databases::safeDropTable( db, qTableName( "relTEST1" ) ); QVERIFY_SQL( q, exec("create table " + qTableName("relTEST1") + " (id int not null primary key, name varchar(20), title_key int, another_title_key int)")); @@ -105,11 +103,9 @@ void tst_QSqlDriver::initTestCase() void tst_QSqlDriver::cleanupTestCase() { - QStringList tableNames; - tableNames << qTableName( "relTEST1" ); foreach (const QString &dbName, dbs.dbNames) { QSqlDatabase db = QSqlDatabase::database(dbName); - tst_Databases::safeDropTables( db, tableNames ); + tst_Databases::safeDropTable( db, qTableName( "relTEST1" ) ); } dbs.close(); } diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 825db6c..9604fa8 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -289,7 +289,8 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) << qTableName( "bindtest" ) << qTableName( "more_results" ) << qTableName( "blobstest" ) - << qTableName( "oraRowId" ); + << qTableName( "oraRowId" ) + << qTableName( "qtest_batch" ); if ( db.driverName().startsWith("QSQLITE") ) tablenames << qTableName( "record_sqlite" ); @@ -303,6 +304,7 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) tablenames << qTableName( "Planet" ); #endif tablenames << qTableName( "task_250026" ); + tablenames << qTableName( "task_234422" ); tst_Databases::safeDropTables( db, tablenames ); } @@ -1902,71 +1904,48 @@ void tst_QSqlQuery::batchExec() QSKIP( "Database can't do BatchOperations", SkipSingle ); QSqlQuery q( db ); + QString tableName = qTableName( "qtest_batch" ); - q.exec( "drop table " + qTableName( "qtest_batch" ) ); - - QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_batch" ) + " (id int, name varchar(20), dt date, num numeric(8, 4))" ) ); - - QVERIFY_SQL( q, prepare( "insert into " + qTableName( "qtest_batch" ) + " (id, name, dt, num) values (?, ?, ?, ?)" ) ); + QVERIFY_SQL( q, exec( "create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4))" ) ); + QVERIFY_SQL( q, prepare( "insert into " + tableName + " (id, name, dt, num) values (?, ?, ?, ?)" ) ); QVariantList intCol; - intCol << 1 << 2 << QVariant( QVariant::Int ); QVariantList charCol; - charCol << QLatin1String( "harald" ) << QLatin1String( "boris" ) << QVariant( QVariant::String ); QVariantList dateCol; - QDateTime dt = QDateTime( QDate::currentDate(), QTime( 1, 2, 3 ) ); - dateCol << dt << dt.addDays( -1 ) << QVariant( QVariant::DateTime ); QVariantList numCol; - numCol << 2.3 << 3.4 << QVariant( QVariant::Double ); q.addBindValue( intCol ); - q.addBindValue( charCol ); - q.addBindValue( dateCol ); - q.addBindValue( numCol ); QVERIFY_SQL( q, execBatch() ); - - QVERIFY_SQL( q, exec( "select id, name, dt, num from " + qTableName( "qtest_batch" ) + " order by id" ) ); + QVERIFY_SQL( q, exec( "select id, name, dt, num from " + tableName + " order by id" ) ); QVERIFY( q.next() ); - QCOMPARE( q.value( 0 ).toInt(), 1 ); - QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) ); - QCOMPARE( q.value( 2 ).toDateTime(), dt ); - QCOMPARE( q.value( 3 ).toDouble(), 2.3 ); QVERIFY( q.next() ); - QCOMPARE( q.value( 0 ).toInt(), 2 ); - QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) ); - QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) ); - QCOMPARE( q.value( 3 ).toDouble(), 3.4 ); QVERIFY( q.next() ); - QVERIFY( q.value( 0 ).isNull() ); - QVERIFY( q.value( 1 ).isNull() ); - QVERIFY( q.value( 2 ).isNull() ); - QVERIFY( q.value( 3 ).isNull() ); } @@ -2344,6 +2323,8 @@ void tst_QSqlQuery::sqlite_finish() QString tableName = qTableName( "qtest_lockedtable" ); QSqlQuery q( db ); + + tst_Databases::safeDropTable( db2, tableName ); q.exec( "CREATE TABLE " + tableName + " (pk_id INTEGER PRIMARY KEY, whatever TEXT)" ); q.exec( "INSERT INTO " + tableName + " values(1, 'whatever')" ); q.exec( "INSERT INTO " + tableName + " values(2, 'whatever more')" ); @@ -2361,7 +2342,8 @@ void tst_QSqlQuery::sqlite_finish() q.finish(); QVERIFY_SQL( q2, exec( "DELETE FROM " + tableName + " WHERE pk_id=2" ) ); QCOMPARE( q2.numRowsAffected(), 1 ); - q.exec( "DROP TABLE " + tableName ); + + tst_Databases::safeDropTable( db2, tableName ); } QSqlDatabase::removeDatabase( "sqlite_finish_sqlite" ); @@ -2574,71 +2556,47 @@ void tst_QSqlQuery::blobsPreparedQuery() QString tableName = qTableName( "blobstest" ); QSqlQuery q( db ); - q.setForwardOnly( true ); // This is needed to make the test work with DB2. - QString shortBLOB( "abc" ); - QString longerBLOB( "abcdefghijklmnopqrstuvxyz¿äëïöü¡ " ); // In PostgreSQL a BLOB is not called a BLOB, but a BYTEA! :-) // ... and in SQL Server it can be called a lot, but IMAGE will do. QString typeName( "BLOB" ); - if ( db.driverName().startsWith( "QPSQL" ) ) typeName = "BYTEA"; else if ( db.driverName().startsWith( "QODBC" ) ) typeName = "IMAGE"; QVERIFY_SQL( q, exec( QString( "CREATE TABLE %1(id INTEGER, data %2)" ).arg( tableName ).arg( typeName ) ) ); - q.prepare( QString( "INSERT INTO %1(id, data) VALUES(:id, :data)" ).arg( tableName ) ); - q.bindValue( ":id", 1 ); - q.bindValue( ":data", shortBLOB.toAscii() ); - QVERIFY_SQL( q, exec() ); q.bindValue( ":id", 2 ); - q.bindValue( ":data", longerBLOB.toAscii() ); - QVERIFY_SQL( q, exec() ); // Two executions and result sets q.prepare( QString( "SELECT data FROM %1 WHERE id = ?" ).arg( tableName ) ); - q.bindValue( 0, QVariant( 1 ) ); - QVERIFY_SQL( q, exec() ); - QVERIFY_SQL( q, next() ); - QCOMPARE( q.value( 0 ).toString(), shortBLOB ); q.bindValue( 0, QVariant( 2 ) ); - QVERIFY_SQL( q, exec() ); - QVERIFY_SQL( q, next() ); - QCOMPARE( q.value( 0 ).toString(), longerBLOB ); // Only one execution and result set q.prepare( QString( "SELECT id, data FROM %1 ORDER BY id" ).arg( tableName ) ); - QVERIFY_SQL( q, exec() ); - QVERIFY_SQL( q, next() ); - QCOMPARE( q.value( 1 ).toString(), shortBLOB ); - QVERIFY_SQL( q, next() ); - QCOMPARE( q.value( 1 ).toString(), longerBLOB ); - - q.exec( QString( "DROP TABLE %1" ).arg( tableName ) ); } // There were problems with navigating past the end of a table returning an error on mysql @@ -2792,7 +2750,6 @@ void tst_QSqlQuery::task_234422() QString tableName = qTableName( "task_234422" ); - query.exec("DROP TABLE " + tableName); QVERIFY_SQL(query,exec("CREATE TABLE " + tableName + " (id int primary key, " "name varchar(20), homecountry varchar(2))")); for (int i = 0; i < m_airlines.count(); ++i) { diff --git a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp index 4588af8..e2dace8 100644 --- a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp +++ b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp @@ -86,6 +86,9 @@ private slots: void escapedRelations(); void escapedTableName(); void whiteSpaceInIdentifiers(); + +private: + void dropTestTables( QSqlDatabase db ); }; @@ -100,18 +103,9 @@ void tst_QSqlRelationalTableModel::initTestCase_data() void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db) { - QSqlQuery q(db); - - QStringList tableNames; - tableNames << qTableName( "reltest1" ) - << qTableName( "reltest2" ) - << qTableName( "reltest3" ) - << qTableName( "reltest4" ) - << qTableName( "reltest5" ) - << db.driver()->escapeIdentifier(qTableName( "rel test6" ), QSqlDriver::TableName) - << db.driver()->escapeIdentifier(qTableName( "rel test7" ), QSqlDriver::TableName); - tst_Databases::safeDropTables( db, tableNames ); + dropTestTables(db); + QSqlQuery q(db); QVERIFY_SQL( q, exec("create table " + qTableName("reltest1") + " (id int not null primary key, name varchar(20), title_key int, another_title_key int)")); QVERIFY_SQL( q, exec("insert into " + qTableName("reltest1") + " values(1, 'harry', 1, 2)")); @@ -157,20 +151,27 @@ void tst_QSqlRelationalTableModel::initTestCase() void tst_QSqlRelationalTableModel::cleanupTestCase() { + foreach (const QString &dbName, dbs.dbNames) { + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE( db ); + dropTestTables( QSqlDatabase::database(dbName) ); + } + dbs.close(); +} + +void tst_QSqlRelationalTableModel::dropTestTables( QSqlDatabase db ) +{ QStringList tableNames; tableNames << qTableName( "reltest1" ) << qTableName( "reltest2" ) << qTableName( "reltest3" ) << qTableName( "reltest4" ) - << qTableName( "reltest5" ); - foreach (const QString &dbName, dbs.dbNames) { - QSqlDatabase db = QSqlDatabase::database(dbName); - QStringList tables = tableNames; - tables << db.driver()->escapeIdentifier(qTableName( "rel test6" ), QSqlDriver::TableName) - << db.driver()->escapeIdentifier(qTableName( "rel test7" ), QSqlDriver::TableName); - tst_Databases::safeDropTables( db, tables ); - } - dbs.close(); + << qTableName( "reltest5" ) + << qTableName( "rel test6", db.driver() ) + << qTableName( "rel test7", db.driver() ) + << qTableName("CASETEST1", db.driver() ) + << qTableName("casetest1", db.driver() ); + tst_Databases::safeDropTables( db, tableNames ); } void tst_QSqlRelationalTableModel::init() @@ -916,11 +917,6 @@ void tst_QSqlRelationalTableModel::casing() if (db.driverName().startsWith("QSQLITE")) QSKIP("The casing test for SQLITE is irrelevant since SQLITE is case insensitive", SkipAll); - QStringList tableNames; - tableNames << qTableName("CASETEST1", db.driver()).toUpper(); - tableNames << qTableName("casetest1", db.driver()); - tst_Databases::safeDropTables(db, tableNames); - QSqlQuery q(db); QVERIFY_SQL( q, exec("create table " + qTableName("CASETEST1", db.driver()).toUpper() + " (id int not null primary key, name varchar(20), title_key int, another_title_key int)")); @@ -974,8 +970,6 @@ void tst_QSqlRelationalTableModel::casing() QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr")); - - tst_Databases::safeDropTables(db, tableNames); } void tst_QSqlRelationalTableModel::escapedRelations() diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index aa882be..1445f34 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -899,7 +899,7 @@ void tst_QSqlTableModel::sqlite_attachedDatabase() QVERIFY_SQL( q, exec("INSERT INTO atest2 VALUES(2, 'attached-atest2')")); QSqlQuery q2(db); - tst_Databases::safeDropTables(db, QStringList() << "atest"); + tst_Databases::safeDropTable(db, "atest"); QVERIFY_SQL(q2, exec("CREATE TABLE atest(id int, text varchar(20))")); QVERIFY_SQL(q2, exec("INSERT INTO atest VALUES(3, 'main')")); QVERIFY_SQL(q2, exec("ATTACH DATABASE \""+attachedDb.databaseName()+"\" as adb")); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 553833c..a859866 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -151,6 +151,8 @@ private slots: void defaultGlobalRestorePolicy(); void globalRestorePolicySetToRestore(); void globalRestorePolicySetToDoNotRestore(); + + void noInitialStateForInitialState(); //void restorePolicyNotInherited(); //void mixedRestoreProperties(); @@ -345,7 +347,7 @@ void tst_QStateMachine::transitionEntersParent() void tst_QStateMachine::defaultErrorState() { QStateMachine machine; - QVERIFY(machine.errorState() != 0); + QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0)); QState *brokenState = new QState(); brokenState->setObjectName("MyInitialState"); @@ -364,9 +366,7 @@ void tst_QStateMachine::defaultErrorState() QCOMPARE(machine.error(), QStateMachine::NoInitialStateError); QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'MyInitialState'")); - - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(machine.errorState())); + QCOMPARE(machine.isRunning(), false); } class CustomErrorState: public QState @@ -424,6 +424,7 @@ void tst_QStateMachine::customGlobalErrorState() QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(customErrorState)); QCOMPARE(customErrorState->error, QStateMachine::NoInitialStateError); @@ -459,6 +460,7 @@ void tst_QStateMachine::customLocalErrorStateInBrokenState() machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(customErrorState)); QCOMPARE(customErrorState->error, QStateMachine::NoInitialStateError); @@ -494,8 +496,7 @@ void tst_QStateMachine::customLocalErrorStateInOtherState() machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(machine.errorState())); + QCOMPARE(machine.isRunning(), false); } void tst_QStateMachine::customLocalErrorStateInParentOfBrokenState() @@ -529,6 +530,7 @@ void tst_QStateMachine::customLocalErrorStateInParentOfBrokenState() machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(customErrorState)); } @@ -607,6 +609,7 @@ void tst_QStateMachine::errorStateHasChildren() machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.configuration().count(), 2); QVERIFY(machine.configuration().contains(customErrorState)); QVERIFY(machine.configuration().contains(childOfErrorState)); @@ -620,7 +623,6 @@ void tst_QStateMachine::errorStateHasErrors() customErrorState->setObjectName("customErrorState"); machine.addState(customErrorState); - QAbstractState *oldErrorState = machine.errorState(); machine.setErrorState(customErrorState); QState *childOfErrorState = new QState(customErrorState); @@ -647,8 +649,7 @@ void tst_QStateMachine::errorStateHasErrors() QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'customErrorState'"); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(oldErrorState)); // Fall back to default + QCOMPARE(machine.isRunning(), false); QCOMPARE(machine.error(), QStateMachine::NoInitialStateError); QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'customErrorState'")); } @@ -680,8 +681,7 @@ void tst_QStateMachine::errorStateIsRootState() QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'brokenState'"); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(machine.errorState())); + QCOMPARE(machine.isRunning(), false); } void tst_QStateMachine::errorStateEntersParentFirst() @@ -759,7 +759,6 @@ void tst_QStateMachine::errorStateEntersParentFirst() void tst_QStateMachine::customErrorStateIsNull() { QStateMachine machine; - QAbstractState *oldErrorState = machine.errorState(); machine.rootState()->setErrorState(0); QState *initialState = new QState(); @@ -780,8 +779,7 @@ void tst_QStateMachine::customErrorStateIsNull() QCoreApplication::processEvents(); QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0)); - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(oldErrorState)); + QCOMPARE(machine.isRunning(), false); } void tst_QStateMachine::clearError() @@ -797,6 +795,7 @@ void tst_QStateMachine::clearError() machine.start(); QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.error(), QStateMachine::NoInitialStateError); QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'brokenState'")); @@ -862,6 +861,7 @@ void tst_QStateMachine::historyStateHasNowhereToGo() machine.postEvent(new QEvent(QEvent::User)); QCoreApplication::processEvents(); + QCOMPARE(machine.isRunning(), true); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(machine.errorState())); QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryStateError); @@ -920,8 +920,7 @@ void tst_QStateMachine::transitionToStateNotInGraph() QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initialState'"); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(qobject_cast<QState*>(machine.rootState())->errorState())); + QCOMPARE(machine.isRunning(), false); } void tst_QStateMachine::customErrorStateNotInGraph() @@ -932,7 +931,7 @@ void tst_QStateMachine::customErrorStateNotInGraph() errorState.setObjectName("errorState"); QTest::ignoreMessage(QtWarningMsg, "QState::setErrorState: error state cannot belong to a different state machine"); machine.setErrorState(&errorState); - QVERIFY(&errorState != machine.errorState()); + QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0)); QState *initialBrokenState = new QState(machine.rootState()); initialBrokenState->setObjectName("initialBrokenState"); @@ -942,9 +941,8 @@ void tst_QStateMachine::customErrorStateNotInGraph() machine.start(); QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'initialBrokenState'"); QCoreApplication::processEvents(); - - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(machine.errorState())); + + QCOMPARE(machine.isRunning(), false); } void tst_QStateMachine::restoreProperties() @@ -1019,8 +1017,7 @@ void tst_QStateMachine::addAndRemoveState() { QStateMachine machine; QStatePrivate *root_d = QStatePrivate::get(machine.rootState()); - QCOMPARE(root_d->childStates().size(), 1); // the error state - QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().size(), 0); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: cannot add null state"); machine.addState(0); @@ -1031,9 +1028,8 @@ void tst_QStateMachine::addAndRemoveState() machine.addState(s1); QCOMPARE(s1->machine(), &machine); QCOMPARE(s1->parentState(), machine.rootState()); - QCOMPARE(root_d->childStates().size(), 2); - QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().size(), 1); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s1); @@ -1042,24 +1038,21 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s2->parentState(), (QState*)0); machine.addState(s2); QCOMPARE(s2->parentState(), machine.rootState()); - QCOMPARE(root_d->childStates().size(), 3); - QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); - QCOMPARE(root_d->childStates().at(2), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 2); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s2); machine.removeState(s1); QCOMPARE(s1->parentState(), (QState*)0); - QCOMPARE(root_d->childStates().size(), 2); - QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 1); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s2); machine.removeState(s2); QCOMPARE(s2->parentState(), (QState*)0); - QCOMPARE(root_d->childStates().size(), 1); - QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().size(), 0); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::removeState: cannot remove null state"); machine.removeState(0); @@ -1067,10 +1060,10 @@ void tst_QStateMachine::addAndRemoveState() { QStateMachine machine2; { - char warning[256]; - sprintf(warning, "QStateMachine::removeState: state %p's machine (%p) is different from this machine (%p)", - machine2.rootState(), &machine2, &machine); - QTest::ignoreMessage(QtWarningMsg, warning); + QString warning; + warning.sprintf("QStateMachine::removeState: state %p's machine (%p) is different from this machine (%p)", + machine2.rootState(), &machine2, &machine); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); machine.removeState(machine2.rootState()); } // ### check this behavior @@ -1129,9 +1122,9 @@ void tst_QStateMachine::stateEntryAndExit() QCOMPARE(trans->sourceState(), (QState*)s2); QCOMPARE(trans->targetState(), (QAbstractState*)s3); { - char warning[256]; - sprintf(warning, "QState::removeTransition: transition %p's source state (%p) is different from this state (%p)", trans, s2, s1); - QTest::ignoreMessage(QtWarningMsg, warning); + QString warning; + warning.sprintf("QState::removeTransition: transition %p's source state (%p) is different from this state (%p)", trans, s2, s1); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); s1->removeTransition(trans); } s2->removeTransition(trans); @@ -1147,9 +1140,9 @@ void tst_QStateMachine::stateEntryAndExit() machine.setInitialState(s1); QCOMPARE(machine.initialState(), (QAbstractState*)s1); { - char warning[256]; - sprintf(warning, "QState::setInitialState: state %p is not a child of this state (%p)", machine.rootState(), machine.rootState()); - QTest::ignoreMessage(QtWarningMsg, warning); + QString warning; + warning.sprintf("QState::setInitialState: state %p is not a child of this state (%p)", machine.rootState(), machine.rootState()); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); machine.setInitialState(machine.rootState()); QCOMPARE(machine.initialState(), (QAbstractState*)s1); } @@ -1614,9 +1607,9 @@ void tst_QStateMachine::parallelStates() s1_2_1->addTransition(s1_2_f); s1_2->setInitialState(s1_2_1); { - char warning[256]; - sprintf(warning, "QState::setInitialState: ignoring attempt to set initial state of parallel state group %p", s1); - QTest::ignoreMessage(QtWarningMsg, warning); + QString warning; + warning.sprintf("QState::setInitialState: ignoring attempt to set initial state of parallel state group %p", s1); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); s1->setInitialState(0); } machine.addState(s1); @@ -2286,9 +2279,9 @@ void tst_QStateMachine::historyStates() QCOMPARE(s0h->defaultState(), (QAbstractState*)0); s0h->setDefaultState(s00); QCOMPARE(s0h->defaultState(), (QAbstractState*)s00); - char warning[256]; - sprintf(warning, "QHistoryState::setDefaultState: state %p does not belong to this history state's group (%p)", s0, s0); - QTest::ignoreMessage(QtWarningMsg, warning); + QString warning; + warning.sprintf("QHistoryState::setDefaultState: state %p does not belong to this history state's group (%p)", s0, s0); + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); s0h->setDefaultState(s0); QState *s1 = new QState(root); QFinalState *s2 = new QFinalState(root); @@ -2393,12 +2386,10 @@ void tst_QStateMachine::targetStateWithNoParent() QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.start(); QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 's1'"); - QTRY_COMPARE(machine.isRunning(), true); QTRY_COMPARE(startedSpy.count(), 1); - QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(machine.isRunning(), false); + QCOMPARE(stoppedSpy.count(), 1); QCOMPARE(finishedSpy.count(), 0); - QCOMPARE(machine.configuration().size(), 1); - QVERIFY(machine.configuration().contains(machine.errorState())); QCOMPARE(machine.error(), QStateMachine::NoCommonAncestorForTransitionError); } @@ -2453,6 +2444,25 @@ void tst_QStateMachine::defaultGlobalRestorePolicy() QCOMPARE(propertyHolder->property("b").toInt(), 4); } +void tst_QStateMachine::noInitialStateForInitialState() +{ + QStateMachine machine; + + QState *initialState = new QState(machine.rootState()); + initialState->setObjectName("initialState"); + machine.setInitialState(initialState); + + QState *childState = new QState(initialState); + + QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: " + "Missing initial state in compound state 'initialState'"); + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.isRunning(), false); + QCOMPARE(int(machine.error()), int(QStateMachine::NoInitialStateError)); +} + /* void tst_QStateMachine::restorePolicyNotInherited() { diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 6727b05..dd9a3e0 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -252,6 +252,7 @@ private slots: void moveChild_data(); void moveChild(); + void showAndMoveChild(); void subtractOpaqueSiblings(); @@ -5318,6 +5319,33 @@ void tst_QWidget::moveChild() parent.color); } +void tst_QWidget::showAndMoveChild() +{ + QWidget parent(0, Qt::FramelessWindowHint); + parent.resize(300, 300); + parent.setPalette(Qt::red); + parent.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&parent); +#endif + QTest::qWait(200); + + const QPoint tlwOffset = parent.geometry().topLeft(); + QWidget child(&parent); + child.resize(100, 100); + child.setPalette(Qt::blue); + child.setAutoFillBackground(true); + + // Ensure that the child is repainted correctly when moved right after show. + // NB! Do NOT processEvents() (or qWait()) in between show() and move(). + child.show(); + child.move(150, 150); + qApp->processEvents(); + + VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue); + VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red); +} + void tst_QWidget::subtractOpaqueSiblings() { #ifdef QT_MAC_USE_COCOA diff --git a/tests/auto/qwizard/tst_qwizard.cpp b/tests/auto/qwizard/tst_qwizard.cpp index 71e1c3e..e5074b3 100644 --- a/tests/auto/qwizard/tst_qwizard.cpp +++ b/tests/auto/qwizard/tst_qwizard.cpp @@ -112,6 +112,7 @@ private slots: void task161658_alignments(); void task177022_setFixedSize(); void task248107_backButton(); + void task255350_fieldObjectDestroyed(); /* Things that could be added: @@ -2517,5 +2518,26 @@ void tst_QWizard::task248107_backButton() QCOMPARE(wizard.currentPage(), &page1); } +class WizardPage_task255350 : public QWizardPage +{ +public: + QLineEdit *lineEdit; + WizardPage_task255350() + : lineEdit(new QLineEdit) + { + registerField("dummy*", lineEdit); + } +}; + +void tst_QWizard::task255350_fieldObjectDestroyed() +{ + QWizard wizard; + WizardPage_task255350 *page = new WizardPage_task255350; + int id = wizard.addPage(page); + delete page->lineEdit; + wizard.removePage(id); // don't crash! + delete page; +} + QTEST_MAIN(tst_QWizard) #include "tst_qwizard.moc" diff --git a/tools/assistant/lib/fulltextsearch/qanalyzer.cpp b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp index 9c380ae..ed018bf 100644 --- a/tools/assistant/lib/fulltextsearch/qanalyzer.cpp +++ b/tools/assistant/lib/fulltextsearch/qanalyzer.cpp @@ -27,6 +27,7 @@ QCLuceneAnalyzerPrivate::QCLuceneAnalyzerPrivate(const QCLuceneAnalyzerPrivate & : QSharedData() { analyzer = _CL_POINTER(other.analyzer); + deleteCLuceneAnalyzer = other.deleteCLuceneAnalyzer; } QCLuceneAnalyzerPrivate::~QCLuceneAnalyzerPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qdocument.cpp b/tools/assistant/lib/fulltextsearch/qdocument.cpp index c2aae98..bad8ea9 100644 --- a/tools/assistant/lib/fulltextsearch/qdocument.cpp +++ b/tools/assistant/lib/fulltextsearch/qdocument.cpp @@ -29,6 +29,7 @@ QCLuceneDocumentPrivate::QCLuceneDocumentPrivate(const QCLuceneDocumentPrivate & : QSharedData() { document = _CL_POINTER(other.document); + deleteCLuceneDocument = other.deleteCLuceneDocument; } QCLuceneDocumentPrivate::~QCLuceneDocumentPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qfield.cpp b/tools/assistant/lib/fulltextsearch/qfield.cpp index 496622d..dc878f3 100644 --- a/tools/assistant/lib/fulltextsearch/qfield.cpp +++ b/tools/assistant/lib/fulltextsearch/qfield.cpp @@ -28,6 +28,7 @@ QCLuceneFieldPrivate::QCLuceneFieldPrivate(const QCLuceneFieldPrivate &other) : QSharedData() { field = _CL_POINTER(other.field); + deleteCLuceneField = other.deleteCLuceneField; } QCLuceneFieldPrivate::~QCLuceneFieldPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qfilter.cpp b/tools/assistant/lib/fulltextsearch/qfilter.cpp index 60a2a1d..837f590 100644 --- a/tools/assistant/lib/fulltextsearch/qfilter.cpp +++ b/tools/assistant/lib/fulltextsearch/qfilter.cpp @@ -26,6 +26,7 @@ QCLuceneFilterPrivate::QCLuceneFilterPrivate(const QCLuceneFilterPrivate &other) : QSharedData() { filter = _CL_POINTER(other.filter); + deleteCLuceneFilter = other.deleteCLuceneFilter; } QCLuceneFilterPrivate::~QCLuceneFilterPrivate () diff --git a/tools/assistant/lib/fulltextsearch/qhits.cpp b/tools/assistant/lib/fulltextsearch/qhits.cpp index 003db17..c2fbf1b 100644 --- a/tools/assistant/lib/fulltextsearch/qhits.cpp +++ b/tools/assistant/lib/fulltextsearch/qhits.cpp @@ -27,6 +27,7 @@ QCLuceneHitsPrivate::QCLuceneHitsPrivate(const QCLuceneHitsPrivate &other) : QSharedData() { hits = _CL_POINTER(other.hits); + deleteCLuceneHits = other.deleteCLuceneHits; } QCLuceneHitsPrivate::~QCLuceneHitsPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qindexreader.cpp b/tools/assistant/lib/fulltextsearch/qindexreader.cpp index a755eae..fc1a3bb 100644 --- a/tools/assistant/lib/fulltextsearch/qindexreader.cpp +++ b/tools/assistant/lib/fulltextsearch/qindexreader.cpp @@ -27,6 +27,7 @@ QCLuceneIndexReaderPrivate::QCLuceneIndexReaderPrivate(const QCLuceneIndexReader : QSharedData() { reader = _CL_POINTER(other.reader); + deleteCLuceneIndexReader = other.deleteCLuceneIndexReader; } QCLuceneIndexReaderPrivate::~QCLuceneIndexReaderPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qindexwriter.cpp b/tools/assistant/lib/fulltextsearch/qindexwriter.cpp index af5a7bb..93e23e7 100644 --- a/tools/assistant/lib/fulltextsearch/qindexwriter.cpp +++ b/tools/assistant/lib/fulltextsearch/qindexwriter.cpp @@ -27,6 +27,7 @@ QCLuceneIndexWriterPrivate::QCLuceneIndexWriterPrivate(const QCLuceneIndexWriter : QSharedData() { writer = _CL_POINTER(other.writer); + deleteCLuceneIndexWriter = other.deleteCLuceneIndexWriter; } QCLuceneIndexWriterPrivate::~QCLuceneIndexWriterPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qquery.cpp b/tools/assistant/lib/fulltextsearch/qquery.cpp index 8bc9607..1760b05 100644 --- a/tools/assistant/lib/fulltextsearch/qquery.cpp +++ b/tools/assistant/lib/fulltextsearch/qquery.cpp @@ -28,6 +28,7 @@ QCLuceneQueryPrivate::QCLuceneQueryPrivate(const QCLuceneQueryPrivate &other) : QSharedData() { query = _CL_POINTER(other.query); + deleteCLuceneQuery = other.deleteCLuceneQuery; } QCLuceneQueryPrivate::~QCLuceneQueryPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qqueryparser.cpp b/tools/assistant/lib/fulltextsearch/qqueryparser.cpp index cbe0147..6f546be 100644 --- a/tools/assistant/lib/fulltextsearch/qqueryparser.cpp +++ b/tools/assistant/lib/fulltextsearch/qqueryparser.cpp @@ -28,6 +28,7 @@ QCLuceneQueryParserPrivate::QCLuceneQueryParserPrivate(const QCLuceneQueryParser : QSharedData() { queryParser = _CL_POINTER(other.queryParser); + deleteCLuceneQueryParser = other.deleteCLuceneQueryParser; } QCLuceneQueryParserPrivate::~QCLuceneQueryParserPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qreader.cpp b/tools/assistant/lib/fulltextsearch/qreader.cpp index fe079a9..3b2d6f5 100644 --- a/tools/assistant/lib/fulltextsearch/qreader.cpp +++ b/tools/assistant/lib/fulltextsearch/qreader.cpp @@ -25,8 +25,9 @@ QCLuceneReaderPrivate::QCLuceneReaderPrivate() QCLuceneReaderPrivate::QCLuceneReaderPrivate(const QCLuceneReaderPrivate &other) : QSharedData() -{ +{ reader = _CL_POINTER(other.reader); + deleteCLuceneReader = other.deleteCLuceneReader; } QCLuceneReaderPrivate::~QCLuceneReaderPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qsearchable.cpp b/tools/assistant/lib/fulltextsearch/qsearchable.cpp index c26868c..70cae91 100644 --- a/tools/assistant/lib/fulltextsearch/qsearchable.cpp +++ b/tools/assistant/lib/fulltextsearch/qsearchable.cpp @@ -26,6 +26,7 @@ QCLuceneSearchablePrivate::QCLuceneSearchablePrivate(const QCLuceneSearchablePri : QSharedData() { searchable = _CL_POINTER(other.searchable); + deleteCLuceneSearchable = other.deleteCLuceneSearchable; } QCLuceneSearchablePrivate::~QCLuceneSearchablePrivate() diff --git a/tools/assistant/lib/fulltextsearch/qsort.cpp b/tools/assistant/lib/fulltextsearch/qsort.cpp index 9c1e902..97ed128 100644 --- a/tools/assistant/lib/fulltextsearch/qsort.cpp +++ b/tools/assistant/lib/fulltextsearch/qsort.cpp @@ -27,6 +27,7 @@ QCLuceneSortPrivate::QCLuceneSortPrivate (const QCLuceneSortPrivate &other) : QSharedData() { sort = _CL_POINTER(other.sort); + deleteCLuceneSort = other.deleteCLuceneSort; } QCLuceneSortPrivate::~QCLuceneSortPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qterm.cpp b/tools/assistant/lib/fulltextsearch/qterm.cpp index 58d5c4d..10a2f3a 100644 --- a/tools/assistant/lib/fulltextsearch/qterm.cpp +++ b/tools/assistant/lib/fulltextsearch/qterm.cpp @@ -27,6 +27,7 @@ QCLuceneTermPrivate::QCLuceneTermPrivate(const QCLuceneTermPrivate &other) : QSharedData() { term = _CL_POINTER(other.term); + deleteCLuceneTerm = other.deleteCLuceneTerm; } QCLuceneTermPrivate::~QCLuceneTermPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qtoken.cpp b/tools/assistant/lib/fulltextsearch/qtoken.cpp index cc5296a..9056a7c 100644 --- a/tools/assistant/lib/fulltextsearch/qtoken.cpp +++ b/tools/assistant/lib/fulltextsearch/qtoken.cpp @@ -27,6 +27,7 @@ QCLuceneTokenPrivate::QCLuceneTokenPrivate(const QCLuceneTokenPrivate &other) : QSharedData() { token = _CL_POINTER(other.token); + deleteCLuceneToken = other.deleteCLuceneToken; } QCLuceneTokenPrivate::~QCLuceneTokenPrivate() diff --git a/tools/assistant/lib/fulltextsearch/qtokenstream.cpp b/tools/assistant/lib/fulltextsearch/qtokenstream.cpp index 8a98c08..0f4ab95 100644 --- a/tools/assistant/lib/fulltextsearch/qtokenstream.cpp +++ b/tools/assistant/lib/fulltextsearch/qtokenstream.cpp @@ -26,6 +26,7 @@ QCLuceneTokenStreamPrivate::QCLuceneTokenStreamPrivate(const QCLuceneTokenStream : QSharedData() { tokenStream = _CL_POINTER(other.tokenStream); + deleteCLuceneTokenStream = other.deleteCLuceneTokenStream; } QCLuceneTokenStreamPrivate::~QCLuceneTokenStreamPrivate() diff --git a/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp index 99dfb9c..38e3501 100644 --- a/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp +++ b/tools/designer/src/components/widgetbox/widgetboxtreewidget.cpp @@ -664,6 +664,9 @@ WidgetBoxTreeWidget::CategoryList WidgetBoxTreeWidget::loadCustomCategoryList() void WidgetBoxTreeWidget::adjustSubListSize(QTreeWidgetItem *cat_item) { QTreeWidgetItem *embedItem = cat_item->child(0); + if (embedItem == 0) + return; + WidgetBoxCategoryListView *list_widget = static_cast<WidgetBoxCategoryListView*>(itemWidget(embedItem, 0)); list_widget->setFixedWidth(header()->width()); list_widget->doItemsLayout(); diff --git a/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h index 0887a7c..8c54492 100644 --- a/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h +++ b/tools/designer/src/plugins/phononwidgets/videoplayertaskmenu.h @@ -47,7 +47,8 @@ #include <QtDesigner/QDesignerTaskMenuExtension> #include <QtDesigner/private/extensionfactory_p.h> -#include <phonon> +#include <Phonon/BackendCapabilities> +#include <Phonon/VideoPlayer> QT_BEGIN_NAMESPACE diff --git a/tools/linguist/lconvert/main.cpp b/tools/linguist/lconvert/main.cpp index 8ecdbc2..534bc11 100644 --- a/tools/linguist/lconvert/main.cpp +++ b/tools/linguist/lconvert/main.cpp @@ -80,6 +80,9 @@ static int usage(const QStringList &args) " -of <outformat>\n" " --output-format <outformat>\n" " Specify output format. See -if.\n\n" + " --input-codec <codec>\n" + " Specify encoding for .qm input files. Default is 'Latin1'.\n" + " UTF-8 is always tried as well, corresponding to the trUtf8() function.\n\n" " --drop-tags <regexp>\n" " Drop named extra tags when writing 'ts' or 'xlf' files.\n" " May be specified repeatedly.\n\n" @@ -138,6 +141,7 @@ int main(int argc, char *argv[]) Translator::LocationsType locations = Translator::DefaultLocations; ConversionData cd; + cd.m_codecForSource = "Latin1"; Translator tr; for (int i = 1; i < args.size(); ++i) { @@ -166,6 +170,10 @@ int main(int argc, char *argv[]) if (++i >= args.size()) return usage(args); inFormat = args[i]; + } else if (args[i] == QLatin1String("-input-codec")) { + if (++i >= args.size()) + return usage(args); + cd.m_codecForSource = args[i].toLatin1(); } else if (args[i] == QLatin1String("-drop-tag")) { if (++i >= args.size()) return usage(args); diff --git a/tools/linguist/shared/qm.cpp b/tools/linguist/shared/qm.cpp index 14f4c2c..323bd29 100644 --- a/tools/linguist/shared/qm.cpp +++ b/tools/linguist/shared/qm.cpp @@ -545,12 +545,20 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) size_t numItems = offsetLength / (2 * sizeof(quint32)); //qDebug() << "NUMITEMS: " << numItems; - // FIXME: that's just a guess, the original locale data is lost... - QTextCodec *codec = QTextCodec::codecForLocale(); + QTextCodec *codec = QTextCodec::codecForName(cd.m_codecForSource); QTextCodec *utf8Codec = 0; if (codec->name() != "UTF-8") utf8Codec = QTextCodec::codecForName("UTF-8"); + QString strProN = QLatin1String("%n"); + QLocale::Language l; + QLocale::Country c; + Translator::languageAndCountry(translator.languageCode(), &l, &c); + QStringList numerusForms; + bool guessPlurals = true; + if (getNumerusInfo(l, c, 0, &numerusForms)) + guessPlurals = (numerusForms.count() == 1); + QString context, contextUtf8; bool contextIsSystem, contextIsUtf8, contextNeeds8Bit; QString sourcetext, sourcetextUtf8; @@ -635,6 +643,15 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) end:; TranslatorMessage msg; msg.setType(TranslatorMessage::Finished); + if (translations.count() > 1) { + // If guessPlurals is not false here, plural form discard messages + // will be spewn out later. + msg.setPlural(true); + } else if (guessPlurals) { + // This might cause false positives, so it is a fallback only. + if (sourcetext.contains(strProN)) + msg.setPlural(true); + } msg.setTranslations(translations); translations.clear(); if (contextNeeds8Bit || sourcetextNeeds8Bit || commentNeeds8Bit) { @@ -649,7 +666,7 @@ bool loadQM(Translator &translator, QIODevice &dev, ConversionData &cd) } if (!(contextIsSystem && sourcetextIsSystem && commentIsSystem)) { cd.appendError(QLatin1String( - "Cannot read file with current system character codec")); + "Cannot read file with specified input codec")); return false; } // The message is 8-bit in the file's encoding (utf-8 or not). diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index 7bde3fe..c0f8677 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -12,6 +12,7 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QM_EXPORT_ICONVIEW \ QM_EXPORT_NETWORK \ QM_EXPORT_OPENGL \ + QM_EXPORT_OPENVG \ QM_EXPORT_SQL \ QM_EXPORT_TABLE \ QM_EXPORT_WORKSPACE \ @@ -50,6 +51,7 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_INTERNAL_WIN_NO_THROW \ Q_NETWORK_EXPORT \ Q_OPENGL_EXPORT \ + Q_OPENVG_EXPORT \ Q_OUTOFLINE_TEMPLATE \ Q_SQL_EXPORT \ Q_SVG_EXPORT \ diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro index 757ba12..358dbae 100644 --- a/tools/qmldebugger/qmldebugger.pro +++ b/tools/qmldebugger/qmldebugger.pro @@ -1,5 +1,7 @@ DESTDIR = ../../bin QT += network declarative +contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl + # Input HEADERS += canvasframerate.h canvasscene.h SOURCES += main.cpp canvasframerate.cpp canvasscene.cpp |